1 - Видача сертифіката для клієнта API Kubernetes за допомогою CertificateSigningRequest

Kubernetes дозволяє використовувати інфраструктуру відкритих ключів (PKI) для автентифікації в кластері як клієнт.

Щоб звичайний користувач міг автентифікуватися й викликати API, потрібно виконати кілька кроків. Спочатку цей користувач повинен мати сертифікат X.509, виданий органом, якому довіряє ваш кластер Kubernetes. Потім клієнт повинен предʼявити цей сертифікат API Kubernetes.

У цьому процесі ви використовуєте CertificateSigningRequest; ви або інший субʼєкт маєте схвалити запит.

Ви створите приватний ключ, потім отримаєте виданий сертифікат і, нарешті, налаштуєте цей приватний ключ для клієнта.

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

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

  • Вам знадобляться утиліти kubectl, openssl та base64.

Ця сторінка передбачає, що ви використовуєте контроль доступу на основі ролей (RBAC) Kubernetes. Якщо у вас є альтернативні або додаткові механізми безпеки для авторизації, їх також потрібно врахувати.

Створіть приватний ключ

На цьому кроці ви створюєте приватний ключ. Цей приватний ключ потрібно тримати в таємниці; будь-хто, хто ним володіє, може видавати себе за цього користувача.

# Створіть приватний ключ
openssl genrsa -out myuser.key 3072

Створіть запит на підписання сертифіката X.509

Примітка:

Це не те саме, що API CertificateSigningRequest з подібною назвою; файл, який ви тут генеруєте, передається в CertificateSigningRequest.

Важливо встановити атрибути CN та O для CSR. CN — це імʼя користувача, а O — група, до якої належатиме цей користувач. Стандартні групи описано на сторінці RBAC.

# Змініть загальне імʼя "myuser" на фактичне імʼя користувача, яке ви хочете використовувати
openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser"

Створіть CertificateSigningRequest Kubernetes

Закодуйте документ CSR за допомогою цієї команди:

cat myuser.csr | base64 | tr -d "\n"

Створіть CertificateSigningRequest і надішліть його до кластера Kubernetes за допомогою kubectl. Нижче наведено фрагмент команд оболонки, за допомогою якого можна згенерувати CertificateSigningRequest.

cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: myuser # example
spec:
  # Це закодований CSR. Змініть його на вміст myuser.csr у кодуванні base64
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400  # one day
  usages:
  - client auth
EOF

Також можна створити файл маніфесту YAML і застосувати його за допомогою kubectl:

apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: myuser # example
spec:
  # This is an encoded CSR. Change this to the base64-encoded contents of myuser.csr
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400 # one day
  usages:
  - client auth

Застосуйте маніфест:

kubectl apply -f myuser.yaml --server-side

Зверніть увагу на кілька моментів:

  • usages має бути client auth.
  • expirationSeconds можна зробити довшим (наприклад, 864000 для десяти днів) або коротшим (наприклад, 3600 для однієї години). Не можна запитати тривалість менше ніж 10 хвилин.
  • request — це закодоване в base64 значення вмісту файлу CSR.

Схваліть CertificateSigningRequest

Використайте kubectl, щоб знайти створений вами CSR, і схваліть його вручну.

Отримайте список CSR:

kubectl get csr

Схваліть CSR:

kubectl certificate approve myuser

Отримайте сертифікат

Отримайте сертифікат із CSR, щоб перевірити, чи він виглядає правильно.

kubectl get csr/myuser -o yaml

Значення сертифіката міститься у форматі Base64 у .status.certificate.

Експортуйте виданий сертифікат з CertificateSigningRequest.

kubectl get csr myuser -o jsonpath='{.status.certificate}'| base64 -d > myuser.crt

Налаштуйте сертифікат у kubeconfig

Наступний крок — додати цього користувача до файлу kubeconfig.

Спочатку потрібно додати нові облікові дані:

kubectl config set-credentials myuser --client-key=myuser.key --client-certificate=myuser.crt --embed-certs=true

