<p>We're running <code>gitlab-runner</code> instances via kubernetes executors inside a kubernetes cluster (let's call it KUBE01). These instances build and deploy to the kubernetes cluster, and runners are given an environment variable <code>KUBECONFIG</code> (pointing to a config file) as follows:</p>

<pre><code>$ cat $KUBECONFIG
---
apiVersion: v1
clusters:
- name: gitlab-deploy
  cluster:
    server: https://KUBE01:6443
    certificate-authority-data: &lt;CA_B64&gt;
contexts:
- name: gitlab-deploy
  context:
    cluster: gitlab-deploy
    namespace: dev
    user: gitlab-deploy
current-context: gitlab-deploy
kind: Config
users:
- name: gitlab-deploy
  user:
    token: gitlab-deploy-token-&lt;secret&gt;
</code></pre>

<p>We can verify that <code>kubectl</code> is actually using the above <code>gitlab-deploy</code> context:</p>

<pre><code>$ kubectl config current-context
gitlab-deploy
</code></pre>

<p>However, attempting to actually affect KUBE01 fails:</p>

<pre><code>$ kubectl get pods
error: You must be logged in to the server (Unauthorized)
</code></pre>

<p>On my machine we can verify that the namespace and service account tokens are correct:</p>

<pre><code>$ kubectl get sa/gitlab-deploy -o yaml --namespace dev
apiVersion: v1
kind: ServiceAccount
metadata:
  &lt;snip metadata&gt;
  name: gitlab-deploy
  namespace: dev
secrets:
- name: gitlab-deploy-token-&lt;secret&gt;
</code></pre>

<p>I cannot find any documentation about this other than <em>it should just work</em>, and all forum/stack exchange issues I've found about this error message are bad user/pass combinations; but as far as I can tell, my token, namespace, and cluster are all correct.</p>

<p>After a more detailed reading of the <a href="https://kubernetes.io/docs/admin/authentication/#service-account-tokens" rel="noreferrer">kuberneter authentication documentation</a> and some trial and error, I have found the issue.</p>

<p>The "secret tokens" inside service account objects are not the <em>actual</em> secret tokens that we use for service account authentication; rather, it is a pointer to a secret object which, in turn, holds the real (bearer) token. It can be found as follows:</p>

<pre><code>$ kubectl get secret gitlab-deploy-token-&lt;secret&gt; -o yaml
apiVersion: v1
data:
  ca.crt: &lt;CA_B64&gt;
  namespace: ZGV2
  token: &lt;BEARER_TOKEN_B64&gt;
kind: Secret
metadata:
  &lt;snip metadata&gt;
  name: gitlab-deploy-token-&lt;secret&gt;
  namespace: dev
type: kubernetes.io/service-account-token
</code></pre>

<p>The bearer token is, of course, base64 encoded due to it being a secret; but oddly enough, we don't base64 encode it in our <code>KUBECONFIG</code> file (like we do with e.g. the CA). Thus, what we had to do was find the above bearer token, decode it from base64, and add it as our token under the <code>gitlab-deploy</code> user. Then, authentication works.</p>
