Початкове завантаження TLS
У кластері Kubernetes компоненти на вузлах робочих навантажень, kubelet та kube-proxy, повинні взаємодіяти з компонентами панелі управління Kubernetes, зокрема з kube-apiserver. Для забезпечення приватності комунікації, її невтручання та переконання, що кожен компонент кластера спілкується з іншим довіреним компонентом, ми наполегливо рекомендуємо використовувати TLS-сертифікати клієнтів на вузлах.
Звичайний процес ініціалізації цих компонентів, особливо робочих вузлів, які потребують сертифікати для безпечної комунікації з kube-apiserver, може бути складним, оскільки він часто виходить за межі Kubernetes і вимагає значної додаткової роботи. Це, своєю чергою, може ускладнити ініціалізацію або масштабування кластера.
З метою спрощення процесу, починаючи з версії 1.4, Kubernetes ввів API запиту та підпису сертифікатів. Пропозицію можна знайти тут.
У цьому документі описано процес ініціалізації вузла, спосіб налаштування початкового завантаження TLS-сертифікатів клієнтів для kubelet та його роботу.
Процес ініціалізації
Коли робочий вузол запускається, kubelet виконує наступне:
- Шукає свій файл
kubeconfig
. - Отримує URL-адресу сервера API та облікові дані, зазвичай ключ TLS та підписаний сертифікат з файлу
kubeconfig
. - Намагається спілкуватися з сервером API, використовуючи облікові дані.
Припускаючи, що kube-apiserver успішно перевіряє облікові дані kubelet, він буде вважати kubelet дійсним вузлом та почне призначати для нього Podʼи.
Зауважте, що вищевказаний процес залежить від:
- Існування ключа та сертифіката на локальному хості у
kubeconfig
. - Підписання сертифіката центром сертифікації (CA), якому довіряє kube-apiserver.
Всі перелічені нижче обовʼязки покладаються на того, хто налаштовує та керує кластером:
- Створення ключа та сертифіката CA.
- Розповсюдження сертифіката CA на вузли панелі управління, де запущений kube-apiserver.
- Створення ключа та сертифіката для кожного kubelet; наполегливо рекомендується мати унікальний ключ з унікальним CN для кожного kubelet.
- Підписання сертифіката kubelet за допомогою ключа CA.
- Розповсюдження ключа та підписаного сертифіката kubelet на конкретний вузол, на якому працює kubelet.
Початкове завантаження TLS, описане у цьому документі, призначене спростити та частково або повністю автоматизувати кроки з 3 по 14, оскільки вони є найбільш поширеними при ініціалізації або масштабуванні кластера.
Ініціалізація початкового завантаження
Під час процесу ініціалізації початкового завантаження відбувається наступне:
- kubelet починає роботу.
- kubelet бачить, що у нього немає файлу
kubeconfig
. - kubelet шукає та знаходить файл
bootstrap-kubeconfig
. - kubelet читає свій файл ініціалізації початкового завантаження, отримуючи URL-адресу сервера API та обмежений "токен".
- kubelet підключається до сервера API, автентифікується за допомогою токена.
- у kubelet тепер є обмежені облікові дані для створення та отримання запиту на підпис сертифіката (CSR).
- kubelet створює CSR для себе з встановленим signerName
kubernetes.io/kube-apiserver-client-kubelet
. - CSR затверджується одним з двох способів:
- Якщо налаштовано, kube-controller-manager автоматично затверджує CSR.
- Якщо налаштовано, зовнішній процес, можливо, людина, затверджує CSR за допомогою API Kubernetes або через
kubectl
.
- Сертифікат створюється для kubelet.
- Сертифікат видано для kubelet.
- kubelet отримує сертифікат.
- kubelet створює належний
kubeconfig
з ключем та підписаним сертифікатом. - kubelet починає нормальну роботу.
- Опціонально: якщо налаштовано, kubelet автоматично запитує поновлення сертифіката, коли той наближається до закінчення строку дії.
- Поновлений сертифікат затверджується та видається, або автоматично, або вручну, залежно від налаштувань.
Усі інші розділи цього документу описують необхідні кроки для налаштування початкового завантаження TLS та його обмежень.
Налаштування
Для налаштування початкового завантаження TLS та опціонального автоматичного затвердження потрібно налаштувати параметри на наступних компонентах:
- kube-apiserver
- kube-controller-manager
- kubelet
- ресурси в кластері:
ClusterRoleBinding
та, можливо,ClusterRole
Крім того, вам потрібен ваш центр сертифікації Kubernetes (CA).
Центр сертифікації
Як і без початкового завантаження, вам знадобиться ключ та сертифікат центру сертифікації (CA). Як і раніше, вони будуть використовуватися для підпису сертифіката kubelet. Як і раніше, ваша відповідальність полягає в їх розповсюджені на вузли панелі управління.
Для цілей цього документу ми припускаємо, що вони розповсюджені на вузли панелі управління за шляхом /var/lib/kubernetes/ca.pem
(сертифікат) та /var/lib/kubernetes/ca-key.pem
(ключ). Ми будемо посилатися на них як "сертифікат та ключ CA Kubernetes".
Всі компоненти Kubernetes, які використовують ці сертифікати — kubelet, kube-apiserver, kube-controller-manager — припускають, що ключ та сертифікат закодовані у PEM-форматі.
Налаштування kube-apiserver
У kube-apiserver є кілька вимог для активації початкового завантаження TLS:
- Визнання CA, який підписує сертифікат клієнта
- Автентифікація початкового завантаження kubelet у групу
system:bootstrappers
- Авторизація початкового завантаження kubelet для створення запиту на підпис сертифіката (CSR)
Визнання сертифікатів клієнтів
Це є нормою для всієї автентифікації сертифікатів клієнтів. Якщо це ще не налаштовано, додайте прапорець --client-ca-file=ФАЙЛ
до команди kube-apiserver, щоб активувати автентифікацію за сертифікатом клієнта, посилаючись на пакет сертифікатів центру сертифікації, наприклад --client-ca-file=/var/lib/kubernetes/ca.pem
.
Початкова автентифікація початкового завантаження
Для того, щоб процес початкового завантаження kubelet міг підʼєднатися до kube-apiserver та запросити сертифікат, спочатку йому потрібно автентифікуватися на сервері. Ви можете використовувати будь-який автентифікатор, який може автентифікувати kubelet.
Хоча будь-яка стратегія автентифікації може бути використана для початкових облікових даних kubelet, рекомендується використовувати наступні два автентифікатори для полегшення надання прав.
Використання токенів початкового завантаження є простішим та зручнішим способом автентифікації kubelet і не вимагає додаткових прапорів при запуску kube-apiserver.
Який би метод ви не обрали, вимога полягає в тому, щоб kubelet міг автентифікуватися як користувач з правами на:
- створення та отримання CSRs
- автоматичне затвердження запиту клієнтських сертифікатів вузлів, якщо увімкнено автоматичне затвердження.
Kubelet, який автентифікується за допомогою початкових токенів, автентифікується як користувач у групі system:bootstrappers
, що є стандартним методом використання.
Оскільки ця функція вдосконалюється, вам слід переконатися, що токени привʼязані до політики управління доступом на основі ролей (RBAC), яка обмежує запити (використовуючи початковий токен) виключно клієнтськими запитами, повʼязаними з наданням сертифікатів. З RBAC можна гнучко налаштовувати обмеження для токенів за групами. Наприклад, ви можете вимкнути доступ певної початкової групи після завершення розгортання вузлів.
Токени початкового завантаження
Токени початкового завантаження докладно описані тут. Це токени, які зберігаються як секрети в кластері Kubernetes і потім видаються окремим kubelet. Ви можете використовувати один токен для всього кластера або видавати по одному на кожен робочий вузол.
Процес складається з двох етапів:
- Створити Secret Kubernetes з ідентифікатором токена, секретом і областю(ями).
- Видати токен kubelet.
З погляду kubelet, один токен такий самий, як інший і не має особливого значення. З погляду kube-apiserver, однак, початковий токен є особливим. Завдяки його type
, namespace
і name
, kube-apiserver розпізнає його як спеціальний токен і надає будь-кому, хто автентифікується з цим токеном, особливі права початкового завантаження, зокрема, розглядаючи їх як члена групи system:bootstrappers
. Це виконує основну вимогу для початкового завантаження TLS.
Деталі щодо створення секрету доступні тут.
Якщо ви хочете використовувати токени початкового завантаження, ви повинні увімкнути їх на kube-apiserver з прапорцем:
--enable-bootstrap-token-auth=true
Файл автентифікації токенів
kube-apiserver має можливість приймати токени для автентифікації. Ці токени можуть бути довільними, але повинні представляти щонайменше 128 біт ентропії, отриманих з надійного генератора випадкових чисел (наприклад, /dev/urandom
у більшості сучасних Linux-систем). Є кілька способів генерації токена. Наприклад:
head -c 16 /dev/urandom | od -An -t x | tr -d ' '
Це згенерує токени, які виглядають так: 02b50b05283e98dd0fd71db496ef01e8
.
Файл токенів повинен виглядати як у наступному прикладі, де перші три значення можуть бути будь-якими, а імʼя групи в лапках повинно бути таким, як показано:
02b50b05283e98dd0fd71db496ef01e8,kubelet-bootstrap,10001,"system:bootstrappers"
Додайте прапорець --token-auth-file=FILENAME
до команди kube-apiserver (можливо, у вашому файлі systemd), щоб увімкнути файл токенів. Докладніше дивіться тут.
Авторизація kubelet на створення CSR
Тепер, коли вузол початкового завантаження автентифікований як частина групи system:bootstrappers
, його потрібно авторизувати на створення запиту на підпис сертифіката (CSR), а також на його отримання після завершення. На щастя, Kubernetes постачається з ClusterRole
, який має саме ці (і тільки ці) дозволи, system:node-bootstrapper
.
Щоб зробити це, потрібно лише створити ClusterRoleBinding
, що звʼязує групу system:bootstrappers
з кластерною роллю system:node-bootstrapper
.
# увімкнення створення CSR для вузлів початкового завантаження
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: create-csrs-for-bootstrapping
subjects:
- kind: Group
name: system:bootstrappers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: system:node-bootstrapper
apiGroup: rbac.authorization.k8s.io
Налаштування kube-controller-manager
Поки apiserver отримує запити на сертифікати від kubelet і автентифікує ці запити, controller-manager відповідає за видачу фактичних підписаних сертифікатів.
Controller-manager виконує цю функцію через цикл управління видачею сертифікатів. Це реалізується у вигляді локального підписувача cfssl, який використовує активи на диску. Зараз всі видані сертифікати стандартно мають один рік дійсності та набір ключів для використання.
Для того, щоб controller-manager міг підписувати сертифікати, йому потрібно наступне:
- доступ до "ключа та сертифіката Kubernetes CA", який ви створили та розповсюдили
- увімкнення підписування CSR
Доступ до ключа та сертифіката
Як описано раніше, вам потрібно створити ключ і сертифікат Kubernetes CA і розповсюдити їх на вузли панелі управління. Ці сертифікати будуть використовуватися controller-manager для підписування сертифікатів kubelet.
Оскільки ці підписані сертифікати, своєю чергою, будуть використовуватися kubelet для автентифікації як звичайного kubelet до kube-apiserver, важливо, щоб CA, наданий controller-manager на цьому етапі, також був довірений kube-apiserver для автентифікації. Це надається kube-apiserver за допомогою прапорця --client-ca-file=FILENAME
(наприклад, --client-ca-file=/var/lib/kubernetes/ca.pem
), як описано в розділі конфігурації kube-apiserver.
Щоб надати ключ і сертифікат Kubernetes CA для kube-controller-manager, використовуйте наступні прапорці:
--cluster-signing-cert-file="/etc/path/to/kubernetes/ca/ca.crt" --cluster-signing-key-file="/etc/path/to/kubernetes/ca/ca.key"
Наприклад:
--cluster-signing-cert-file="/var/lib/kubernetes/ca.pem" --cluster-signing-key-file="/var/lib/kubernetes/ca-key.pem"
Тривалість дійсності підписаних сертифікатів можна налаштувати за допомогою прапорця:
--cluster-signing-duration
Затвердження
Щоб затвердити CSR, потрібно вказати controller-manager, що їх можна затверджувати. Це робиться шляхом надання прав доступу RBAC потрібній групі.
Існують два різні набори дозволів:
nodeclient
: Якщо вузол створює новий сертифікат для вузла, тоді у нього ще немає сертифіката. Він автентифікується за допомогою одного з токенів, зазначених вище, і таким чином є частиною групиsystem:bootstrappers
.selfnodeclient
: Якщо вузол оновлює свій сертифікат, тоді у нього вже є сертифікат (за визначенням), який він використовує для автентифікації як частина групиsystem:nodes
.
Щоб дозволити kubelet запитувати та отримувати новий сертифікат, створіть ClusterRoleBinding
, що звʼязує групу, в якій є членом вузол початкового завантаження, system:bootstrappers
, з ClusterRole
, що надає їй дозвіл, system:certificates.k8s.io:certificatesigningrequests:nodeclient
:
# Затвердження всіх CSR для групи "system:bootstrappers"
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: auto-approve-csrs-for-group
subjects:
- kind: Group
name: system:bootstrappers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: system:certificates.k8s.io:certificatesigningrequests:nodeclient
apiGroup: rbac.authorization.k8s.io
Щоб дозволити kubelet оновлювати власний клієнтський сертифікат, створіть ClusterRoleBinding
, що звʼязує групу, в якій є членом повнофункціональний вузол, system:nodes
, з ClusterRole
, що
надає їй дозвіл, system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
:
# Затвердження запитів на оновлення CSR для групи "system:nodes"
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: auto-approve-renewals-for-nodes
subjects:
- kind: Group
name: system:nodes
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
apiGroup: rbac.authorization.k8s.io
Контролер csrapproving
, який постачається як частина kube-controller-manager, стандартно увімкнено. Контролер використовує API SubjectAccessReview
для визначення, чи авторизований користувач для запиту CSR, а потім затверджує на основі результатів авторизації. Щоб уникнути конфліктів з іншими затверджувачами, вбудований затверджувач не відхиляє CSR явним чином. Він лише ігнорує неавторизовані запити. Контролер також видаляє прострочені сертифікати в рамках збору сміття.
Налаштування kubelet
Нарешті, з правильно налаштованими вузлами панелі управління та всією необхідною автентифікацією та авторизацією, ми можемо налаштувати kubelet.
Для початкового завантаження kubelet потрібна наступна конфігурація:
- Шлях для зберігання ключа та сертифіката, які він генерує (опціонально, можна використовувати стандартні)
- Шлях до файлу
kubeconfig
, який ще не існує; тут буде збережено конфігураційний файл після початкового завантаження - Шлях до початкового файлу
kubeconfig
, що містить URL сервера та початкові облікові дані, наприклад, початковий токен - Опціонально: інструкції щодо ротації сертифікатів
Початковий файл kubeconfig
має бути в шляху, доступному для kubelet, наприклад /var/lib/kubelet/bootstrap-kubeconfig
.
Його формат ідентичний звичайному файлу kubeconfig
. Приклад файлу може виглядати наступним чином:
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /var/lib/kubernetes/ca.pem
server: https://my.server.example.com:6443
name: bootstrap
contexts:
- context:
cluster: bootstrap
user: kubelet-bootstrap
name: bootstrap
current-context: bootstrap
preferences: {}
users:
- name: kubelet-bootstrap
user:
token: 07401b.f395accd246ae52d
Важливі елементи:
certificate-authority
: шлях до файлу CA, використовується для перевірки сертифіката сервера, представленого kube-apiserverserver
: URL до kube-apiservertoken
: токен для використання
Формат токена не має значення, головне, щоб він відповідав очікуванням kube-apiserver. У наведеному прикладі ми використали початковий токен. Як зазначалося раніше, будь-який дійсний метод автентифікації може бути використаний, а не тільки токени.
Оскільки початковий kubeconfig
є стандартним kubeconfig
, ви можете використовувати kubectl
для його створення. Щоб створити вищезазначений приклад файлу:
kubectl config --kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig set-cluster bootstrap --server='https://my.server.example.com:6443' --certificate-authority=/var/lib/kubernetes/ca.pem
kubectl config --kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig set-credentials kubelet-bootstrap --token=07401b.f395accd246ae52d
kubectl config --kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig set-context bootstrap --user=kubelet-bootstrap --cluster=bootstrap
kubectl config --kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig use-context bootstrap
Щоб вказати kubelet використовувати початковий kubeconfig
, використовуйте наступний прапорець:
--bootstrap-kubeconfig="/var/lib/kubelet/bootstrap-kubeconfig" --kubeconfig="/var/lib/kubelet/kubeconfig"
Під час запуску kubelet, якщо файл, вказаний через --kubeconfig
, не існує, початковий kubeconfig, вказаний через --bootstrap-kubeconfig
, використовується для запиту клієнтського сертифіката від API сервера. Після затвердження запиту на сертифікат і його отримання kubelet, конфігураційний файл kubeconfig, що посилається на згенерований ключ і отриманий сертифікат, буде записаний у шлях, вказаний за допомогою --kubeconfig
. Файл сертифіката і ключа буде розміщено в теці, вказаній прапорцем --cert-dir
.
Клієнтські та серверні сертифікати
Все вищезазначене стосується клієнтських сертифікатів kubelet, зокрема сертифікатів, які kubelet використовує для автентифікації до kube-apiserver.
kubelet також може використовувати серверні сертифікати. Сам kubelet відкриває https-точку доступу для певних функцій. Для їх захисту, kubelet може робити одне з наступного:
- використовувати наданий ключ та сертифікат через прапорці
--tls-private-key-file
та--tls-cert-file
- створити самопідписаний ключ та сертифікат, якщо ключ та сертифікат не надані
- запитати серверні сертифікати у сервера кластера через API CSR
Клієнтський сертифікат, наданий під час початкового завантаження TLS, стандартно підписується лише для client auth
і, отже, не може використовуватися як серверний сертифікат, або server auth
.
Однак, ви можете увімкнути його серверний сертифікат, принаймні частково, через ротацію сертифікатів.
Ротація сертифікатів
З версії Kubernetes v1.8 та вище kubelet реалізує функції для увімкнення ротації його клієнтських і/або серверних сертифікатів. Зверніть увагу, що ротація серверного сертифіката є бета функцією та потребує функціональної можливості RotateKubeletServerCertificate
на kubelet (стандартно увімкнено).
Ви можете налаштувати kubelet для ротації його клієнтських сертифікатів, створюючи нові CSRs при закінченні терміну дії його поточних облікових даних. Щоб увімкнути цю функцію, використовуйте поле rotateCertificates
у файлі конфігурації kubelet або передайте наступний аргумент командного рядка kubelet (застаріло):
--rotate-certificates
Увімкнення RotateKubeletServerCertificate
призводить до того, що kubelet одночасно
запитує серверний сертифікат після початкового завантаження своїх клієнтських облікових даних і ротує цей сертифікат. Щоб увімкнути цю поведінку, використовуйте поле serverTLSBootstrap
у файлі конфігурації kubelet або передайте наступний аргумент командного рядка kubelet (застаріло):
--rotate-server-certificates
Примітка:
Контролери, що затверджують CSR, реалізовані в ядрі Kubernetes, не затверджують серверні сертифікати вузла з міркувань безпеки. Для використання RotateKubeletServerCertificate
операторам потрібно запустити власний контролер затвердження або вручну затвердити запити на серверні сертифікати.
Процес затвердження серверних сертифікатів kubelet, специфічний для розгортання, зазвичай повинен затверджувати лише CSRs, які:
- запитані вузлами (забезпечте, що поле
spec.username
має формуsystem:node:<nodeName>
іspec.groups
міститьsystem:nodes
) - запитують використання для серверного сертифіката (забезпечте, що
spec.usages
міститьserver auth
, додатково міститьdigital signature
таkey encipherment
, і не містить інших використань) - мають лише IP та DNS subjectAltNames, які належать запитуючому вузлу, і не мають URI та Email subjectAltNames (розібрати x509 Certificate Signing Request в
spec.request
, щоб перевіритиsubjectAltNames
)
Інші складові автентифікації
Усі процеси завантаження TLS, описані у цьому документі, стосуються kubelet. Однак інші компоненти можуть потребувати прямого звʼязку з kube-apiserver. Особливо важливим є kube-proxy, який є частиною компонентів вузла Kubernetes і запускається на кожному вузлі, але може також включати інші компоненти, такі як моніторинг чи роботу з мережею.
Подібно до kubelet, цим іншим компонентам також потрібен метод автентифікації у kube-apiserver. У вас є кілька варіантів для генерації цих облікових даних:
- Традиційний спосіб: Створіть і розповсюдьте сертифікати так само як ви це робили для kubelet перед завантаженням TLS.
- DaemonSet: Оскільки сам kubelet завантажується на кожний вузол і достатньо для запуску базових служб, ви можете запускати kube-proxy та інші служби, специфічні для вузла, не як самостійний процес, а як daemonset у просторі імен
kube-system
. Оскільки він буде в кластері, ви можете надати йому відповідний службовий обліковий запис з відповідними дозволами для виконання своїх дій. Це може бути найпростішим способом налаштування таких служб.
Затвердження за допомогою kubectl
Запити на сертифікати можна затвердити поза процесом затвердження, вбудованим у контролер керування.
Контролер підпису не негайно підписує всі запити на сертифікати. Замість цього він чекає, доки вони не будуть позначені статусом "Approved" відповіднbv привілейованим користувачем. Цей процес призначений для того, щоб дозволити автоматичне затвердження, яке обробляється зовнішнім контролером затвердження або controller-manager, реалізованим в основному controller-manager. Однак адміністратори кластера також можуть вручну затверджувати запити на сертифікати за допомогою kubectl. Адміністратор може отримати перелік CSRs за допомогою kubectl get csr
та детально описати один з них за допомогою kubectl describe csr <name>
. Адміністратор може затвердити або відхилити CSR за допомогою kubectl certificate approve <name>
та kubectl certificate deny <name>
.