RBAC — стандартный механизм авторизации в Kubernetes: кто может делать что с какими ресурсами. Включается флагом --authorization-mode=RBAC на kube-apiserver; в kubeadm, EKS, GKE, AKS, k3s — по умолчанию.
RBAC работает аддитивно: можно только разрешать, явного deny нет. Если ни одна роль не покрывает запрос — он запрещён. Least-privilege by default: новый ServiceAccount без привязок ничего не может.
Запрос к apiserver проходит три стадии: аутентификация (кто ты), авторизация (что можно), admission control (соответствует ли политикам). RBAC — только вторая стадия.
[source: kubernetes.io/docs/reference/access-authn-authz/rbac/]
Четыре объекта RBAC
Четыре объекта, разделённые по scope:
Субъект (subject) — кто получает права:
- User — аутентифицирован через OIDC, X.509-сертификат, токен
- Group — группа пользователей (
system:masters,system:authenticated) - ServiceAccount — машинный аккаунт для Pod
User и Group — внешние идентичности (Kubernetes их не хранит). ServiceAccount — единственный нативный объект K8s API среди субъектов.
Структура правила (rule)
Три обязательных поля:
- apiGroups —
""для core (Pod, Service, ConfigMap, Secret),"apps"для Deployment/StatefulSet/DaemonSet,"batch"для Job/CronJob,"networking.k8s.io"для Ingress/NetworkPolicy - resources —
pods,deployments,secrets,configmapsи т.д. - verbs —
get,list,watch,create,update,patch,delete,deletecollection
Опциональное resourceNames ограничивает доступ конкретными объектами (например, только Secret db-password).
Разница verbs: get — один объект по имени, list — список, watch — подписка на события. update — замена объекта целиком, patch — частичное обновление. deletecollection — удалить по label-селектору (отдельный verb от delete).
Role — права внутри namespace
Role — namespace-scoped объект. Права из Role применяются только в том namespace, где она создана.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: app
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
pods/log, pods/exec, pods/portforward — sub-resources, задаются отдельно от pods.
ClusterRole — права на уровне кластера
ClusterRole нужна в двух случаях:
- Права на non-namespaced ресурсы:
nodes,persistentvolumes,namespaces,clusterroles,storageclasses - Права, которые хочется переиспользовать в нескольких namespace без дублирования
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-wide-reader
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "nodes", "namespaces"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulsets", "daemonsets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources: ["jobs", "cronjobs"]
verbs: ["get", "list", "watch"]
nodes — non-namespaced ресурс, его можно задать только в ClusterRole.
RoleBinding — привязка роли к субъекту
RoleBinding связывает роль с субъектом в namespace. Может ссылаться на Role или ClusterRole; во втором случае права применяются только в namespace этого RoleBinding — основной механизм переиспользования ролей.
Привязка dev-ivan к Role pod-reader в namespace app:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: app
subjects:
- kind: User
name: dev-ivan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Три типа субъектов в одном RoleBinding:
subjects:
# Пользователь
- kind: User
name: dev-ivan
apiGroup: rbac.authorization.k8s.io
# Группа
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.io
# ServiceAccount
- kind: ServiceAccount
name: my-app-sa
namespace: app
Все субъекты в одном RoleBinding получают одинаковые права.
RoleBinding на ClusterRole
Паттерн для multi-tenant: одна ClusterRole, RoleBinding в каждом namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-alpha-view
namespace: alpha
subjects:
- kind: Group
name: team-alpha
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole # ссылается на ClusterRole
name: view # встроенная ClusterRole
apiGroup: rbac.authorization.k8s.io
Группа team-alpha получает view (read-only) только в namespace alpha.
ClusterRoleBinding — права на весь кластер
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-reader-binding
subjects:
- kind: User
name: dev-ivan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-wide-reader
apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding даёт права во всех namespace и на cluster-scoped ресурсы. Только для системных компонентов, операторов, мониторинговых агентов.
Встроенные ClusterRole
Четыре заготовленные ClusterRole:
Используй через RoleBinding вместо кастомных ролей. Для "дай разработчику доступ в namespace" встроенных хватает.
Посмотреть содержимое:
kubectl describe clusterrole view
kubectl describe clusterrole edit
kubectl describe clusterrole admin
Aggregated ClusterRoles
admin, edit, view поддерживают агрегацию: другие ClusterRole расширяют их через label. Операторы добавляют права на свои CRD в стандартные роли без патчинга.
Пример: CRD-оператор добавляет ресурсы в view:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: myapp-viewer
labels:
rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["myapp.example.com"]
resources: ["widgets", "gadgets"]
verbs: ["get", "list", "watch"]
view имеет aggregationRule с селектором rbac.authorization.k8s.io/aggregate-to-view: "true" — Kubernetes подтянет эти rules. Аналогичные label есть для edit и admin.
Проверить:
kubectl get clusterrole view -o yaml | grep aggregationRule -A 10
[source: kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles]
Диагностика: kubectl auth can-i
Проверка и отладка прав:
# Могу ли я создать Deployment в текущем namespace?
kubectl auth can-i create deployments
# Может ли dev-ivan читать Pod в namespace app?
kubectl auth can-i get pods --namespace app --as dev-ivan
# Может ли ServiceAccount my-sa в namespace app читать secrets?
kubectl auth can-i get secrets --namespace app \
--as system:serviceaccount:app:my-sa
# Список всех разрешённых действий в namespace для пользователя
kubectl auth can-i --list --namespace app --as dev-ivan
# Проверить доступ к конкретному sub-resource
kubectl auth can-i create pods/exec --namespace app --as dev-ivan
Формат impersonation для SA: system:serviceaccount:<namespace>:<name>.
Ограничение: can-i проверяет authorization layer через SelfSubjectAccessReview и работает с настроенным authorizer chain. Admission Controllers (OPA/Gatekeeper, Kyverno, PodSecurity), ResourceQuota и LimitRange он не проверяет: запрос может пройти authorization и быть отклонён на admission.
kubectl auth reconcile
Для применения RBAC из GitOps:
# Проверить и применить RBAC-манифесты без лишних изменений
kubectl auth reconcile -f rbac-manifests/
# Посмотреть, что изменится (dry-run)
kubectl auth reconcile -f rbac-manifests/ --dry-run=client
reconcile идемпотентен: он добавляет недостающие rules, но не удаляет лишние.
Полный пример: read-only доступ для разработчика
Задача: дать dev-ivan право читать Pod и их логи в namespace app, запускать exec, но не изменять и не удалять ничего.
---
apiVersion: v1
kind: Namespace
metadata:
name: app
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: app
name: dev-readonly
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "services", "configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-ivan-readonly
namespace: app
subjects:
- kind: User
name: dev-ivan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: dev-readonly
apiGroup: rbac.authorization.k8s.io
Проверка:
kubectl auth can-i get pods --namespace app --as dev-ivan # yes
kubectl auth can-i delete pods --namespace app --as dev-ivan # no
kubectl auth can-i get secrets --namespace app --as dev-ivan # no
kubectl auth can-i create pods/exec --namespace app --as dev-ivan # yes
Когда использовать
Role + RoleBinding — изолированный namespace: разработчики команды, CI-пайплайн проекта, приложение с доступом к своим ресурсам. По умолчанию.
ClusterRole + RoleBinding в разных namespace — один набор прав в нескольких namespace без дублирования.
ClusterRole + ClusterRoleBinding — мониторинг (Prometheus, Datadog), Kubernetes operators с CRD кластерного уровня, компоненты control plane.
Встроенные роли (view, edit, admin) — стандартный уровень доступа без кастомизации. Расширяются через Aggregated ClusterRoles для CRD.
Типичные ошибки
apiGroups: [""] для apps-ресурсов. Deployment/StatefulSet/DaemonSet/ReplicaSet — в apps, Job/CronJob — в batch. apiGroups: [""] с resources: ["deployments"] не сработает (без явной ошибки).
# Неправильно — deployments в core group не существует
rules:
- apiGroups: [""]
resources: ["deployments"]
verbs: ["get", "list"]
# Правильно
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]
Проверка: kubectl api-resources | grep deployment — столбец APIVERSION покажет apps/v1.
ClusterRoleBinding вместо RoleBinding. Случайно выдал права на весь кластер вместо namespace. Проверяй kind объекта и roleRef.
Забыли sub-resources. kubectl logs → pods/log, exec → pods/exec, port-forward → pods/portforward, attach → pods/attach. Не включаются автоматически в права на pods.
roleRef immutable. Чтобы изменить — удали и создай заново. kubectl apply выдаст ошибку.
can-i отвечает yes, но доступ закрыт. Сработал Admission Controller (OPA/Gatekeeper, Kyverno) или PodSecurity.
Права на secrets без resourceNames. Кто может get secrets — видит все токены, пароли, TLS-ключи. Используй resourceNames для конкретного Secret.
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["db-password"] # только этот конкретный Secret
verbs: ["get"]
Альтернативы
ABAC — ранний механизм через файл политик на диске apiserver. Требует перезапуска при изменениях. В современных кластерах не используется.
Webhook Authorization — apiserver отправляет каждый запрос на внешний HTTP-эндпоинт. Для кастомной логики, недостижимой в RBAC: права от времени суток, внешней БД, атрибутов объекта.
OPA/Gatekeeper, Kyverno — дополнение к RBAC на уровне Admission. Политики по содержимому манифестов: запрет hostNetwork: true, registry whitelist, обязательные label. RBAC контролирует может ли субъект, Gatekeeper — соответствует ли объект.
[source: kubernetes.io/docs/reference/access-authn-authz/authorization/]