Базовый RBAC

Уровень: beginner ~50 мин Практика: Grafana (AGPL-3.0)

Что нужно знать перед уроком

  • M1.05 — Namespace, labels, selectors — нужно понимать namespace-scoped vs cluster-scoped объекты

Что нужно знать перед уроком

M1 урок 5 — namespace-scoped vs cluster-scoped ресурсы. RBAC (Role-Based Access Control) — механизм, который решает, кто и что может делать с объектами Kubernetes API, и он напрямую использует это же разделение.

Теория

Фундаментальный принцип: «по умолчанию нет прав ни у кого»

RBAC в Kubernetes построен на принципе явного разрешения: субъект (пользователь, группа, ServiceAccount) не имеет никаких прав на объекты API, пока это право не выдано явным биндингом. Нет прав «по умолчанию» ни у кого, кроме встроенных системных ролей.

Role/ClusterRole — что разрешено

Role — namespace-scoped набор правил, ClusterRole — тот же формат правил, но действует cluster-wide (либо применим сразу ко всем namespace через ClusterRoleBinding, либо к одному через RoleBinding, см. ниже):

1
2
3
4
5
6
7
8
9
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: grafana-configmap-reader
  namespace: course-m1-rbac
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list", "watch"]

apiGroups ("" — core API group, где живут Pod/Service/ConfigMap/Secret), resources (тип объекта), verbs (get/list/watch/create/update/patch/delete) — три оси, которые вместе определяют «что разрешено».

RoleBinding/ClusterRoleBinding — кому разрешено

RoleBinding привязывает Role или ClusterRole к конкретному субъекту (ServiceAccount/User/Group):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: grafana-reads-configmaps
  namespace: course-m1-rbac
subjects:
  - kind: ServiceAccount
    name: grafana
    namespace: course-m1-rbac
roleRef:
  kind: Role
  name: grafana-configmap-reader
  apiGroup: rbac.authorization.k8s.io
Ключевой факт: RoleBinding + ClusterRole = права только в одном namespace
RoleBinding может ссылаться не только на Role, но и на ClusterRole (тот же roleRef.kind: ClusterRole) — в этом случае право действует только в namespace самого биндинга, а не во всём кластере. Это удобный, широко используемый паттерн: определить один общий ClusterRole (например, «read-only доступ к стандартным ресурсам») и переиспользовать его во множестве namespace через отдельные RoleBinding, не дублируя правила заново в каждом namespace.

ClusterRoleBinding, в отличие от RoleBinding, действует во всём кластере сразу — используется для по-настоящему cluster-wide прав (администраторские роли, системные компоненты).

ServiceAccount — identity для Pod’ов, не для людей

ServiceAccount — объект identity именно для процессов внутри Pod’а (люди авторизуются через User/Group, обычно через внешний OIDC-провайдер, вне рамок этого курса). У каждого namespace автоматически существует ServiceAccount с именем default, без каких-либо прав по умолчанию (кроме базового доступа к API-серверу как аутентифицированный субъект).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
kind: ServiceAccount
metadata: { name: grafana, namespace: course-m1-rbac }
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: grafana, namespace: course-m1-rbac }
spec:
  template:
    spec:
      serviceAccountName: grafana # без этого поля Pod получит default SA
      containers: [...]

Практический смысл для Application-разработчика: если вашему приложению нужно обращаться к Kubernetes API самостоятельно (например, читать список своих же ConfigMap или мониторить статус других объектов, как это иногда делает Grafana-плагины для service discovery) — создайте отдельный ServiceAccount с минимально необходимым набором прав через Role+RoleBinding, а не полагайтесь на default (у которого прав нет, значит, такой код просто не будет работать) и тем более не расширяйте права default SA для всех Pod’ов namespace бездумно.

Частые ошибки и подводные камни

  • Расширять права default ServiceAccount вместо создания отдельного. Это негласно расширяет права всех Pod’ов namespace, у которых явно не указан serviceAccountName — грубое нарушение принципа минимальных привилегий.
  • Использовать ClusterRoleBinding, когда достаточно RoleBinding с ClusterRole. Если права нужны только в одном namespace — ClusterRoleBinding даёт избыточные права во всём кластере, хотя тот же ClusterRole можно переиспользовать точечно через RoleBinding.
  • Забыть про apiGroups: [""] для core-ресурсов. Частая опечатка — указывать apiGroups: ["core"], тогда как правильное значение для core API group (Pod/Service/ConfigMap/Secret/Namespace) — пустая строка "".

Практика в кластере

🧩 Практика урока: Grafana · лицензия AGPL-3.0

Grafana — платформа визуализации метрик/дашбордов — хороший пример для RBAC, т.к. в реальных сценариях ей может требоваться собственный ServiceAccount для service discovery источников данных внутри кластера.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
kubectl create namespace course-m1-rbac