Потім потрібно додати контекст:

kubectl config set-context myuser --cluster=kubernetes --user=myuser

Перевірте:

kubectl --context myuser auth whoami

Ви маєте побачити вивід, який підтверджує, що ви — «myuser».

Створіть Role та RoleBinding

Примітка:

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

Після створення сертифіката настав час визначити Role і RoleBinding, щоб цей користувач мав доступ до ресурсів кластера Kubernetes.

Це приклад команди для створення Role для цього нового користувача:

kubectl create role developer --verb=create --verb=get --verb=list --verb=update --verb=delete --resource=pods

Еквівалентний YAML:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["create", "get", "list", "update", "delete"]

Це приклад команди для створення RoleBinding для цього нового користувача:

kubectl create rolebinding developer-binding-myuser --role=developer --user=myuser

Еквівалентний YAML:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-binding-myuser
subjects:
- kind: User
  name: myuser
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

Що далі

2 - Керування сертифікатами TLS у кластері

Kubernetes надає API certificates.k8s.io, який дозволяє отримувати сертифікати TLS, підписані центром сертифікації (CA), який ви контролюєте. Ці CA й сертифікати ваші робочі навантаження можуть використовувати для встановлення довіри.

API certificates.k8s.io використовує протокол, подібний до чернетки ACME.

Примітка:

Сертифікати, створені за допомогою API certificates.k8s.io, підписуються окремим CA. Кластер можна налаштувати на використання для цього кореневого CA кластера, але ніколи не слід на це покладатися. Не вважайте, що ці сертифікати проходитимуть перевірку кореневим CA кластера.

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

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

Вам потрібен інструмент cfssl. Ви можете завантажити cfssl з https://github.com/cloudflare/cfssl/releases.

Деякі кроки на цій сторінці використовують інструмент jq. Якщо у вас немає jq, ви можете встановити його із джерел програмного забезпечення вашої операційної системи або завантажити з https://jqlang.github.io/jq/.

Довіра до TLS у кластері

Довіра до власного CA із застосунку, що працює як Pod, зазвичай потребує додаткової конфігурації застосунку. Потрібно додати набір сертифікатів CA до списку сертифікатів CA, яким довіряє клієнт або сервер TLS. Наприклад, у конфігурації TLS у Golang для цього можна розібрати ланцюжок сертифікатів і додати розібрані сертифікати до поля RootCAs у структурі tls.Config.

Примітка:

Хоча власний сертифікат CA може бути у файловій системі (у ConfigMap kube-root-ca.crt), не слід використовувати цей центр сертифікації для будь-яких цілей, окрім перевірки внутрішніх точок доступу Kubernetes. Приклад внутрішньої точки доступу Kubernetes — Service з назвою kubernetes у просторі імен default.

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

Запит сертифіката

У наведеному нижче розділі показано, як створити сертифікат TLS для сервісу Kubernetes, до якого звертаються через DNS.

Примітка:

У цьому навчальному матеріалі використовується CFSSL: набір інструментів PKI та TLS від Cloudflare. Докладніше дивіться в статті блогу Cloudflare Introducing CFSSL - CloudFlare's PKI toolkit.

Створення запиту на підписання сертифіката

Згенеруйте приватний ключ і запит на підписання сертифіката (CSR), виконавши таку команду:

cat <<EOF | cfssl genkey - | cfssljson -bare server
{
  "hosts": [
    "my-svc.my-namespace.svc.cluster.local",
    "my-pod.my-namespace.pod.cluster.local",
    "192.0.2.24",
    "10.0.34.2"
  ],
  "CN": "my-pod.my-namespace.pod.cluster.local",
  "key": {
    "algo": "ecdsa",
    "size": 256
  }
}
EOF

Де 192.0.2.24 — кластерний IP сервісу, my-svc.my-namespace.svc.cluster.local — DNS-імʼя сервісу, 10.0.34.2 — IP Podʼа, а my-pod.my-namespace.pod.cluster.local — DNS-імʼя Podʼа. Ви маєте побачити вивід, подібний до такого:

