Налаштування службових облікових записів для Podʼів

Kubernetes пропонує два відмінні способи автентифікації для клієнтів, які працюють у межах вашого кластера або мають взаємозвʼязок з панеллю управління вашого кластера для автентифікації в API-сервері.

Службовий обліковий запис надає ідентичність процесам, які працюють у Podʼі, і відповідає обʼєкту ServiceAccount. Коли ви автентифікуєтеся в API-сервері, ви ідентифікуєте себе як певного користувача. Kubernetes визнає поняття користувача, але сам Kubernetes не має API User.

Це завдання стосується Службових облікових записів, які існують в API Kubernetes. Керівництво показує вам деякі способи налаштування Службових облікових записів для Podʼів.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Використання стандартного службового облікового запису для доступу до API-сервера

Коли Podʼи звертаються до API-сервера, вони автентифікуються як певний Службовий обліковий запис (наприклад, default). В кожному просторі імен завжди є принаймні один Службовий обліковий запис.

У кожному просторі імен Kubernetes завжди міститься принаймні один Службовий обліковий запис: стандартний службовий обліковий запис для цього простору імен, з назвою default. Якщо ви не вказуєте Службовий обліковий запис при створенні Podʼа, Kubernetes автоматично призначає Службовий обліковий запис з назвою default у цьому просторі імен.

Ви можете отримати деталі для Podʼа, який ви створили. Наприклад:

kubectl get pods/<імʼя_пода> -o yaml

У виводі ви побачите поле spec.serviceAccountName. Kubernetes автоматично встановлює це значення, якщо ви не вказали його при створенні Podʼа.

Застосунок, який працює усередині Podʼа, може отримати доступ до API Kubernetes, використовуючи автоматично змонтовані облікові дані службового облікового запису. Для отримання додаткової інформації див. доступ до кластера.

Коли Pod автентифікується як Службовий обліковий запис, його рівень доступу залежить від втулка авторизації та політики, які використовуються.

Облікові дані API автоматично відкликаються, коли Pod видаляється, навіть якщо є завершувачі. Зокрема, облікові дані API відкликаються через 60 секунд після встановленого на Pod значення .metadata.deletionTimestamp (час видалення зазвичай дорівнює часу, коли запит на видалення був прийнятий плюс період належного завершення роботи Pod).

Відмова від автоматичного монтування облікових даних API

Якщо ви не бажаєте, щоб kubelet автоматично монтував облікові дані API ServiceAccount, ви можете відмовитися від такої стандартної поведінки. Ви можете відмовитися від автоматичного монтування облікових даних API у /var/run/secrets/kubernetes.io/serviceaccount/token для службового облікового запису, встановивши значення automountServiceAccountToken: false у ServiceAccount:

Наприклад:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-robot
automountServiceAccountToken: false
...

Ви також можете відмовитися від автоматичного монтування облікових даних API для певного Podʼа:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  serviceAccountName: build-robot
  automountServiceAccountToken: false
  ...

Якщо як ServiceAccount, так і .spec Podʼа вказують значення для automountServiceAccountToken, специфікація Podʼа має перевагу.

Використання більше ніж одного ServiceAccount

У кожному просторі імен є принаймні один ServiceAccount: типовий ServiceAccount, який називається default. Ви можете переглянути всі ресурси ServiceAccount у вашому поточному просторі імен за допомогою:

kubectl get serviceaccounts

Вихідні дані схожі на наступні:

NAME      SECRETS    AGE
default   1          1d

Ви можете створити додаткові обʼєкти ServiceAccount таким чином:

kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-robot
EOF

Імʼя обʼєкта ServiceAccount повинно бути дійсним DNS-піддоменним імʼям.

Якщо ви отримуєте повний дамп обʼєкта ServiceAccount, подібний до цього:

kubectl get serviceaccounts/build-robot -o yaml

Вихідні дані схожі на наступні:

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2019-06-16T00:12:34Z
  name: build-robot
  namespace: default
  resourceVersion: "272500"
  uid: 721ab723-13bc-11e5-aec2-42010af0021e

Ви можете використовувати розширення дозволів для встановлення дозволів на облікові записи служб.

Щоб використовувати не-стандартний обліковий запис, встановіть поле spec.serviceAccountName Podʼа на імʼя ServiceAccount, який ви хочете використовувати.

Ви можете встановити лише поле serviceAccountName при створенні Podʼа або в шаблоні для нового Podʼа. Ви не можете оновлювати поле .spec.serviceAccountName Podʼа, який вже існує.

Очищення

Якщо ви спробували створити ServiceAccount build-robot з прикладу вище, ви можете видалити його виконавши:

kubectl delete serviceaccount/build-robot

Вручну створіть API-токен для ServiceAccount