kubectl apply -n course-m1-rbac -f - <<'EOF'
apiVersion: v1
kind: ServiceAccount
metadata: { name: grafana }
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: { name: grafana-configmap-reader }
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: { name: grafana-reads-configmaps }
subjects:
  - kind: ServiceAccount
    name: grafana
    namespace: course-m1-rbac
roleRef: { kind: Role, name: grafana-configmap-reader, apiGroup: rbac.authorization.k8s.io }
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: grafana }
spec:
  replicas: 1
  selector: { matchLabels: { app: grafana } }
  template:
    metadata: { labels: { app: grafana } }
    spec:
      serviceAccountName: grafana
      containers:
        - name: grafana
          image: grafana/grafana:latest
          ports: [{ containerPort: 3000 }]
          resources:
            requests: { cpu: "100m", memory: "128Mi" }
            limits: { cpu: "400m", memory: "384Mi" }
EOF
  1. Проверьте права через kubectl auth can-i — самый быстрый способ диагностики RBAC:
1
2
3
kubectl auth can-i list configmaps --as=system:serviceaccount:course-m1-rbac:grafana -n course-m1-rbac      # yes
kubectl auth can-i delete configmaps --as=system:serviceaccount:course-m1-rbac:grafana -n course-m1-rbac    # no
kubectl auth can-i list pods --as=system:serviceaccount:course-m1-rbac:grafana -n course-m1-rbac            # no
  1. Проверьте, что default ServiceAccount того же namespace не получил прав «за компанию»:
1
kubectl auth can-i list configmaps --as=system:serviceaccount:course-m1-rbac:default -n course-m1-rbac      # no
  1. Создайте ClusterRole и продемонстрируйте паттерн «один ClusterRole — много RoleBinding в разных namespace»:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kubectl apply -f - <<'EOF'
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata: { name: course-configmap-reader }
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list"]
EOF
kubectl create rolebinding shared-cr-binding -n course-m1-rbac \
  --clusterrole=course-configmap-reader \
  --serviceaccount=course-m1-rbac:grafana
kubectl auth can-i get configmaps --as=system:serviceaccount:course-m1-rbac:grafana -n course-m1-jobs   # no — право действует ТОЛЬКО в namespace биндинга

Практика разработки

Используется официальный образ grafana/grafana; собственная сборка — в M3.

Шпаргалка команд урока

1
2
3
4
5
kubectl create serviceaccount <name> [-n <ns>]
kubectl create role <name> --verb=get,list --resource=configmaps [-n <ns>]
kubectl create rolebinding <name> --role=<role>|--clusterrole=<cr> --serviceaccount=<ns>:<sa> [-n <ns>]
kubectl auth can-i <verb> <resource> --as=system:serviceaccount:<ns>:<sa> [-n <ns>]
kubectl get role,rolebinding,clusterrole,clusterrolebinding [-n <ns>]

Вопросы для самопроверки

Какие права имеет ServiceAccount по умолчанию сразу после создания (без биндингов)?

Фундаментальный принцип RBAC Kubernetes — «по умолчанию нет прав ни у кого», всё выдаётся явными Role/ClusterRoleBinding.

Источник: Kubernetes — rbac

RoleBinding ссылается на ClusterRole. Где действует итоговое право?

Ключевой факт: RoleBinding, даже ссылаясь на ClusterRole, ограничивает действие права namespace'ом самого биндинга — удобный способ переиспользовать один ClusterRole в разных namespace.

Источник: Kubernetes — rbac

Для кого предназначен ServiceAccount?

ServiceAccount — identity именно для Pod'ов; аутентификация людей обычно идёт через User/Group и внешний identity-провайдер.

Источник: Kubernetes — rbac

Какой apiGroups соответствует core-ресурсам (Pod, Service, ConfigMap, Secret)?

Core API group в правилах RBAC указывается пустой строкой — частая ошибка новичков писать "core".

Источник: Kubernetes — rbac

Какая команда быстрее всего проверит, есть ли у конкретного ServiceAccount заданное право?

kubectl auth can-i с флагом --as позволяет напрямую и быстро проверить конкретное право без ручного разбора цепочки Role/RoleBinding.

Источник: Kubernetes — authorization

Рекомендуемая литература

Официальная документация

Статьи и блоги

Книги

  • Marko Lukša. Kubernetes in Action. 2nd ed., 2022. ISBN 978-1617297618.
  • Kelsey Hightower, Brendan Burns, Joe Beda. Kubernetes: Up and Running. 3rd ed., 2022. ISBN 978-1098110201.
  • Michael Hausenblas, Stefan Schimanski. Programming Kubernetes. 2019. ISBN 978-1492047107.

Связанные материалы