2022/02/01 11:45:32 [INFO] generate received request
2022/02/01 11:45:32 [INFO] received CSR
2022/02/01 11:45:32 [INFO] generating key: ecdsa-256
2022/02/01 11:45:32 [INFO] encoded CSR

Ця команда генерує два файли: server.csr із запитом на сертифікат PKCS#10 у кодуванні PEM і server-key.pem із ключем у кодуванні PEM до сертифіката, який ще буде створено.

Створення обʼєкта CertificateSigningRequest для надсилання до API Kubernetes

Згенеруйте маніфест CSR (у форматі YAML) і надішліть його на API-сервер. Для цього виконайте таку команду:

cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: my-svc.my-namespace
spec:
  request: $(cat server.csr | base64 | tr -d '\n')
  signerName: example.com/serving
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF

Зверніть увагу, що файл server.csr, створений на кроці 1, закодовано в base64 і поміщено в поле .spec.request. Ви також запитуєте сертифікат із використаннями ключа "digital signature", "key encipherment" і "server auth", підписаний прикладом підписувача example.com/serving. Потрібно запитати конкретний signerName. Докладніше дивіться в документації про підтримувані назви підписувачів.

Тепер CSR має бути видимий в API у стані Pending. Його можна побачити, виконавши:

kubectl describe csr my-svc.my-namespace
Name:                   my-svc.my-namespace
Labels:                 <none>
Annotations:            <none>
CreationTimestamp:      Tue, 01 Feb 2022 11:49:15 -0500
Requesting User:        yourname@example.com
Signer:                 example.com/serving
Status:                 Pending
Subject:
        Common Name:    my-pod.my-namespace.pod.cluster.local
        Serial Number:
Subject Alternative Names:
        DNS Names:      my-pod.my-namespace.pod.cluster.local
                        my-svc.my-namespace.svc.cluster.local
        IP Addresses:   192.0.2.24
                        10.0.34.2
Events: <none>

Отримання схвалення CertificateSigningRequest

Схвалення запиту на підписання сертифіката виконується або автоматичним процесом схвалення, або разово адміністратором кластера. Якщо ви маєте право схвалювати запити на сертифікати, це можна зробити вручну за допомогою kubectl; наприклад:

kubectl certificate approve my-svc.my-namespace
certificatesigningrequest.certificates.k8s.io/my-svc.my-namespace approved

Тепер ви маєте побачити таке:

kubectl get csr
NAME                  AGE   SIGNERNAME            REQUESTOR              REQUESTEDDURATION   CONDITION
my-svc.my-namespace   10m   example.com/serving   yourname@example.com   <none>              Approved

Це означає, що запит на сертифікат схвалено і він чекає, поки запитаний підписувач його підпише.

Підписання CertificateSigningRequest

Далі ви зіграєте роль підписувача сертифікатів, видасте сертифікат і завантажите його в API.

Підписувач зазвичай відстежує в API CertificateSigningRequest обʼєкти зі своїм signerName, перевіряє, що їх схвалено, підписує сертифікати для цих запитів і оновлює статус обʼєкта API, додаючи виданий сертифікат.

Створення центру сертифікації

Вам потрібен центр сертифікації, який надасть цифровий підпис для нового сертифіката.

Спочатку створіть сертифікат для підписування, виконавши таку команду:

cat <<EOF | cfssl gencert -initca - | cfssljson -bare ca
{
  "CN": "My Example Signer",
  "key": {
    "algo": "rsa",
    "size": 2048
  }
}
EOF

Ви маєте побачити вивід, подібний до такого:

2022/02/01 11:50:39 [INFO] generating a new CA key and certificate from CSR
2022/02/01 11:50:39 [INFO] generate received request
2022/02/01 11:50:39 [INFO] received CSR
2022/02/01 11:50:39 [INFO] generating key: rsa-2048
2022/02/01 11:50:39 [INFO] encoded CSR
2022/02/01 11:50:39 [INFO] signed certificate with serial number 263983151013686720899716354349605500797834580472

