<h3>First, I have created a service account <code>jenkins</code></h3>
<pre><code>&gt; kubectl create serviceaccount jenkins
serviceaccount/jenkins created
</code></pre>
<h3>Second, create a token for this service account.</h3>
<pre><code>&gt; kubectl create token jenkins
eyJhbGc****************iQS-AVXfIzA
</code></pre>
<h3>Then, I run <code>kubectl describe serviceaccount jenkins</code> command to check the tokens of newly created service account.</h3>
<p>But the output shows None tokens.</p>
<pre><code>&gt; kubectl describe serviceaccount jenkins

Name:                jenkins
Namespace:           default
Labels:              &lt;none&gt;
Annotations:         &lt;none&gt;
Image pull secrets:  &lt;none&gt;  
Mountable secrets:   &lt;none&gt;
Tokens:              &lt;none&gt;   &lt;===== look at this!
Events:              &lt;none&gt;
</code></pre>
<h3>Questions</h3>
<ol>
<li><p>The output shows &quot;None&quot; tokens, how do I know there is a token associated with this service account?</p>
</li>
<li><p>If I run <code>kubectl create token jenkins</code> command multiple times, will kubernetes create multiple tokens for this account? or the latest one will overwrite the previous one?</p>
<pre><code># first time
kubectl create token jenkins
# second time
kubectl create token jenkins
# third time
kubectl create token jenkins
`

</code></pre>
</li>
<li><p>What's the mapping relation between the service account and the token? is it <code>1:n</code> ?</p>
</li>
</ol>

Ryan Lyu
<p>The mechanism of service accounts and tokens has been changed (Moved to stable in v1.22).</p>
<p>In the past, you have created a service account. Then in the first time you ran a pod with that service account, Kubernetes created a long-lived, never expired, token that resided in secret of type <code>kubernetes.io/service-account-token</code>. Kubernetes attached this token to the pod via volume mount.</p>
<p>Due to the unsecured nature of long-lived tokens this has been changed to something called <code>Bound Service Account Token Volumes</code>.</p>
<p>In short, Kubernetes no more creates a secret with a token for the service account but instead Kubelet injects a short-lived token with a default timespan of 1 hour to the pod and refresh it when it's expired.</p>
<p>When you ran <code>kubectl describe serviceaccount jenkins</code> you saw <code>&lt;none&gt;</code> in the section of the <code>Tokens</code> because it represents the 'old fashioned' static tokens that as mentioned are not created by default anymore.</p>
<p>You can manually create such a static token with</p>
<pre><code>&gt; cat &lt;&lt;EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
  name: jenkins
  annotations:
    kubernetes.io/service-account.name: jenkins
EOF
</code></pre>
<p>and then when you run <code>describe</code> again and you will the new token</p>
<pre><code>&gt; kubectl describe serviceaccount jenkins
Name:                jenkins
Namespace:           jenkins-demo
Labels:              &lt;none&gt;
Annotations:         &lt;none&gt;
Image pull secrets:  &lt;none&gt;
Mountable secrets:   &lt;none&gt;
Tokens:              jenkins
Events:              &lt;none&gt;
</code></pre>
<p>You can create multiple tokens with different names and you will see all of them in the <code>describe</code> output.</p>
<p><strong>BUT</strong> This is a bad practice to create these static tokens because they never expired. You should use short-lived token that you can create with the command you mentioned <code>kubectl create token jenkins</code></p>
<p>You can control the duration with <code>--duration &lt;seconds&gt;s</code> and create a token with an expiration of up to 48h. The default is 1h.</p>
<p>The creation of new token doesn't overwrite the previous one. These tokens are JWTs - meaning they are signed and distributed, and are not kept on the server. If you want to see the content of a token you can paste the output
of <code>kubectl create token jenkins</code> in <a href="https://jwt.io/" rel="noreferrer">jwt.io</a>.</p>
<p>Same as with the static token. You can run
<code>kubectl get secret jenkins --output=jsonpath='{.data.token}' | base64 -d</code>
and paste the output in <a href="https://jwt.io/" rel="noreferrer">jwt.io</a>. You can notice this token doesn't have an expiration date.</p>
<p>Reference:</p>
<ol>
<li><a href="https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/" rel="noreferrer">https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/</a></li>
<li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-an-api-token-for-a-serviceaccount" rel="noreferrer">https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-an-api-token-for-a-serviceaccount</a></li>
<li><a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/1205-bound-service-account-tokens" rel="noreferrer">https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/1205-bound-service-account-tokens</a></li>
<li><a href="https://github.com/kubernetes/enhancements/issues/542" rel="noreferrer">https://github.com/kubernetes/enhancements/issues/542</a></li>
</ol>