Припустимо, у вас вже є службовий обліковий запис з назвою "build-robot", як зазначено вище.

Ви можете отримати тимчасовий API-токен для цього ServiceAccount за допомогою kubectl:

kubectl create token build-robot

Вихідні дані з цієї команди — це токен, який ви можете використовувати для автентифікації цього ServiceAccount. Ви можете запросити певний час дії токена, використовуючи аргумент командного рядка --duration для kubectl create token (фактичний час дії виданого токену може бути коротшим або навіть довшим).

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.31 [beta] (стандартно увімкнено: true)

Використовуючи kubectl v1.31 або новішу версію, можна створити токен службового облікового запису, який буде безпосередньо привʼязано до вузла:

kubectl create token build-robot --bound-object-kind Node --bound-object-name node-001 --bound-object-uid 123...456

Токен буде чинний до закінчення його терміну дії або до видалення відповідного вузла чи службового облікового запису.

Вручну створіть довговічний API-токен для ServiceAccount

Якщо ви бажаєте отримати API-токен для службового облікового запису, ви створюєте новий Secret з особливою анотацією kubernetes.io/service-account.name.

kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: build-robot-secret
  annotations:
    kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF

Якщо ви переглянете Secret використовуючи:

kubectl get secret/build-robot-secret -o yaml

ви побачите, що тепер Secret містить API-токен для ServiceAccount "build-robot".

Через анотацію, яку ви встановили, панель управління автоматично генерує токен для цього службового облікового запису і зберігає їх у відповідному Secret. Крім того, панель управління також очищає токени для видалених облікових записів служб.

kubectl describe secrets/build-robot-secret

Вивід схожий на такий:

Name:           build-robot-secret
Namespace:      default
Labels:         <none>
Annotations:    kubernetes.io/service-account.name: build-robot
                kubernetes.io/service-account.uid: da68f9c6-9d26-11e7-b84e-002dc52800da

Type:   kubernetes.io/service-account-token

Data
====
ca.crt:         1338 байтів
namespace:      7 байтів
token:          ...

При видаленні ServiceAccount, який має відповідний Secret, панель управління Kubernetes автоматично очищає довговічний токен з цього Secret.

Додайте ImagePullSecrets до ServiceAccount

Спочатку створіть imagePullSecret. Потім перевірте, чи він був створений. Наприклад:

  • Створіть imagePullSecret, як описано в Вказування ImagePullSecrets в контейнері.

    kubectl create secret docker-registry myregistrykey --docker-server=<імʼя реєстру> \
            --docker-username=ІМ'Я_КОРИСТУВАЧА --docker-password=ПАРОЛЬ_ДЛЯ_DOCKER \
            --docker-email=ЕЛЕКТРОННА_ПОШТА_ДЛЯ_DOCKER
    
  • Перевірте, чи він був створений.

    kubectl get secrets myregistrykey
    

    Вивід схожий на такий:

    NAME             TYPE                              DATA    AGE
    myregistrykey    kubernetes.io/.dockerconfigjson   1       1д
    

Додайте imagePullSecret до ServiceAccount

Далі, змініть типовий обліковий запис служби для цього простору імен так, щоб він використовував цей Secret як imagePullSecret.

kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'

Ви можете досягти того ж самого результату, відредагувавши обʼєкт вручну:

kubectl edit serviceaccount/default

Вивід файлу sa.yaml буде схожий на такий:

Вибраний вами текстовий редактор відкриється з конфігурацією, що схожа на цю:

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2021-07-07T22:02:39Z
  name: default
  namespace: default
  resourceVersion: "243024"
  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6

За допомогою вашого редактора видаліть рядок з ключем resourceVersion, додайте рядки для imagePullSecrets: та збережіть це. Залиште значення uid таким же, як ви його знайшли.

Після внесення змін, відредагований ServiceAccount виглядатиме схоже на це:

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2021-07-07T22:02:39Z
  name: default
  namespace: default
  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
imagePullSecrets:
  - name: myregistrykey

Перевірте, що imagePullSecrets встановлені для нових Podʼів

Тепер, коли створюється новий Pod у поточному просторі імен і використовується типовий ServiceAccount, у новому Podʼі автоматично встановлюється поле spec.imagePullSecrets:

kubectl run nginx --image=<імʼя реєстру>/nginx --restart=Never
kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'

Вивід:

myregistrykey

Проєцювання токенів ServiceAccount

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.20 [stable]

Kubelet також може проєцювати токен ServiceAccount в Pod. Ви можете вказати бажані властивості токена, такі як аудиторія та тривалість дії. Ці властивості не конфігуруються для типового токена ServiceAccount. Токен також стане недійсним щодо API, коли будь-який з Podʼів або ServiceAccount буде видалено.

