Introduction to Service Accounts

Service Accounts in Kubernetes are special accounts used by Pods (not humans) to interact with the Kubernetes API. Unlike regular user accounts that may be managed externally, Service Accounts are managed within the Kubernetes cluster.

Creating and Managing Service Accounts

To create a new service account, you can use the kubectl command:

kubectl create serviceaccount my-service-account

You can also create it using a YAML file:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-service-account

Apply it using:

kubectl apply -f service-account.yaml

Using Service Accounts with Pods

By default, Pods use the default service account within their namespace. To specify a different service account, set the serviceAccountName field in the Pod specification.

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  serviceAccountName: my-service-account
  containers:
  - name: my-container
    image: my-image

RBAC and Service Accounts

Role-Based Access Control (RBAC) can be applied to service accounts to define what actions they can perform. You can bind a Role or ClusterRole to a Service Account using a RoleBinding or ClusterRoleBinding.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
subjects:
- kind: ServiceAccount
  name: my-service-account
  namespace: default
roleRef:
  kind: Role
  apiGroup: rbac.authorization.k8s.io
  name: pod-reader

When a service account is created, a secret containing a token is automatically generated and associated with the service account. This token is used to authenticate the service account when interacting with the Kubernetes API.

Viewing Tokens

To view the token for a service account, first find the associated secret:

kubectl get serviceaccounts my-service-account -o jsonpath='{.secrets[*].name}'

Then, to view the token, describe the secret:

kubectl get secret [SECRET_NAME] -o jsonpath='{.data.token}' | base64 --decode

Mounting Tokens to Pods

The service account token is automounted to /var/run/secrets/kubernetes.io/serviceaccount/ in each Pod using that service account. To disable this, use automountServiceAccountToken:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  serviceAccountName: my-service-account
  automountServiceAccountToken: false
  ...

Best Practices and Considerations

  1. Least Privilege: Only grant the permissions necessary for the service account to perform its tasks.
  2. Audit: Regularly review and audit permissions for service accounts.
  3. Namespace Isolation: Use different service accounts for different namespaces.
  4. Token Review: Service account tokens are long-lived; rotate them or set expiration where applicable.
  5. Automate Management: Automate the creation, deletion, and permissions management for service accounts.

Troubleshooting Exercise

Setup Commands

Create a service account and a Pod that uses it:

kubectl create serviceaccount troubleshooting-sa
kubectl run troubleshooting-pod --image=busybox --serviceaccount=troubleshooting-sa -- sleep 3600

Exercise

Your Pod is not able to read ConfigMaps, even though it should have the permission.

Debugging Steps

  1. Check the service account token mounted in the Pod.

    kubectl exec -it troubleshooting-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
    
  2. Check the Role and RoleBinding for the service account.

    kubectl get role,rolebinding -o yaml
    

Solution

Make sure the service account is properly bound to a Role that has permission to read ConfigMaps:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: configmap-reader
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-configmaps
subjects:
- kind: ServiceAccount
  name: troubleshooting-sa
  namespace: default
roleRef:
  kind: Role
  apiGroup: rbac.authorization.k8s.io
  name: configmap-reader

Apply the changes:

kubectl apply -f role-and-rolebinding.yaml