Це створює файл ключа центру сертифікації (ca-key.pem) і сертифікат (ca.pem).

Видача сертифіката

{
    "signing": {
        "default": {
            "usages": [
                "digital signature",
                "key encipherment",
                "server auth"
            ],
            "expiry": "876000h",
            "ca_constraint": {
                "is_ca": false
            }
        }
    }
}

Використайте конфігурацію підписування server-signing-config.json, а також файл ключа й сертифікат центру сертифікації, щоб підписати запит на сертифікат:

kubectl get csr my-svc.my-namespace -o jsonpath='{.spec.request}' | \
  base64 --decode | \
  cfssl sign -ca ca.pem -ca-key ca-key.pem -config server-signing-config.json - | \
  cfssljson -bare ca-signed-server

Ви маєте побачити вивід, подібний до такого:

2022/02/01 11:52:26 [INFO] signed certificate with serial number 576048928624926584381415936700914530534472870337

Це створює файл підписаного серверного сертифіката ca-signed-server.pem.

Завантаження підписаного сертифіката

Нарешті, додайте підписаний сертифікат до статусу обʼєкта API:

kubectl get csr my-svc.my-namespace -o json | \
  jq '.status.certificate = "'$(base64 ca-signed-server.pem | tr -d '\n')'"' | \
  kubectl replace --raw /apis/certificates.k8s.io/v1/certificatesigningrequests/my-svc.my-namespace/status -f -

Примітка:

Тут використовується інструмент командного рядка jq для заповнення поля .status.certificate вмістом, закодованим у base64. Якщо у вас немає jq, можна також зберегти вивід JSON у файл, заповнити це поле вручну й завантажити отриманий файл.

Після схвалення CSR і завантаження підписаного сертифіката виконайте:

kubectl get csr

Вивід подібний до такого:

NAME                  AGE   SIGNERNAME            REQUESTOR              REQUESTEDDURATION   CONDITION
my-svc.my-namespace   20m   example.com/serving   yourname@example.com   <none>              Approved,Issued

Завантаження сертифіката та його використання

Тепер як користувач, що подав запит, ви можете завантажити виданий сертифікат і зберегти його у файл server.crt, виконавши таку команду:

kubectl get csr my-svc.my-namespace -o jsonpath='{.status.certificate}' \
    | base64 --decode > server.crt

Тепер ви можете додати server.crt і server-key.pem до Secret, який пізніше можна змонтувати в Pod (наприклад, для використання з вебсервером, що обслуговує HTTPS).

kubectl create secret tls server --cert server.crt --key server-key.pem
secret/server created

Нарешті, ви можете зберегти ca.pem у ConfigMap і використовувати його як корінь довіри для перевірки серверного сертифіката:

kubectl create configmap example-serving-ca --from-file ca.crt=ca.pem
configmap/example-serving-ca created

Схвалення CertificateSigningRequests

Адміністратор Kubernetes (з відповідними дозволами) може вручну схвалювати або відхиляти CertificateSigningRequests за допомогою команд kubectl certificate approve і kubectl certificate deny. Однак якщо ви плануєте активно використовувати цей API, варто розглянути написання автоматизованого контролера сертифікатів.

Увага:

Можливість схвалювати CSR визначає, хто кому довіряє у вашому середовищі. Цю можливість не слід надавати широко або легковажно.

Перш ніж надати дозвіл approve, переконайтеся, що ви впевнено розумієте і вимоги до перевірки, покладені на схвалювача, і наслідки видачі конкретного сертифіката.

