RBAC-паттерны Kubernetes: per-namespace роли в GitOps
Published: 2026-04-08
RBAC в среде с несколькими кластерами и командами требует единой структуры. Команды kubectl create rolebinding, выполненные вручную, теряются. Все роли и биндинги хранятся в infra-репозитории и применяются Flux.
Иерархия ролей
| Роль | Кто | Область |
|---|---|---|
view (встроенная) |
Разработчики | Read-only: поды, логи, события, сервисы |
developer (кастомная) |
Команды разработки | view + exec в поды, port-forward |
devops (кастомная) |
Платформенная команда | developer + деплой (Deployments, ConfigMaps, Secrets) |
cluster-admin (встроенная) |
Только Flux SA | Всё |
Никто не получает cluster-admin интерактивно: у Flux он есть, у людей — нет.
Кастомная ClusterRole: developer
yamlapiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: developer
labels:
rbac.example.com/aggregate-to-devops: "true"
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: [""]
resources: ["pods/exec", "pods/portforward"]
verbs: ["create"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
aggregationRule автоматически включает все view-aggregate правила. Добавление нового CRD в view-набор распространяется автоматически — не нужно обновлять каждую кастомную роль.
Метка rbac.example.com/aggregate-to-devops: "true" делает developer автоматически частью devops через агрегацию.
Кастомная ClusterRole: devops
yamlapiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: devops
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-devops: "true"
rules:
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets", "daemonsets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["configmaps", "secrets", "serviceaccounts"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["helm.toolkit.fluxcd.io"]
resources: ["helmreleases"]
verbs: ["get", "list", "watch", "patch"]
devops агрегирует developer через метку и добавляет права на деплой. Явное правило для helmreleases позволяет делать patch для ручного запуска reconcile без cluster-admin.
RoleBinding по namespace
yaml# spoke/rbac/dev-bindings.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-team-developer
namespace: dev
subjects:
- kind: Group
name: "example/dev-team"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: developer
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: platform-team-devops
namespace: dev
subjects:
- kind: Group
name: "example/platform-team"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: devops
apiGroup: rbac.authorization.k8s.io
RoleBinding (не ClusterRoleBinding) ограничивает права одним namespace. Тот же файл применяется для test, staging с изменением только namespace — через трансформацию Kustomize.
Read-only доступ ко всему кластеру для всех команд
Namespace мониторинга (Prometheus, Grafana) должен быть доступен всем на чтение:
yamlapiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: all-teams-view-observability
subjects:
- kind: Group
name: "example/dev-team"
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: "example/platform-team"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding + view — инженеры читают все namespace, но не пишут за пределами своих.
Структура файлов RBAC
spoke/rbac/
clusterroles.yaml # определения developer + devops ClusterRole
dev-bindings.yaml # RoleBindings для namespace dev
test-bindings.yaml # RoleBindings для namespace test
monitoring-binding.yaml # ClusterRoleBinding для чтения observability
Трансформация namespace в Kustomize
Добавление нового окружения без копирования файлов binding:
yaml# kustomization.yaml для namespace test
resources:
- ../../base/rbac
namespace: test
Kustomize перепишет все поля metadata.namespace. Одни и те же манифесты — разные namespace.
Аудит RBAC
Проверить, что может пользователь в namespace:
bashkubectl auth can-i --list -n dev --as=developer-user
kubectl auth can-i create deployments -n dev --as=developer-user
Список всех rolebinding в namespace:
bashkubectl get rolebindings,clusterrolebindings -n dev -o wide
Типичные ошибки
ClusterRoleBinding там, где достаточно RoleBinding — даёт доступ ко всем namespace. Для доступа в пределах namespace всегда используйте RoleBinding, даже если он ссылается на ClusterRole.
cluster-admin для CI-сервисных аккаунтов — CI достаточно минимальных прав: только на те типы ресурсов, которые он применяет.
Ручные kubectl для выдачи прав — изменения не отслеживаются, не проходят ревью и перезатираются Flux при следующем reconcile.