Ви можете налаштувати цю поведінку для spec Podʼа за допомогою типу projected тому, що називається ServiceAccountToken.

Токен з цього projected тому — JSON Web Token (JWT). JSON-вміст цього токена слідує чітко визначеній схемі — приклад вмісту для токена, повʼязаного з Pod:

{
  "aud": [  # відповідає запитаним аудиторіям або стандартним аудиторіям API-сервера, якщо явно не запитано
    "https://kubernetes.default.svc"
  ],
  "exp": 1731613413,
  "iat": 1700077413,
  "iss": "https://kubernetes.default.svc",  # відповідає першому значенню, переданому прапорцю --service-account-issuer
  "jti": "ea28ed49-2e11-4280-9ec5-bc3d1d84661a",
  "kubernetes.io": {
    "namespace": "kube-system",
    "node": {
      "name": "127.0.0.1",
      "uid": "58456cb0-dd00-45ed-b797-5578fdceaced"
    },
    "pod": {
      "name": "coredns-69cbfb9798-jv9gn",
      "uid": "778a530c-b3f4-47c0-9cd5-ab018fb64f33"
    },
    "serviceaccount": {
      "name": "coredns",
      "uid": "a087d5a0-e1dd-43ec-93ac-f13d89cd13af"
    },
    "warnafter": 1700081020
  },
  "nbf": 1700077413,
  "sub": "system:serviceaccount:kube-system:coredns"
}

Запуск Podʼа з використанням проєцювання токену службового облікового запису

Щоб надати Podʼу токен з аудиторією vault та терміном дії дві години, ви можете визначити маніфест Podʼа, схожий на цей:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - mountPath: /var/run/secrets/tokens
      name: vault-token
  serviceAccountName: build-robot
  volumes:
  - name: vault-token
    projected:
      sources:
      - serviceAccountToken:
          path: vault-token
          expirationSeconds: 7200
          audience: vault

Створіть Pod:

kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml

Kubelet буде: запитувати та зберігати токен від імені Podʼа; робити токен доступним для Podʼа за налаштованим шляхом до файлу; і оновлювати токен поблизу його закінчення. Kubelet активно запитує ротацію для токена, якщо він старший, ніж 80% від загального часу життя (TTL), або якщо токен старший, ніж 24 години.

Застосунок відповідає за перезавантаження токена при його ротації. Зазвичай для застосунку достатньо завантажувати токен за розкладом (наприклад: один раз кожні 5 хвилин), без відстеження фактичного часу закінчення.

Виявлення емітента службового облікового запису

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.21 [stable]

Якщо ви увімкнули проєцювання токенів для ServiceAccounts у вашому кластері, то ви також можете скористатися функцією виявлення. Kubernetes надає спосіб клієнтам обʼєднуватись як постачальник ідентифікаційних даних, щоб одна або кілька зовнішніх систем могли діяти як сторона, що їм довіряє.

Якщо увімкнено, Kubernetes API-сервер публікує документ конфігурації постачальника OpenID через HTTP. Документ конфігурації публікується за адресою /.well-known/openid-configuration. Документ конфігурації OpenID постачальника іноді називається документом виявлення. Kubernetes API-сервер також публікує повʼязаний набір ключів JSON Web (JWKS), також через HTTP, за адресою /openid/v1/jwks.

Кластери, які використовують RBAC, включають типову роль кластера з назвою system:service-account-issuer-discovery. Типовий ClusterRoleBinding надає цю роль групі system:serviceaccounts, до якої неявно належать всі ServiceAccounts. Це дозволяє Podʼам, які працюють у кластері, отримувати доступ до документа виявлення службового облікового запису через їх змонтований токен службового облікового запису. Адміністратори також можуть вибрати привʼязку ролі до system:authenticated або system:unauthenticated залежно від їх вимог до безпеки та зовнішніх систем, з якими вони мають намір обʼєднуватись.

Відповідь JWKS містить публічні ключі, які може використовувати залежна сторона для перевірки токенів службових облікових записів Kubernetes. Залежні сторони спочатку запитують конфігурацію постачальника OpenID, а потім використовують поле jwks_uri у відповіді, щоб знайти JWKS.

У багатьох випадках API-сервери Kubernetes не доступні через глобальну мережу, але публічні точки доступу, які обслуговують кешовані відповіді від API-сервера, можуть бути доступні для користувачів або постачальників послуг. У таких випадках можливо перевизначити jwks_uri в конфігурації постачальника OpenID, щоб вона вказувала на глобальну точку доступу, а не на адресу API-сервера, передаючи прапорець --service-account-jwks-uri до API-сервера. Як і URL емітента, URI JWKS повинен використовувати схему https.

Що далі

Дивіться також:

Змінено December 17, 2024 at 11:53 AM PST: Sync upstream after v1.32 release (d7b08bbf8e)