Незалежно від того, чи є схвалювач машиною, чи людиною, що використовує kubectl, як описано вище, роль схвалювача полягає в перевірці, що CSR відповідає двом вимогам:

  1. Субʼєкт CSR контролює приватний ключ, використаний для підписання CSR. Це усуває загрозу того, що третя сторона видаватиме себе за авторизованого субʼєкта. У наведеному вище прикладі цей крок полягав би в перевірці, що Pod контролює приватний ключ, використаний для генерації CSR.
  2. Субʼєкт CSR має право діяти в запитаному контексті. Це усуває загрозу приєднання до кластера небажаного субʼєкта. У наведеному вище прикладі цей крок полягав би в перевірці, що Pod має право брати участь у запитаному сервісі.

Схвалювач має схвалити CSR тоді й лише тоді, коли виконано ці дві вимоги; інакше він має відхилити CSR.

Докладніше про схвалення сертифікатів і контроль доступу читайте на довідковій сторінці Запити на підписання сертифікатів.

Налаштування кластера для підписування

Ця сторінка передбачає, що підписувач налаштований обслуговувати API сертифікатів. Менеджер контролерів Kubernetes надає стандартну реалізацію підписувача. Щоб увімкнути її, передайте менеджеру контролерів параметри --cluster-signing-cert-file і --cluster-signing-key-file зі шляхами до пари ключів вашого центру сертифікації.

3 - Налаштування ротації сертифікатів для kubelet

На цій сторінці показано, як увімкнути й налаштувати ротацію сертифікатів для kubelet.

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.19

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

  • Потрібна версія Kubernetes 1.8.0 або новіша

Огляд

kubelet використовує сертифікати для автентифікації в API Kubernetes. Стандартно ці сертифікати видаються на один рік, щоб їх не потрібно було оновлювати надто часто.

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

Увімкнення ротації клієнтських сертифікатів

Процес kubelet приймає аргумент --rotate-certificates, який визначає, чи автоматично kubelet запитуватиме новий сертифікат, коли наближається завершення строку дії поточного сертифіката.

Процес kube-controller-manager приймає аргумент --cluster-signing-duration (--experimental-cluster-signing-duration до версії 1.19), який визначає, на який строк видаватимуться сертифікати.

Розуміння налаштувань ротації сертифікатів

Якщо під час запуску kubelet налаштований на початкове завантаження (за допомогою прапорця --bootstrap-kubeconfig), він використає свій початковий сертифікат, щоб підʼєднатися до API Kubernetes і надіслати запит на підписання сертифіката. Переглянути стан запитів на підписання сертифікатів можна за допомогою:

kubectl get csr

Спочатку запит на підписання сертифіката від kubelet на вузлі матиме статус Pending. Якщо запит відповідає певним критеріям, менеджер контролерів автоматично схвалить його, і він матиме статус Approved. Далі менеджер контролерів підпише сертифікат, виданий на строк, вказаний параметром --cluster-signing-duration, і підписаний сертифікат буде прикріплено до запиту на підписання сертифіката.

kubelet отримає підписаний сертифікат з API Kubernetes і запише його на диск у місце, вказане в --cert-dir. Потім kubelet використовуватиме новий сертифікат для підʼєднання до API Kubernetes.

Коли наближається завершення строку дії підписаного сертифіката, kubelet автоматично надсилає новий запит на підписання сертифіката через API Kubernetes. Це може статися в будь-який момент, коли лишається від 30% до 10% строку дії сертифіката. Менеджер контролерів знову автоматично схвалює запит на сертифікат і прикріплює підписаний сертифікат до запиту на підписання сертифіката. kubelet отримує новий підписаний сертифікат з API Kubernetes і записує його на диск. Потім він оновлює свої зʼєднання з API Kubernetes, щоб перепідʼєднатися з новим сертифікатом.

4 - Ручна ротація сертифікатів центру сертифікації (CA)

На цій сторінці показано, як вручну виконати ротацію сертифікатів центру сертифікації (CA).

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

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

  • Докладніше про автентифікацію в Kubernetes дивіться в розділі Автентифікація.
  • Докладніше про рекомендації щодо сертифікатів CA дивіться в розділі Один кореневий CA.

Ручна ротація сертифікатів CA

Увага:

