Chapter 9.2 - Service Accounts
Learning Objectives
By the end of this chapter, you will be able to:
- Understand what a Service Account is
- Create and use Service Accounts
- Bind Service Accounts to Pods
- Understand tokens and secrets
- Manage permissions with RBAC
- Use Service Accounts for API access
Introduction
A Service Account provides an identity for Pods running in the cluster. It allows applications to interact with the Kubernetes API securely.
What is a Service Account?
A Service Account is a Kubernetes identity used by Pods to:
- Authenticate with the Kubernetes API
- Access resources according to RBAC permissions
- Interact with other services in the cluster
By default: Each namespace has a default Service Account.
Creating a Service Account
Basic Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-sa
namespace: default
Service Account with Annotations
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-sa
namespace: default
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-role
Using in a Pod
Specifying the Service Account
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: my-app-sa
containers:
- name: app
image: my-app:1.0
Result: The Pod uses my-app-sa instead of the default Service Account.
Automatic Service Account
If serviceAccountName is not specified, the Pod uses the default Service Account of the namespace.
Tokens and Secrets
Automatic Token
Kubernetes automatically creates a token (Secret) for each Service Account:
# View automatically created secrets
kubectl get secrets | grep my-app-sa
# Token details
kubectl describe secret my-app-sa-token-xxxxx
Token Mounting
The token is automatically mounted in the Pod at /var/run/secrets/kubernetes.io/serviceaccount/:
# Inside the Pod
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
RBAC Permissions
Binding a Service Account to a Role
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-role-binding
namespace: default
subjects:
- kind: ServiceAccount
name: my-app-sa
namespace: default
roleRef:
kind: Role
name: app-role
apiGroup: rbac.authorization.k8s.io
Complete Example
Step 1: Create the Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
name: pod-reader-sa
namespace: default
Step 2: Create the Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
Step 3: Create the RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader-binding
namespace: default
subjects:
- kind: ServiceAccount
name: pod-reader-sa
namespace: default
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Step 4: Use in a Pod
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
serviceAccountName: pod-reader-sa
containers:
- name: app
image: my-app:1.0
Result: The Pod can read Pods in the default namespace.
Accessing the Kubernetes API
Using the Token in the Application
import os
import requests
# Read the token
with open('/var/run/secrets/kubernetes.io/serviceaccount/token', 'r') as f:
token = f.read().strip()
# Read the namespace
with open('/var/run/secrets/kubernetes.io/serviceaccount/namespace', 'r') as f:
namespace = f.read().strip()
# API call
api_url = f"https://kubernetes.default.svc/api/v1/namespaces/{namespace}/pods"
headers = {
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
response = requests.get(api_url, headers=headers, verify='/var/run/secrets/kubernetes.io/serviceaccount/ca.crt')
print(response.json())
Image Pull Secrets
Service Accounts can have imagePullSecrets to access private Docker registries:
apiVersion: v1
kind: ServiceAccount
metadata:
name: private-registry-sa
namespace: default
imagePullSecrets:
- name: regcred
Result: All Pods using this Service Account can pull images from the private registry.
Default Service Account
Disabling Automatic Mounting
apiVersion: v1
kind: ServiceAccount
metadata:
name: no-token-sa
namespace: default
automountServiceAccountToken: false
Result: The token is not mounted in Pods using this Service Account.
At the Pod Level
apiVersion: v1
kind: Pod
metadata:
name: no-token-pod
spec:
serviceAccountName: my-app-sa
automountServiceAccountToken: false
containers:
- name: app
image: my-app:1.0
Best Practices
1. One Service Account per Application
Create a dedicated Service Account for each application.
2. Principle of Least Privilege
Grant only the necessary permissions via RBAC.
3. Avoid Default Service Account
Avoid using the default Service Account in production.
4. Disable Token if Not Needed
Use automountServiceAccountToken: false if the application does not need API access.
5. Token Rotation
Tokens are automatically renewed by Kubernetes.
Useful Commands
Management
# Create a Service Account
kubectl create serviceaccount my-app-sa
# View Service Accounts
kubectl get serviceaccounts
kubectl get sa
# Details
kubectl describe serviceaccount my-app-sa
# View associated secrets
kubectl get secrets | grep my-app-sa
Usage
# Create a Pod with a Service Account
kubectl run my-pod --image=my-app:1.0 --serviceaccount=my-app-sa
# View the token in a Pod
kubectl exec my-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
Summary
In this chapter, you learned:
Service Account: Identity for Pods in Kubernetes
Creation: Simple Kubernetes resource
Usage: Via serviceAccountName in Pods
Tokens: Automatically created and mounted at /var/run/secrets/kubernetes.io/serviceaccount/
RBAC: Bind Service Accounts to Roles for permissions
API Access: Use the token to call the Kubernetes API
Image Pull Secrets: To access private registries
Best practices: One Service Account per application, least privilege
Next Steps
Chapter 9.3: Network Policies
Chapter 9.4: Pod Security Standards
Lab 9.2: Service Accounts and Permissions
Chapter created on: December 2024