Управление доступом в Kubernetes часто начинается с использования встроенных ролей вроде cluster-admin или admin. Это быстро, но опасно: избыточные права — главный вектор атак и причина инцидентов в кластере. Данное руководство — это практический пошаговый план по переходу от широких прав к гранулярному контролю. Вы научитесь создавать безопасные кастомные роли для конкретных задач: от изоляции команд разработки до настройки минимально необходимых прав для CI/CD-систем вроде ArgoCD. Все инструкции проверены на практике в production-средах и сопровождаются готовыми YAML-манифестами, которые можно адаптировать под вашу инфраструктуру.
Мы начнем с основ RBAC и различий между Role и ClusterRole, затем детально разберем структуру правил доступа, включая работу с API-группами и неименованными ресурсами. Основное внимание уделим решению двух высокоприоритетных задач: безопасной интеграции ArgoCD и созданию изолированных ролей для команд dev, staging и prod. В завершение вы получите методологию аудита существующих прав и чек-лист для отладки типовых проблем.
Зачем вам кастомные роли? От базовых концепций RBAC к практической необходимости
RBAC (Role-Based Access Control) — стандартный механизм управления доступом в Kubernetes, основанный на принципе наименьших привилегий (Least Privilege). Его суть в том, что пользователь или сервис получает ровно те права, которые необходимы для выполнения задачи, и не более. Использование встроенной роли cluster-admin для служебного ServiceAccount ArgoCD или admin для всей команды разработки — это грубое нарушение этого принципа, которое может привести к катастрофическим последствиям: от случайного удаления production-нагрузки до полной компрометации кластера через атаку на уязвимый под.
Кастомные роли — это инструмент точной настройки. Они позволяют:
- Повысить безопасность: ограничить потенциальный ущерб от ошибок или компрометации одной учетной записи.
- Соответствовать compliance-требованиям: реализовать разделение обязанностей (SoD) между командами.
- Упростить аудит: четко видеть, кто и к каким ресурсам имеет доступ.
Ключевые сущности RBAC, которые мы будем использовать:
- Role / ClusterRole: набор правил, определяющих права на ресурсы.
- ServiceAccount: учетная запись для программного доступа (поды, CI/CD).
- RoleBinding / ClusterRoleBinding: связь между ролью и субъектом (пользователем, группой, ServiceAccount).
Role vs ClusterRole: в чем разница и когда что использовать
Выбор между Role и ClusterRole — первый и критически важный шаг. Ошибка приведет к тому, что правила доступа просто не будут работать.
| Сущность | Область видимости | Когда использовать | Пример |
|---|---|---|---|
| Role | Один конкретный Namespace. | Права для команды или сервиса в рамках одного проекта/среды (например, доступ к Pods в namespace staging). |
Разработчики имеют полный доступ к ресурсам в namespace: dev. |
| ClusterRole | Весь кластер (кластерные ресурсы) или шаблон для нескольких Namespace. | 1. Доступ к кластерным ресурсам (Nodes, PersistentVolumes). 2. Права, которые должны быть одинаковыми в нескольких Namespace. 3. Использование в агрегированных ClusterRole. | 1. Мониторинговый сервис читает метрики Nodes. 2. Роль для ArgoCD, управляющего приложениями в разных Namespace. |
Важное замечание: ClusterRole можно привязать к субъекту в конкретном Namespace через RoleBinding. В этом случае права из ClusterRole будут действовать только в пределах этого Namespace. Это удобный шаблон для тиражирования одинаковых правил.
Строим Role с нуля: ресурсы, API-группы и глаголы доступа
Структура манифеста Role или ClusterRole основана на трех ключевых полях: apiGroups, resources и verbs. Понимание каждого из них — залог создания корректной роли.
- apiGroups: Группа API, к которой принадлежит ресурс. Для основных ресурсов (Pods, Services, ConfigMaps) используется пустая строка
""(часто называемая "core"). Для других —"apps/v1"(Deployments, StatefulSets),"networking.k8s.io/v1"(Ingress),"rbac.authorization.k8s.io/v1"(Role, RoleBinding). Узнать группу можно командой:kubectl api-resources. - resources: Множественное имя ресурса (например,
pods,deployments,secrets). - verbs: Действия, которые можно совершать. Основные:
get,list,watch(чтение),create,update,patch,delete(запись). Реже:deletecollection,impersonate,bind.
Пример минимальной роли, разрешающей чтение Pods и Deployments в namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-viewer
namespace: my-app
rules:
- apiGroups: [""] # Core API
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps/v1"]
resources: ["deployments"]
verbs: ["get", "list", "watch"]
Особый случай: доступ к неименованным ресурсам и субресурсам
Некоторые операции в Kubernetes не привязаны к конкретному ресурсу с именем. Например, чтение логов (kubectl logs) или выполнение команды в контейнере (kubectl exec). Для них используются специальные правила.
- Неименованные ресурсы (nonResourceURLs): Это пути к API, не являющиеся объектами (например,
/api,/apis,/healthz,/logs). Доступ к ним настраивается только вClusterRole. - Субресурсы (subresources): Часть именованного ресурса. Указываются через слэш:
pods/log,pods/exec,pods/portforward.
Пример ClusterRole, разрешающей чтение логов, но запрещающей выполнение команд в подах:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: log-reader-only
rules:
- apiGroups: [""]
resources: ["pods/log"] # Субресурс
verbs: ["get", "list"]
- nonResourceURLs: ["/logs"] # Неименованный ресурс
verbs: ["get"]
# Права на pods/exec НЕ включены — это намеренное ограничение.
Предупреждение о безопасности: Право pods/exec эквивалентно получению root-доступа в контейнере. Выдавайте его с крайней осторожностью и только тем субъектам, которым это абсолютно необходимо для отладки.
Практика: безопасная настройка доступа для ArgoCD (CI/CD)
Типичная ошибка — использование ServiceAccount с ролью cluster-admin для ArgoCD. Это дает инструменту непрерывного развертывания неограниченную власть над кластером, включая возможность читать любые Secrets или удалять системные компоненты. Наша задача — создать минимально достаточный набор прав.
Постановка задачи: ServiceAccount для ArgoCD должен иметь возможность создавать, обновлять и удалять рабочие нагрузки (Deployments, Services, Ingress) в целевых namespace, но не иметь доступа к управлению самим ArgoCD, Secrets других приложений или кластерными ресурсами.
Решение:
- Создаем отдельный namespace
argocd(если еще не создан). - Создаем ServiceAccount
argocd-managerв этом namespace. - Создаем
ClusterRoleс правами только на целевые ресурсы в целевых namespace. Явно запрещаем доступ к ресурсам в namespaceargocdи к Secrets. - Привязываем роль через
ClusterRoleBinding, ограничивая ее действие только на нужные namespace с помощьюRoleBindingв каждом из них (рекомендуемый способ) или через одноClusterRoleBinding, если ArgoCD управляет многими namespace.
Пример ClusterRole для ArgoCD:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argocd-manager-role
rules:
# Правило для основных рабочих нагрузок
- apiGroups: ["apps", ""]
resources: ["deployments", "statefulsets", "daemonsets", "replicasets", "services", "configmaps", "pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Правило для Ingress
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Правило для чтения Secrets ТОЛЬКО в namespace argocd (для собственной конфигурации)
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
resourceNames: ["argocd-secret"] # Конкретный секрет
# Ограничение по namespace будет задано в RoleBinding, а не здесь.
Далее создаем RoleBinding в каждом целевом namespace (например, my-app-production), который связывает наш ClusterRole с ServiceAccount ArgoCD:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: argocd-manager-binding
namespace: my-app-production # Целевой namespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argocd-manager-role
subjects:
- kind: ServiceAccount
name: argocd-manager
namespace: argocd # Namespace, где создан ServiceAccount
Такой подход изолирует права ArgoCD в каждом namespace и соответствует принципу наименьших привилегий. Для более глубокого понимания работы с развертываниями рекомендуем наше полное руководство по Kubernetes Deployment.
Альтернатива: использование AppProject для изоляции внутри ArgoCD
ArgoCD предоставляет встроенный механизм AppProject для дополнительной изоляции. Вместо того чтобы полагаться только на RBAC Kubernetes, вы можете ограничить, к каким ресурсам, кластерам и namespace имеет доступ каждое приложение ArgoCD. Это создает второй уровень защиты.
В AppProject можно задать:
- Разрешенные источники (репозитории Git).
- Разрешенные целевые namespace.
- Разрешенные кластеры (для мультикластерных сценариев).
- Список ресурсов, которые можно/нельзя изменять (например, запрет на изменение ресурсов Kind:
Secret).
Сочетание тонко настроенного RBAC на уровне Kubernetes и политик AppProject в ArgoCD дает максимально безопасную конфигурацию. Подробнее о настройке ArgoCD читайте в нашем отдельном руководстве.
Изоляция команд: роли для dev, staging и prod в одном кластере
Организация работы нескольких команд в одном кластере требует четкого разделения прав. Цель — предотвратить ситуацию, когда разработчик по ошибке удалил ресурс в production.
Архитектура решения:
- Создаем отдельные namespace:
project-dev,project-staging,project-prod. - Создаем ServiceAccount для каждой команды или среды.
- Создаем специфичные
Roleв каждом namespace. - Привязываем роли через
RoleBindingвнутри соответствующих namespace. - Дополняем изоляцию
ResourceQuotaиLimitRangeдля контроля за ресурсами.
Пример роли для разработчиков (namespace: project-dev):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: project-dev
name: developer-full-access
rules:
- apiGroups: ["", "apps", "networking.k8s.io", "batch"]
resources: ["*"] # Полный доступ ко всем ресурсам в этих группах
verbs: ["*"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"] # К Secrets — только чтение
Пример роли для инженеров staging (namespace: project-staging):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: project-staging
name: staging-engineer
rules:
- apiGroups: ["", "apps"]
resources: ["deployments", "services", "pods", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch"] # Нет delete
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
# Дополнительно: RoleBinding, дающее этой роли права на чтение в project-prod
Пример роли для продакшен-инженеров (namespace: project-prod):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: project-prod
name: production-operator
rules:
- apiGroups: ["", "apps"]
resources: ["deployments", "services", "pods"]
verbs: ["get", "list", "watch", "patch"] # Только patch, нет update/delete
- apiGroups: ["batch"]
resources: ["jobs", "cronjobs"]
verbs: ["get", "list", "watch"]
# Явный запрет на delete в любых ресурсах
Такая схема гарантирует, что права каждой команды ограничены своей зоной ответственности, а доступ к production — максимально ограничен и контролируем.
От аудита к безопасности: как декомпозировать широкие роли
Если в вашем кластере уже используются широкие роли (например, многие ServiceAccount привязаны к cluster-admin), необходим планомерный подход к исправлению ситуации. Резкая отмена прав может сломать рабочие процессы.
Методология декомпозиции:
- Аудит текущих привязок:
kubectl get clusterrolebindings -o wide && kubectl get rolebindings --all-namespaces -o wide
Определите, какие ServiceAccount или пользователи имеют избыточные права. - Анализ реального использования прав: Используйте команду
kubectl auth can-i --as=system:serviceaccount:<namespace>:<sa-name> <verb> <resource>для проверки гипотез. Но лучше — анализ логов аудита кластера (audit logs), чтобы увидеть, какие API-вызовы действительно делает сервис. - Создание новой, узкой роли: На основе данных аудита создайте
RoleилиClusterRoleс минимально необходимыми правами. - Параллельная привязка и тестирование: Создайте новое
RoleBindingдля ServiceAccount, оставив старое. Протестируйте работу сервиса с новыми правами. Инструменты вродеrbac-lookupпомогут визуализировать привязки. - Удаление старой привязки: После успешного тестирования удалите старый
RoleBindingилиClusterRoleBinding.
Инструменты проверки: kubectl auth can-i и не только
Команда kubectl auth can-i — основной инструмент для проверки прав.
- Проверка от имени конкретного ServiceAccount:
kubectl auth can-i create deployments --as=system:serviceaccount:argocd:argocd-manager -n my-app - Проверка всех прав для ServiceAccount в namespace (с помощью плагина
kubectl-who-canили скриптов). - Просмотр эффективных прав:
kubectl describe rolebinding <binding-name> -n <namespace>
Для анализа сложных связей и поиска неиспользуемых прав рекомендуется настроить сбор аудит-логов кластера и использовать специализированные инструменты анализа RBAC. Если вы работаете с кастомными ресурсами, убедитесь в их корректности с помощью гайда по диагностике Custom Resources.
Чек-лист безопасности и отладка типовых проблем
Чек-лист безопасности при создании ролей:
- Принцип наименьших привилегий: Каждая роль должна решать одну конкретную задачу.
- Запрет на wildcard ('*') в ресурсах: Избегайте
resources: ["*"], особенно в сочетании с широкими глаголами. Явно перечисляйте ресурсы. - Осторожность с глаголами write:
update,patch,deleteдолжны быть явно обоснованы. - Избегайте опасных комбинаций: Например,
create pods+patch podsпозволяет запустить произвольный контейнер. Если такая комбинация необходима, рассмотрите использование Pod Security Standards. - Проверка манифестов: Всегда используйте
kubectl apply --dry-run=client -f role.yamlперед применением.
Алгоритм отладки проблем с доступом:
- Существуют ли объекты?
kubectl get serviceaccount <name> -n <namespace>
kubectl get role/rolebinding <name> -n <namespace> - Правильно ли они связаны?
ПроверьтеroleRefвRoleBinding: ссылается ли он на правильную роль? Совпадают лиapiGroupиkind?
ПроверьтеsubjectsвRoleBinding: правильно ли указаныkind,nameиnamespaceServiceAccount? - Действуют ли права?
Используйтеkubectl auth can-iдля проверки конкретного действия от имени ServiceAccount. - Есть ли ошибки в событиях?
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
Таблица частых ошибок:
| Симптом | Возможная причина | Решение |
|---|---|---|
| "User cannot list pods in namespace" | 1. RoleBinding ссылается на Role в другом namespace. 2. В правилах Role отсутствует глагол list.3. ServiceAccount не указан в subjects RoleBinding. |
Проверить namespace всех объектов. Проверить verbs в Role. Проверить subjects в RoleBinding. |
| Права есть, но операция запрещена (403) | 1. Попытка доступа к субресурсу (logs, exec) без явного правила. 2. Admission Webhook (например, Pod Security) блокирует операцию. |
Добавить правило для субресурса (pods/log). Проверить логи admission-контроллеров. |
| RoleBinding есть, но права не применяются | Используется RoleBinding для привязки ClusterRole, но не указан namespace в metadata RoleBinding. | Убедиться, что RoleBinding создан в нужном namespace и его metadata.namespace указан. |
Создание гранулярных ролей — это непрерывный процесс, тесно связанный с развитием вашей инфраструктуры. Регулярный аудит прав, использование представленных практик и инструментов позволит поддерживать высокий уровень безопасности кластера без ущерба для эффективности работы команд.