How humans and application clients authenticate to Kubernetes, how authorization is enforced with RBAC, and how ServiceAccounts power in-cluster identity. Includes practical YAML examples and real-life scenarios.
kubectl get pods.
RBAC decides whether they can read pods in that namespace.
Authentication answers: “Who are you?” The API Server validates your identity using one of several mechanisms.
Your organization wants developers to authenticate using corporate SSO, not shared kubeconfig files. Users login to IdP → get token → API server validates token → RBAC enforces permissions.
apiVersion: v1
kind: Config
users:
- name: dev-user
user:
auth-provider:
name: oidc
config:
idp-issuer-url: https://idp.example.com
client-id: k8s-cli
# token is obtained via login flow and cached by client tooling
Authorization answers: “What are you allowed to do?” RBAC evaluates requested actions (verb + resource + namespace scope) against policies.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: spring-demo
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: devs-can-read-pods
namespace: spring-demo
subjects:
- kind: User
name: alice@company.com
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
A ServiceAccount is the identity used by workloads running inside the cluster. Pods can call the Kubernetes API using a token associated with their ServiceAccount. RBAC then controls what the workload can do.
A “deployment automation” Pod needs permission to create Jobs in its namespace (but nothing else). You create a ServiceAccount + Role + RoleBinding to enforce least privilege.
apiVersion: v1
kind: ServiceAccount
metadata:
name: job-runner
namespace: spring-demo
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: job-runner-role
namespace: spring-demo
rules:
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create", "get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: job-runner-binding
namespace: spring-demo
subjects:
- kind: ServiceAccount
name: job-runner
namespace: spring-demo
roleRef:
kind: Role
name: job-runner-role
apiGroup: rbac.authorization.k8s.io
Pods authenticate to the Kubernetes API by presenting a ServiceAccount token. Modern clusters often use projected service account tokens with bounded lifetime. The token is mounted into the Pod filesystem (and the API server validates it).
A controller Pod calls https://kubernetes.default.svc and uses the mounted token to authenticate.
RBAC then determines whether it can list secrets, create jobs, patch deployments, etc.
apiVersion: v1
kind: Pod
metadata:
name: api-client
namespace: spring-demo
spec:
serviceAccountName: job-runner
containers:
- name: client
image: alpine:3.20
command: ["sh","-c"]
args:
- |
apk add --no-cache curl;
TOKEN=$(cat /var/run/secrets/tokens/k8s-token);
curl -sSk -H "Authorization: Bearer $TOKEN" \
https://kubernetes.default.svc/api/v1/namespaces/spring-demo/pods;
sleep 3600
volumeMounts:
- name: sa-token
mountPath: /var/run/secrets/tokens
readOnly: true
volumes:
- name: sa-token
projected:
sources:
- serviceAccountToken:
path: k8s-token
expirationSeconds: 3600
audience: https://kubernetes.default.svc
Humans should authenticate using corporate identity (SSO), then receive RBAC permissions based on team role. This avoids shared credentials and supports auditing.
A platform engineer can manage cluster-wide resources; a developer can only view logs and restart pods inside the dev namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-troubleshooter
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "events"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-troubleshooting-access
namespace: spring-demo
subjects:
- kind: Group
name: dev-team
roleRef:
kind: ClusterRole
name: namespace-troubleshooter
apiGroup: rbac.authorization.k8s.io
spring-demo but cannot scale deployments or modify services.
Keep configuration out of container images. Store non-sensitive values in ConfigMaps and sensitive values in Secrets. Control access via RBAC and limit what workloads can read.
The UI uses a public API URL from ConfigMap and a database password from Secret. Only the app’s ServiceAccount is allowed to read those objects.
apiVersion: v1
kind: Pod
metadata:
name: spring-ui-api
namespace: spring-demo
spec:
serviceAccountName: spring-ui-api-sa
containers:
- name: app
image: myacr.azurecr.io/spring-ui-api:1.0
env:
- name: API_BASE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: API_BASE_URL
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_PASSWORD
Admission controls enforce organizational standards before objects are stored in etcd. Examples: enforce non-root containers, block privileged pods, require resource limits, enforce image registry allow-lists.
Your security team prevents developers from deploying privileged containers to production and requires all pods to specify CPU/memory requests and limits.
apiVersion: v1
kind: Namespace
metadata:
name: spring-demo
labels:
pod-security.kubernetes.io/enforce: "baseline"
pod-security.kubernetes.io/audit: "baseline"
pod-security.kubernetes.io/warn: "baseline"