0

My NodeJS microservice is deployed to k8s cluster.

I am running this with my local Docker Desktop k8s environment.

I would like this microservice to access the k8s API server. For that, I guess I need to create a ServiceAccount for it. So I did this:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-service-account
  namespace: myapp-ns

Then, I also created a ClusterRole to define the permissions:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: myapp-cluster-role
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]

Finally, I created a ClusterRoleBinding:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: my-app-role-binding
  namespace: myapp-ns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: myapp-cluster-role
subjects:
- kind: ServiceAccount
  name: my-app-service-account
  namespace: myapp-ns

I applied them to my cluster. Then, I noticed the created Service Account doesn't have a secret provisioned:

> k get sa -n myapp-ns
NAME                      SECRETS   AGE
default                   0         11h
my-app-service-account    0         1h

So, I created a secret for my service account by applying the following manifest:

apiVersion: v1
kind: Secret
metadata:
  name: my-sa-token
  namespace: myapp-ns
  annotations:
    kubernetes.io/service-account.name: "my-app-service-account"
type: kubernetes.io/service-account-token

I can see that this secret is created successfully:

> k get secret -n myapp-ns
NAME          TYPE                             DATA   AGE
my-sa-token   kubernetes.io/dockerconfigjson   1      10s

Then, I check my previously created service account:

> k get sa -n myapp-ns
NAME                      SECRETS   AGE
default                   0         11h
my-app-service-account    0         1h

It still shows 0 secret associated with it.

Why is that? How can I have my service account to have a secret associated?

user842225
  • 5,445
  • 15
  • 69
  • 119

1 Answers1

0

I think you misunderstand the semantics of the secrets field of the ServiceAccount. From the Kubernetes API reference:

Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a "kubernetes.io/enforce-mountable-secrets" annotation set to "true". This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret

In other words, secrets is a list you specify that limits which secrets a given service account should be able to use. Furthermore, I think something went wrong during the creation of your secret because your question shows it has type kubernetes.io/dockerconfigjson. When I kubectl apply the file containing the secret definition I get something very different:

NAME          TYPE                                  DATA   AGE
my-sa-token   kubernetes.io/service-account-token   3      4m13s

Inspecting the secret as YAML shows that Kubernetes has added a token, namespace and ca.crt field, as expected.

Furthermore, kubectl describe links the ServiceAccount and the Secret:

Name:                my-app-service-account
Namespace:           myapp-ns
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   <none>
Tokens:              my-sa-token
Events:              <none>
Botje
  • 26,269
  • 3
  • 31
  • 41
  • I am running the local Docker Desktop k8s environment. Do you mean my resources are running correctly? Or do I need to change anything in the code? As you see in my code, I have specified which service account my secret is associated with via the annotation `kubernetes.io/service-account.name:` – user842225 Mar 13 '23 at 09:38
  • Or do you mean I should add the annotation `kubernetes.io/enforce-mountable-secrets: true` in my service account manifest? – user842225 Mar 13 '23 at 09:42
  • Can you show *how* you created the secret? Because the type is not what it should be, as my answer shows. As for your other question: it is normal that "secrets" stays as 0, because you did not specify anything in the `secrets` field. And you should only do this if you intend to make use of the "limit this serviceaccount to these secrets" feature. – Botje Mar 13 '23 at 09:49
  • I think I already showed how I created, using the YAML manifest I posted, then `k apply mysecret-yaml`. So, the type of the secret is based on this : https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-long-lived-api-token-for-a-serviceaccount – user842225 Mar 13 '23 at 09:51
  • I mean, I don't get what is the way you do this? could you please provide the code of what you did that works? I could change to another option. What should I specify in the secret? Could you please show your secret manifest in your answer? – user842225 Mar 13 '23 at 09:52
  • All I can say is that I did `kubectl apply` on the same YAML file, but mine has the correct type. FWIW this is on kubernetes 1.26.1 (on minikube, but that should not matter) – Botje Mar 13 '23 at 09:54
  • And again I ask you: do you *want* to limit that service account to a specific list of secrets, or do you just have a pathologic need to see a "1" in that column? If you `kubectl describe` your serviceaccount you will see that the secret *is* listed. (if created with the right type) – Botje Mar 13 '23 at 09:55
  • OK, then what is the "correct type"? Could you please show me your secret manifest to be more clear since your answer doesn't say the "working solution" but only shows "something wrong". – user842225 Mar 13 '23 at 09:55
  • Last time I repeat myself: your secret has been created with the wrong type. I don't know how or what you did wrong, and I cannot reproduce your error given the inputs you posted. But Kubernetes will not fill in the Secret if the type is wrong. So nuke the secret and try again. – Botje Mar 13 '23 at 09:56
  • I am not sure, I just seek for the most valid solution to make my service account having a secret associated to access API server. Either way is fine as long as it works. – user842225 Mar 13 '23 at 09:57
  • It *IS* associated, at least on my side. I wrote that in my answer. I will edit my answer with `kubectl describe` output. – Botje Mar 13 '23 at 09:58
  • Man, thanks for the help! Really. But you keep saying "type is wrong" and I just want to know what is the correct type then? otherwise, this is not helpful... I also linked the official doc to explain where that "type" comes from. – user842225 Mar 13 '23 at 09:58
  • The type, as reported by `kubectl get secret` should be `kubernetes.io/service-account-token`. Your question shows it is `kubernetes.io/dockerconfigjson`. So clearly you did *not* do the equivalent of `kubectl apply`, but I have no idea what you did, and neither do you. – Botje Mar 13 '23 at 10:00
  • My manifest is there, you can see I am using the `kubernetes.io/service-account-token` as type, if you just see my secret manifest yaml code. The output shows the `kubernetes.io/dockerconfigjso` indeed is weird, but it is not my behaviour, I only control the manifest yaml definition like you too... So, when you say "type is wrong", I really don't feel what I can do then... anyway, thanks for the help. – user842225 Mar 13 '23 at 10:01
  • Here is the explanation of the type `kubernetes.io/dockerconfigjson` https://kubernetes.io/docs/concepts/configuration/secret/#docker-config-secrets – user842225 Mar 13 '23 at 10:46
  • I know very well what the different secret types do, thank you. – Botje Mar 13 '23 at 10:49