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.