RBAC: roles, bindings and service accounts
Who may do what in a cluster: Roles list allowed actions, bindings hand them out, and kubectl auth can-i proves it.
Key ideas in this lesson · tap one for a simple explanation
What you will be able to do
- Create a ServiceAccount, a Role and a RoleBinding with kubectl in under two minutes.
- Choose between a Role and a ClusterRole, and between a RoleBinding and a ClusterRoleBinding.
- Write rules with the right API group, plural resource names and subresources such as
pods/log. - Check access with
kubectl auth can-i, issue a short-lived token, and take back access that is too broad.
(role-based access control) decides who may do what in a cluster. May your Django app's read ? May the user maya delete Pods? RBAC answers these questions. On the exam it is one of the surest sources of points, because most tasks take three short commands.
The grader does not read your . It asks the whether someone may do something, the same way kubectl auth can-i does. So a rule that looks right but names the wrong API group still fails.
Four objects with look-alike names
RBAC uses four objects. Learn them in pairs: a role says what is allowed, and a binding says who gets it. A role does nothing until a binding hands it out.
Subject
a user, a group or a service account
maya
RoleBinding
gives the role to the subject
Role
a named list of rules
config-editor
Rules
verbs on resources
get, list on configmaps
The binding joins who (the subject) to what (the role). The role holds the rules: which actions on which objects.
- Subjects are who gets access. A user is a person, such as
maya. A group is a set of users, such asplatform-oncall. A is an identity for a program that runs in a Pod. Users and groups are not objects you create in the cluster. - Permissions only add up. A subject gets the rules of every binding that names it. There are no deny rules, so to take access away you delete or narrow a binding.
- A RoleBinding may point at a ClusterRole. The rules then apply only in the binding's namespace, and rules about cluster-wide objects such as nodes give nothing. This lets you reuse one ClusterRole, such as
edit, in many namespaces. - A ClusterRoleBinding can only point at a ClusterRole, never at a Role.
Writing a rule
A rule has three parts: the API group, the resources and the verbs (the actions). Here is a Role with two rules, and a RoleBinding that gives it to all three kinds of subject:
# To try it: kubectl create namespace arx-rbac-demo first, then kubectl apply -f this file
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: config-editor
namespace: arx-rbac-demo
rules:
- apiGroups: [""] # "" is the core group: pods, services, configmaps, secrets
resources: ["configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "deployments/scale"]
verbs: ["get", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: config-editor
namespace: arx-rbac-demo
roleRef: # cannot be changed: to point elsewhere, delete and recreate the binding
apiGroup: rbac.authorization.k8s.io
kind: Role
name: config-editor
subjects:
- kind: ServiceAccount # no apiGroup; always give its namespace
name: settings-sync
namespace: arx-rbac-demo
- kind: User # the user name from their certificate or login
apiGroup: rbac.authorization.k8s.io
name: maya
- kind: Group # a group from their certificate or login
apiGroup: rbac.authorization.k8s.io
name: platform-oncallNot sure of a group or a plural? kubectl api-resources -o wide lists every resource with its API group and its verbs.
Create it with kubectl
On the exam you rarely write RBAC YAML. kubectl create makes each object in one line. The flags take comma-separated lists, and a resource outside the core group is written <resource>.<group>, such as deployments.apps.
kubectl create namespace arx-rbac-demo
kubectl -n arx-rbac-demo create serviceaccount settings-sync
# Role: comma-separated verbs, any number of resources; non-core resources as <resource>.<group>
kubectl -n arx-rbac-demo create role app-reader \
--verb=get,list,watch --resource=pods,services,deployments.apps
kubectl -n arx-rbac-demo create role settings-writer \
--verb=update,patch --resource=configmaps --resource-name=app-settings
# RoleBinding: --role or --clusterrole, then any mix of subjects (SA is <namespace>:<name>)
kubectl -n arx-rbac-demo create rolebinding app-reader --role=app-reader \
--serviceaccount=arx-rbac-demo:settings-sync --user=maya --group=platform-oncall
kubectl -n arx-rbac-demo create rolebinding settings-writer --role=settings-writer --user=maya
# Cluster-wide rules and binding
kubectl create clusterrole pv-viewer --verb=get,list,watch \
--resource=persistentvolumes,storageclasses.storage.k8s.io
kubectl create clusterrolebinding pv-viewer --clusterrole=pv-viewer --group=platform-oncall
# Generate YAML instead when you need to add something the flags cannot express
kubectl -n arx-rbac-demo create role app-reader --verb=get --resource=pods --dry-run=client -o yamlLook at how the binding names the service account: namespace:name. You write a service account three different ways, depending on where you use it:
Prove it with auth can-i
Always check your work before you move on. kubectl auth can-i asks the API server whether a request would be allowed. It prints yes or no and changes nothing. Add --as to ask on behalf of someone else.
# Ask the API server as the subject. "yes" exits 0, "no" exits 1.
kubectl auth can-i list deployments.apps -n arx-rbac-demo \
--as=system:serviceaccount:arx-rbac-demo:settings-sync
kubectl auth can-i update configmaps/app-settings -n arx-rbac-demo --as=maya # TYPE/NAME form
kubectl auth can-i get pods --subresource=log -n arx-rbac-demo --as=maya # subresources need the flag
kubectl auth can-i list persistentvolumes --as=anyone --as-group=platform-oncall # --as-group needs --as
kubectl auth can-i --list -n arx-rbac-demo --as=system:serviceaccount:arx-rbac-demo:settings-sync
kubectl auth whoami # who you are right nowService accounts and tokens
A ServiceAccount is an identity for a program, not a person. Example: your Django app needs to list Pods through the API. You create a service account for it, bind a Role to that account, and run the app's Pods as that account.
- A Pod runs as the account named in
spec.serviceAccountName. Leave it out and the Pod runs asdefault. - The puts a short-lived token into the Pod, at
/var/run/secrets/kubernetes.io/serviceaccount/token, and renews it for you. kubectl create tokengives you a token on demand. Kubernetes no longer creates token Secrets by itself.- Set
automountServiceAccountToken: falseon the Pod or the account when the app never calls the API.
kubectl -n arx-rbac-demo create serviceaccount report-bot
kubectl -n arx-rbac-demo create token report-bot --duration=2h > /tmp/cka/report-bot.token
# The token is printed once and stored nowhere. A token that never expires needs a Secret of type kubernetes.io/service-account-token: avoid it unless asked.
# Run as the account: kubectl run has no SA flag, so override the spec (or set it in YAML)
kubectl -n arx-rbac-demo run reporter --image=busybox:1.36 --restart=Never \
--overrides='{"spec":{"serviceAccountName":"report-bot"}}' -- sleep 3600
kubectl -n arx-rbac-demo set serviceaccount deployment/web report-bot # an existing DeploymentBuilt-in ClusterRoles
Kubernetes comes with ready-made ClusterRoles. Bind one when it fits, instead of writing your own. For example, kubectl -n shop create rolebinding maya-edit --clusterrole=edit --user=maya lets maya change most things in shop, and nothing anywhere else.
Your admin gets cluster-admin through the group kubeadm:cluster-admins. Certificates and kubeconfig shows where users and groups come from.
In the official docs· open on exam day too
- Using RBAC Authorizationsearch: rbac authorization
- Configure Service Accounts for Podssearch: configure service accounts
- kubectl auth can-isearch: kubectl auth can-i
- Managing Service Accountssearch: managing service accounts
A service account that can deploy, and a token for it
arx-rbac, create a ServiceAccount named deployer and a Role named deployer that allows get, list, watch, create, update and patch on Deployments, and get, list, watch on Pods, and nothing else. Bind the Role to the ServiceAccount with a RoleBinding named deployer-binding. Finally, create a token for deployer that is valid for 2 hours and write only the token to /tmp/cka/rbac/deployer.token.Cluster:kubectl config use-context kind-cka
- 1
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-1/setup | bash - 2
Solve it in your terminal
Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under
/tmp/cka/. - 3
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-1/verify | bashGot FAIL? Read which check failed, fix it, run it again. - 4
Clean up (optional)
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-1/cleanup | bash
Read-only node access for a group
arx-ops need to inspect nodes and PersistentVolumes across the cluster without changing anything. Create a ClusterRole named arx-node-reader that allows get, list and watch on nodes and persistentvolumes, and grant it to the group arx-ops with a ClusterRoleBinding named arx-node-reader-ops. The group must not gain any other access.Cluster:kubectl config use-context kind-cka
- 1
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-2/setup | bash - 2
Solve it in your terminal
Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under
/tmp/cka/. - 3
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-2/verify | bashGot FAIL? Read which check failed, fix it, run it again. - 4
Clean up (optional)
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-2/cleanup | bash
Take back cluster-admin from a service account
log-shipper in namespace arx-rbac-fix was given cluster-admin to get a log collector working. It only needs to read Pods and their logs in its own namespace. Remove the excess access, then grant exactly get, list, watch on Pods and get on Pod logs in arx-rbac-fix, using a Role named log-reader and a RoleBinding named log-shipper-read. Do not delete the ServiceAccount.Cluster:kubectl config use-context kind-cka
- 1
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-3/setup | bash - 2
Solve it in your terminal
Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under
/tmp/cka/. - 3
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-3/verify | bashGot FAIL? Read which check failed, fix it, run it again. - 4
Clean up (optional)
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-3/cleanup | bash
Finished this lesson?
0 of 3 tasks passed. Your readiness counts tasks, so run them before you move on.