RBAC: Role-Based Access Control
RBAC отвечает на единственный вопрос: «У этого identity есть право выполнить эту операцию над этим ресурсом?». Identity — User, Group или ServiceAccount; операция — verb (get, list, create, …); ресурс — pods, deployments, secrets и т.д. Всё остальное — это сочетание четырёх объектов: Role + RoleBinding (namespaced) и ClusterRole + ClusterRoleBinding (cluster-scoped). На CKAD без RBAC не сдать одну-две задачи из 16; в production без RBAC — кластер не аудит-compliant.
sudo: super user, sudoers и принцип least privilege
Четыре объекта: scope-матрица
Ключевая комбинация на CKAD: RoleBinding может ссылаться на ClusterRole. Это удобный способ переиспользовать built-in ClusterRoles (view, edit) на namespace-level. Никакой “доступ ко всему кластеру” от этого не появляется — RoleBinding всё ещё ограничен своим namespace.
Role: что в spec
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
resourceNames: ["my-app"]
verbs: ["get", "patch"]
Структура rules — это список независимых правил, объединённых OR (permissions аддитивны):
- apiGroups — список API groups.
""(пустая строка) — это core API group (Pods, Services, ConfigMaps, Nodes). Другие группы:apps(Deployment, StatefulSet),batch(Job, CronJob),networking.k8s.io(Ingress, NetworkPolicy),rbac.authorization.k8s.io,policyи т.д. - resources — типы ресурсов. Plural в lower-case:
pods, неPod. Подресурсы через слэш:pods/log(логи),pods/exec(exec),pods/portforward. - verbs — действия.
get,list,watch,create,update,patch,delete,deletecollection,*(все). - resourceNames — опционально, ограничить правило конкретными именами ресурсов. Например, разрешить
patchтолько Deploymentmy-app, а не любой.
resourceNames работает только для verbs, которые указывают имя: get, update, patch, delete. Для list/watch/create resourceNames бесполезен — list возвращает всё, что разрешено по другим правилам.
Verbs: список и tricky cases
Privilege escalation paths: bind на ClusterRole позволяет создавать RoleBinding на эту ClusterRole — то есть давать другим её permissions. escalate позволяет создавать Roles/ClusterRoles с правами, превышающими ваши собственные (иначе apiserver запрещает). impersonate — выполнять запросы от имени другого user/SA. Эти три verbs дают эффективно admin доступ. Никогда не давайте их app-Pods.
RoleBinding: соединение Role и subjects
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-pod-reader
namespace: default
subjects:
- kind: ServiceAccount
name: app-sa
namespace: default
- kind: User
name: [email protected]
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Поля:
- subjects — список identities, которым даём permissions. Три типа:
ServiceAccount— требуетnamespace(SA — namespaced object).User— внешняя identity, обычно из OIDC/x509-сертификатов. K8s не управляет users.Group— группа identities. Group attribution делает authenticator (OIDCgroupsclaim, x509 OU и т.д.).
- roleRef — на какую Role/ClusterRole ссылаемся.
kindлибоRole, либоClusterRole. Поле immutable — нельзя поменять roleRef после создания, нужно удалить и пересоздать.
roleRef immutable — это защита от accidental privilege escalation. Если бы можно было переключить RoleBinding с маленькой Role на cluster-admin ClusterRole, права subjects вырастали бы без видимого изменения. K8s заставляет удалять и пересоздавать — намного заметнее в audit logs.
ClusterRole: для чего
Три use-case ClusterRole:
- Cluster-scoped ресурсы — nodes, persistent volumes, storage classes, custom resource definitions. Role их не покрывает.
- Non-resource URLs —
/healthz,/metrics,/version. Только ClusterRole. - Reusable templates для namespaced ресурсов — определить «view» один раз, привязать через RoleBinding в множестве namespaces.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list"]
Привязка через ClusterRoleBinding (cluster-wide) или RoleBinding (namespace-limited):
# Вариант 1: cluster-wide — alice видит pods во ВСЕХ namespaces
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: alice-cluster-reader
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-pod-reader
apiGroup: rbac.authorization.k8s.io
---
# Вариант 2: namespace-limited — alice видит pods ТОЛЬКО в production
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: alice-prod-reader
namespace: production
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-pod-reader
apiGroup: rbac.authorization.k8s.io
Built-in ClusterRoles
K8s поставляется с несколькими default ClusterRoles:
Killer-момент: view ClusterRole не даёт доступ к Secrets. Это сделано специально — иначе view был бы способом утечки credentials. Если разработчику нужно читать Secrets — нужна отдельная Role или edit ClusterRole.
kubectl auth can-i: проверка permissions
# Могу я (текущий user) создать Deployment в default?
kubectl auth can-i create deployments
# Может ли SA app-sa в namespace default создать Pod?
kubectl auth can-i create pods --as=system:serviceaccount:default:app-sa
# Может ли SA читать Secrets в production?
kubectl auth can-i list secrets -n production \
--as=system:serviceaccount:default:app-sa
# Все мои permissions
kubectl auth can-i --list
Формат --as для SA: system:serviceaccount:<namespace>:<sa-name>. Это формат, который apiserver видит при authentication запроса от Pod с этим SA. Это знание встретится на CKAD.
kubectl auth can-i --list — must-know для troubleshooting RBAC. Показывает полный набор разрешений текущего user или указанного через —as. Сразу видно, чего не хватает.
Типовое CKAD-задание
Шаги, которые встретятся на экзамене:
# 1. Создать namespace
kubectl create namespace devops
# 2. Создать ServiceAccount
kubectl create serviceaccount deploy-sa -n devops
# 3. Создать Role (можно императивно)
kubectl create role deploy-manager \
--verb=get,list,watch,create,update,patch \
--resource=deployments,replicasets \
-n devops
# 4. Создать RoleBinding
kubectl create rolebinding deploy-sa-binding \
--role=deploy-manager \
--serviceaccount=devops:deploy-sa \
-n devops
# 5. Проверить
kubectl auth can-i create deployments \
--as=system:serviceaccount:devops:deploy-sa \
-n devops
# yes
kubectl auth can-i delete deployments \
--as=system:serviceaccount:devops:deploy-sa \
-n devops
# no
# 6. Использовать в Pod
kubectl run app --image=nginx \
--overrides='{"spec":{"serviceAccountName":"deploy-sa"}}' \
-n devops
На экзамене вместо kubectl create role чаще требуют YAML — но логика та же.
Aggregated ClusterRoles
Продвинутая фича: ClusterRole может агрегировать правила из других ClusterRoles по labels:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # будут заполнены controller'ом
Любой ClusterRole с label rbac.example.com/aggregate-to-monitoring: "true" автоматически вольёт свои rules в monitoring. Используется built-in admin, edit, view — они агрегируют ClusterRoles, добавляемые operators (Prometheus, Istio).
На CKAD это знать необязательно, но если в задаче встретится aggregationRule — не пугаться.