Модуль 4.5: Сервісні акаунти
Складність:
[MEDIUM]— Важливо для доступу до API та ідентифікаціїЧас на виконання: 35–45 хвилин
Передумови: Модуль 4.4 (SecurityContexts), розуміння основ RBAC
Що ви зможете робити
Розділ «Що ви зможете робити»Після завершення цього модуля ви зможете:
- Налаштувати Піди для використання конкретних ServiceAccounts для автентифікації в API-сервері
- Пояснити як токени ServiceAccount монтуються та використовуються застосунками всередині Підів
- Діагностувати помилки прав доступу до API, простежуючи ланцюжок від Пода до ServiceAccount та прив’язок ролей
- Спроєктувати налаштування ServiceAccount з найменшими привілеями, що обмежує доступ Пода лише до необхідних ресурсів
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Сервісні акаунти надають ідентифікацію подам для взаємодії з API Kubernetes. Коли вашому застосунку потрібно отримати список подів, створити ConfigMaps або отримати доступ до інших ресурсів кластера, він використовує облікові дані свого Сервісного акаунта.
На іспиті CKAD перевіряють:
- Створення та призначення Сервісних акаунтів
- Розуміння монтування токенів
- Налаштування ідентифікації пода
- Відмова від автоматичного монтування токенів
Аналогія з бейджем працівника
Сервісні акаунти — це як бейджі працівників. Кожен працівник (під) отримує бейдж (Сервісний акаунт), який ідентифікує його для систем безпеки (API-сервер). Стандартний бейдж (Сервісний акаунт за замовчуванням) дає базовий доступ, але конкретні ролі потребують конкретних бейджів. Без бейджа ви не потрапите далі лобі.
Основи Сервісних акаунтів
Розділ «Основи Сервісних акаунтів»Сервісний акаунт за замовчуванням
Розділ «Сервісний акаунт за замовчуванням»Кожен простір імен має Сервісний акаунт default:
# Переглянути Сервісний акаунт за замовчуваннямk get serviceaccount# NAME SECRETS AGE# default 0 10d
# Описати йогоk describe sa defaultКожен під отримує Сервісний акаунт
Розділ «Кожен під отримує Сервісний акаунт»# Перевірити Сервісний акаунт подаk get pod my-pod -o jsonpath='{.spec.serviceAccountName}'# default
# Або через describek describe pod my-pod | grep "Service Account"Створення Сервісних акаунтів
Розділ «Створення Сервісних акаунтів»Імперативно
Розділ «Імперативно»# Створити Сервісний акаунтk create serviceaccount my-app-sa
# У конкретному просторі іменk create sa my-app-sa -n my-namespaceДекларативно
Розділ «Декларативно»apiVersion: v1kind: ServiceAccountmetadata: name: my-app-sa namespace: defaultПризначення Сервісних акаунтів подам
Розділ «Призначення Сервісних акаунтів подам»У специфікації пода
Розділ «У специфікації пода»apiVersion: v1kind: Podmetadata: name: my-podspec: serviceAccountName: my-app-sa # Використовувати цей Сервісний акаунт containers: - name: app image: nginxУ Deployment
Розділ «У Deployment»apiVersion: apps/v1kind: Deploymentmetadata: name: my-appspec: replicas: 2 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: serviceAccountName: my-app-sa # Шаблон пода використовує цей SA containers: - name: app image: nginxМонтування токенів
Розділ «Монтування токенів»Автоматичне монтування токенів (за замовчуванням)
Розділ «Автоматичне монтування токенів (за замовчуванням)»За замовчуванням Kubernetes монтує токен у /var/run/secrets/kubernetes.io/serviceaccount/:
# Переглянути файли змонтованого токенаk exec my-pod -- ls /var/run/secrets/kubernetes.io/serviceaccount/# ca.crt# namespace# token
# Переглянути токенk exec my-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/tokenВміст токена
Розділ «Вміст токена»| Файл | Призначення |
|---|---|
token | JWT-токен для автентифікації в API |
ca.crt | Сертифікат CA для перевірки API-сервера |
namespace | Простір імен пода |
Вимкнення автоматичного монтування токенів
Розділ «Вимкнення автоматичного монтування токенів»Для подів, яким не потрібен доступ до API:
На рівні пода:
apiVersion: v1kind: Podmetadata: name: no-api-accessspec: automountServiceAccountToken: false # Не монтувати токен containers: - name: app image: nginxНа рівні Сервісного акаунта:
apiVersion: v1kind: ServiceAccountmetadata: name: restricted-saautomountServiceAccountToken: false # За замовчуванням для подів з цим SAТипи токенів Сервісних акаунтів
Розділ «Типи токенів Сервісних акаунтів»Прив’язані токени (Kubernetes 1.22+)
Розділ «Прив’язані токени (Kubernetes 1.22+)»Сучасні токени:
- Обмежені в часі — закінчуються автоматично
- Прив’язані до аудиторії — дійсні лише для конкретних цілей
- Прив’язані до об’єкта — прив’язані до конкретного пода
# Запит токена з конкретною аудиторієюapiVersion: v1kind: Podmetadata: name: my-podspec: serviceAccountName: my-app-sa containers: - name: app image: my-app volumeMounts: - name: token mountPath: /var/run/secrets/tokens volumes: - name: token projected: sources: - serviceAccountToken: path: token expirationSeconds: 3600 # 1 година audience: my-audienceЗастарілі токени (до 1.24)
Розділ «Застарілі токени (до 1.24)»До Kubernetes 1.24 довготривалі токени зберігалися в Secrets. Це застаріло.
# Старий спосіб (застарілий) — НЕ використовуйтеk create token my-app-sa # Створює короткотривалий токен натомістьВізуалізація
Розділ «Візуалізація»┌─────────────────────────────────────────────────────────────┐│ Потік Сервісного акаунта │├─────────────────────────────────────────────────────────────┤│ ││ 1. Створити Сервісний акаунт ││ ┌─────────────────────────────────┐ ││ │ k create sa my-app-sa │ ││ └─────────────────────────────────┘ ││ │ ││ ▼ ││ 2. Призначити поду ││ ┌─────────────────────────────────┐ ││ │ spec: │ ││ │ serviceAccountName: my-app-sa │ ││ └─────────────────────────────────┘ ││ │ ││ ▼ ││ 3. Токен монтується автоматично ││ ┌─────────────────────────────────┐ ││ │ /var/run/secrets/kubernetes.io/ │ ││ │ serviceaccount/ │ ││ │ ├── token ← JWT-токен │ ││ │ ├── ca.crt ← серт. CA API │ ││ │ └── namespace ← простір імен │ ││ └─────────────────────────────────┘ ││ │ ││ ▼ ││ 4. Під використовує токен для доступу до API ││ ┌─────────────────────────────────┐ ││ │ curl -H "Authorization: │ ││ │ Bearer $(cat /var/run/...)" │ ││ │ https://kubernetes/api/v1/... │ ││ └─────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────┘Використання токенів Сервісних акаунтів
Розділ «Використання токенів Сервісних акаунтів»Зсередини пода
Розділ «Зсередини пода»# Всередині пода — запит до APITOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crtNAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
# Отримати список подів у поточному просторі іменcurl -s --cacert $CACERT \ -H "Authorization: Bearer $TOKEN" \ https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/podsЗ kubectl
Розділ «З kubectl»# Створити короткотривалий токенk create token my-app-sa
# Створити токен з тривалістюk create token my-app-sa --duration=1hСервісні акаунти та RBAC
Розділ «Сервісні акаунти та RBAC»Сервісні акаунти самі по собі не надають дозволів. Потрібен RBAC:
# 1. Створити Сервісний акаунтapiVersion: v1kind: ServiceAccountmetadata: name: pod-reader-sa---# 2. Створити Role з дозволамиapiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: pod-readerrules:- apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]---# 3. Прив'язати Role до Сервісного акаунтаapiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: read-podssubjects:- kind: ServiceAccount name: pod-reader-sa namespace: defaultroleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.ioШвидка довідка
Розділ «Швидка довідка»# Створити Сервісний акаунтk create sa NAME
# Переглянути Сервісні акаунтиk get sak describe sa NAME
# Призначити подуspec: serviceAccountName: NAME
# Вимкнути автомонтуванняspec: automountServiceAccountToken: false
# Створити короткотривалий токенk create token NAME
# Перевірити SA подаk get pod POD -o jsonpath='{.spec.serviceAccountName}'Чи знали ви?
Розділ «Чи знали ви?»-
Сервісний акаунт за замовчуванням не має спеціальних дозволів. Він нічого не може робити, поки ви не додасте правила RBAC. Це безпечно за замовчуванням.
-
Токени — це JWT. Ви можете декодувати їх, щоб побачити претензії:
cat token | cut -d. -f2 | base64 -d | jq -
Сервісні акаунти мають простір імен. Сервісний акаунт у просторі імен A не може використовуватися подами у просторі імен B.
-
kubectl auth can-i --as=system:serviceaccount:default:my-saдозволяє перевірити, що може робити Сервісний акаунт.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це шкодить | Рішення |
|---|---|---|
| Очікування дозволів у SA за замовчуванням | Виклики API не вдаються з 403 | Створіть RBAC для SA |
| Використання застарілих довготривалих токенів | Ризик безпеки | Використовуйте k create token або прив’язані токени |
| Не вимикати монтування, коли не потрібно | Зайва поверхня атаки | Встановіть automountServiceAccountToken: false |
| Неправильна назва Сервісного акаунта | Під використовує SA за замовчуванням | Перевірте через k describe pod |
| Плутати SA з RBAC | SA сам по собі не надає доступ | Потрібні SA + Role + RoleBinding |
Тест
Розділ «Тест»-
Як призначити Сервісний акаунт поду?
Відповідь
Додайте `serviceAccountName: my-sa` до специфікації пода. -
Де монтується токен Сервісного акаунта в поді?
Відповідь
`/var/run/secrets/kubernetes.io/serviceaccount/`, що містить файли `token`, `ca.crt` та `namespace`. -
Як заборонити поду доступ до API?
Відповідь
Встановіть `automountServiceAccountToken: false` у специфікації пода або Сервісного акаунта. -
Чи надає створення Сервісного акаунта автоматично якісь дозволи?
Відповідь
Ні. Сервісні акаунти не мають дозволів за замовчуванням. Потрібно створити правила RBAC (Role/ClusterRole + RoleBinding/ClusterRoleBinding) для надання дозволів.
Практична вправа
Розділ «Практична вправа»Завдання: Створити та використати Сервісний акаунт.
Частина 1: Створення Сервісного акаунта
k create sa app-sa
# Перевіритиk get sa app-saЧастина 2: Під з власним Сервісним акаунтом
cat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: sa-demospec: serviceAccountName: app-sa containers: - name: app image: busybox command: ['sh', '-c', 'cat /var/run/secrets/kubernetes.io/serviceaccount/namespace && sleep 3600']EOF
# Перевірити призначений SAk get pod sa-demo -o jsonpath='{.spec.serviceAccountName}'echo
# Перевірити монтування токенаk exec sa-demo -- ls /var/run/secrets/kubernetes.io/serviceaccount/Частина 3: Під без монтування токена
cat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: no-tokenspec: serviceAccountName: app-sa automountServiceAccountToken: false containers: - name: app image: busybox command: ['sh', '-c', 'ls /var/run/secrets 2>&1 || echo "No secrets mounted" && sleep 3600']EOF
k logs no-token# Має показати: No secrets mounted (або директорія не знайдена)Очищення:
k delete pod sa-demo no-tokenk delete sa app-saПрактичні вправи
Розділ «Практичні вправи»Вправа 1: Створення Сервісного акаунта (Ціль: 1 хвилина)
Розділ «Вправа 1: Створення Сервісного акаунта (Ціль: 1 хвилина)»k create sa drill1-sak get sa drill1-sak delete sa drill1-saВправа 2: Під із Сервісним акаунтом (Ціль: 2 хвилини)
Розділ «Вправа 2: Під із Сервісним акаунтом (Ціль: 2 хвилини)»k create sa drill2-sa
cat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: drill2spec: serviceAccountName: drill2-sa containers: - name: app image: busybox command: ['sleep', '3600']EOF
k get pod drill2 -o jsonpath='{.spec.serviceAccountName}'echo
k delete pod drill2 sa drill2-saВправа 3: Перевірка розташування токена (Ціль: 2 хвилини)
Розділ «Вправа 3: Перевірка розташування токена (Ціль: 2 хвилини)»k run drill3 --image=busybox --restart=Never -- sleep 3600
k exec drill3 -- ls /var/run/secrets/kubernetes.io/serviceaccount/k exec drill3 -- cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
k delete pod drill3Вправа 4: Вимкнення монтування токена (Ціль: 2 хвилини)
Розділ «Вправа 4: Вимкнення монтування токена (Ціль: 2 хвилини)»cat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: drill4spec: automountServiceAccountToken: false containers: - name: app image: busybox command: ['sh', '-c', 'ls /var/run/secrets/kubernetes.io/serviceaccount 2>&1; sleep 3600']EOF
k logs drill4# Має показати помилку (директорія не існує)
k delete pod drill4Вправа 5: Створення токена (Ціль: 2 хвилини)
Розділ «Вправа 5: Створення токена (Ціль: 2 хвилини)»k create sa drill5-sa
# Створити короткотривалий токенk create token drill5-sa
# Створити з тривалістюk create token drill5-sa --duration=30m
k delete sa drill5-saВправа 6: Deployment із Сервісним акаунтом (Ціль: 3 хвилини)
Розділ «Вправа 6: Deployment із Сервісним акаунтом (Ціль: 3 хвилини)»k create sa drill6-sa
cat << 'EOF' | k apply -f -apiVersion: apps/v1kind: Deploymentmetadata: name: drill6spec: replicas: 2 selector: matchLabels: app: drill6 template: metadata: labels: app: drill6 spec: serviceAccountName: drill6-sa containers: - name: app image: nginxEOF
# Перевірити, що всі поди використовують правильний SAk get pods -l app=drill6 -o jsonpath='{.items[*].spec.serviceAccountName}'echo
k delete deploy drill6 sa drill6-saНаступний модуль
Розділ «Наступний модуль»Модуль 4.6: Custom Resource Definitions — Розширення Kubernetes за допомогою власних ресурсів.