Kubernetes cookbook · Intermediate
Give a CI pipeline least-privilege deploy access
CI deploys with cluster-admin; restrict it to one namespace and the resources it manages.
Approach
Create a ServiceAccount for the pipeline, a Role with the verbs it needs on the resources it deploys, and a RoleBinding in that namespace only. Authenticate CI with short-lived tokens or OIDC.
Solution
apiVersion: v1
kind: ServiceAccount
metadata: {name: ci-deployer, namespace: shop}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: {name: deployer, namespace: shop}
rules:
- apiGroups: [apps]
resources: [deployments]
verbs: [get, list, watch, create, update, patch]
- apiGroups: [""]
resources: [services, configmaps]
verbs: [get, list, watch, create, update, patch]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: {name: ci-deployer, namespace: shop}
roleRef: {apiGroup: rbac.authorization.k8s.io, kind: Role, name: deployer}
subjects: [{kind: ServiceAccount, name: ci-deployer, namespace: shop}]
Pitfalls
- Granting Secret read access "just in case"; the pipeline rarely needs it.
- Long-lived tokens stored in CI secrets; prefer
kubectl create token --durationor OIDC federation.
Variations
- GitOps: the pipeline only commits to Git and Argo CD deploys, so CI needs no cluster access at all.
- Verify with
kubectl auth can-i --list --as=system:serviceaccount:shop:ci-deployer -n shop.
Further reading: RBAC good practices
Reference: https://kubernetes.io/docs/concepts/security/rbac-good-practices/
More Kubernetes recipes
- Autoscale a Deployment on CPU and memory
- Debug a distroless pod with an ephemeral container
- Default-deny network policies that keep DNS working
- Enforce the restricted Pod Security Standard
- Expose a service over HTTPS with automatic certificates
- Handle SIGTERM in your application for Kubernetes
- Manage dev, staging and prod with Kustomize overlays
- Restart pods automatically when configuration changes