Обовʼязково створіть резервну копію теки сертифікатів разом із файлами конфігурації та іншими потрібними файлами.

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

Конфігурації з одним API-сервером будуть недоступні під час перезапуску API-сервера.

  1. Розподіліть нові сертифікати CA й приватні ключі (наприклад, ca.crt, ca.key, front-proxy-ca.crt і front-proxy-ca.key) на всі вузли панелі управління в теку сертифікатів Kubernetes.

  2. Оновіть прапорець --root-ca-file для kube-controller-manager, щоб він містив і старий, і новий CA, а потім перезапустіть kube-controller-manager.

    Будь-який ServiceAccount, створений після цього, отримає Secrets, що містять і старий, і новий CA.

    Примітка:

    Файли, вказані у прапорцях kube-controller-manager --client-ca-file і --cluster-signing-cert-file, не можуть бути наборами CA. Якщо ці прапорці та --root-ca-file вказують на той самий файл ca.crt, який тепер є набором (містить і старий, і новий CA), ви отримаєте помилку. Щоб обійти цю проблему, скопіюйте новий CA в окремий файл і вкажіть цю копію в прапорцях --client-ca-file і --cluster-signing-cert-file. Коли ca.crt більше не буде набором, ви зможете знову вказати ca.crt у цих прапорцях і видалити копію.

    Issue 1350 для kubeadm відстежує помилку, через яку kube-controller-manager не може прийняти набір CA.

  3. Зачекайте, поки менеджер контролерів оновить ca.crt у Secrets для ServiceAccount, щоб вони містили і старі, і нові сертифікати CA.

    Якщо якісь Podʼи запускаються до того, як API-сервери почнуть використовувати новий CA, нові Podʼи отримають це оновлення й довірятимуть і старим, і новим CA.

  4. Перезапустіть усі Podʼи, що використовують конфігурації всередині кластера (наприклад, kube-proxy, CoreDNS тощо), щоб вони могли використовувати оновлені дані центру сертифікації із Secrets, повʼязаних із ServiceAccounts.

    • Переконайтеся, що CoreDNS, kube-proxy та інші Podʼи, які використовують конфігурації всередині кластера, працюють належним чином.
  5. Додайте і старий, і новий CA до файлу, вказаного у прапорцях --client-ca-file і --kubelet-certificate-authority, у конфігурації kube-apiserver.

  6. Додайте і старий, і новий CA до файлу, вказаного у прапорці --client-ca-file, у конфігурації kube-scheduler.

  7. Оновіть сертифікати облікових записів користувачів, замінивши вміст client-certificate-data і client-key-data відповідно.

    Докладніше про створення сертифікатів для окремих облікових записів користувачів дивіться в розділі Налаштування сертифікатів для облікових записів користувачів.

    Крім того, оновіть розділ certificate-authority-data у файлах kubeconfig, вказавши відповідно закодовані в Base64 дані старого й нового центру сертифікації.

  8. Оновіть прапорець --root-ca-file для Cloud Controller Manager, щоб він містив і старий, і новий CA, а потім перезапустіть cloud-controller-manager.

    Примітка:

    Якщо у вашому кластері немає cloud-controller-manager, цей крок можна пропустити.
  9. Виконайте наведені нижче кроки поетапно.

    1. Перезапустіть усі інші агреговані API-сервери або обробники вебхуків, щоб вони довіряли новим сертифікатам CA.

    2. Перезапустіть kubelet, оновивши файл, вказаний у clientCAFile у конфігурації kubelet, і certificate-authority-data у kubelet.conf, щоб використовувати і старий, і новий CA на всіх вузлах.

      Якщо ваш kubelet не використовує ротацію клієнтських сертифікатів, оновіть client-certificate-data і client-key-data у kubelet.conf на всіх вузлах, а також файл клієнтського сертифіката kubelet, який зазвичай міститься в /var/lib/kubelet/pki.

    3. Перезапустіть API-сервери із сертифікатами (apiserver.crt, apiserver-kubelet-client.crt і front-proxy-client.crt), підписаними новим CA. Ви можете використовувати наявні або нові приватні ключі. Якщо ви змінили приватні ключі, оновіть їх і в теці сертифікатів Kubernetes.

      Оскільки Podʼи у вашому кластері довіряють і старим, і новим CA, буде короткочасне відʼєднання, після якого клієнти Kubernetes у Podʼах перепідʼєднаються до нового API-сервера. Новий API-сервер використовує сертифікат, підписаний новим CA.

      • Перезапустіть kube-scheduler, щоб він використовував нові CA й довіряв їм.
      • Переконайтеся, що логи компонентів панелі управління не містять помилок TLS.

      Примітка:

        Щоб згенерувати сертифікати й приватні ключі для вашого кластера за допомогою інструмента командного рядка `openssl`, дивіться [Сертифікати (`openssl`)](/docs/tasks/administer-cluster/certificates/#openssl). Також можна використовувати [`cfssl`](/docs/tasks/administer-cluster/certificates/#cfssl).
      
    4. Додайте анотації до DaemonSets і Deployments, щоб запустити заміну Podʼів безпечнішим поетапним способом.

      for namespace in $(kubectl get namespace -o jsonpath='{.items[*].metadata.name}'); do
          for name in $(kubectl get deployments -n $namespace -o jsonpath='{.items[*].metadata.name}'); do
              kubectl patch deployment -n ${namespace} ${name} -p '{"spec":{"template":{"metadata":{"annotations":{"ca-rotation": "1"}}}}}';
          done
          for name in $(kubectl get daemonset -n $namespace -o jsonpath='{.items[*].metadata.name}'); do
              kubectl patch daemonset -n ${namespace} ${name} -p '{"spec":{"template":{"metadata":{"annotations":{"ca-rotation": "1"}}}}}';
          done
      done
      

      Примітка:

        Щоб обмежити кількість одночасних порушень, яких зазнає ваш застосунок, дивіться [налаштування бюджету порушень Podʼів](/docs/tasks/run-application/configure-pdb/).
      

      Залежно від того, як ви використовуєте StatefulSets, вам також може знадобитися виконати подібну поетапну заміну.

  10. Якщо ваш кластер використовує токени початкового завантаження для приєднання вузлів, оновіть ConfigMap cluster-info у просторі імен kube-public, додавши новий CA.

    base64_encoded_ca="$(base64 -w0 /etc/kubernetes/pki/ca.crt)"
    
    kubectl get cm/cluster-info --namespace kube-public -o yaml | \
        /bin/sed "s/\(certificate-authority-data:\).*/\1 ${base64_encoded_ca}/" | \
        kubectl apply -f -
    
  11. Перевірте роботу кластера.

    1. Перевірте логи компонентів панелі управління, а також kubelet і kube-proxy. Переконайтеся, що ці компоненти не повідомляють про помилки TLS; докладніше дивіться в розділі перегляд логів.

    2. Перевірте логи агрегованих API-серверів і Podʼів, що використовують конфігурацію всередині кластера.

  12. Після успішної перевірки роботи кластера:

    1. Оновіть усі токени ServiceAccount, щоб вони містили лише новий сертифікат CA.

      • Усі Podʼи, що використовують kubeconfig всередині кластера, зрештою потрібно буде перезапустити, щоб вони отримали новий Secret і жоден Pod не залежав від старого CA кластера.
    2. Перезапустіть компоненти панелі управління, вилучивши старий CA з файлів kubeconfig і файлів, вказаних у прапорцях --client-ca-file і --root-ca-file відповідно.

    3. На кожному вузлі перезапустіть kubelet, вилучивши старий CA з файлу, вказаного в прапорці clientCAFile, і з файлу kubeconfig kubelet. Виконуйте це як поетапне оновлення.

      Якщо ваш кластер дозволяє внести цю зміну, ви також можете розгорнути її заміною вузлів, а не їх переналаштуванням.