У всіх кластерах Kubernetes є дві категорії користувачів: службові облікові записи, які керуються Kubernetes, і звичайні користувачі.
Припускається, що незалежна від кластера служба керує звичайними користувачами наступними способами:
адміністратор розповсюджує приватні ключі
сховище користувачів, таке як Keystone або Google Accounts
файл зі списком імен користувачів та паролів
У цьому відношенні Kubernetes не має обʼєктів, які представляють звичайні облікові записи користувачів. Звичайні користувачі не можуть бути додані до кластера через API виклик.
Хоча звичайного користувача не можна додати через API виклик, будь-який користувач, який предʼявляє дійсний сертифікат, підписаний центром сертифікації (CA) кластера, вважається автентифікованим. У цій конфігурації Kubernetes визначає імʼя користувача з поля загального імені (CN) у сертифікаті (наприклад, "/CN=bob"). Після цього підсистема контролю доступу на основі ролей (RBAC) визначає, чи авторизований користувач для виконання певної операції з ресурсом. Детальніше про це можна прочитати у темі про звичайних користувачів у запиті сертифікатів.
На відміну від цього, службові облікові записи є користувачами, якими керує Kubernetes API. Вони привʼязані до певних просторів імен і створюються автоматично API сервером або вручну через API виклики. Службові облікові записи привʼязані до набору облікових даних, збережених як Secrets, які монтуються в Podʼи, що дозволяє процесам всередині кластера взаємодіяти з Kubernetes API.
API запити привʼязані або до звичайного користувача, або до службово облікового запису, або обробляються як анонімні запити. Це означає, що кожен процес всередині або поза кластером, від користувача, який вводить kubectl на робочій станції, до kubelets на вузлах, до членів панелі управління, повинен автентифікуватися при виконанні запитів до API сервера, або бути обробленим як анонімний користувач.
Стратегії автентифікації
Kubernetes використовує клієнтські сертифікати, токени на предʼявника (bearer tokens) або проксі для автентифікації (authenticating proxy) для автентифікації API запитів через втулки автентифікації. Під час виконання HTTP запитів до API сервера втулки намагаються асоціювати наступні атрибути із запитом:
Імʼя користувача: рядок, який ідентифікує кінцевого користувача. Загальноприйняті значення можуть бути kube-admin або jane@example.com.
UID: рядок, який ідентифікує кінцевого користувача та намагається бути більш стабільним і унікальним, ніж імʼя користувача.
Групи: набір рядків, кожен з яких вказує на членство користувача в певній логічній групі користувачів. Загальноприйняті значення можуть бути system:masters або devops-team.
Додаткові поля: елемент map рядків для отримання переліку рядків, що містить додаткову інформацію, яку авторизатори можуть вважати корисною.
Усі значення є непрозорими для системи автентифікації та мають значення лише при інтерпретації авторизатором.
Ви можете одночасно ввімкнути кілька методів автентифікації. Зазвичай вам слід використовувати принаймні два методи:
токени службових облікових записів
принаймні один інший метод для автентифікації користувачів.
Коли увімкнено кілька модулів автентифікаторів, перший модуль, який успішно автентифікує запит, перериває подальшу оцінку. API сервер не гарантує порядок виконання автентифікаторів.
Група system:authenticated включена до списку груп для всіх автентифікованих користувачів.
Інтеграції з іншими протоколами автентифікації (LDAP, SAML, Kerberos, альтернативні схеми x509 тощо) можуть бути здійснені за допомогою проксі автентифікації або вебхука автентифікації.
X509 клієнтські сертифікати
Автентифікація за допомогою клієнтських сертифікатів увімкнена шляхом передачі опції --client-ca-file=SOMEFILE до API сервера. Вказаний файл повинен містити один або більше центрів сертифікації для використання у валідації клієнтських сертифікатів, представлених API серверу. Якщо представлено клієнтський сертифікат і він підтверджений, загальне імʼя субʼєкта використовується як імʼя користувача для запиту. Починаючи з Kubernetes 1.4, клієнтські сертифікати також можуть вказувати на членство користувача в групах, використовуючи поля організації сертифіката. Щоб включити кілька членств у групах для користувача, включіть кілька полів організації в сертифікат.
Наприклад, використовуючи командний рядок openssl для генерації запиту на підпис сертифіката:
Це створить CSR для імені користувача "jbeda", який належить до двох груп, "app1" і "app2".
Дивіться Керування сертифікатами для отримання інформації про те, як створити клієнтський сертифікат.
Статичний файл токенів
API сервер читає токени на предʼявника (bearer tokens) з файлу при використанні опції --token-auth-file=SOMEFILE у командному рядку. Наразі токени діють безстроково, і список токенів не можна змінити без перезавантаження API сервера.
Файл токенів є csv-файлом з мінімум 3 стовпцями: токен, імʼя користувача, uid користувача, а також необовʼязкові імена груп.
Примітка:
Якщо у вас є більше однієї групи, стовпець має бути взятий у подвійні лапки, наприклад:
token,user,uid,"group1,group2,group3"
Використання токена на предʼявника у запиті
При використанні автентифікації за допомогою токенів з HTTP клієнта, API сервер очікує заголовок Authorization зі значенням Bearer <token>. Маркер має бути послідовністю символів, яку можна помістити в значення HTTP заголовка, використовуючи лише можливості кодування та цитування HTTP. Наприклад, якщо токен — 31ada4fd-adec-460c-809a-9e56ceb75269, тоді він буде виглядати у заголовку HTTP, як показано нижче.
Для спрощення початкового налаштування нових кластерів, Kubernetes включає тип токена на предʼявника (bearer token), який керується динамічно, так званий Bootstrap Token. Ці токени зберігаються як Secrets у просторі імен kube-system, де ними можна динамічно керувати та створювати. Менеджер контролерів містить контролер TokenCleaner, який видаляє bootstrap токени в міру їх завершення.
Токени мають форму [a-z0-9]{6}.[a-z0-9]{16}. Перший компонент є ID токена, а другий компонент є Secret токена. Ви вказуєте токен у HTTP заголовку наступним чином:
Authorization: Bearer 781292.db7bc3a58fc5f07e
Ви повинні увімкнути Bootstrap Token Authenticator з прапорцем --enable-bootstrap-token-auth на API сервері. Ви повинні увімкнути контролер TokenCleaner за допомогою прапорця --controllers у Controller Manager. Це робиться за допомогою чогось типу --controllers=*,tokencleaner. kubeadm зробить це за вас, якщо ви використовуєте його для початкового налаштування кластера.
Автентифікатор автентифікує як system:bootstrap:<Token ID>. Він включений у групу system:bootstrappers. Імена користувачів та групи навмисно обмежені, щоб перешкоджати користувачам використовувати ці токени після початкового налаштування. Імена користувачів та групи можна використовувати (і використовуються kubeadm) для створення відповідних політик авторизації для підтримки початкового налаштування кластера.
Детальнішу інформацію про автентифікатор Bootstrap Token та контролери, а також про керування цими токенами за допомогою kubeadm, дивіться у Bootstrap Tokens.
Токени службових облікових записів
Службовий обліковий запис є автоматично увімкненим автентифікатором, який використовує підписані токени на предʼявника (bearer tokens) для перевірки запитів. Втулок приймає два необовʼязкові прапорці:
--service-account-key-file Файл, що містить PEM-кодовані x509 RSA або ECDSA приватні або публічні ключі, що використовуються для перевірки токенів службових облікових записів. Вказаний файл може містити кілька ключів, і прапорець може бути вказаний кілька разів з різними файлами. Якщо не вказано, використовується --tls-private-key-file.
--service-account-lookup Якщо увімкнено, токени, які видаляються з API, будуть відкликані.
Службові облікові записи зазвичай створюються автоматично API сервером та асоціюються з Podʼами, які працюють у кластері через ServiceAccountКонтролер допуску. Токени на предʼявника (bearer tokens) монтуються в Podʼи у відомих місцях, що дозволяє процесам всередині кластера взаємодіяти з API сервером. Облікові записи можуть бути явно асоційовані з Podʼами, використовуючи поле serviceAccountName у PodSpec.
Примітка:
serviceAccountName зазвичай опускається, оскільки це робиться автоматично.
apiVersion:apps/v1# ця apiVersion актуальна станом з Kubernetes 1.9kind:Deploymentmetadata:name:nginx-deploymentnamespace:defaultspec:replicas:3template:metadata:# ...spec:serviceAccountName:bob-the-botcontainers:- name:nginximage:nginx:1.14.2
Токени на предʼявника службових облікових записів (bearer tokens) є цілком дійсними для використання за межами кластера і можуть бути використані для створення ідентичностей для тривалих завдань, які бажають взаємодіяти з API Kubernetes. Щоб вручну створити службовий обліковий запис, використовуйте команду kubectl create serviceaccount (NAME). Це створює службовий обліковий запис у поточному просторі імен.
kubectl create serviceaccount jenkins
serviceaccount/jenkins created
Створіть асоційований токен:
kubectl create token jenkins
eyJhbGciOiJSUzI1NiIsImtp...
Створений токен є підписаним JSON Web Token (JWT).
Підписаний JWT може бути використаний як токен на предʼявника (bearer token) для автентифікації як вказаний службовий обліковий запис. Дивіться вище для інформації про те, як токен включається у запит. Зазвичай ці токени монтуються в Podʼи для доступу до API сервера всередині кластера, але можуть бути використані й ззовні кластера.
Службові облікові записи автентифікуються з імʼям користувача system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT), і належать групам system:serviceaccounts та system:serviceaccounts:(NAMESPACE).
Попередження:
Оскільки токени службових облікових записів також можуть зберігатися в обʼєктах Secret API, будь-який користувач з правами на запис до Secrets може запитати токен, і будь-який користувач з правами на читання до тих Secrets може автентифікуватися як службовий обліковий запис. Будьте обережні при наданні дозволів на службові облікові записи та можливості читання або запису для Secrets.
Токени OpenID Connect
OpenID Connect — це варіант OAuth2, підтримуваний деякими провайдерами OAuth2, зокрема Microsoft Entra ID, Salesforce та Google. Головне розширення протоколу OAuth2 полягає в додатковому полі, яке повертається разом із токеном доступу, називається ID Token. Цей токен є JSON Web Token (JWT) з добре відомими полями, такими як електронна пошта користувача, підписаними сервером.
Для ідентифікації користувача автентифікатор використовує id_token (а не access_token) з відповіді токена OAuth2 як токен носія. Дивіться вище для того, як токен включається у запит.
Увійдіть до свого провайдера ідентичності.
Ваш провайдер ідентичності надасть вам access_token, id_token та refresh_token.
Використовуючи kubectl, використовуйте свій id_token із прапорцем --token або додайте його безпосередньо до вашого kubeconfig.
kubectl надсилає ваш id_token у заголовку Authorization до сервера API.
Сервер API перевіряє, чи є підпис JWT дійсним.
Перевіряє, чи не минув термін дії id_token.
Виконує перевірку вимог та/або користувача, якщо з AuthenticationConfiguration налаштовані вирази CEL.
Переконується, що користувач авторизований.
Після авторизації сервер API повертає відповідь kubectl.
kubectl надає зворотній звʼязок користувачу.
Оскільки всі дані, необхідні для верифікації вашої особи, містяться в id_token, Kubernetes не потрібно "дзвонити додому" до провайдера ідентичності. У моделі, де кожен запит є stateless, це забезпечує дуже масштабоване рішення для автентифікації. Це має кілька викликів:
Kubernetes не має "вебінтерфейсу" для ініціювання процесу автентифікації. Немає оглядача або інтерфейсу для збору облікових даних, тому вам потрібно спочатку автентифікуватися у свого провайдера ідентичності.
id_token не можна відкликати, він схожий на сертифікат, тому він повинен бути короткостроковим (лише кілька хвилин), що може бути дуже незручним, оскільки потрібно отримувати новий токен кожні кілька хвилин.
Для автентифікації в панелі управління Kubernetes, ви повинні використовувати команду kubectl proxy або зворотний проксі, який вставляє id_token.
Налаштування сервера API
Використання прапорців
Щоб увімкнути втулок, налаштуйте наступні прапорці на сервері API:
Параметр
Опис
Приклад
Обовʼязковий
--oidc-issuer-url
URL провайдера, який дозволяє серверу API знаходити публічні ключі підпису. Приймаються лише URL-адреси, що використовують схему https://. Це зазвичай URL виявлення провайдера, змінений на порожній шлях
Якщо URL виявлення OIDC провайдера https://accounts.provider.example/.well-known/openid-configuration, значення повинно бути https://accounts.provider.example
Так
--oidc-client-id
Ідентифікатор клієнта, для якого мають бути видані всі токени.
kubernetes
Так
--oidc-username-claim
JWT вимога для використання як імені користувача. Стандартно sub, яке очікується що має бути унікальним ідентифікатором кінцевого користувача. Адміністратори можуть вибрати інші вимоги, такі як email або name, залежно від свого провайдера. Однак, вимоги, відмінні від email, будуть мати префікс URL провайдера, щоб уникнути зіткнень назв з іншими втулками.
sub
Ні
--oidc-username-prefix
Префікс, доданий до вимог імені користувача, щоб уникнути зіткнень з наявними іменами (наприклад, користувачами system:). Наприклад, значення oidc: створить імена користувачів, такі як oidc:jane.doe. Якщо цей прапорець не вказано, і значення --oidc-username-claim відрізняється від email, стандартний префікс ( Issuer URL )#, де ( Issuer URL ) — це значення --oidc-issuer-url. Значення - можна використовувати для відключення всіх префіксів.
oidc:
Ні
--oidc-groups-claim
JWT вимога для використання як групи користувача. Якщо вимога присутня, вона повинна бути масивом рядків.
groups
Ні
--oidc-groups-prefix
Префікс, доданий до вимог груп, щоб уникнути зіткнень з наявними назвами (наприклад, групами system:). Наприклад, значення oidc: створить назви груп, такі як oidc:engineering та oidc:infra.
oidc:
Ні
--oidc-required-claim
Пара ключ=значення, яка описує обовʼязкову вимогу в ID Token. Якщо встановлено, вимога перевіряється на наявність в ID Token з відповідним значенням. Повторіть цей прапорець, щоб вказати кілька вимог.
claim=value
Ні
--oidc-ca-file
Шлях до сертифіката для ЦС, який підписав вебсертифікат вашого провайдера ідентичності. Стандартно використовується кореневий ЦС хосту.
/etc/kubernetes/ssl/kc-ca.pem
Ні
--oidc-signing-algs
Прийняті алгоритми підпису. Стандартно "RS256".
RS512
Ні
Налаштування автентифікації з файлу
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.30 [beta] (стандартно увімкнено: true)
JWT Автентифікатор є автентифікатором для автентифікації користувачів Kubernetes за допомогою токенів, що відповідають стандарту JWT. Автентифікатор спробує розібрати необроблений ID токен, перевірити, чи він підписаний налаштованим видавцем. Публічний ключ для перевірки підпису перевіряється на публічній точці доступу видавця за допомогою OIDC discovery.
Мінімальний допустимий JWT повинен містити наступні твердження:
{
"iss": "https://example.com", // має збігатися з issuer.url
"aud": ["my-app"], // принаймні один з елементів в issuer.audiences повинен збігатися з твердженням "aud" в наданих JWT.
"exp": 1234567890, // закінчення терміну дії токена у вигляді часу Unix (кількість секунд, що минули з 1 січня 1970 року UTC)
"<username-claim>": "user"// це твердження для імені користувача, налаштоване в claimMappings.username.claim або claimMappings.username.expression
}
Підхід з використанням конфігураційного файлу дозволяє налаштовувати декілька JWT автентифікаторів, кожен з унікальними issuer.url та issuer.discoveryURL. Конфігураційний файл навіть дозволяє використовувати CEL вирази для зіставлення тверджень на атрибути користувача, а також для перевірки тверджень та інформації про користувача. API сервер також автоматично перезавантажує автентифікатори при зміні конфігураційного файлу. Ви можете використовувати метрику apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds для моніторингу часу останнього перезавантаження конфігурації сервером API.
Необхідно вказати шлях до конфігураційного файлу автентифікації за допомогою прапорця --authentication-config на сервері API. Якщо ви хочете використовувати командні прапорці замість конфігураційного файлу, вони продовжать працювати як раніше. Щоб отримати нові можливості, такі як налаштування декількох автентифікаторів, встановлення декількох аудиторій для одного видавця, перейдіть на використання конфігураційного файлу.
Для Kubernetes версії v1.31, формат файлу структурованої конфігурації автентифікації є на рівні бета-версії, і механізм використання цієї конфігурації також є на рівні бета-версії. За умови, що ви не вимкнули спеціально функційну можливістьStructuredAuthenticationConfiguration для вашого кластера, ви можете увімкнути структуровану автентифікацію, вказавши аргумент командного рядка --authentication-config для kube-apiserver. Приклад файлу конфігурації структурованої автентифікації наведено нижче.
Примітка:
Якщо ви вкажете --authentication-config разом з будь-якими аргументами командного рядка --oidc-*, це є некоректною конфігурацією. У цій ситуації сервер API повідомить про помилку й одразу завершить роботу. Якщо ви хочете перейти на використання структурованої конфігурації автентифікації, вам потрібно видалити аргументи командного рядка --oidc-* і використовувати конфігураційний файл замість них.
---## УВАГА: це приклад конфігурації.# Не використовуйте це для вашого кластера!#apiVersion:apiserver.config.k8s.io/v1beta1kind:AuthenticationConfiguration# список автентифікаторів для автентифікації користувачів Kubernetes за допомогою токенів, що відповідають стандарту JWT.# максимальна кількість дозволених автентифікаторів – 64.jwt:- issuer:# URL має бути унікальним для всіх автентифікаторів.# URL не повинен конфліктувати з видавцем, налаштованим у --service-account-issuer.url:https://example.com# Те ж саме, що і --oidc-issuer-url.# discoveryURL, якщо вказано, замінює URL, що використовується для отримання інформації про виявлення,# замість використання "{url}/.well-known/openid-configuration".# Точно вказане значення використовується, тому "/.well-known/openid-configuration"# має бути включено у discoveryURL, якщо це потрібно.## Поле "issuer" у отриманій інформації про виявлення має збігатися з полем "issuer.url"# в AuthenticationConfiguration і буде використовуватися для перевірки твердження "iss" у наданих JWT.# Це для сценаріїв, коли точки доступу well-known та jwks розміщені в іншому# місці, ніж видавець (наприклад, локально в кластері).# discoveryURL має відрізнятися від URL, якщо вказано, і має бути унікальним для всіх автентифікаторів.discoveryURL:https://discovery.example.com/.well-known/openid-configuration# PEM-кодовані сертифікати CA, які використовуються для перевірки підключення при отриманні# інформації про виявлення. Якщо не вказано, буде використовуватися системний перевіряючий.# Те саме значення, що і вміст файлу, на який посилається прапорець --oidc-ca-file.certificateAuthority:<PEM-кодовані сертифікати CA> # audiences – це набір прийнятних аудиторій, для яких повинен бути виданий JWT.# Принаймні один з елементів повинен збігатися з твердженням "aud" у наданих JWT.audiences:- my-app# Те ж саме, що і --oidc-client-id.- my-other-app# це повинно бути встановлено на "MatchAny", коли вказано кілька аудиторій.audienceMatchPolicy:MatchAny# правила, що застосовуються для перевірки тверджень токена для автентифікації користувачів.claimValidationRules:# Те ж саме, що і --oidc-required-claim key=value.- claim:hdrequiredValue:example.com# Замість claim та requiredValue, ви можете використовувати expression для перевірки твердження.# expression – це вираз CEL, який оцінюється до булевого значення.# всі вирази повинні бути true для успішної перевірки.- expression:'claims.hd == "example.com"'# Повідомлення налаштовує повідомлення про помилку, яке відображається в логах сервера API, коли перевірка не вдається.message:твердження hd повинно бути встановлено у example.com- expression:'claims.exp - claims.nbf <= 86400'message:загальний час життя токена не повинен перевищувати 24 годиниclaimMappings:# username представляє опцію для атрибута імені користувача.# Це єдиний обовʼязковий атрибут.username:# Те ж саме, що і --oidc-username-claim. Взаємовиключно з username.expression.claim:"sub"# Те ж саме, що і --oidc-username-prefix. Взаємовиключно з username.expression.# якщо username.claim встановлено, username.prefix обовʼязково має бути встановлено.# Встановіть значення "" явно, якщо префікс не потрібен.prefix:""# Взаємовиключно з username.claim і username.prefix.# expression – це вираз CEL, який оцінюється як рядок.## 1. Якщо у виразі username.expression використовується 'claims.email', то 'claims.email_verified' має бути використано у# username.expression або extra[*].valueExpression або claimValidationRules[*].expression.# Приклад виразу правила валідації заявки, який автоматично збігається з валідацією# застосовується, коли username.claim має значення 'email' - 'claims.?email_verified.orValue(true)'.# 2. Якщо імʼя користувача, що оцінюється на основі виразу username.expression, є порожнім рядком, запит на автентифікацію# запит не буде виконано.expression:'claims.username + ":external-user"'# groups представляє опцію для атрибута групи.groups:# Те ж саме, що і --oidc-groups-claim. Взаємовиключно з groups.expression.claim:"sub"# Те ж саме, що і --oidc-groups-prefix. Взаємовиключно з groups.expression.# якщо groups.claim встановлено, groups.prefix обовʼязково має бути встановлено.# Встановіть значення "" явно, якщо префікс не потрібен.prefix:""# Взаємовиключно з groups.claim і groups.prefix.# expression – це вираз CEL, який оцінюється як рядок або список рядків.expression:'claims.roles.split(",")'# uid представляє опцію для атрибута унікального ідентифікатора.uid:# Взаємовиключно з uid.expression.claim:"sub"# Взаємовиключно з uid.claim.# expression – це вираз CEL, який оцінюється як рядок.expression:'claims.uid'# екстра атрибути для додавання до обʼєктв UserInfo. Ключі мають бути у вигляді шляху з префіксом домену та бути унікальними.extra:- key:"example.com/tenant"# valueExpression – це вираз CEL, який оцінюється як рядок або список рядків.valueExpression:'claims.tenant'# правила валідації, що застосовуються до фінального обʼєкта користувача.userValidationRules:# expression – це вираз CEL, який оцінюється до булевого значення.# всі вирази повинні бути true для успішної перевірки.- expression:"!user.username.startsWith('system:')"# message налаштовує повідомлення про помилку, яке відображається в логах сервера API, коли перевірка не вдається.message:'неможна використовувате це імʼя користувача, зарезервовано префіксом system:'- expression:"user.groups.all(group, !group.startsWith('system:'))"message:'неможна використовувате цю назву групи, зарезервовано префіксом system:'
Вираз правил валідації твердження (claim)
jwt.claimValidationRules[i].expression представляє вираз, який буде оцінений CEL. Вирази CEL мають доступ до вмісту корисного навантаження токена, організованого у змінну CEL claims.
claims - це карта імен тверджень (як рядків) до значень тверджень (будь-якого типу).
Вираз правила валідації користувача
jwt.userValidationRules[i].expression представляє вираз, який буде оцінений CEL. Вирази CEL мають доступ до вмісту userInfo, організованого у змінну CEL user. Зверніться до UserInfo API документації для отримання схеми user.
Вираз зіставлення твердження
jwt.claimMappings.username.expression, jwt.claimMappings.groups.expression, jwt.claimMappings.uid.expressionjwt.claimMappings.extra[i].valueExpression представляє вираз, який буде оцінений CEL. Вирази CEL мають доступ до вмісту корисного навантаження токена, організованого у змінну CEL claims. claims — зіствлення імен тверджень (як рядків) до значень тверджень (будь-якого типу).
apiVersion:apiserver.config.k8s.io/v1beta1kind:AuthenticationConfigurationjwt:- issuer:url:https://example.comaudiences:- my-appclaimValidationRules:- expression:'claims.hd == "example.com"'# маркер нижче не має цього твердження, тому перевірка не вдасться.message:the hd claim must be set to example.comclaimMappings:username:expression:'claims.username + ":external-user"'groups:expression:'claims.roles.split(",")'uid:expression:'claims.sub'extra:- key:'example.com/tenant'valueExpression:'claims.tenant'userValidationRules:- expression:"!user.username.startsWith('system:')"# tвибарз буде оцінений як true, тоож валідація пройде успішно.message: 'username cannot used reserved system:prefix'
Токен із зазначеною вище AuthenticationConfiguration не зможе автентифікуватись, оскільки твердження hd не має значення example.com. Сервер API поверне помилку 401 Unauthorized.
apiVersion:apiserver.config.k8s.io/v1beta1kind:AuthenticationConfigurationjwt:- issuer:url:https://example.comaudiences:- my-appclaimValidationRules:- expression:'claims.hd == "example.com"'message:the hd claim must be set to example.comclaimMappings:username:expression:'"system:" + claims.username'# це призведе до додавання префіксу "system:" до імені користувача і не пройде перевірку.groups:expression:'claims.roles.split(",")'uid:expression:'claims.sub'extra:- key:'example.com/tenant'valueExpression:'claims.tenant'userValidationRules:- expression:"!user.username.startsWith('system:')"# імʼя користувача буде system:foo, а вираз матиме значення false, тому перевірка не вдасться.message: 'username cannot used reserved system:prefix'
який не пройде перевірку користувача, оскільки ім’я користувача починається з system:. Сервер API поверне помилку 401 Unauthorized.
Обмеження
Розподілені твердження не працюють через вирази CEL.
Конфігурація селектора вихідного трафіку не підтримується для викликів до issuer.url та issuer.discoveryURL.
Kubernetes не надає провайдера ідентифікації OpenID Connect. Ви можете використовувати наявного публічного провайдера ідентифікації OpenID Connect (наприклад, Google або інші). Або ж ви можете запустити власного провайдера ідентифікації, такого як dex,
Keycloak, CloudFoundry UAA, або Tremolo Security's OpenUnison.
Для того, щоб провайдер ідентифікації працював з Kubernetes, він повинен:
Публічний ключ для перевірки підпису отримується з публічної точки доступу видавця за допомогою OIDC discovery. Якщо ви використовуєте файл конфігурації автентифікації, провайдер ідентифікації не обовʼязково має публічно відкривати точку доступу discovery. Ви можете розмістити точку доступу discovery в іншому місці, ніж видавець (наприклад, локально в кластері) і вказати issuer.discoveryURL у файлі конфігурації.
Працювати через TLS з не застарілими шифрами
Мати сертифікат, підписаний ЦС (навіть якщо ЦС не комерційний або самопідписаний)
Примітка щодо вимоги №3 вище, що потреби в сертифікаті, підписаного ЦС. Якщо ви розгортаєте власного провайдера ідентифікації (на відміну від одного з хмарних провайдерів, таких як Google або Microsoft), ви ПОВИІННІ мати сертифікат вебсервера провайдера ідентифікації, підписаний сертифікатом з прапорцем CA, встановленим на TRUE, навіть якщо він самопідписаний. Це повʼязано з тим, що реалізація клієнта TLS в GoLang дуже сувора до стандартів перевірки сертифікатів. Якщо у вас немає під рукою ЦС, ви можете використовувати скрипт gencert від команди Dex для створення простого ЦС і пари підписаного сертифіката та ключа. Або ви можете використовувати цей подібний скрипт, який генерує сертифікати SHA256 з довшим терміном дії та більшим розміром ключа.
Перший варіант — використання автентифікатора kubectl oidc, який встановлює id_token як токен на предʼявника для всіх запитів і оновлює токен після закінчення його терміну дії. Після того, як ви увійшли до свого провайдера, використовуйте kubectl, щоб додати ваші id_token, refresh_token, client_id та client_secret для налаштування втулка.
Провайдери, які не повертають id_token як частину відповіді на оновлення токена, не підтримуються цим втулком і повинні використовувати "Варіант 2" нижче.
kubectl config set-credentials USER_NAME \
--auth-provider=oidc \
--auth-provider-arg=idp-issuer-url=( issuer url )\
--auth-provider-arg=client-id=( your client id )\
--auth-provider-arg=client-secret=( your client secret )\
--auth-provider-arg=refresh-token=( your refresh token )\
--auth-provider-arg=idp-certificate-authority=( path to your ca certificate )\
--auth-provider-arg=id-token=( your id_token )
Як приклад, запустіть наведену нижче команду після автентифікації у постачальника ідентифікаційної інформації:
Після закінчення терміну дії вашого id_tokenkubectl спробує оновити ваш id_token за допомогою ваших refresh_token і client_secret, зберігаючи нові значення для refresh_token і id_token у вашому .kube/config.
Варіант 2 — Використання опції --token
Команда kubectl дозволяє передати токен за допомогою параметра --token. Скопіюйте та вставте id_token у цей параметр:
kubectl --token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL21sYi50cmVtb2xvLmxhbjo4MDQzL2F1dGgvaWRwL29pZGMiLCJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNDc0NTk2NjY5LCJqdGkiOiI2RDUzNXoxUEpFNjJOR3QxaWVyYm9RIiwiaWF0IjoxNDc0NTk2MzY5LCJuYmYiOjE0NzQ1OTYyNDksInN1YiI6Im13aW5kdSIsInVzZXJfcm9sZSI6WyJ1c2VycyIsIm5ldy1uYW1lc3BhY2Utdmlld2VyIl0sImVtYWlsIjoibXdpbmR1QG5vbW9yZWplZGkuY29tIn0.f2As579n9VNoaKzoF-dOQGmXkFKf1FMyNV0-va_B63jn-_n9LGSCca_6IVMP8pO-Zb4KvRqGyTP0r3HkHxYy5c81AnIh8ijarruczl-TK_yF5akjSTHFZD-0gRzlevBDiH8Q79NAr-ky0P4iIXS8lY9Vnjch5MF74Zx0c3alKJHJUnnpjIACByfF2SCaYzbWFMUNat-K1PaUk5-ujMBG7yYnr95xD-63n8CO8teGUAAEMx6zRjzfhnhbzX-ajwZLGwGUBT4WqjMs70-6a7_8gZmLZb2az1cZynkFRj2BaCkVT3A2RrjeEwZEtGXlMqKJ1_I2ulrOVsYx01_yD35-rw get nodes
Автентифікація за допомогою вебхука
Автентифікація за допомогою вебхука — це механізм перевірки маркерів носіїв.
--authentication-token-webhook-config-file — файл конфігурації, який описує, як отримати доступ до віддаленого сервісу вебхука.
--authentication-token-webhook-cache-ttl — як довго кешувати рішення щодо автентифікації. Стандартно дві хвилини.
--authentication-token-webhook-version визначає, чи використовувати authentication.k8s.io/v1beta1 або authentication.k8s.io/v1
обʼєкти TokenReview для надсилання/отримання інформації від вебхука. Стандартно v1beta1.
Файл конфігурації використовує формат файлу kubeconfig. У файлі clusters посилається на віддалений сервіс, а
users посилається на вебхук API-сервера. Приклад:
# Версія API KubernetesapiVersion:v1# Тип обʼєкта APIkind:Config# clusters посилається на віддалений сервіс.clusters:- name:name-of-remote-authn-servicecluster:certificate-authority:/path/to/ca.pem # ЦС для перевірки віддаленого сервісу.server:https://authn.example.com/authenticate# URL віддаленого сервісу для запиту. 'https' рекомендовано для промислового застосування.# users посилається на конфігурацію вебхука API-сервера.users:- name:name-of-api-serveruser:client-certificate:/path/to/cert.pem# сертифікат для використання втулком вебхукаclient-key:/path/to/key.pem # ключ, що відповідає сертифікату# файли kubeconfig потребують контексту. Надати один для API-сервера.current-context:webhookcontexts:- context:cluster:name-of-remote-authn-serviceuser:name-of-api-servername:webhook
Коли клієнт намагається автентифікуватись на API-сервері за допомогою токена на предʼявника, як розглядалось вище, вебхук автентифікації надсилає POST-запит з JSON-серіалізованим обʼєктом TokenReview, що містить токен для віддаленого сервісу.
Зверніть увагу, що обʼєкти API вебхука підпадають під ті ж правила сумісності версій, що й інші обʼєкти API Kubernetes. Виконавці повинні перевірити поле apiVersion запиту, щоб забезпечити правильну десеріалізацію, і повинні відповідати обʼєктом TokenReview тієї ж версії, що й запит.
API-сервер Kubernetes типово надсилає запити authentication.k8s.io/v1beta1 для зворотної сумісності. Щоб отримувати запити authentication.k8s.io/v1, API-сервер повинен бути запущений з параметром --authentication-token-webhook-version=v1.
{"apiVersion": "authentication.k8s.io/v1","kind": "TokenReview","spec": {# Непрозорий токен на прежʼявника носія, надісланий на API-сервер"token": "014fbff9a07c...",# Необовʼязковий список ідентифікаторів аудиторії для сервера, якому був представлений токен.# Автентифікатори токенів, що враховують аудиторію (наприклад, OIDC автентифікатори токенів)# повинні перевірити, що токен був призначений для принаймні однієї з аудиторій у цьому списку,# і повернути перетин цього списку та дійсних аудиторій для токена в статусі відповіді.# Це гарантує, що токен дійсний для автентифікації на сервері, якому він був представлений.# Якщо аудиторії не надані, токен повинен бути перевірений для автентифікації на API-сервері Kubernetes."audiences": ["https://myserver.example.com","https://myserver.internal.example.com"]}}
{"apiVersion": "authentication.k8s.io/v1beta1","kind": "TokenReview","spec": {# Непрозорий токен на предʼявника, надісланий на API-сервер"token": "014fbff9a07c...",# Необовʼязковий список ідентифікаторів аудиторії для сервера, якому був представлений токен.# Автентифікатори токенів, що враховують аудиторію (наприклад, OIDC автентифікатори токенів)# повинні перевірити, що токен був призначений для принаймні однієї з аудиторій у цьому списку,# і повернути перетин цього списку та дійсних аудиторій для токена в статусі відповіді.# Це гарантує, що токен дійсний для автентифікації на сервері, якому він був представлений.# Якщо аудиторії не надані, токен повинен бути перевірений для автентифікації на API-сервері Kubernetes."audiences": ["https://myserver.example.com","https://myserver.internal.example.com"]}}
Віддалений сервіс повинен заповнити поле status запиту, щоб вказати на успішність входу. Поле spec тіла відповіді ігнорується та може бути опущене. Віддалений сервіс повинен повернути відповідь, використовуючи ту ж версію API TokenReview, яку він отримав. Успішна перевірка маркера носія буде виглядати так:
{"apiVersion": "authentication.k8s.io/v1","kind": "TokenReview","status": {"authenticated": true,"user": {# Обовʼязково"username": "janedoe@example.com",# Необовʼязково"uid": "42",# Необовʼязкові членства у групах"groups": ["developers","qa"],# Необовʼязкова додаткова інформація, надана автентифікатором.# Це не повинно містити конфіденційних даних, оскільки це може бути записано в логах# або обʼєктах API та доступно для вебхуків допуску."extra": {"extrafield1": ["extravalue1","extravalue2"]}},# Необовʼязковий список, який можуть повернути автентифікатори токенів, що враховують аудиторію,# містить аудиторії зі списку `spec.audiences`, для яких токен був дійсним.# Якщо це опущено, токен вважається дійсним для автентифікації на API-сервері Kubernetes."audiences": ["https://myserver.example.com"]}}
{"apiVersion": "authentication.k8s.io/v1beta1","kind": "TokenReview","status": {"authenticated": true,"user": {# Обовʼязково"username": "janedoe@example.com",# Необовʼязково"uid": "42",# Необовʼязкові членства у групах"groups": ["developers","qa"],# Необовʼязкова додаткова інформація, надана автентифікатором.# Це не повинно містити конфіденційних даних, оскільки це може бути записано в логах# або обʼєктах API та доступно для вебхуків допуску."extra": {"extrafield1": ["extravalue1","extravalue2"]}},# Необовʼязковий список, який можуть повернути автентифікатори токенів, що враховують аудиторію,# містить аудиторії зі списку `spec.audiences`, для яких токен був дійсним.# Якщо це опущено, токен вважається дійсним для автентифікації на API-сервері Kubernetes."audiences": ["https://myserver.example.com"]}}
{"apiVersion": "authentication.k8s.io/v1","kind": "TokenReview","status": {"authenticated": false,# Необовʼязково включати деталі, чому автентифікація не вдалася.# Якщо помилка не вказана, API поверне загальне повідомлення Unauthorized.# Поле error ігнорується, коли authenticated=true."error": "Credentials are expired"}}
{"apiVersion": "authentication.k8s.io/v1beta1","kind": "TokenReview","status": {"authenticated": false,# Необовʼязково включати деталі, чому автентифікація не вдалася.# Якщо помилка не вказана, API поверне загальне повідомлення Unauthorized.# Поле error ігнорується, коли authenticated=true."error": "Credentials are expired"}}
Проксі автентифікації
API-сервер може бути налаштований для ідентифікації користувачів на основі значень заголовків запиту, таких як X-Remote-User. Цей механізм призначений для використання в комбінації з проксі-сервером автентифікації, який встановлює значення заголовка запиту.
--requestheader-username-headers Обовʼязково, нечутливий до регістру. Імена заголовків для перевірки, у порядку, для ідентифікації користувача. Перший заголовок, який містить значення, використовується як імʼя користувача.
--requestheader-group-headers Версія 1.6+. Необовʼязково, нечутливий до регістру. Пропонується використовувати "X-Remote-Group". Імена заголовків для перевірки, у порядку, для визначення груп користувача. Усі значення в усіх зазначених заголовках використовуються як імена груп.
--requestheader-extra-headers-prefix Версія 1.6+. Необовʼязково, нечутливий до регістру. Пропонується використовувати "X-Remote-Extra-". Префікси заголовків для перевірки додаткової інформації про користувача (зазвичай використовується налаштованим втулком авторизації). У всіх заголовків, які починаються з будь-якого з зазначених префіксів, префікси вилучаються. Решта імені заголовка перетворюється на нижній регістр і декодується у відповідності з RFC 3986, і стає додатковим ключем, а значення заголовка — додатковим значенням.
Для запобігання підробці заголовків, проксі-сервер автентифікації повинен представити дійсний клієнтський сертифікат на API-сервер для перевірки за допомогою вказаного CA перед тим, як заголовки запиту будуть перевірені. ПОПЕРЕДЖЕННЯ: не використовуйте CA, який використовується в іншому контексті, якщо ви не розумієте ризики та механізми захисту використання CA.
--requestheader-client-ca-file Обовʼязково. Файл з сертифікатами у форматі PEM. Дійсний клієнтський сертифікат повинен бути представлений і перевірений за допомогою сертифікатів у вказаному файлі перед перевіркою заголовків запиту для імен користувачів.
--requestheader-allowed-names Необовʼязково. Список значень Common Name (CN). Якщо встановлено, дійсний клієнтський сертифікат з CN з вказаного списку повинен бути представлений перед перевіркою заголовків запиту для імен користувачів. Якщо порожній, дозволений будь-який CN.
Анонімні запити
Коли увімкнено, запити, які не відхиляються іншими налаштованими методами автентифікації, розглядаються як анонімні запити та отримують імʼя користувача system:anonymous і групу system:unauthenticated.
Наприклад, на сервері з налаштованою автентифікацією за допомогою токенів та увімкненим анонімним доступом, запит із недійсним токеном автентифікації отримає помилку 401 Unauthorized. Запит без токена автентифікації буде розглядатися як анонімний запит.
У версіях 1.5.1-1.5.x анонімний доступ типово вимкнено і може бути увімкнено шляхом додавання опції --anonymous-auth=true до API-сервера.
У версіях 1.6+ анонімний доступ типово увімкнено, якщо використовується режим авторизації, відмінний від AlwaysAllow, і може бути вимкнено шляхом додавання опції --anonymous-auth=false до API-сервера. Починаючи з версії 1.6, авторизатори ABAC і RBAC вимагають явної авторизації користувача system:anonymous або групи system:unauthenticated, тому застарілі правила політики, які надають доступ користувачеві * або групі *, не включають анонімних користувачів.
Налаштування анонімної автентифікації
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.31 [alpha] (стандартно увімкнено: false)
AuthenticationConfiguration можна використовувати для налаштування анонімного автентифікатора. Щоб увімкнути налаштування анонімної автентифікації через конфігураційний файл, потрібно увімкнути функціональну можливість AnonymousAuthConfigurableEndpoints. Коли ця функціональна можливість увімкнена, ви не можете встановити прапорець --anonymous-auth.
Основна перевага налаштування анонімного автентифікатора за допомогою конфігураційного файлу автентифікації полягає в тому, що, крім увімкнення та вимкнення анонімної автентифікації, ви також можете налаштувати, які точки доступу що підтримують анонімну автентифікацію.
Ось приклад конфігураційного файлу автентифікації:
---## УВАГА: це приклад конфігурації.# Не використовуйте його для вашого власного кластера!#apiVersion:apiserver.config.k8s.io/v1beta1kind:AuthenticationConfigurationanonymous:enabled:trueconditions:- path:/livez- path:/readyz- path:/healthz
У наведеній конфігурації лише точки доступу /livez, /readyz і /healthz доступні для анонімних запитів. Будь-які інші точки доступу будуть недоступні, навіть якщо це дозволено конфігурацією RBAC.
Імперсонізація користувачів
Користувач може діяти від імені іншого користувача через заголовки імперсонізації. Це дозволяє вручну перевизначити інформацію про користувача, який виконує запит. Наприклад, адміністратор може використовувати цю функцію для налагодження політики авторизації, тимчасово імперсонуючи іншого користувача та перевіряючи, чи запит відхилено.
Запити з імперсонізацією спочатку автентифікуються як запити від імені запитувача, потім переключаються на імперсоновану інформацію про користувача.
Користувач робить API-запит зі своїми обліковими даними і заголовками імперсонізації.
API-сервер автентифікує користувача.
API-сервер переконується, що автентифіковані користувачі мають права імперсонізації.
Інформація про користувача замінюється значеннями імперсонізації.
Запит оцінюється, авторизація діє на основі імперсонованої інформації про користувача.
Для здійснення запиту на імперсонізацію можна використовувати такі заголовки HTTP:
Impersonate-User: Імʼя користувача, від імені якого потрібно діяти.
Impersonate-Group: Імʼя групи, від імені якої потрібно діяти. Може надаватися кілька разів для встановлення кількох груп. Опціонально. Потрібен Impersonate-User.
Impersonate-Extra-( extra name ): Динамічний заголовок для звʼязування додаткових полів з користувачем. Опціонально. Потрібен Impersonate-User. Для збереження послідовності ( extra name ) повинно бути малими літерами, а будь-які символи, які не є допустимими в HTTP-заголовках, МАЮТЬ бути у форматі utf8 та процентно-кодовані.
Impersonate-Uid: Унікальний ідентифікатор, який представляє імперсонованого користувача. Опціонально. Потрібен Impersonate-User. Kubernetes не накладає жодних вимог щодо формату цього рядка.
Примітка:
До версії 1.11.3 (та 1.10.7, 1.9.11), ( extra name ) міг містити лише символи, які були допустимими в HTTP-заголовках.
Примітка:
Impersonate-Uid доступний лише у версіях 1.22.0 і вище.
Приклад заголовків імперсонізації при імперсонуванні користувача з групами:
Для використання kubectl встановіть прапорець --as для налаштування заголовка Impersonate-User, встановіть прапорець --as-group для налаштування заголовка Impersonate-Group.
kubectl drain mynode
Error from server (Forbidden): User "clark" cannot get nodes at the cluster scope. (get nodes mynode)
kubectl не може імперсонувати додаткові поля або UID.
Для імперсонізації користувача, групи, ідентифікатора користувача (UID) або додаткових полів, користувач, який виконує імперсонізацію, повинен мати можливість виконувати дію "impersonate" з типом атрибута, який імперсонується ("user", "group", "uid" і т.д.). Для кластерів, що використовують втулок авторизації RBAC, наступна роль ClusterRole охоплює правила, необхідні для налаштування заголовків імперсонізації користувачів і груп:
Для імперсонізації, додаткові поля та імперсоновані UID належать до групи apiGroup "authentication.k8s.io". Додаткові поля оцінюються як субресурси ресурсу "userextras". Щоб дозволити користувачеві використовувати заголовки імперсонізації для додаткового поля "scopes" та для UID, користувачеві слід надати таку роль:
apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:name:scopes-and-uid-impersonatorrules:# Може встановлювати заголовок "Impersonate-Extra-scopes" та заголовок "Impersonate-Uid".- apiGroups:["authentication.k8s.io"]resources:["userextras/scopes","uids"]verbs:["impersonate"]
Значення заголовків імперсонізації також можна обмежити, обмеживши набір resourceNames, які ресурс може приймати.
apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:name:limited-impersonatorrules:# Може імперсонувати користувача "jane.doe@example.com"- apiGroups:[""]resources:["users"]verbs:["impersonate"]resourceNames:["jane.doe@example.com"]# Може імперсонувати групи "developers" та "admins"- apiGroups:[""]resources:["groups"]verbs:["impersonate"]resourceNames:["developers","admins"]# Може імперсонувати додаткове поле "scopes" зі значеннями "view" і "development"- apiGroups:["authentication.k8s.io"]resources:["userextras/scopes"]verbs:["impersonate"]resourceNames:["view","development"]# Може імперсонувати UID "06f6ce97-e2c5-4ab8-7ba5-7654dd08d52b"- apiGroups:["authentication.k8s.io"]resources:["uids"]verbs:["impersonate"]resourceNames:["06f6ce97-e2c5-4ab8-7ba5-7654dd08d52b"]
Примітка:
Імперсонізація користувача або групи дозволяє вам виконувати будь-які дії, якби ви були цим користувачем або групою; з цієї причини імперсонізація не є обмеженою областю.
Якщо ви хочете дозволити імперсонізацію за допомогою Kubernetes RBAC, це вимагає використання ClusterRole та ClusterRoleBinding, а не Role та RoleBinding.
Втулки облікових даних client-go
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.22 [stable]
k8s.io/client-go та інструменти, які використовують його, такі як kubectl та kubelet, можуть виконувати зовнішню команду для отримання облікових даних користувача.
Ця функція призначена для клієнтських інтеграцій з протоколами автентифікації, які не підтримуються на рівні k8s.io/client-go (LDAP, Kerberos, OAuth2, SAML та ін.). Вутулок реалізує логіку, специфічну для протоколу, а потім повертає непрозорі облікові дані для використання. Майже всі випадки використання втулків автентифікації потребують наявності компоненту на стороні сервера з підтримкою автентифікації токенів webhook, щоб інтерпретувати формат облікових даних, який генерується клієнтським втулком.
Примітка:
У попередніх версіях kubectl вбудовано підтримувалися автентифікація в AKS та GKE, але це більше не актуально.
Приклад використання
У гіпотетичному сценарії використання організація запускає зовнішню службу, яка обмінює облікові дані LDAP на підписані токени, специфічні для користувача. Служба також може відповідати на запити автентифікатора токенів webhook, щоб перевірити токени. Користувачам буде потрібно встановити втулок автентифікації на своїй робочій станції.
Для автентифікації в API:
Користувач видає команду kubectl.
Вутулок облікових даних запитує користувача облікові дані LDAP, обмінює облікові дані зовнішньою службою на токен.
Вутулок облікових даних повертає токен client-go, який використовує його як токен власника на сервері API.
apiVersion:v1kind:Configusers:- name:my-useruser:exec:# Команда для виконання. Обовʼязково.command:"example-client-go-exec-plugin"# Версія API, яку слід використовувати при декодуванні ресурсу ExecCredentials. Обовʼязково.## Версія API, що повертається втулком, ПОВИННА відповідати версії, вказаній тут.## Щоб інтегруватися з інструментами, які підтримують кілька версій (наприклад, client.authentication.k8s.io/v1beta1),# встановіть змінну середовища, передайте аргумент інструменту, що вказує, яку версію очікує втулка виконання,# або прочитайте версію з обʼєкта ExecCredential у змінній середовища KUBERNETES_EXEC_INFO.apiVersion:"client.authentication.k8s.io/v1"# Змінні середовища, що встановлюються під час виконання втулку. Необовʼязково.env:- name:"FOO"value:"bar"# Аргументи, які передаються під час виконання втулку. Необовʼязково.args:- "arg1"- "arg2"# Текст, який показуєтсья користувачу, коли виконуваний файл не знайдено. Необовʼязково.installHint:| example-client-go-exec-plugin потрібно для автентифікації
в поточному кластері. Його можна встановити:
На macOS: brew install example-client-go-exec-plugin
На Ubuntu: apt-get install example-client-go-exec-plugin
На Fedora: dnf install example-client-go-exec-plugin
...# Чи надавати інформацію про кластер, яка може містити# дуже великі дані сертифікату CA, цьому втулка виконання як частину KUBERNETES_EXEC_INFO# змінної середовища.provideClusterInfo:true# Угода між втулком виконання та стандартним введенням/виведенням. Якщо# угода не може бути виконана, цей втулок виконання не буде запущено, та буде# повернено помилку. Допустимі значення: "Never" (цей втулок виконання ніколи не використовує стандартний ввід),# "IfAvailable" (цей втулок виконання хоче використовувати стандартний ввід, якщо він доступний),# або "Always" (цей втулок виконання вимагає стандартний ввід для роботи). Обовʼязково.interactiveMode:Neverclusters:- name:my-clustercluster:server:"https://172.17.4.100:6443"certificate-authority:"/etc/kubernetes/ca.pem"extensions:- name:client.authentication.k8s.io/exec# зарезервоване імʼя розширення для кожної конфігурації виконання кластераextension:arbitrary:configthis:може бути надано через змінну середовища KUBERNETES_EXEC_INFO при встановленні provideClusterInfoyou:["можете","покласти","будь-що","тут"]contexts:- name:my-clustercontext:cluster:my-clusteruser:my-usercurrent-context:my-cluster
apiVersion:v1kind:Configusers:- name:my-useruser:exec:# Команда для виконання. Обовʼязково.command:"example-client-go-exec-plugin"# Версія API, яку слід використовувати при декодуванні ресурсу ExecCredentials. Обовʼязково.## Версія API, повернута втулком, ПОВИННА відповідати версії, вказаній тут.## Щоб інтегруватися з інструментами, які підтримують кілька версій (наприклад, client.authentication.k8s.io/v1),# встановіть змінну середовища, перед ```yamlapiVersion:"client.authentication.k8s.io/v1beta1"# Змінні середовища, що встановлюються під час виконання втулку. Необовʼязково.env:- name:"FOO"value:"bar"# Аргументи, які передаються під час виконання втулку. Необовʼязково.args:- "arg1"- "arg2"# Текст, який показується користувачу, коли виконуваний файл не знайдено. Необовʼязково.installHint:| example-client-go-exec-plugin потрібно для автентифікації
в поточному кластері. Його можна встановити:
На macOS: brew install example-client-go-exec-plugin
На Ubuntu: apt-get install example-client-go-exec-plugin
На Fedora: dnf install example-client-go-exec-plugin
...# Чи надавати інформацію про кластер, яка може містити# дуже великі дані сертифікату CA, цьому втулку виконання як частину KUBERNETES_EXEC_INFO# змінної середовища.provideClusterInfo:true# Угода між втулком виконання та стандартним введенням/виведенням. Якщо# угода не може бути виконана, цей втулок виконання не буде запущено, а буде# повернено помилку. Допустимі значення: "Never" (цей втулок виконання ніколи не використовує стандартний ввід),# "IfAvailable" (цей втулок виконання хоче використовувати стандартний ввід, якщо він доступний),# або "Always" (цей втулок виконання вимагає стандартний ввід для роботи). Необовʼязково.# За замовчуванням - "IfAvailable".interactiveMode:Neverclusters:- name:my-clustercluster:server:"https://172.17.4.100:6443"certificate-authority:"/etc/kubernetes/ca.pem"extensions:- name:client.authentication.k8s.io/exec# зарезервоване імʼя розширення для кожної конфігурації виконання кластераextension:arbitrary:configthis:може бути надано через змінну середовища KUBERNETES_EXEC_INFO при встановленні provideClusterInfoyou:["можете","покласти","будь-що","тут"]contexts:- name:my-clustercontext:cluster:my-clusteruser:my-usercurrent-context:my-cluster
Відносні шляхи до команд інтерпретуються відносно теки файлу конфігурації. Якщо KUBECONFIG встановлено на /home/jane/kubeconfig, а команда виконання — ./bin/example-client-go-exec-plugin, то виконується бінарний файл /home/jane/bin/example-client-go-exec-plugin.
- name:my-useruser:exec:# Шлях відносно теки kubeconfigcommand:"./bin/example-client-go-exec-plugin"apiVersion:"client.authentication.k8s.io/v1"interactiveMode:Never
Формати вводу та виводу
Виконана команда виводить обʼєкт ExecCredential у stdout. k8s.io/client-go автентифікується в Kubernetes API, використовуючи отримані облікові дані в status. Виконана команда отримує обʼєкт ExecCredential на вхід через змінну середовища KUBERNETES_EXEC_INFO. Цей вхід містить корисну інформацію, таку як очікувана версія API поверненого обʼєкта ExecCredential та чи може втулок використовувати stdin для взаємодії з користувачем.
Під час запуску з інтерактивної сесії (тобто термінал), stdin може бути наданий прямо втулку. Втулки повинні використовувати поле spec.interactive вхідного обʼєкта ExecCredential зі змінної середовища KUBERNETES_EXEC_INFO для визначення, чи був наданий stdin. Вимоги втулка до stdin (тобто чи stdin є необовʼязковим, строго обовʼязковим або ніколи не використовується для успішного запуску втулка) вказується за допомогою поля user.exec.interactiveMode у kubeconfig (див. таблицю нижче для дійсних значень). Поле user.exec.interactiveMode є необовʼязковим у client.authentication.k8s.io/v1beta1 і обовʼязковим у client.authentication.k8s.io/v1.
Значення interactiveMode
Значення interactiveMode
Значення
Never
Цей втулок виконання ніколи не потребує використання стандартного вводу, і тому втулок виконання буде запущений незалежно від того, чи доступний стандартний ввід для введення користувача.
IfAvailable
Цей втулок виконання хоче використовувати стандартний ввід, якщо він доступний, але може працювати, якщо стандартний ввід недоступний. Тому втулок виконання буде запущений незалежно від наявності введення з стандартного вводу. Якщо стандартний ввід доступний для введення користувача, він буде наданий цьому втулку виконання.
Always
Цей втулок виконання потребує стандартний ввід для роботи, і тому втулок виконання буде запущений лише тоді, коли стандартний ввід доступний для введення користувача. Якщо стандартний ввід недоступний для введення користувача, втулок виконання не буде запущений, і виконавець втулку поверне помилку.
Для використання облікових даних токена власника, втулок повертає токен у статусі ExecCredential
Альтративно, можна повернути PEM-кодований сертифікат клієнта та ключ для використання TLS-автентифікації клієнта. Якщо втулок повертає різний сертифікат та ключ при наступному виклику, k8s.io/client-go закриє існуючі зʼєднання з сервером, щоб змусити новий TLS-обмін.
Якщо вказано, що clientKeyData та clientCertificateData повинні бути присутніми.
clientCertificateData може містити додаткові проміжні сертифікати для відправки на сервер.
Додатково відповідь може включати термін дії облікового запису, форматований як
RFC 3339 мітка часу.
Наявність або відсутність терміну дії має такий вплив:
Якщо термін дії включений, токен власника та TLS-облікові дані кешуються до
моменту закінчення строку дії, або якщо сервер відповідає з кодом стану HTTP 401,
або при завершенні процесу.
Якщо термін дії відсутній, токен власника та TLS-облікові дані кешуються до
моменту, коли сервер відповідає з кодом стану HTTP 401 або до моменту завершення процесу.
Щоб дозволити втулку виконання отримувати інформацію, що специфічна для кластера, встановіть provideClusterInfo у поле user.exec в kubeconfig. Втулок потім отримає цю інформацію, специфічну для кластера, у змінній середовища KUBERNETES_EXEC_INFO. Інформацію з цієї змінної середовища можна використовувати для виконання логіки отримання облікових даних, специфічних для кластера. Наступний маніфест ExecCredential описує зразок інформації для кластера.
{
"apiVersion": "client.authentication.k8s.io/v1",
"kind": "ExecCredential",
"spec": {
"cluster": {
"server": "https://172.17.4.100:6443",
"certificate-authority-data": "LS0t...",
"config": {
"arbitrary": "config",
"this": "can be provided via the KUBERNETES_EXEC_INFO environment variable upon setting provideClusterInfo",
"you": ["can", "put", "anything here"]
},
"interactive": true }
}
{
"apiVersion": "client.authentication.k8s.io/v1beta1",
"kind": "ExecCredential",
"spec": {
"cluster": {
"server": "https://172.17.4.100:6443",
"certificate-authority-data": "LS0t...",
"config": {
"arbitrary": "config",
"this": "can be provided via the KUBERNETES_EXEC_INFO environment variable upon setting provideClusterInfo",
"you": ["can", "put", "anything", "here"]
}
},
"interactive": true }
}
Доступ API до інформації про автентифікацію для клієнта
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.28 [stable]
Якщо ваш кластер має включений API, ви можете використовувати API SelfSubjectReview, щоб дізнатися, як ваш кластер Kubernetes показує вашу інформацію про автентифікацію, щоб ідентифікувати вас як клієнта. Це працює незалежно від того, чи автентифікуєтеся ви як користувач (зазвичай представляючи реальну особу), чи як обліковий запис ServiceAccount.
Обʼєкти SelfSubjectReview не мають полів, які конфігуруються. При отриманні запиту API-сервер Kubernetes заповнює статус атрибутами користувача та повертає його користувачеві.
Приклад запиту (тіло буде SelfSubjectReview):
POST /apis/authentication.k8s.io/v1/selfsubjectreviews
Для зручності доступний також запит kubectl auth whoami. Виконання цієї команди призведе до
наступного виводу (але різні атрибути користувача будуть показані):
Простий приклад виводу
ATTRIBUTE VALUE
Username jane.doe
Groups [system:authenticated]
Складний приклад, який включає додаткові атрибути
ATTRIBUTE VALUE
Username jane.doe
UID b79dbf30-0c6a-11ed-861d-0242ac120002
Groups [students teachers system:authenticated]
Extra: skills [reading learning]
Extra: subjects [math sports]
За допомогою прапорця виводу також можна надрукувати JSON- або YAML-представлення результату:
API-сервер Kubernetes заповнює userInfo після застосування всіх механізмів автентифікації,
включаючи імперсонізаацію. Якщо ви, або автентифікаційний проксі, робите SelfSubjectReview за допомогою імперсонізації, ви побачите деталі та властивості користувача, який був імперсонований.
Стандартно всі автентифіковані користувачі можуть створювати обʼєкти SelfSubjectReview, коли функція APISelfSubjectReview включена. Це дозволено за допомогою кластерної ролі system:basic-user.
Примітка:
Ви можете робити запити SelfSubjectReview тільки якщо:
включено функціоналAPISelfSubjectReview для вашого кластера (не потрібно для Kubernetes 1.31, але більш старі версії Kubernetes можуть не надавати цю функцію або за стандартно вимикати її)
(якщо ви запускаєте версію Kubernetes старішу за v1.28) API-сервер для вашого кластера має увімкнений API-групи authentication.k8s.io/v1alpha1 або authentication.k8s.io/v1beta1.
Bootstrap-токени — це простий токен на предʼявника, який призначений для використання під час створення нових кластерів або приєднання нових вузлів до наявного кластера. Він був створений для підтримки kubeadm, але може використовуватися в інших контекстах для користувачів, які бажають створювати кластери без kubeadm. Також він призначений для роботи, через політику RBAC, з kubelet TLS Bootstrapping.
Огляд Bootstrap-токенів
Bootstrap-токени визначені як певний тип secretʼів (bootstrap.kubernetes.io/token), що знаходяться в просторі імен kube-system. Ці secret читаються Bootstrap Authenticator з API Server. Протерміновані токени видаляються контролером TokenCleaner у Controller Manager. Токени також використовуються для створення підпису для конкретного ConfigMap, який використовується у процесі "виявлення" через контролер BootstrapSigner.
Формат токена
Bootstrap-токени мають форму abcdef.0123456789abcdef. Більш формально, вони повинні відповідати регулярному виразу [a-z0-9]{6}\.[a-z0-9]{16}.
Перша частина токена — це "ID токена" і вважається публічною інформацією. Вона використовується, коли потрібно посилатися на токен без розкриття секретної частини, яка використовується для автентифікації. Друга частина — це "Секрет токена" і нею треба ділитися тільки з довіреними сторонами.
Увімкнення автентифікації за допомогою Bootstrap-токенів
Автентифікатор Bootstrap Token можна увімкнути за допомогою наступного прапорця на API-сервері:
--enable-bootstrap-token-auth
Після увімкнення, токени для завантаження можуть використовуватися як облікові дані токена на предʼявника для автентифікації запитів до API-сервера.
Authorization: Bearer 07401b.f395accd246ae52d
Токени автентифікуються як імʼя користувача system:bootstrap:<token id> і є членами групи system:bootstrappers. Додаткові групи можуть бути вказані в секреті токена.
Протерміновані токени можуть бути автоматично видалені шляхом увімкнення контролера tokencleaner у Controller Manager.
--controllers=*,tokencleaner
Формат Secretʼу Bootstrap-токена
Кожен дійсний токен підтримується секретом у просторі імен kube-system. Повний документ проєктування можна знайти тут.
Ось як виглядає цей Secret.
apiVersion:v1kind:Secretmetadata:# Назва МАЄ бути у формі "bootstrap-token-<token id>"name:bootstrap-token-07401bnamespace:kube-system# Тип МАЄ бути 'bootstrap.kubernetes.io/token'type:bootstrap.kubernetes.io/tokenstringData:# Опис, зрозумілий людині. Необовʼязково.description:"Стандартний bootstrap-токен, згенерований 'kubeadm init'."# ID та секрет токена. Обовʼязково.token-id:07401btoken-secret:f395accd246ae52d# Термін дії. Необовʼязково.expiration:2017-03-10T03:22:11Z# Дозволені використання.usage-bootstrap-authentication:"true"usage-bootstrap-signing:"true"# Додаткові групи для автентифікації токена. Мають починатися з "system:bootstrappers:"auth-extra-groups:system:bootstrappers:worker,system:bootstrappers:ingress
Тип секрету має бути bootstrap.kubernetes.io/token, а назва має бути bootstrap-token-<token id>. Він також повинен знаходитися в просторі імен kube-system.
Члени usage-bootstrap-* вказують, для чого цей секрет призначений. Значення має бути встановлено в true, щоб увімкнути відповідне використання.
usage-bootstrap-authentication вказує, що токен може використовуватися для автентифікації до API-сервера як токен-носій.
usage-bootstrap-signing вказує, що токен може використовуватися для підпису ConfigMap cluster-info, як описано нижче.
Поле expiration контролює термін дії токена. Протерміновані токени відхиляються при спробі автентифікації та ігноруються під час підпису ConfigMap. Значення терміну дії кодується як абсолютний UTC-час за стандартом RFC3339. Увімкніть контролер tokencleaner, щоб автоматично видаляти протерміновані токени.
Управління токенами за допомогою kubeadm
Ви можете використовувати інструмент kubeadm для управління токенами на запущеному кластері. Деталі дивіться в документації kubeadm token.
Підпис ConfigMap
Окрім автентифікації, токени можуть використовуватися для підпису ConfigMap. Це використовується на ранніх етапах процесу завантаження кластера до того, як клієнт довіряє API-серверу. Підписаний ConfigMap може бути автентифікований спільним токеном.
Увімкніть підпис ConfigMap, увімкнувши контролер bootstrapsigner у Controller Manager.
--controllers=*,bootstrapsigner
ConfigMap, який підписується, це cluster-info у просторі імен kube-public. Типовий процес полягає в тому, що клієнт читає цей ConfigMap без автентифікації та ігноруючи помилки TLS. Потім він перевіряє коректність ConfigMap, переглядаючи підпис, вбудований у ConfigMap.
Елемент kubeconfig у ConfigMap є конфігураційним файлом, який містить лише інформацію про кластер. Ключовим моментом, що передається, є certificate-authority-data. Це може бути розширено в майбутньому.
Підпис є підписом JWS, що використовує "відокремлений" режим. Щоб перевірити підпис, користувач має закодувати вміст kubeconfig відповідно до правил JWS (закодовано base64, відкидаючи будь-які кінцеві =). Цей закодований вміст потім використовується для формування повного JWS шляхом вставки його між 2 крапками. Ви можете перевірити JWS, використовуючи схему HS256 (HMAC-SHA256) з повним токеном (наприклад, 07401b.f395accd246ae52d) як спільний секрет. Користувачі повинні перевірити, що використовується HS256.
Попередження:
Будь-яка сторона з токеном завантаження може створити дійсний підпис для цього токена. Коли використовується підпис ConfigMap, не рекомендується ділитися одним токеном з багатьма клієнтами, оскільки скомпрометований клієнт може потенційно провести атаку "людина посередині" на іншого клієнта, який покладається на підпис для завантаження довіри TLS.
Деталі механізмів авторизації Kubernetes і підтримувані режими авторизації.
Авторизація в Kubernetes відбувається після автентифікації. Зазвичай клієнт, що робить запит, має бути автентифікований (увійти в систему), перш ніж його запит може бути дозволений; однак, Kubernetes також дозволяє анонімні запити за деяких обставин.
Авторизація запитів до API в Kubernetes відбувається всередині API-сервера. API-сервер оцінює всі атрибути запиту щодо всіх політик, потенційно також звертаючись до зовнішніх сервісів, і потім дозволяє або відхиляє запит.
Усі частини запиту до API повинні бути дозволені деяким механізмом авторизації, щоб він міг продовжити виконання. Іншими словами: стандартно доступ заборонений.
Примітка:
Контроль доступу і політики, що залежать від конкретних полів конкретних видів обʼєктів, обробляються контролерами допуску.
Контроль допуску в Kubernetes відбувається після завершення авторизації (і, отже, тільки коли рішення про авторизацію було дозволити запит).
Коли налаштовано кілька модулів авторизації, кожен перевіряється по черзі. Якщо будь-який авторизатор схвалює або відхиляє запит, це рішення негайно повертається і жоден інший авторизатор не перевіряється. Якщо всі модулі не мають думки щодо запиту, то запит відхиляється. Загальний вердикт "відхилено" означає, що API-сервер відхиляє запит і відповідає зі статусом HTTP 403 (Forbidden).
Атрибути запиту, що використовуються для авторизації
Kubernetes розглядає тільки наступні атрибути запиту до API:
user — Рядок user, наданий під час автентифікації.
group — Список імен груп, до яких належить автентифікований користувач.
extra — Map довільних рядкових ключів з рядковими значеннями, надана шаром автентифікації.
API — Вказує, чи є запит запитом на ресурс API.
Request path — Шлях до різних нересурсних точок доступу, таких як /api або /healthz.
API request verb — Дієслова API, такі як get, list, create, update, patch, watch, delete і deletecollection, використовуються для запитів до ресурсів. Щоб визначити дієслово запиту для точки доступу API ресурсу, дивіться дієслова запитів та авторизація.
HTTP request verb — Методи HTTP в нижньому регістрі, такі як get, post, put і delete, використовуються для нересурсних запитів.
Resource — Ідентифікатор або імʼя ресурсу, до якого здійснюється доступ (тільки для запитів до ресурсів). Для запитів до ресурсів, що використовують дієслова get, update, patch і delete, ви повинні надати імʼя ресурсу.
Subresource — Субесурс, до якого здійснюється доступ (тільки для запитів до ресурсів).
Namespace — Простір імен обʼєкта, до якого здійснюється доступ (тільки для запитів до ресурсів у просторі імен).
API group — Група API, до якої здійснюється доступ (тільки для запитів до ресурсів). Порожній рядок позначає основнугрупу API.
Дієслова запиту та авторизація
Нересурсні запити
Запити до точок доступу, відмінних від /api/v1/... або /apis/<group>/<version>/..., вважаються нересурсними запитами та використовують метод HTTP як дієслово в нижньому регістрі. Наприклад, виконання запиту GET за допомогою HTTP до точок доступу, таких як /api або /healthz, буде використовувати get як дієслово.
Ресурсні запити
Щоб визначити дієслово запиту для точки доступу API ресурсу, Kubernetes показує використаний HTTP метод і розглядає, чи діє запит на індивідуальний ресурс чи на колекцію ресурсів:
HTTP метод
дієслово запиту
POST
create
GET, HEAD
get (для індивідуальних ресурсів), list (для колекцій, включаючи повний вміст обʼєктів), watch (для спостереження за індивідуальним ресурсом або колекцією ресурсів)
PUT
update
PATCH
patch
DELETE
delete (для індивідуальних ресурсів), deletecollection (для колекцій)
Увага:
Дієслова get, list та watch можуть повертати повні деталі ресурсу. В плані доступу до повернених даних вони є еквівалентними. Наприклад, list для secrets розкриє атрибути data будь-яких повернених ресурсів.
Іноді Kubernetes перевіряє авторизацію для додаткових дозволів, використовуючи спеціалізовані дієслова. Наприклад:
Дієслова bind та escalate для ресурсів roles та clusterroles у групі API rbac.authorization.k8s.io.
Контекст авторизації
Kubernetes очікує атрибути, які є загальними для запитів до REST API. Це означає, що авторизація в Kubernetes працює з наявними системами контролю доступу на рівні організації або
хмарного провайдера, які можуть обробляти інші API крім Kubernetes API.
Режими авторизації
API-сервер Kubernetes може авторизувати запит, використовуючи один з декількох режимів авторизації:
AlwaysAllow
Цей режим дозволяє всі запити, що несе ризики для безпеки. Використовуйте цей режим авторизації тільки якщо вам не потрібна авторизація для ваших запитів до API (наприклад, для тестування).
AlwaysDeny
Цей режим блокує всі запити. Використовуйте цей режим авторизації тільки для тестування.
Режим ABAC в Kubernetes визначає парадигму управління доступом, згідно з якою права доступу надаються користувачам за допомогою політик, які обʼєднують атрибути разом. Політики можуть використовувати будь-який тип атрибутів (атрибути користувача, атрибути ресурсу, обʼєкта, середовища тощо).
Kubernetes RBAC — це метод регулювання доступу до компʼютерних або мережевих ресурсів на основі ролей окремих користувачів в організації. У цьому контексті доступ — це можливість окремого користувача виконувати певне завдання, наприклад, переглядати, створювати або змінювати файл. В цьому режимі Kubernetes використовує групу API rbac.authorization.k8s.io для прийняття рішень щодо авторизації, що дозволяє вам динамічно налаштовувати політики дозволів через API Kubernetes.
Node
Спеціальний режим авторизації, який надає дозволи для kubeletʼів на основі запланованих до запуску Podʼів. Щоб дізнатися більше про режим авторизації вузла, див. Авторизація вузла.
Webhook
Kubernetes режим webhook для авторизації робить синхронний HTTP-виклик, блокуючи запит до тих пір, поки віддалений HTTP-сервіс не відповість на нього. Ви можете написати власне програмне забезпечення для обробки виклику або використовувати рішення з екосистеми.
Ви повинні вибрати один з двох підходів до конфігурації: задати обидва шляхи --authorization-config і налаштувати вебхук авторизації за допомогою аргументів командного рядка --authorization-mode та --authorization-webhook-* не допускається. Якщо ви спробуєте це зробити, API сервер повідомить про помилку під час запуску та одразу завершить роботу.
Конфігурація режиму авторизації через командний рядок
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.8 [stable]
Ви можете використовувати наступні режими:
--authorization-mode=ABAC (режим контролю доступу на основі атрибутів)
--authorization-mode=RBAC (режим контролю доступу на основі ролей)
Ви можете вибрати більше одного режиму авторизації; наприклад: --authorization-mode=Node,Webhook
Kubernetes перевіряє модулі авторизації на основі порядку, який ви вказуєте в командному рядку API сервера, тому раніше зазначений модуль має вищий пріоритет для дозволу або відмови в запиті.
Ви вказуєте шлях до конфігурації авторизації за допомогою аргументу командного рядка --authorization-config.
Якщо ви хочете використовувати параметри командного рядка замість конфігураційного файлу, це також є дійсним і підтримуваним підходом. Деякі можливості авторизації (наприклад: кілька вебхуків, політика відмови вебхука та правила попередньої фільтрації) доступні тільки при використанні конфігураційного файлу авторизації.
Приклад конфігурації
---## НЕ ВИКОРИСТОВУЙТЕ КОНФІГУРАЦІЮ ТАК, ЯК ВОНА Є. ЦЕ ПРИКЛАД.#apiVersion:apiserver.config.k8s.io/v1beta1kind:AuthorizationConfigurationauthorizers:* type:Webhook# Назва, що використовується для опису авторизатора# Це явно використовується в механізмі моніторингу для метрик# Примітка:# - Перевірка цього поля схожа на перевірку міток K8s на сьогодні.# Обовʼязково, немає стандартного значенняname:webhookwebhook:# Тривалість кешування відповідей 'authorized' від вебхука# авторизатора.# Те саме, що і встановлення прапорця `--authorization-webhook-cache-authorized-ttl`.# Стандартно: 5m0sauthorizedTTL:30s# Тривалість кешування відповідей 'unauthorized' від вебхука# авторизатора.# Те саме, що і встановлення прапорця `--authorization-webhook-cache-unauthorized-ttl`.# Стандартно: 30 сunauthorizedTTL:30s# Тайм-аут для запиту вебхука# Максимально допустимий: 30 с# Обовʼязково, немає стандартного значенняtimeout:3s# Версія API для SubjectAccessReview в authorization.k8s.io, яка# надсилається до вебхука та очікується від нього.# Те саме, що і встановлення прапорця `--authorization-webhook-version`.# Обовʼязково, немає стандартного значення# Допустимі значення: v1beta1, v1subjectAccessReviewVersion:v1# MatchConditionSubjectAccessReviewVersion визначає версію SubjectAccessReview# за якою оцінюються вирази CEL# Допустимі значення: v1# Обовʼязково, немає стандартного значенняmatchConditionSubjectAccessReviewVersion:v1# Керує рішенням авторизації, коли запит вебхука не вдалося# виконати або отримано некоректну відповідь або помилки під час оцінки# виразів matchConditions.# Допустимі значення:# - NoOpinion: продовжувати до наступних авторизаторів, щоб перевірити, чи дозволяє один з них запит# - Deny: відхиляти запит без консультації з наступними авторизаторами# Обовʼязково, немає стандартного значенняfailurePolicy:DenyconnectionInfo:# Керує тим, як вебхук повинен спілкуватися з сервером.# Допустимі значення:# - KubeConfigFile: використовуйте файл, вказаний у kubeConfigFile для пошуку сервера.# - InClusterConfig: використовуйте конфігурацію внутрішнього кластера для виклику API SubjectAccessReview,# що розміщується kube-apiserver. Цей режим не дозволяється для kube-apiserver.type:KubeConfigFile# Шлях до файлу KubeConfigFile для інформації про підключення# Обовʼязково, якщо connectionInfo.Type є KubeConfigFilekubeConfigFile:/kube-system-authz-webhook.yaml# matchConditions - це список умов, які повинні бути виконані для того, щоб запит було відправлено на цей# вебхук. Порожній список matchConditions підходить для всіх запитів.# Є максимально допустимі 64 умови відповідності.## Логіка точного порівняння така (в порядку):# 1. Якщо принаймні одна matchCondition оцінюється як FALSE, тоді вебхук пропускається.# 2. Якщо ВСІ matchConditions оцінюються як TRUE, тоді вебхук викликається.# 3. Якщо принаймні одна matchCondition оцінюється як помилка (але ні одна не є FALSE):# - Якщо failurePolicy=Deny, тоді вебхук відхиляє запит.# - Якщо failurePolicy=NoOpinion, тоді помилка ігнорується, а вебхук пропускається.matchConditions:# expression - це вираз CEL, який оцінюється для кожного запиту. Повертає булеве значення.# CEL вираз має доступ до вмісту SubjectAccessReview у версії v1.# Якщо версія у SubjectAccessReview в запиті змінної є v1beta1,# вміст буде конвертовано у v1 перед оцінкою виразу CEL.## Документація CEL: https://kubernetes.io/docs/reference/using-api/cel/## лише надсилати запити ресурсівв до вебхука* expression:has(request.resourceAttributes)# лише перехоплювати запити до kube-system* expression:request.resourceAttributes.namespace == 'kube-system'# не перехоплювати запити від облікових записів служб kube-system* expression:"!('system:serviceaccounts:kube-system' in request.user.groups)"* type:Nodename:node* type:RBACname:rbac* type:Webhookname:in-cluster-authorizerwebhook:authorizedTTL:5хвunauthorizedTTL:30сtimeout:3сsubjectAccessReviewVersion:v1failurePolicy:NoOpinionconnectionInfo:type:InClusterConfig
Під час налаштування ланцюжка авторизації за допомогою файлу конфігурації переконайтеся, що всі вузли панелі управління мають однаковий вміст файлу. Зверніть увагу на конфігурацію API сервера при оновленні / зниженні версії вашого кластера. Наприклад, якщо ви оновлюєтеся з Kubernetes 1.30 до Kubernetes 1.31, вам потрібно переконатися, що файл конфігурації має формат, який розуміє Kubernetes 1.31, перш ніж ви оновите кластер. Якщо ви знижуєте версію до 1.30, вам потрібно відповідно налаштувати конфігурацію.
Конфігурація авторизації та перезавантаження
Kubernetes перезавантажує файл конфігурації авторизації, коли API сервер виявляє зміну у файлі, а також за 60-секундним графіком, якщо події змін не спостерігаються.
Примітка:
Ви повинні забезпечити, щоб всі типи авторизаторів, крім вебхука, залишалися незмінними у файлі під час перезавантаження.
Перезавантаження не повинно додавати або видаляти авторизаторів вузла або RBAC (їх можна перевпорядкувати, але не можна додавати або видаляти).
Підвищення привілеїв через створення або редагування робочих навантажень
Користувачі, які можуть створювати/редагувати Podʼи в просторі імен, або безпосередньо, або через обʼєкт, що дозволяє опосередковане управління робочими навантаженнями, можуть мати можливість підвищити свої привілеї в цьому просторі імен. Потенційні шляхи до підвищення привілеїв включають розширення API Kubernetes та повʼязані з ними контролери.
Увага:
Як адміністратор кластера, будьте обережні, надаючи доступ до створення або редагування робочих навантажень. Деякі деталі того, як вони можуть бути використані не за призначенням, задокументовані в шляхах підвищення привілеїв.
Шляхи підвищення привілеїв
Існують різні способи, за якими зловмисник або ненадійний користувач може отримати додаткові привілеї в межах простору імен, якщо ви дозволяєте їм запускати довільні Podʼи в цьому просторі імен:
Монтування довільних Secretʼів в цьому просторі імен
Може бути використано для доступу до конфіденційної інформації, призначеної для інших робочих навантажень
Може бути використано для отримання токена службового облікового запису більш привілейованого ServiceAccount
Використання довільних службових облікових записів в цьому просторі імен
Може виконувати дії Kubernetes API як інше робоче навантаження (імперсонізація)
Може виконувати будь-які привілейовані дії, які має цей ServiceAccount
Монтування або використання ConfigMaps, призначених для інших робочих навантажень в цьому просторі імен
Може бути використано для отримання інформації, призначеної для інших робочих навантажень, таких як імена хостів баз даних.
Монтування томів, призначених для інших робочих навантажень в цьому просторі імен
Може бути використано для отримання інформації, призначеної для інших робочих навантажень, та її зміни.
Увага:
Як системному адміністратору, вам слід бути обережними при впровадженні власних визначень ресурсів, що дозволяють користувачам вносити зміни у вищезазначених областях. Це може відкрити шляхи до підвищення привілеїв. Розгляньте наслідки цього виду змін при виборі контролю за авторизацією.
Перевірка доступу до API
kubectl надає підкоманду auth can-i для швидкого запиту до рівня авторизації API. Команда використовує API SelfSubjectAccessReview, щоб визначити, чи може поточний користувач виконати
вказану дію, і працює незалежно від режиму авторизації, який використовується.
kubectl auth can-i create deployments --namespace dev
SelfSubjectAccessReview є частиною групи API authorization.k8s.io, яка викладає авторизацію сервера API для зовнішніх служб. Інші ресурси у цій групі включають:
SubjectAccessReview
Перегляд доступу для будь-якого користувача, не лише поточного. Корисно для делегування рішень про авторизацію серверу API. Наприклад, kubelet та API розширень сервери використовують це для визначення доступу користувача до своїх власних API.
LocalSubjectAccessReview
Подібно до SubjectAccessReview, але обмежено для конкретного простору імен.
SelfSubjectRulesReview
Перегляд, який повертає набір дій, які користувач може виконати в межах простору імен. Корисно для користувачів для швидкого узагальнення їх власного доступу, або для інтерфейсів користувача для приховування/відображення дій.
Ці API можна опитати, створивши звичайні ресурси Kubernetes, де поле відповіді status
поверненого обʼєкта є результатом запиту. Наприклад:
Контроль доступу на основі ролей (RBAC) — це метод регулювання доступу до компʼютерних або мережевих ресурсів на основі ролей окремих користувачів у вашій організації.
RBAC авторизація використовує групу API rbac.authorization.k8s.ioгрупа API для прийняття рішень щодо авторизації, дозволяючи вам динамічно налаштовувати політики через Kubernetes API.
Щоб увімкнути RBAC, запустіть API сервер з прапорцем --authorization-mode, встановленим на список, розділений комами, що включає RBAC; наприклад:
RBAC API визначає чотири типи обʼєктів Kubernetes: Role, ClusterRole, RoleBinding та ClusterRoleBinding. Ви можете описувати або змінювати обʼєкти RBAC за допомогою таких інструментів, як kubectl, так само як і будь-який інший обʼєкт Kubernetes.
Увага:
Ці обʼєкти за своєю конструкцією накладають обмеження на доступ. Якщо ви вносите зміни до кластера під час навчання, перегляньте розділ запобігання підвищенню привілеїв та початкове налаштування, щоб зрозуміти, як ці обмеження можуть завадити вам вносити деякі зміни.
Role та ClusterRole
RBAC Role або ClusterRole містять правила, які представляють набір дозволів. Дозволи є виключно адитивними (немає правил "заборони").
Role завжди встановлює дозволи в межах певного простору імен; коли ви створюєте Role, ви повинні вказати простір імен, до якого вона належить.
ClusterRole, на відміну, є ресурсом, який не належить до простору імен. Ресурси мають різні назви (Role і ClusterRole), оскільки обʼєкт Kubernetes завжди повинен бути або привʼязаним до простору імен, або не привʼязаним до простору імен; він не може бути одночасно і тим, і іншим.
ClusterRole мають кілька використань. Ви можете використовувати ClusterRole для:
визначення дозволів на ресурси, що належать до простору імен, і надання доступу в межах окремих просторів імен
визначення дозволів на ресурси, що належать до простору імен, і надання доступу до всіх просторів імен
визначення дозволів на ресурси, що належать до кластера
Якщо ви хочете визначити роль в межах простору імен, використовуйте Role; якщо ви хочете визначити роль для всього кластера, використовуйте ClusterRole.
Приклад Role
Ось приклад Role в просторі імен "default", яку можна використовувати для надання доступу на читання до Podʼів:
apiVersion:rbac.authorization.k8s.io/v1kind:Rolemetadata:namespace:defaultname:pod-readerrules:- apiGroups:[""]# "" означає основну групу APIresources:["pods"]verbs:["get","watch","list"]
Приклад ClusterRole
ClusterRole може бути використана для надання тих самих дозволів, що й Role. Оскільки ClusterRole стосуються всього кластера, ви також можете використовувати їх для надання доступу до:
ресурсів, що належать до кластера (наприклад, вузли)
точок доступу, що не є ресурсами (наприклад, /healthz)
ресурсів, що належать до простору імен (наприклад, контейнерів), в усіх просторах імен
Наприклад: ви можете використовувати ClusterRole для дозволу конкретному користувачу виконувати kubectl get pods --all-namespaces.
Ось приклад ClusterRole, яку можна використовувати для надання доступу на читання Secretʼів в будь-якому просторі імен або в усіх просторах імен (залежно від того, як вона звʼязана):
apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:# "namespace" пропущено, оскільки ClusterRole не привʼязані до простору іменname:secret-readerrules:- apiGroups:[""]## на рівні HTTP, назва ресурсу для доступу до обʼєктів Secret# це "secrets"resources:["secrets"]verbs:["get","watch","list"]
RoleBinding надає дозволи, визначені в ролі, користувачу або групі користувачів та містить список субʼєктів (користувачів, груп або облікових записів сервісів) і посилання на роль, що надається. RoleBinding надає дозволи в межах конкретного простору імен, тоді як ClusterRoleBinding надає доступ на рівні всього кластера.
RoleBinding може посилатися на будь-яку Role в тому ж просторі імен. Альтернативно, RoleBinding може посилатися на ClusterRole і звʼязувати цю ClusterRole з простором імен RoleBinding. Якщо ви хочете звʼязати ClusterRole з усіма просторами імен у вашому кластері, використовуйте ClusterRoleBinding.
Назва обʼєкта RoleBinding або ClusterRoleBinding повинна бути дійсною назвою сегмента шляху.
Приклади RoleBinding
Ось приклад RoleBinding, який надає роль "pod-reader" користувачу "jane" в межах простору імен "default". Це дозволяє "jane" читати Podʼи в просторі імен "default".
apiVersion:rbac.authorization.k8s.io/v1# Це рольове звʼязування дозволяє "jane" читати Podʼи в просторі імен "default".# Ви повинні вже мати роль з назвою "pod-reader" в цьому просторі імен.kind:RoleBindingmetadata:name:read-podsnamespace:defaultsubjects:# Ви можете вказати більше одного "субʼєкта"- kind:Username:jane# "name" чутливе до регіструapiGroup:rbac.authorization.k8s.ioroleRef:# "roleRef" вказує на звʼязування з Role / ClusterRolekind:Role# має бути Role або ClusterRolename:pod-reader# має збігатися з назвою Role або ClusterRole, з якою ви хочете звʼязатиapiGroup:rbac.authorization.k8s.io
RoleBinding також може посилатися на ClusterRole для надання дозволів, визначених у цій ClusterRole, на ресурси в межах простору імен RoleBinding. Такий вид посилання дозволяє визначати набір загальних ролей для всього вашого кластера, а потім використовувати їх у декількох просторах імен.
Наприклад, хоча наступний RoleBinding посилається на ClusterRole, "dave" (субʼєкт, чутливий до регістру) зможе читати Secretʼи лише в просторі імен "development", оскільки простір імен RoleBinding (у його метаданих) — "development".
apiVersion:rbac.authorization.k8s.io/v1# Це рольове звʼязування дозволяє "dave" читати Secretʼи в просторі імен "development".# Ви повинні вже мати ClusterRole з назвою "secret-reader".kind:RoleBindingmetadata:name:read-secrets## Простір імен RoleBinding визначає, де надаються дозволи.# Це надає дозволи лише в просторі імен "development".namespace:developmentsubjects:- kind:Username:dave# Name чутливе до регіструapiGroup:rbac.authorization.k8s.ioroleRef:kind:ClusterRolename:secret-readerapiGroup:rbac.authorization.k8s.io
Приклад ClusterRoleBinding
Щоб надати дозволи на рівні всього кластера, ви можете використовувати ClusterRoleBinding. Наступний ClusterRoleBinding дозволяє будь-якому користувачу з групи "manager" читати Secretʼи в будь-якому просторі імен.
apiVersion:rbac.authorization.k8s.io/v1# Це звʼязування кластерної ролі дозволяє будь-якому користувачу з групи "manager" читати Secretʼи в будь-якому просторі імен.kind:ClusterRoleBindingmetadata:name:read-secrets-globalsubjects:- kind:Groupname:manager# Name чутливе до регіструapiGroup:rbac.authorization.k8s.ioroleRef:kind:ClusterRolename:secret-readerapiGroup:rbac.authorization.k8s.io
Після створення звʼязування ви не можете змінити Role або ClusterRole, на які вони посилаються. Якщо ви спробуєте змінити roleRef звʼязування, ви отримаєте помилку валідації. Якщо ви дійсно хочете змінити roleRef для звʼязування, вам потрібно видалити обʼєкт звʼязування і створити новий.
Існує дві причини для цього обмеження:
Роблячи roleRef незмінним, можна надати комусь дозвіл update на наявний обʼєкт звʼязування, щоб він міг керувати списком субʼєктів, без можливості змінити роль, яка надається цим субʼєктам.
Звʼязування з іншою роллю є принципово іншим звʼязуванням. Вимога видалення/створення нового звʼязування для зміни roleRef гарантує, що весь список субʼєктів у звʼязуванні має намір отримати нову роль (на відміну від можливості випадково змінити лише roleRef без перевірки того, чи всі наявні субʼєкти повинні отримати дозволи нової ролі).
Команда kubectl auth reconcile створює або оновлює файл маніфесту, що містить обʼєкти RBAC, і обробляє видалення та відновлення обʼєктів звʼязування, якщо необхідно змінити роль, на яку вони посилаються. Дивіться використання команд та приклади для отримання додаткової інформації.
Посилання на ресурси
У Kubernetes API більшість ресурсів представлені та доступні за допомогою рядкового представлення їхнього імені обʼєкта, наприклад, pods для Pod. RBAC посилається на ресурси, використовуючи точно таку ж назву, яка зʼявляється в URL для відповідної точки доступу API. Деякі Kubernetes API включають субресурс, такий як логи для Pod. Запит на логи Pod виглядає так:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
У цьому випадку pods є ресурсом простору імен для Pod, а log є субресурсом pods. Щоб представити це в ролі RBAC, використовуйте слеш (/) для розділення ресурсу та субресурсу. Щоб дозволити субʼєкту читати pods і також отримувати доступ до субресурсу log для кожного з цих Pod, напишіть:
Ви також можете посилатися на ресурси за назвою для певних запитів через список resourceNames. Коли зазначено, запити можуть бути обмежені окремими екземплярами ресурсу. Ось приклад, що обмежує субʼєкт лише до get або updateConfigMap з назвою my-configmap:
apiVersion:rbac.authorization.k8s.io/v1kind:Rolemetadata:namespace:defaultname:configmap-updaterrules:- apiGroups:[""]## на рівні HTTP, назва ресурсу для доступу до обʼєктів ConfigMap є "configmaps"resources:["configmaps"]resourceNames:["my-configmap"]verbs:["update","get"]
Примітка:
Ви не можете обмежити запити create або deletecollection за назвою ресурсу. Для create це обмеження виникає через те, що назва нового обʼєкта може бути невідомою на момент авторизації. Якщо ви обмежуєте list або watch за resourceName, клієнти повинні включати селектор поля metadata.name у свої запити list або watch, що відповідає зазначеному resourceName, щоб отримати авторизацію. Наприклад, kubectl get configmaps --field-selector=metadata.name=my-configmap
Замість того, щоб посилатися на окремі resources, apiGroups і verbs, ви можете використовувати символ підстановки *, щоб посилатися на всі такі обʼєкти. Для nonResourceURLs ви можете використовувати символ підстановки * як суфікс для глобального збігу. Для resourceNames порожній набір означає, що все дозволено. Ось приклад, що дозволяє виконувати будь-яку поточну і майбутню дію для всіх поточних та майбутніх ресурсів в API групі example.com. Це схоже на вбудовану роль cluster-admin.
apiVersion:rbac.authorization.k8s.io/v1kind:Rolemetadata:namespace:defaultname:example.com-superuser# НЕ ВИКОРИСТОВУЙТЕ ЦЮ РОЛЬ, ЦЕ ЛИШЕ ПРИКЛАДrules:- apiGroups:["example.com"]resources:["*"]verbs:["*"]
Увага:
Використання символів підстановки в записах ресурсів і дій може призвести до надмірно широкого доступу до чутливих ресурсів. Наприклад, якщо додано новий тип ресурсу або новий субресурс, або перевірено нову спеціальну дію, запис символу підстановки автоматично надає доступ, що може бути небажаним. Слід застосовувати принцип мінімальних привілеїв, використовуючи конкретні ресурси та дії, щоб забезпечити лише ті дозволи, які необхідні для правильного функціонування робочого навантаження.
Агреговані ClusterRole
Ви можете агрегувати декілька ClusterRole в одну комбіновану ClusterRole. Контролер, який працює як частина панелі управління кластера, слідкує за обʼєктами ClusterRole з встановленим aggregationRule. aggregationRule визначає мітку селектора, яку використовує контролер для вибору інших обʼєктів ClusterRole, що мають бути обʼєднані у поле rules цього обʼєкта.
Увага:
Панель управління перезаписує будь-які значення, які ви вручну вказуєте в полі rules агрегованої ClusterRole. Якщо ви хочете змінити або додати правила, робіть це в обʼєктах ClusterRole, вибраних за допомогою aggregationRule.
Ось приклад агрегованої ClusterRole:
apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:name:monitoringaggregationRule:clusterRoleSelectors:- matchLabels:rbac.example.com/aggregate-to-monitoring:"true"rules:[]# Панель управління автоматично заповнює правила
Якщо ви створюєте нову ClusterRole, що відповідає селектору міток поточної агрегованої ClusterRole, це зміна ініціює додавання нових правил до агрегованої ClusterRole. Ось приклад, що додає правила до ClusterRole "monitoring" шляхом створення іншої ClusterRole з міткою rbac.example.com/aggregate-to-monitoring: true.
apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:name:monitoring-endpointslabels:rbac.example.com/aggregate-to-monitoring:"true"# При створенні ClusterRole "monitoring-endpoints",# правила нижче будуть додані до ClusterRole "monitoring".rules:- apiGroups:[""]resources:["services","endpointslices","pods"]verbs:["get","list","watch"]
Стандартні ролі для користувачів використовують агрегацію ClusterRole. Це дозволяє вам, як адміністратору кластера, включати правила для спеціальних ресурсів, таких як ті, що надаються CustomResourceDefinitions або агрегованими API серверами, щоб розширити стандартні ролі.
Наприклад: наступні ClusterRole дозволяють стандартним ролям "admin" і "edit" керувати спеціальним ресурсом з назвою CronTab, тоді як роль "view" може виконувати лише читання ресурсів CronTab. Ви можете припустити, що обʼєкти CronTab називаються "crontabs" в URL, як це бачить API сервер.
apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:name:aggregate-cron-tabs-editlabels:# Додайте ці дозволи до стандартних ролей "admin" і "edit".rbac.authorization.k8s.io/aggregate-to-admin:"true"rbac.authorization.k8s.io/aggregate-to-edit:"true"rules:- apiGroups:["stable.example.com"]resources:["crontabs"]verbs:["get","list","watch","create","update","patch","delete"]---kind:ClusterRoleapiVersion:rbac.authorization.k8s.io/v1metadata:name:aggregate-cron-tabs-viewlabels:# Додайте ці дозволи до стандартної ролі "view".rbac.authorization.k8s.io/aggregate-to-view:"true"rules:- apiGroups:["stable.example.com"]resources:["crontabs"]verbs:["get","list","watch"]
Приклади ролей
Наступні приклади є фрагментами обʼєктів Role або ClusterRole, що показують лише секцію rules.
Дозволити читання ресурсів "pods" у базовій API Group:
rules:- apiGroups:[""]## на рівні HTTP, назва ресурсу для доступу до обʼєктів Pod# є "pods"resources:["pods"]verbs:["get","list","watch"]
Дозволити читання/запис обʼєктів Deployment (на рівні HTTP: обʼєкти з "deployments" у частині ресурсу їх URL) в групах API "apps":
rules:- apiGroups:["apps"]## на рівні HTTP, назва ресурсу для доступу до обʼєктів Deployment# є "deployments"resources:["deployments"]verbs:["get","list","watch","create","update","patch","delete"]
Дозволити читання Podʼів у базовій групі API, а також читання або запис ресурсів Job у групі API "batch":
rules:- apiGroups:[""]## на рівні HTTP, назва ресурсу для доступу до обʼєктів Pod# є "pods"resources:["pods"]verbs:["get","list","watch"]- apiGroups:["batch"]## на рівні HTTP, назва ресурсу для доступу до обʼєктів Job# є "jobs"resources:["jobs"]verbs:["get","list","watch","create","update","patch","delete"]
Дозволити читання ConfigMap з назвою "my-config" (повинно бути повʼязано з RoleBinding, щоб обмежити до одного ConfigMap в одному просторі імен):
rules:- apiGroups:[""]## на рівні HTTP, назва ресурсу для доступу до обʼєктів ConfigMap# є "configmaps"resources:["configmaps"]resourceNames:["my-config"]verbs:["get"]
Дозволити читання ресурсу "nodes" у базовій групі (оскільки Node є кластерним ресурсом, це повинно бути у ClusterRole, повʼязаної з ClusterRoleBinding, щоб бути ефективним):
rules:- apiGroups:[""]## на рівні HTTP, назва ресурсу для доступу до обʼєктів Node# є "nodes"resources:["nodes"]verbs:["get","list","watch"]
Дозволити GET і POST запити до не-ресурсної точки доступу /healthz та всіх субшляхів (повинно бути в ClusterRole, повʼязаній з ClusterRoleBinding, щоб бути ефективним):
rules:- nonResourceURLs:["/healthz","/healthz/*"]# '*' у nonResourceURL є суфіксом для глобального збігуverbs:["get","post"]
Посилання на субʼєктів
RoleBinding або ClusterRoleBinding привʼязує роль до субʼєктів. Субʼєктами можуть бути групи, користувачі або ServiceAccounts.
Kubernetes представляє імена користувачів у вигляді рядків. Це можуть бути: звичайні імена, такі як "alice"; імена в стилі електронної пошти, як "bob@example.com"; або числові ідентифікатори користувачів, представлені у вигляді рядків. Вам, як адміністратору кластера, належить налаштувати модулі автентифікації, щоб автентифікація генерувала імена користувачів у бажаному форматі.
Увага:
Префікс system: зарезервований для використання системою Kubernetes, тому переконайтеся, що випадково не маєте користувачів або груп з іменами, що починаються з system:. Окрім цього спеціального префікса, система авторизації RBAC не вимагає жодного формату для імен користувачів.
У Kubernetes модулі Автентифікатора надають інформацію про групи. Групи, як і користувачі, представлені у вигляді рядків, і цей рядок не має жодних вимог до формату, крім того, що префікс system: зарезервований.
ServiceAccounts мають імена з префіксом system:serviceaccount:, і належать до груп, що мають імена з префіксом system:serviceaccounts:.
Примітка:
system:serviceaccount: (однина) є префіксом для імен користувачів службових облікових записів.
system:serviceaccounts: (множина) є префіксом для імен груп службових облікових записів.
Приклади RoleBinding
Наступні приклади є фрагментами RoleBinding, що показують лише секцію subjects.
API-сервери створюють набір стандартних обʼєктів ClusterRole і ClusterRoleBinding. Багато з них мають префікс system:, що вказує на те, що ресурс безпосередньо керується панеллю управління кластера. Усі стандартні ролі та привʼязки ролей мають мітку kubernetes.io/bootstrapping=rbac-defaults.
Увага:
Будьте обережні при зміні ClusterRole і ClusterRoleBinding з іменами, що мають префікс system:. Зміни цих ресурсів можуть призвести до несправних кластерів.
Автоматичне узгодження
При кожному запуску API-сервер оновлює стандартні ролі кластера, додаючи будь-які відсутні дозволи, та оновлює стандартні привʼязки ролей, додаючи будь-які відсутні субʼєкти. Це дозволяє кластеру виправляти випадкові зміни та допомагає підтримувати ролі та привʼязки ролей в актуальному стані, оскільки дозволи та субʼєкти змінюються у нових випусках Kubernetes.
Щоб відмовитися від цього узгодження, встановіть анотацію rbac.authorization.kubernetes.io/autoupdate на стандартній кластерній ролі або стандартній RoleBinding у значення false. Зверніть увагу, що відсутність стандартних дозволів та субʼєктів може призвести до несправних кластерів.
Автоматичне узгодження стандартно увімкнено, якщо авторизатор RBAC активний.
Ролі виявлення API
Стандартні кластерні привʼязки ролей дозволяють неавторизованим і авторизованим користувачам читати інформацію про API, яка вважається безпечною для публічного доступу (включаючи CustomResourceDefinitions). Щоб вимкнути анонімний неавторизований доступ, додайте прапорець --anonymous-auth=false до конфігурації API-сервера.
Щоб переглянути конфігурацію цих ролей через kubectl, запустіть:
kubectl get clusterroles system:discovery -o yaml
Примітка:
Якщо ви зміните цю ClusterRole, ваші зміни будуть перезаписані при перезапуску API-сервера через Автоматичне узгодження. Щоб уникнути цього перезапису, або не редагуйте роль вручну, або вимкніть Автоматичне узгодження.
Ролі виявлення API Kubernetes RBAC
Стандартна ClusterRole
Стандартна ClusterRoleBinding
Опис
system:basic-user
Група system:authenticated
Дозволяє користувачеві доступ лише для читання базової інформації про себе. До v1.14 ця роль також була стандартно повʼязана з system:unauthenticated.
system:discovery
Група system:authenticated
Дозволяє доступ лише для читання точок доступу виявлення API, необхідних для виявлення та узгодження рівня API. До v1.14 ця роль також була стандартно повʼязана з system:unauthenticated.
system:public-info-viewer
Групи system:authenticated і system:unauthenticated
Дозволяє доступ лише для читання несекретної інформації про кластер. Представлено у Kubernetes v1.14.
Ролі для користувачів
Деякі зі стандартних ClusterRoles не мають префікса system:. Вони включають ролі суперкористувача (cluster-admin), ролі, призначені для надання у всьому кластері за допомогою ClusterRoleBindings, а також ролі, призначені для надання у певних просторах імен простору імен за допомогою RoleBindings (admin, edit, view).
Ролі для користувачів використовують агрегацію ClusterRole, щоб дозволити адміністраторам включати правила для спеціальних ресурсів у ці ClusterRole. Щоб додати правила до ролей admin, edit або view, створіть ClusterRole з однією або кількома з наступних міток:
Дозволяє доступ суперкористувача для виконання будь-якої дії на будь-якому ресурсі. При використанні в ClusterRoleBinding, надає повний контроль над кожним ресурсом у кластері та у всіх просторах імен. При використанні в RoleBinding, надає повний контроль над кожним ресурсом у просторі імен, включаючи сам простір імен.
admin
Немає
Дозволяє доступ адміністратора, призначений для надання в межах простору імен за допомогою RoleBinding.
Якщо використовується в RoleBinding, дозволяє доступ для читання/запису до більшості ресурсів у просторі імен, включаючи можливість створювати ролі та привʼязки ролей у просторі імен. Ця роль не дозволяє доступу для запису до квоти ресурсів або до самого простору імен. Ця роль також не дозволяє доступу для запису до EndpointSlices (або Endpoints) у кластерах, створених за допомогою Kubernetes v1.22+. Більше інформації доступно у розділі
"Достпу на запису у EndpointSlices та Endpoints".
edit
Немає
Дозволяє доступ для читання/запису до більшості обʼєктів у просторі імен.
Ця роль не дозволяє переглядати або змінювати ролі або привʼязки ролей. Однак ця роль дозволяє доступ до Secretʼів і запуску Podʼів як будь-який ServiceAccount у просторі імен, тому вона може бути використана для отримання рівня доступу API будь-якого ServiceAccount у просторі імен. Ця роль також не дозволяє доступу для запису до EndpointSlices (або Endpoints) у кластерах, створених за допомогою Kubernetes v1.22+. Більше інформації доступно у розділі "Достпу на запису у EndpointSlices та Endpoints".
view
Немає
Дозволяє доступ лише для читання до більшості обʼєктів у просторі імен. Ця роль не дозволяє переглядати ролі або привʼязки ролей. Ця роль не дозволяє переглядати Secretʼи, оскільки читання вмісту секретів дозволяє доступ до облікових даних ServiceAccount у просторі імен, що дозволило б доступ до API як будь-який ServiceAccount у просторі імен (форма ескалації привілеїв).
Ролі основних компонентів
Стандартна ClusterRole
Стандартна ClusterRoleBinding
Опис
system:kube-scheduler
system:kube-scheduler користувач
Дозволяє доступ до ресурсів, необхідних компоненту планувальника.
system:volume-scheduler
system:kube-scheduler користувач
Дозволяє доступ до ресурсів обʼєму, необхідних компоненту kube-scheduler.
Дозволяє доступ до ресурсів, необхідних для kubelet, включаючи доступ на читання до всіх секретів та доступ на запис до всіх обʼєктів стану Podʼів.
Ви повинні використовувати Node authorizer та втулок допуску NodeRestriction замість ролі system:node та дозволяти надання доступу до API для kubelet на основі Podʼів, які заплановано для запуску на них.
Роль system:node існує лише для сумісності з кластерами Kubernetes, оновленими з версій до v1.8.
system:node-proxier
system:kube-proxy користувач
Дозволяє доступ до ресурсів, необхідних компоненту kube-proxy.
Ролі інших компонентів
Стандартна ClusterRole
Стандартна ClusterRoleBinding
Опис
system:auth-delegator
Немає
Дозволяє делеговані перевірки автентифікації та авторизації. Це зазвичай використовується серверами надбудов API для уніфікованої автентифікації та авторизації.
Дозволяє доступ на читання до точок доступу моніторингу панелі управління (тобто kube-apiserver точки доступу придатності та готовності (/healthz, /livez, /readyz), індивідуальні точки доступу перевірки стану (/healthz/*, /livez/*, /readyz/*) та /metrics). Зверніть увагу, що індивідуальні точки доступу перевірки стану та точка доступу метрик можуть розкривати конфіденційну інформацію.
Ролі для вбудованих контролерів
Менеджер контролерів Kubernetes запускає контролери, які вбудовані в панель управління Kubernetes. Коли його викликають з --use-service-account-credentials, kube-controller-manager запускає кожен контролер використовуючи окремий службовий обліковий запис. Для кожного вбудованого контролера існують відповідні ролі з префіксом system:controller:. Якщо менеджер контролерів не запускається з --use-service-account-credentials, він виконує всі контрольні цикли використовуючи власні облікові дані, які повинні мати всі відповідні ролі. Ці ролі включають:
Запобігання ескалації привілеїв і початкове налаштування
API RBAC запобігає ескалації привілеїв користувачами шляхом редагування ролей або привʼязок ролей. Оскільки це реалізується на рівні API, це застосовується навіть коли авторизатор RBAC не використовується.
Обмеження на створення або оновлення ролей
Ви можете створити/оновити роль, тільки якщо виконується хоча б одна з наступних умов:
Ви вже маєте всі дозволи, що містяться в ролі, в тій же області, що й обʼєкт, який модифікується (кластерний рівень для ClusterRole, у тому ж просторі імен або кластерний рівень для Role).
Вам надано явний дозвіл виконувати дієслово escalate для ресурсу roles або clusterroles в групі API rbac.authorization.k8s.io.
Наприклад, якщо user-1 не має можливості отриамння переліку Secrets на кластерному рівні, він не може створити ClusterRole, що містить цей дозвіл. Щоб дозволити користувачу створювати/оновлювати ролі:
Надайте йому роль, що дозволяє створювати/оновлювати обʼєкти Role або ClusterRole, те що треба.
Надати йому дозвіл включати конкретні дозволи в ролі, які він створює/оновлює:
неявно, надаючи йому ці дозволи (якщо він спробує створити або модифікувати Role або ClusterRole з дозволами, які йому самому не надані, запит до API буде заборонений)
або явно дозволити вказувати будь-які дозволи в Role або ClusterRole, надаючи йому дозвіл виконувати дієслово escalate для ресурсів roles або clusterroles в групі API rbac.authorization.k8s.io.
Обмеження на створення або оновлення привʼязок ролей
Ви можете створити/оновити привʼязку ролі, тільки якщо вже маєте всі дозволи, що містяться в згаданій ролі (в тій же області, що й привʼязка ролі) або якщо вам надано дозвіл виконувати дієслово bind для згаданої ролі. Наприклад, якщо user-1 не має можливості отримувати перелік Secrets на кластерному рівні, він не може створити ClusterRoleBinding для ролі, яка надає цей дозвіл. Щоб дозволити користувачу створювати/оновлювати привʼязки ролей:
Надати йому роль, що дозволяє створювати/оновлювати обʼєкти RoleBinding або ClusterRoleBinding, як необхідно.
Надати йому дозволи, необхідні для привʼязки певної ролі:
неявно, надаючи йому дозволи, що м стяться в ролі.
явно, надаючи йому дозвіл виконувати дієслово bind для певної Role (або ClusterRole).
Наприклад, цей ClusterRole і RoleBinding дозволять user-1 надавати іншим користувачам ролі admin, edit і view у просторі імен user-1-namespace:
apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:name:role-grantorrules:- apiGroups:["rbac.authorization.k8s.io"]resources:["rolebindings"]verbs:["create"]- apiGroups:["rbac.authorization.k8s.io"]resources:["clusterroles"]verbs:["bind"]# пропустіть resourceNames, щоб дозволити привʼязку будь-якої ClusterRoleresourceNames:["admin","edit","view"]---apiVersion:rbac.authorization.k8s.io/v1kind:RoleBindingmetadata:name:role-grantor-bindingnamespace:user-1-namespaceroleRef:apiGroup:rbac.authorization.k8s.iokind:ClusterRolename:role-grantorsubjects:- apiGroup:rbac.authorization.k8s.iokind:Username:user-1
Коли початково налаштовуються перші ролі та привʼязки ролей, необхідно, щоб початковий користувач надав дозволи, які він ще не має. Щоб початково налаштувати ролі та привʼязки ролей:
Використовуйте облікові дані з групою "system:masters", яка стандартно привʼязана до ролі суперкористувача "cluster-admin".
Утиліти командного рядка
kubectl create role
Створює обʼєкт Role, що визначає дозволи в межах одного простору імен. Приклади:
Створити Role з назвою "pod-reader", яка дозволяє користувачам виконувати get, watch і list для pods:
kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
Створити Role з назвою "pod-reader" зі специфікованими resourceNames:
kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
Створити Role з назвою "foo" зі специфікованими apiGroups:
kubectl create role foo --verb=get,list,watch --resource=replicasets.apps
Створити Role з назвою "foo" з дозволами на субресурси:
kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
Створити Role з назвою "my-component-lease-holder" з дозволами на отримання/оновлення ресурсу зі специфічною назвою:
kubectl create role my-component-lease-holder --verb=get,list,watch,update --resource=lease --resource-name=my-component
kubectl create clusterrole
Створює ClusterRole. Приклади:
Створити ClusterRole з назвою "pod-reader", яка дозволяє користувачам виконувати get, watch і list для pods:
Типові політики RBAC надають обмежені права компонентам панелі управління, вузлам і контролерам, але не надають жодних дозволів службовим обліковим записам за межами простору імен kube-system (поза межами дозволів, наданих ролями виявлення API).
Це дозволяє надавати конкретні ролі конкретним ServiceAccounts за необхідності. Тонке налаштування привʼязок ролей забезпечує більшу безпеку, але вимагає більше зусиль для адміністрування. Ширші привʼязки можуть надати зайвий (і потенційно ескалуючий) доступ до API ServiceAccounts, але їх легше адмініструвати.
Підходи від найбезпечніших до найменш безпечних:
Надання ролі для службового облікового запису для конкретного застосунку (найкращий варіант)
Це вимагає від застосунку зазначення serviceAccountName в його специфікації Pod, і створення службового облікового запису (через API, маніфест програми, kubectl create serviceaccount, тощо).
Наприклад, надати права лише на читання в межах "my-namespace" службовому обліковому запису "my-sa":
Багато надбудов працюють від імені службового облікового запису "default" у просторі імен kube-system. Щоб дозволити цим надбудовам працювати з правами суперкористувача, надайте права cluster-admin службовому обліковому запису "default" у просторі імен kube-system.
Увага:
Включення цього означає, що в просторі імен kube-system знаходяться Secretʼи, які надають доступ суперкористувача до API вашого кластера.
Надання ролі всім службовим обліковим записам у просторі імен
Якщо ви хочете, щоб усі програми в просторі імен мали роль, незалежно від того, який службовий обліковий запис вони використовують, ви можете надати роль групі службових облікових записів для цього простору імен.
Наприклад, надати права лише на читання в межах "my-namespace" усім службовим обліковим записам у цьому просторі імен:
Надання прав суперкористувача всім службовим обліковим записам у кластері (категорично не рекомендується)
Якщо вам не важливо розподіляти дозволи взагалі, ви можете надати права суперкористувача всім службовим обліковим записам.
Попередження:
Це надає будь-якому застосунку повний доступ до вашого кластера, а також надає будь-якому користувачеві з правами читання Secretʼів (або здатності створювати будь-які Pod) повний доступ до вашого кластера.
Кластери Kubernetes, створені до версії Kubernetes v1.22, включають права запису для EndpointSlices (і Endpoints) у ролях "edit" і "admin". У рамках помʼякшення наслідків CVE-2021-25740, цей доступ не є частиною агрегованих ролей у кластерах, створених із використанням Kubernetes v1.22 або пізніших версій.
Кластери, які були оновлені до Kubernetes v1.22, не підпадають під цю зміну. Оголошення CVE включає вказівки щодо обмеження цього доступу в поточних кластерах.
Якщо ви хочете, щоб нові кластери зберігали цей рівень доступу в агрегованих ролях, ви можете створити наступну ClusterRole:
apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:annotations:kubernetes.io/description:|- Add endpoints write permissions to the edit and admin roles. This was
removed by default in 1.22 because of CVE-2021-25740. See
https://issue.k8s.io/103675. This can allow writers to direct LoadBalancer
or Ingress implementations to expose backend IPs that would not otherwise
be accessible, and can circumvent network policies or security controls
intended to prevent/isolate access to those backends.
EndpointSlices were never included in the edit or admin roles, so there
is nothing to restore for the EndpointSlice API.labels:rbac.authorization.k8s.io/aggregate-to-edit:"true"name:custom:aggregate-to-edit:endpoints# виможете змінити це поле, за бажаннямrules:- apiGroups:[""]resources:["endpoints"]verbs:["create","delete","deletecollection","patch","update"]
Оновлення з ABAC
Кластери, що спочатку працювали на старіших версіях Kubernetes, часто використовували дозвільні політики ABAC, включаючи надання повного доступу до API всім службовим обліковим записам.
Типові політики RBAC надають обмежені права компонентам панелі управління, вузлам і контролерам, але не надають жодних дозволів службовим обліковим записам за межами простору імен kube-system (поза межами дозволів, наданих ролями виявлення API).
Хоча це набагато безпечніше, це може бути руйнівним для поточних робочих навантажень, які очікують автоматичного отримання дозволів API. Ось два підходи для управління цим переходом:
Паралельні авторизатори
Запускайте як RBAC, так і ABAC авторизатори, і вкажіть файл політики, що містить стару політику ABAC:
Щоб детально пояснити цей перший параметр командного рядка: якщо раніші авторизатори, такі як Node, відхиляють запит, тоді авторизатор RBAC намагається авторизувати запит до API. Якщо RBAC також відхиляє цей запит до API, тоді запускається авторизатор ABAC. Це означає, що будь-який запит, дозволений будь-якою політикою RBAC або ABAC, буде дозволений.
Коли kube-apiserver запускається з рівнем логування 5 або вище для компонента RBAC (--vmodule=rbac*=5 або --v=5), ви можете побачити відмови RBAC у лозі сервера API (позначені як RBAC). Ви можете використовувати цю інформацію для визначення, які ролі потрібно надати яким користувачам, групам або службовим обліковим записам.
Після того, як ви надали ролі службовим обліковим записам і робочі навантаження працюють без повідомлень про відмову RBAC у логах сервера, ви можете видалити авторизатор ABAC.
Дозвільні права RBAC
Ви можете відтворити дозвільну політику ABAC, використовуючи привʼязки ролей RBAC.
Попередження:
Наступна політика дозволяє ВСІМ службовим обліковим записам діяти як адміністратори кластера. Будь-який застосунок, що працює в контейнері, автоматично отримує облікові дані службового облікового запису і може виконувати будь-яку дію з API, включаючи перегляд секретів і зміну дозволів. Це не рекомендована політика.
Після переходу на використання RBAC, ви повинні налаштувати контроль доступу для вашого кластера, щоб забезпечити відповідність вашим інформаційним вимогам безпеки.
5 - Використання авторизації вузлів
Авторизація вузлів — це режим авторизації спеціального призначення, який спеціально авторизує запити API, зроблені kubelet-ами.
Огляд
Авторизатор вузлів дозволяє kubelet-ам виконувати операції з API. Це включає:
Операції читання:
services
endpoints
nodes
pods
secrets, configmaps, persistent volume claims та persistent volumes, що стосуються Podʼів, привʼязаних до вузла kubelet-а
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.31 [alpha] (стандартно увімкнено: false)
Коли функціональну можливість AuthorizeNodeWithSelectors увімкнено (разом із передумовою AuthorizeWithSelectors), kubelets можуть читати лише власні обʼєкти Node і можуть читати лише Podʼи, привʼязані до їхнього вузла.
Операції запису:
вузли та статус вузлів (увімкніть втулок допуску NodeRestriction, щоб обмежити
kubelet у зміні свого власного вузла)
поди та статус подів (увімкніть втулок допуску NodeRestriction, щоб обмежити
kubelet у зміні подів, привʼязаних до себе)
можливість створювати TokenReview та SubjectAccessReview для делегованої
автентифікації/авторизації
У майбутніх випусках авторизатор вузлів може додавати або видаляти дозволи, щоб забезпечити kubelet-и мінімальним набором дозволів, необхідних для правильної роботи.
Для того, щоб бути авторизованими авторизатором вузлів, kubelet-и повинні використовувати облікові дані, які ідентифікують їх як членів групи system:nodes, з іменем користувача system:node:<nodeName>. Цей формат групи та імені користувача відповідає ідентичності, створеній для кожного kubelet-а в рамках TLS початкового запуску kubelet-а.
Значення <nodeName>має точно відповідати імені вузла, як зареєстровано kubelet-ом. Стандартно це імʼя хосту, надане hostname, або замінене за допомогою опції kubelet--hostname-override. Однак, при використанні опції kubelet --cloud-provider, конкретне імʼя хосту може бути визначено постачальником хмарних послуг, ігноруючи локальний hostname та опцію --hostname-override. Для деталей щодо визначення імені хосту kubelet-ом, дивіться довідник з опцій kubelet.
Щоб увімкнути авторизатор вузлів, запустіть apiserver з --authorization-mode=Node.
Щоб обмежити обʼєкти API, які можуть писати kubelet-и, увімкніть втулок допуску NodeRestriction
шляхом запуску apiserver з --enable-admission-plugins=...,NodeRestriction,....
Міркування щодо міграції
Kubelet-и поза групою system:nodes
Kubelet-и, що знаходяться поза групою system:nodes, не будуть авторизовані режимом авторизації Node, і їм потрібно буде продовжувати авторизацію через механізм, який їх наразі авторизує. Вутлок допуску вузлів не буде обмежувати запити від цих kubelet-ів.
Kubelet-и з недиференційованими іменами користувачів
У деяких розгортаннях kubelet-и мають облікові дані, що розміщують їх у групі system:nodes, але не ідентифікують конкретний вузол, з яким вони повʼязані, оскільки вони не мають імені користувача у форматі system:node:.... Ці kubelet-и не будуть авторизовані режимом авторизації Node, і їм потрібно буде продовжувати авторизацію через механізм, який їх наразі авторизує.
Втулок допуску NodeRestriction буде ігнорувати запити від цих kubelet-ів, оскільки стандартна реалізація ідентифікатора вузла не вважатиме це ідентичністю вузла.
6 - Режим Webhook
Webhook — це зворотний виклик HTTP: HTTP POST, який відбувається, коли щось стається; просте сповіщення про подію через HTTP POST. Вебзастосунок, що реалізує Webhook, буде надсилати POST повідомлення на URL, коли відбуваються певні події.
Коли вказано режим Webhook, Kubernetes звертається до зовнішнього REST сервісу для визначення привілеїв користувача.
Формат файлу конфігурації
Режим Webhook потребує файл для HTTP конфігурації, що вказується за допомогою прапорця --authorization-webhook-config-file=SOME_FILENAME.
Файл конфігурації використовує формат файлу kubeconfig. У файлі "users" стосується конфігурації webhook API сервера, а "clusters" — до віддаленого сервісу.
Приклад конфігурації, що використовує клієнтську автентифікацію HTTPS:
# Версія Kubernetes APIapiVersion:v1# тип API обʼєктаkind:Config# кластери відносяться до віддаленого сервісуclusters:- name:name-of-remote-authz-servicecluster:# CA для перевірки віддаленого сервісуcertificate-authority:/path/to/ca.pem# URL віддаленого сервісу для запитів. Має використовувати 'https'. Не може включати параметри.server:https://authz.example.com/authorize# користувачі відносяться до конфігурації webhook API сервераusers:- name:name-of-api-serveruser:client-certificate:/path/to/cert.pem# сертифікат для використання webhook втулкомclient-key:/path/to/key.pem # ключ, що відповідає сертифікату# файли kubeconfig вимагають контекст. Вкажіть один для API сервера.current-context:webhookcontexts:- context:cluster:name-of-remote-authz-serviceuser:name-of-api-servername:webhook
Запити корисного навантаження
При ухваленні рішення про авторизацію, API сервер надсилає JSON- серіалізований обʼєкт authorization.k8s.io/v1beta1SubjectAccessReview, що описує дію. Цей обʼєкт містить поля, що описують користувача, який намагається зробити запит, та деталі про ресурс, до якого здійснюється доступ, або атрибути запиту.
Зверніть увагу, що обʼєкти API webhook підлягають тим самим правилам сумісності версій, що й інші обʼєкти API Kubernetes. Імплементатори повинні бути обізнані з менш суворими обіцянками сумісності для бета-обʼєктів і перевіряти поле "apiVersion" запиту для забезпечення правильної десеріалізації. Додатково, API сервер повинен увімкнути групу розширень API authorization.k8s.io/v1beta1 (--runtime-config=authorization.k8s.io/v1beta1=true).
Віддалений сервіс має заповнити поле status запиту і відповісти, дозволяючи або забороняючи доступ. Поле spec у відповіді ігнорується і може бути пропущене. Дозвільна відповідь виглядатиме так:
Перший метод є кращим у більшості випадків і вказує, що webhook авторизації не дозволяє або не має "думки" ("no opinion") щодо запиту, але якщо інші авторизатори налаштовані, вони отримують шанс дозволити запит. Якщо немає інших авторизаторів або жоден з них не дозволяє запит, запит забороняється. Webhook поверне:
{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"status": {
"allowed": false,
"reason": "user does not have read access to the namespace" }
}
Другий метод негайно відмовляє, перериваючи оцінку іншими налаштованими авторизаторами. Це слід використовувати лише вебхуками, які мають детальні знання про повну конфігурацію авторизатора кластера. Webhook поверне:
{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"status": {
"allowed": false,
"denied": true,
"reason": "user does not have read access to the namespace" }
}
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.31 [alpha] (стандартно увімкнено: false)
З увімкненою функцією AuthorizeWithSelectors поля та мітки селекторів у запиті передаються до вебхуку авторизації. Вебхук може приймати рішення про авторизацію, орієнтуючися на обмежені селектори полів і міток, якщо бажає.
Документація API SubjectAccessReview надає вказівки щодо того, як ці поля мають інтерпретуватися і оброблятися вебхуками авторизації, зокрема використанням розібраних вимог замість сирих рядків селекторів та як безпечно обробляти невідомі оператори.
Нересурсні шляхи включають: /api, /apis, /metrics, /logs, /debug, /healthz, /livez, /openapi/v2, /readyz та /version. Клієнти потребують доступу до /api, /api/*, /apis, /apis/*, та /version для визначення, які ресурси та версії присутні на сервері. Доступ до інших нересурсних шляхів може бути заборонений без обмеження доступу до REST API.
Авторизація на основі атрибутів (ABAC) визначає парадигму контролю доступу, за якою права доступу надаються користувачам за допомогою політик, які комбінують атрибути.
Формат файлу політики
Для увімкнення режиму ABAC вказуйте --authorization-policy-file=SOME_FILENAME та --authorization-mode=ABAC при запуску.
Формат файлу — один обʼєкт JSON на рядок. Не повинно бути жодного вкладеного списку або map, тільки один map на рядок.
Кожний рядок — "обʼєкт політики", де такий обʼєкт є map із такими властивостями:
Властивості версіювання:
apiVersion, типу string; допустимі значення "abac.authorization.kubernetes.io/v1beta1". Дозволяє версіювання та конвертацію формату політики.
kind, типу string: допустимі значення "Policy". Дозволяє версіювання та конвертацію формату політики.
Властивість spec встановлена на мапу з такими властивостями:
Властивості зіставлення субʼєкта:
user, типу string; рядок користувача з --token-auth-file. Якщо ви вказуєте user, він повинен збігатися з імʼям користувача автентифікованого користувача.
group, типу string; якщо ви вказуєте group, він повинен збігатися з однією з груп автентифікованого користувача. system:authenticated збігається з усіма автентифікованими запитами. system:unauthenticated збігається з усіма неавтентифікованими запитами.
Властивості зіставлення ресурсу:
apiGroup, типу string; група API.
Наприклад: apps, networking.k8s.io
Маска: * збігається з усіма групами API.
namespace, типу string; простір імен.
Наприклад: kube-system
Маска: * збігається з усіма запитами ресурсів.
resource, типу string; тип ресурсу
Наприклад: pods, deployments
Маска: * збігається з усіма запитами ресурсів.
Властивості зіставлення нересурсів:
nonResourcePath, типу string; шляхи запитів нересурсів.
Наприклад: /version або /apis
Маска:
* збігається з усіма запитами нересурсів.
/foo/* збігається з усіма підшляхами /foo/.
readonly, типу boolean, якщо true, означає, що політика, що зіставляється з ресурсом, застосовується тільки до операцій get, list, та watch, а політика, що зіставляється з нересурсами, застосовується тільки до операції get.
Примітка:
Невстановлена властивість є такою самою, як властивість, що встановлена на нульове значення для свого типу (наприклад, порожній рядок, 0, false). Проте невстановлена властивість має перевагу для зручності читання.
У майбутньому політики можна буде виражати у форматі JSON і керувати ними через REST-інтерфейс.
Алгоритм авторизації
У запиту є атрибути, які відповідають властивостям обʼєкта політики.
Коли отримано запит, визначаються атрибути. Невідомі атрибути встановлюються на нульове значення свого типу (наприклад, порожній рядок, 0, false).
Властивість, встановлена на "*", буде збігатися з будь-яким значенням відповідного атрибута.
Кортеж атрибутів перевіряється на відповідність кожній політиці в файлі політики. Якщо принаймні один рядок відповідає атрибутам запиту, тоді запит авторизований (але може зазнати невдачі під час подальшої перевірки).
Щоб дозволити будь-якому автентифікованому користувачеві зробити щось, створіть політику з властивістю group, встановленою на "system:authenticated".
Щоб дозволити будь-якому неавтентифікованому користувачеві зробити щось, створіть політику з властивістю group, встановленою на "system:unauthenticated".
Щоб дозволити користувачеві зробити все, створіть політику з властивостями apiGroup, namespace, resource та nonResourcePath, встановленими на "*".
Kubectl
Kubectl використовує точки доступу /api та /apis apiserver для виявлення сервісів, які обслуговують типи ресурсів, і перевіряє обʼєкти, надіслані до API за допомогою операцій create/update, використовуючи інформацію про схему, розташовану в /openapi/v2.
При використанні авторизації на основі атрибутів, ці спеціальні ресурси мають бути явно відкриті за допомогою властивості nonResourcePath в політиці (див. приклади нижче):
/api, /api/*, /apis та /apis/* для вибору версії API.
/version для отримання версії сервера через kubectl version.
/swaggerapi/* для операцій create/update.
Щоб перевірити HTTP-виклики, повʼязані з певною операцією kubectl, ви можете збільшити рівень деталізації:
Кожен службовий обліковий запис має відповідне імʼя користувача ABAC, і імʼя цього службового облікового запису генерується згідно з конвенцією щодо найменування:
Створюючи новий простір імен, створюється новий службовий обліковий запис у наступному форматі:
system:serviceaccount:<namespace>:default
Наприклад, якщо ви хочете надати стандартному службовому обліковому запису (у просторі імен kube-system) повні привілеї в API за допомогою ABAC, ви додаєте цей рядок до файлу політики:
apiserver повинен бути перезапущений, щоб використати нові рядки.
8 - Контролери допуску
Ця сторінка надає огляд контролерів допуску.
Що це таке?
Контролер допуску — це фрагмент коду, який перехоплює запити до сервера API Kubernetes перед збереженням обʼєкта, але після того, як запит був автентифікований та авторизований.
Контролери допуску можуть бути валідаційними, модифікуючими або обома. Модифікуючі контролери можуть змінювати обʼєкти, повʼязані з запитами, які вони допускають; валідаційні контролери не можуть цього робити.
Контролери допуску обмежують запити на створення, видалення, зміну обʼєктів. Контролери допуску також можуть блокувати нестандартні дієслова, такі як запити на підключення до Podʼа через проксі сервера API. Контролери допуску не блокують (і не можуть) запити на читання (get, watch або list) обʼєктів.
Контролери допуску в Kubernetes 1.31 складаються зі списку нижче, вбудовані у двійковий файл kube-apiserver і можуть бути налаштовані тільки адміністратором кластера. У цьому списку є два спеціальні контролери: MutatingAdmissionWebhook і ValidatingAdmissionWebhook. Вони виконують модифікуючі та валідаційні (відповідно) вебхуки контролю допуску,
які налаштовуються в API.
Етапи контролю допуску
Процес контролю допуску проходить у два етапи. На першому етапі виконуються модифікуючі контролери допуску. На другому етапі виконуються валідаційні контролери допуску. Знову ж таки, деякі контролери є обома.
Якщо будь-який з контролерів на будь-якому етапі відхиляє запит, весь запит негайно відхиляється, і користувачу повертається помилка.
Нарешті, окрім іноді модифікації обʼєкта, про який йдеться, контролери допуску можуть іноді мати побічні ефекти, тобто змінювати повʼязані ресурси в процесі обробки запиту. Збільшення використання квоти є класичним прикладом того, чому це необхідно. Будь-який такий побічний ефект потребує відповідного процесу рекламації або узгодження, оскільки даний контролер допуску не знає напевно, що даний запит пройде через всі інші контролери допуску.
Чому вони потрібні?
Кілька важливих функцій Kubernetes вимагають увімкнення контролера допуску для належної підтримки функції. Як результат, сервер API Kubernetes, який неправильно налаштований з необхідним набором контролерів допуску, є неповним сервером і не підтримуватиме всі функції, які ви очікуєте.
Як увімкнути контролер допуску?
Прапорець сервера API Kubernetes enable-admission-plugins приймає через кому список втулків контролю допуску, які слід викликати перед зміною обʼєктів у кластері. Наприклад, наступна команда увімкне втулки контролю допуску NamespaceLifecycle та LimitRanger:
Залежно від того, як ваш кластер Kubernetes розгорнутий і як запускається сервер API, вам може знадобитися застосувати налаштування різними способами. Наприклад, вам може знадобитися змінити файл системного блоку systemd, якщо сервер API розгорнуто як службу systemd ви можете змінити файл маніфесту для сервера API, якщо Kubernetes розгорнуто як самостійний хостинг.
Як вимкнути контролер допуску?
Прапорець сервера API Kubernetes disable-admission-plugins приймає через кому список втулків контролю допуску, які слід вимкнути, навіть якщо вони є у списку втулків, що є стандартно увімкненими.
Втулок допуску ValidatingAdmissionPolicy стандартно увімкнений, але активний тільки, якщо ви увімкнете функціональні можливостіValidatingAdmissionPolicyта API admissionregistration.k8s.io/v1alpha1.
Що робить кожен контролер допуску?
AlwaysAdmit
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.13 [deprecated]
Тип: Валідаційний.
Цей контролер допуску дозволяє запуск всіх Podʼів в кластер. Він застарілий, оскільки його поведінка така ж, якби не було ніякого контролера допуску взагалі.
AlwaysDeny
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.13 [deprecated]
Тип: Валідаційний.
Відхиляє всі запити. AlwaysDeny застарілий, оскільки не має реального значення.
AlwaysPullImages
Тип: Модифікуючий та Валідаційний.
Цей контролер допуску модифікує кожен новий Pod, щоб примусити використовувати політику завантаження образів Always. Це корисно в багатокористувацькому кластері, щоб користувачі могли бути впевнені, що їхні приватні образи можуть використовувати лише ті, хто має відповідні облікові дані для їх завантаження. Без цього контролера допуску, після того, як образи було завантажено на вузол, будь-який Pod будь-якого користувача може використовувати його, знаючи імʼя образу (за умови, що Pod розміщений на правильному вузлі), без жодної перевірки вторизації для образу. Коли цей контролер допуску увімкнений, образи завжди завантажуються перед запуском контейнерів, що означає, що потрібні дійсні облікові дані.
CertificateApproval
Тип: Валідаційний.
Цей контролер допуску спостерігає за запитами на затвердження ресурсів CertificateSigningRequest і виконує додаткові перевірки авторизації, щоб переконатися, що користувач, який затверджує, має дозвіл на затвердження запитів сертифікатів із запитаним spec.signerName у ресурсі CertificateSigningRequest.
Дивіться Запити на підписання сертифікатів для отримання додаткової інформації про дозволи, необхідні для виконання різних дій з ресурсами CertificateSigningRequest.
CertificateSigning
Тип: Валідаційний.
Цей контролер допуску спостерігає за оновленнями поля status.certificate ресурсів CertificateSigningRequest і виконує додаткові перевірки авторизації, щоб переконатися, що користувач, який підписує, має дозвіл на підписання запитів сертифікатів із запитаним spec.signerName у ресурсі CertificateSigningRequest.
Дивіться Запити на підписання сертифікатів для отримання додаткової інформації про дозволи, необхідні для виконання різних дій з ресурсами CertificateSigningRequest.
CertificateSubjectRestriction
Тип: Валідаційний.
Цей контролер допуску спостерігає за створенням ресурсів CertificateSigningRequest, які мають spec.signerName значення kubernetes.io/kube-apiserver-client. Він відхиляє будь-який запит, який вказує групу (або атрибут організації) system:masters.
DefaultIngressClass
Тип: Модифікуючий.
Цей контролер допуску спостерігає за створенням обʼєктів Ingress, які не запитують жодного конкретного класу ingress, і автоматично додає до них стандартний клас ingress. Таким чином, користувачі, які не запитують жодного спеціального класу ingress, не повинні про це турбуватися та отримають стандартний клас.
Цей контролер допуску нічого не робить, коли не налаштований жоден стандартний клас ingress. Коли більше одного класу ingress позначено як стандартний клас, він відхиляє будь-яке створення Ingress з помилкою, і адміністратор повинен переглянути свої обʼєкти IngressClass та позначити лише один як стандартний клас (з анотацією "ingressclass.kubernetes.io/is-default-class"). Цей контролер допуску ігнорує будь-які оновлення Ingress; він діє тільки при створенні.
Дивіться документацію Ingress для отримання додаткової інформації про класи ingress і як позначити один як стандартний клас.
DefaultStorageClass
Тип: Модифікуючий.
Цей контролер допуску спостерігає за створенням обʼєктів PersistentVolumeClaim, які не запитують жодного конкретного класу зберігання, і автоматично додає до них стандартний клас зберігання. Таким чином, користувачі, які не запитують жодного спеціального класу зберігання, не повинні про це турбуватися та отримають стандартний клас.
Цей контролер допуску нічого не робить, коли не налаштований жоден стандартний клас зберігання. Коли більше одного класу зберігання позначено як стандартний клас, він відхиляє будь-яке створення PersistentVolumeClaim з помилкою, і адміністратор повинен переглянути свої обʼєкти StorageClass і позначити лише один як стандартний клас. Цей контролер допуску ігнорує будь-які оновлення PersistentVolumeClaim; він діє тільки при створенні.
Дивіться документацію постійних томів про persistent volume claims та класи зберігання, а також як позначити клас зберігання як стандартний клас.
DefaultTolerationSeconds
Тип: Модифікуючий.
Цей контролер допуску встановлює стандартне значення толерантності для Podʼів, щоб терпіти taints notready:NoExecute та unreachable:NoExecute на основі параметрів введення k8s-apiserver default-not-ready-toleration-seconds та default-unreachable-toleration-seconds, якщо Podʼи ще не мають толерантності до taints node.kubernetes.io/not-ready:NoExecute або node.kubernetes.io/unreachable:NoExecute. Стандартне значення для default-not-ready-toleration-seconds та default-unreachable-toleration-seconds становить 5 хвилин.
DenyServiceExternalIPs
Тип: Валідаційний.
Цей контролер допуску відхиляє всі нові використання поля externalIPs у Service. Ця функція дуже потужна (дозволяє перехоплення мережевого трафіку) і не контролюється належним чином політиками. Коли цей контролер увімкнено, користувачі кластера не можуть створювати нові Serviceʼи, які використовують externalIPs, і не можуть додавати нові значення до externalIPs в поточних обʼєктах Service. Поточні використання externalIPs не зачіпаються, і користувачі можуть видаляти значення з externalIPs в наявних обʼєктах Service.
Більшість користувачів взагалі не потребує цієї функції, і адміністратори кластера повинні розглянути можливість її вимкнення. Кластери, які потребують цієї функції, повинні розглянути можливість використання власних політик для керування її використанням.
Цей контролер допуску стандартно вимкнено.
EventRateLimit
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.13 [alpha]
Тип: Валідаційний.
Цей контролер допуску зменшує проблему, коли API-сервер переповнюється запитами на зберігання нових подій (Events). Адміністратор кластера може вказати обмеження швидкості подій, виконавши такі кроки:
Увімкнути контролер допуску EventRateLimit;
Посилатися на конфігураційний файл EventRateLimit з файлу, наданого у командному рядку API-сервера з прапорцем --admission-control-config-file:
Цей втулок полегшує створення виділених вузлів з розширеними ресурсами. Якщо оператори хочуть створити виділені вузли з розширеними ресурсами (наприклад, GPU, FPGA тощо), вони повинні накладати taint на вузол з іменем розширеного ресурсу як ключем. Цей контролер допуску, якщо він увімкнений, автоматично додає толерантності до таких taint у Podʼи, які запитують розширені ресурси, тому користувачам не потрібно вручну додавати ці толерантності.
Цей контролер допуску стандартно вимкнено.
ImagePolicyWebhook
Тип: Валідаційний.
Контролер допуску ImagePolicyWebhook дозволяє бекенд-вебхуку приймати рішення про допуск.
Цей контролер допуску стандартно вимкнено.
Формат конфігураційного файлу
ImagePolicyWebhook використовує конфігураційний файл для налаштування поведінки бекенду. Цей файл може бути у форматі JSON або YAML і має наступний формат:
imagePolicy:kubeConfigFile:/path/to/kubeconfig/for/backend# час у секундах для кешування дозволуallowTTL:50# час у секундах для кешування відмовиdenyTTL:50# час у мілісекундах між спробами повторуretryBackoff:500# визначає поведінку у разі відмови бекенда вебхукаdefaultAllow:true
Посилання на конфігураційний файл ImagePolicyWebhook повинно бути зазначене у файлі, який передається прапорцю командного рядка API-сервера --admission-control-config-file:
Конфігураційний файл ImagePolicyWebhook повинен посилатися на файл у форматі kubeconfig, який налаштовує зʼєднання з бекендом. Бекенд повинен здійснювати комунікацію через TLS.
Поле cluster у файлі kubeconfig має посилатися на віддалений сервіс, а поле user повинно містити дані авторизації.
# clusters посилається на віддалений сервіс.clusters:- name:name-of-remote-imagepolicy-servicecluster:certificate-authority:/path/to/ca.pem # CA для верифікації віддаленого сервісу.server:https://images.example.com/policy# URL віддаленого сервісу для запитів. Повинен використовувати 'https'.# users посилається на конфігурацію вебхука API-сервера.users:- name:name-of-api-serveruser:client-certificate:/path/to/cert.pem# сертифікат для використання контролером допуску вебхукаclient-key:/path/to/key.pem # ключ, що відповідає сертифікату
Для додаткової конфігурації HTTP дивіться документацію kubeconfig.
Вміст запитів
Під час прийняття рішення про допуск, API-сервер надсилає POST-запит з серіалізованим у форматі JSON обʼєктом imagepolicy.k8s.io/v1alpha1ImageReview, що описує дію. Цей обʼєкт містить поля, що описують контейнери, які підлягають допуску, а також будь-які анотації Podʼа, що відповідають *.image-policy.k8s.io/*.
Примітка:
Обʼєкти API вебхуків підлягають тим самим правилам сумісності версій, що й інші обʼєкти API Kubernetes. Імплементатори повинні знати про менш жорсткі обіцянки сумісності для альфа-обʼєктів і перевіряти поле apiVersion запиту для забезпечення правильної десеріалізації. Крім того, API-сервер повинен увімкнути групу розширень API imagepolicy.k8s.io/v1alpha1 (--runtime-config=imagepolicy.k8s.io/v1alpha1=true).
Віддалений сервіс повинен заповнити поле status запиту і відповісти з дозволом або відмовою доступу. Поле spec тіла відповіді ігнорується, і його можна не включати. Відповідь, яка дозволяє доступ, виглядатиме так:
Усі анотації на Podʼі, що відповідають *.image-policy.k8s.io/*, надсилаються до вебхука. Надсилання анотацій дозволяє користувачам, які знають про бекенд політики образів, надсилати додаткову інформацію до нього, а також дозволяє реалізаціям різних бекендів приймати різну інформацію.
Приклади інформації, яку ви можете тут розмістити:
запит на "пробиття" для обходу політики у разі надзвичайної ситуації;
номер квитка з системи квитків, що документує запит на "пробиття";
підказка серверу політики щодо imageID наданого образу для економії часу на пошук.
У будь-якому випадку, анотації надаються користувачем і не перевіряються Kubernetes будь-яким чином.
LimitPodHardAntiAffinityTopology
Тип: Валідаційний.
Цей контролер допуску забороняє будь-який Pod, який визначає ключ топології AntiAffinity відмінний від kubernetes.io/hostname у requiredDuringSchedulingRequiredDuringExecution.
Цей контролер допуску стандартно вимкнено.
LimitRanger
Тип: Модифікуючий та Валідаційний.
Цей контролер допуску спостерігає за вхідним запитом та забезпечує, щоб він не порушував жодних обмежень, перерахованих в обʼєкті LimitRange в Namespace. Якщо ви використовуєте обʼєкти LimitRange у своєму розгортанні Kubernetes, ви МАЄТЕ використовувати цей контролер допуску для забезпечення дотримання цих обмежень. LimitRanger також може використовуватися для застосування стандартних ресурсних запитів до Pod, які їх не вказують; наразі стандартний LimitRanger застосовує вимогу до 0.1 CPU до всіх Pod у default namespace.
Цей контролер допуску викликає будь-які модифікуючі вебхуки, які відповідають запиту. Відповідні вебхуки викликаються послідовно; кожен з них може змінити обʼєкт, якщо це необхідно.
Цей контролер допуску (як випливає з назви) працює лише на етапі модифікації.
Якщо вебхук, викликаний цим контролером, має побічні ефекти (наприклад, зменшення квоти), він повинен мати систему узгодження, оскільки не гарантується, що наступні вебхуки або контролери допуску дозволять завершити запит.
Якщо ви вимкнете MutatingAdmissionWebhook, ви також повинні вимкнути обʼєкт MutatingWebhookConfiguration у групі/версії admissionregistration.k8s.io/v1 за допомогою прапорця --runtime-config, обидва стандартно увімкнені.
Будьте обережні при створенні та встановленні модифікуючих вебхуків
Користувачі можуть бути спантеличені, коли обʼєкти, які вони намагаються створити, відрізняються від того, що вони отримують назад.
Вбудовані контрольні цикли можуть зламатися, коли обʼєкти, які вони намагаються створити, відрізняються при зворотному читанні.
Встановлення спочатку незаданих полів менш ймовірно викличе проблеми, ніж переписування полів, встановлених у початковому запиті. Уникайте останнього.
Майбутні зміни в контрольних циклах для вбудованих або сторонніх ресурсів можуть зламати вебхуки, які добре працюють сьогодні. Навіть коли API вебхука для установки буде фіналізовано, не всі можливі поведінки вебхука будуть гарантовано підтримуватися нескінченно.
NamespaceAutoProvision
Тип: Модифікуючий.
Цей контролер допуску перевіряє всі вхідні запити на ресурси, що належать до namespace, і перевіряє чи існує зазначений namespace. Він створює namespace, якщо його не знайдено. Цей контролер допуску корисний у розгортаннях, які не хочуть обмежувати створення namespace до його використання.
NamespaceExists
Тип: Валідаційний.
Цей контролер допуску перевіряє всі запити на ресурси, що належать до namespace, крім самого Namespace. Якщо namespace, на який посилається запит, не існує, запит відхиляється.
NamespaceLifecycle
Тип: Валідаційний.
Цей контролер допуску забезпечує, що Namespace, який знаходиться в процесі завершення, не може мати нові обʼєкти, створені в ньому, і забезпечує відхилення запитів у неіснуючому Namespace. Цей контролер допуску також запобігає видаленню трьох системно зарезервованих namespaces: default, kube-system, kube-public.
Видалення Namespace запускає послідовність операцій, які видаляють усі обʼєкти (Pod, Service, тощо) у цьому namespace. Для забезпечення цілісності цього процесу, ми наполегливо рекомендуємо використовувати цей контролер допуску.
NodeRestriction
Тип: Валідаційний.
Цей контролер допуску обмежує обʼєкти Node і Pod, які kubelet може змінювати. Для того, щоб бути обмеженим цим контролером допуску, kubelets повинні використовувати облікові дані у групі system:nodes, з іменем користувача у формі system:node:<nodeName>. Такі kubelets будуть мати дозвіл лише змінювати свої власні обʼєкти API Node, і лише змінювати обʼєкти API Pod, які привʼязані до їх вузла. kubelets не мають права оновлювати або видаляти taint зі свого обʼєкта API Node.
Втулок допуску NodeRestriction перешкоджає kubelets видаляти їх обʼєкт API Node, і забезпечує оновлення kubeletʼом міток з префіксами kubernetes.io/ або k8s.io/ наступним чином:
Перешкоджає kubelets додавання/видалення/оновлення міток з префіксом node-restriction.kubernetes.io/. Цей префікс міток зарезервовано для адміністраторів для позначення мітками своїх обʼєктів Node з метою ізоляції робочих навантажень, і kubelets не буде дозволено змінювати мітки з цим префіксом.
Дозволяє kubelets додавати/видаляти/оновлювати ці мітки та префікси міток:
Використання будь-яких інших міток під префіксами kubernetes.io або k8s.io kubelets зарезервовано, і може бути заборонено або дозволено втулком допуску NodeRestriction у майбутньому.
Майбутні версії можуть додати додаткові обмеження для забезпечення того, щоб kubelets мали мінімальний набір дозволів, необхідних для правильної роботи.
OwnerReferencesPermissionEnforcement
Тип: Валідаційний.
Цей контролер допуску захищає доступ до metadata.ownerReferences обʼєкта, так що тільки користувачі з правами delete у обʼєкта можуть його змінювати. Цей контролер допуску також захищає доступ до metadata.ownerReferences[x].blockOwnerDeletion обʼєкта, так що тільки користувачі з правами update у субресурсу finalizers посилального власника можуть його змінювати.
PersistentVolumeClaimResize
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.24 [stable]
Тип: Валідаційний.
Цей контролер допуску реалізує додаткові перевірки для перевірки вхідних запитів на зміну розміру PersistentVolumeClaim.
Рекомендується увімкнути контролер допуску PersistentVolumeClaimResize. Цей контролер допуску запобігає зміні розміру всіх вимог за замовчуванням, якщо тільки StorageClass вимоги явно не дозволяє зміну розміру, встановлюючи allowVolumeExpansion на true.
Наприклад: всі PersistentVolumeClaim, створені з наступного StorageClass, підтримують розширення тому:
Для отримання додаткової інформації про persistent volume claims, дивіться PersistentVolumeClaims.
PodNodeSelector
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.5 [alpha]
Тип: Валідаційний.
Цей контролер допуску задає та обмежує, які селектори вузлів можуть використовуватися в межах namespace, шляхом читання анотації namespace та глобальної конфігурації.
Цей контролер допуску стандартно вимкнено.
Формат конфігураційного файлу
PodNodeSelector використовує конфігураційний файл для налаштування параметрів поведінки бекенду. Зверніть увагу, що формат конфігураційного файлу буде змінено на версійований файл у майбутньому випуску. Цей файл може бути у форматі json або yaml і має наступний формат:
Якщо Namespace має анотацію з ключем scheduler.alpha.kubernetes.io/node-selector, використовуйте її значення як селектор вузлів.
Якщо namespace не має такої анотації, використовуйте clusterDefaultNodeSelector, визначений у конфігураційному файлі втулка PodNodeSelector, як селектор вузлів.
Оцініть селектор вузлів Podʼа щодо селектора вузлів namespace на предмет конфліктів. Конфлікти призводять до відхилення.
Оцініть селектор вузлів Podʼа щодо дозволеного селектора, визначеного у конфігураційному файлі плагіну для конкретного namespace. Конфлікти призводять до відхилення.
Примітка:
PodNodeSelector дозволяє змусити Podʼи працювати на вузлах зі спеціальними мітками. Дивіться також втулок допуску PodTolerationRestriction, який дозволяє запобігти запуску Podʼів на вузлах зі спеціальними taintʼами.
PodSecurity
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.25 [stable]
Тип: Валідаційний.
Контролер допуску PodSecurity перевіряє нові Podʼи перед їх допуском і визначає, чи варто їх допускати на основі запитуваного контексту безпеки та обмежень щодо дозволених Стандартів безпеки для Podʼів для namespace, в якому буде знаходитися Pod.
PodSecurity замінив старіший контролер допуску під назвою PodSecurityPolicy.
PodTolerationRestriction
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.7 [alpha]
Тип: Модифікуючий та Валідаційний.
Контролер допуску PodTolerationRestriction перевіряє конфлікти між толерантностями Podʼа та толерантностями його namespace. Він відхиляє запит Podʼа у разі конфлікту. Потім він обʼєднує толерантності, анотовані на namespace, з толерантностями Podʼа. Отримані толерантності перевіряються щодо списку дозволених толерантностей, анотованих на namespace. Якщо перевірка пройде успішно, запит Podʼа допускається, інакше він відхиляється.
Якщо namespace Podʼа не має повʼязаних з ним стандартних толерантностей або дозволених толерантностей, анотованих, використовуються стандартні толерантності на рівні кластера або список дозволених толерантностей на рівні кластера, якщо вони зазначені.
Толерантності призначаються namespace за допомогою ключа анотації scheduler.alpha.kubernetes.io/defaultTolerations. Список дозволених толерантностей можна додати за допомогою ключа анотації scheduler.alpha.kubernetes.io/tolerationsWhitelist.
Контролер допуску Priority використовує поле priorityClassName і заповнює ціле значення пріоритету. Якщо клас пріоритету не знайдено, Pod відхиляється.
ResourceQuota
Тип: Валідаційний.
Цей контролер допуску спостерігає за вхідним запитом і гарантує, що він не порушує жодних обмежень, перерахованих у обʼєкті ResourceQuota у Namespace. Якщо ви використовуєте обʼєкти ResourceQuota у вашому розгортанні Kubernetes, ви МАЄТЕ використовувати цей контролер допуску для забезпечення дотримання квот.
Якщо ви визначаєте RuntimeClass з налаштованими накладними витратами, повʼязаними з роботою Podʼів, цей контролер допуску перевіряє вхідні Podʼи. При увімкненні, цей контролер допуску відхиляє будь-які запити на створення Podʼів, які вже мають встановлений overhead. Для Podʼів, які мають налаштований і обраний у своєму .spec RuntimeClass, цей контролер допуску встановлює .spec.overhead у Pod на основі значення, визначеного у відповідному RuntimeClass.
Цей контролер допуску реалізує автоматизацію для службових облікових записів. Проєкт Kubernetes наполегливо рекомендує увімкнути цей контролер допуску. Вам слід увімкнути цей контролер допуску, якщо ви маєте намір використовувати обʼєкти ServiceAccount в Kubernetes.
Щодо анотації kubernetes.io/enforce-mountable-secrets: Хоча назва анотації вказує, що вона стосується лише монтування Secrets, її застосування також поширюється на інші способи використання Secrets в контексті Pod. Тому важливо переконатися, що всі зазначені секрети правильно вказані в ServiceAccount.
StorageObjectInUseProtection
Тип: Модифікуючий.
Втулок StorageObjectInUseProtection додає завершувачі kubernetes.io/pvc-protection або kubernetes.io/pv-protection до новостворених Persistent Volume Claims (PVC) або Persistent Volumes (PV). У випадку видалення користувача PVC або PV PVC або PV не видаляється, поки завершувач не буде видалений з PVC або PV за допомогою контролера захисту PVC або PV.
Дивіться Захист обʼєктів зберігання які використовуються для отримання детальнішої інформації.
TaintNodesByCondition
Тип: Модифікуючий.
Цей контролер допуску додає taint до новостворених вузлів таких як NotReady та NoSchedule. Це позначення доволє уникнути стану перегонів, який може призвести до того, що Podʼи будуть заплановані на нових вузлах до того, як їх taint будуть оновлені для точної відповідності їх звітніх умов.
ValidatingAdmissionPolicy
Тип: Валідаційний.
Цей контролер допуску реалізує перевірку CEL для вхідних запитів, що збігаються. Він увімкнений, коли увімкнені як функціональна можливість validatingadmissionpolicy, так і група/версія admissionregistration.k8s.io/v1alpha1. Якщо будь-яка з політик ValidatingAdmissionPolicy не вдасться, запит не вдасться.
ValidatingAdmissionWebhook
Тип: Валідаційний.
Цей контролер допуску викликає будь-які валідуючі вебхуки, які відповідають запиту. Валідуючі вебхуки викликаються паралельно; якщо будь-який з них відхиляє запит, запит не вдається. Цей контролер допуску працює лише на етапі валідації; вебхуки, які він викликає, не можуть змінювати обʼєкт, на відміну від вебхуків, які викликаються контролером допуску MutatingAdmissionWebhook.
Якщо вебхук який викликається цим контролером, має побічні ефекти (наприклад, зменшення квоти), то обовʼязково має бути система реконсіляції, оскільки не гарантується, що подальші вебхуки або інші валідаційні контролери допуску дозволять закінчити запит.
Якщо ви вимкнете ValidatingAdmissionWebhook, вам також слід вимкнути обʼєкт ValidatingWebhookConfiguration у групі/версії admissionregistration.k8s.io/v1 за допомогою прапорця --runtime-config.
Чи існує рекомендований набір контролерів допуску для використання?
Так. Рекомендовані контролери допуску стандартно увімкнені (дивіться тут), тому вам не потрібно явно вказувати їх. Ви можете увімкнути додаткові контролери допуску поза стандартним набором за допомогою прапорця --enable-admission-plugins (порядок не має значення).
9 - Динамічне керування допуском
Окрім вбудованих втулків допуску, втулки допуску можуть бути розроблені як розширення і виконуватися як вебхуки, налаштовані під час роботи. Ця сторінка описує, як будувати, налаштовувати, використовувати та контролювати вебхуки допуску.
Що таке вебхуки допуску?
Вебхуки допуску — це зворотні виклики HTTP, які отримують запити на допуск та роблять з ними щось. Ви можете визначити два типи вебхуків допуску, валідаційний вебхук допуску та модифікуючий вебхук допуску. Модифікуючі вебхуки допуску викликаються першими та можуть змінювати обʼєкти, які надсилаються на сервер API, щоб застосовувати власні стандартні значення. Після завершення всіх модифікацій обʼєктів і після того, як вхідний обʼєкт перевірений сервером API, викликаються валідаційні вебхуки допуску та можуть відхиляти запити для застосування власних політик.
Примітка:
Вебхуки допуску, які потребують гарантії того, що вони бачать кінцевий стан обʼєкта, щоб застосувати політику, повинні використовувати валідаційний вебхук допуску, оскільки обʼєкти можуть бути змінені після того, як їх оглянули модифікуючі вебхуки.
Експерименти з вебхуками допуску
Вебхуки допуску фактично є частиною панелі управління кластера. Ви повинні писати та розгортати їх з великою обережністю. Будь ласка, прочитайте посібники користувача для інструкцій, якщо ви маєте намір писати/розгортати вебхуки допуску промислового рівня. Нижче ми описуємо, як швидко експериментувати з вебхуками допуску.
Передумови
Переконайтеся, що контролери допуску MutatingAdmissionWebhook та ValidatingAdmissionWebhook
увімкнені. Тут є рекомендований набір контролерів допуску для загального увімкнення.
Переконайтеся, що API admissionregistration.k8s.io/v1 увімкнено.
Написання сервера вебхуків допуску
Будь ласка, зверніться до реалізації сервера вебхуків допуску, який перевірено в е2е-тесті Kubernetes. Сервер вебхуків обробляє запити AdmissionReview, надіслані серверами API, і повертає своє рішення як обʼєкт AdmissionReview в тій же версії, що й отримав.
Дивіться розділ запиту вебхуку для деталей щодо даних, надісланих до вебхуків.
Дивіться розділ відповіді вебхуку для деталей щодо даних, які очікуються від вебхуків.
Приклад сервера вебхуків допуску залишає поле ClientAuthпорожнім, що типово дорівнює NoClientCert. Це означає, що сервер вебхуків не автентифікує ідентичність клієнтів, які, припускається, є серверами API. Якщо вам потрібен взаємний TLS або інші способи автентифікації клієнтів, дивіться як автентифікувати сервери API.
Розгортання служби вебхуків допуску
Сервер вебхуків у е2е-тесті розгортається в кластері Kubernetes за допомогою API deployment. Тест також створює службу як фронтенд сервера вебхуків. Дивіться код.
Ви також можете розгортати свої вебхуки поза кластером. Вам потрібно буде оновити відповідно ваші конфігурації вебхуків.
Приклад ValidatingWebhookConfiguration, конфігурація модифікуючого вебхуку подібна. Дивіться розділ конфігурації вебхуку для деталей про кожне поле конфігурації.
Ви повинні замінити <CA_BUNDLE> у вищезазначеному прикладі на дійсний пакунок CA це PEM-кодований (значення поля закодовано у Base64) пакунок CA для перевірки вебсервера сертифіката.
Поле scope вказує, чи тільки ресурси з області кластера ("Cluster") або з області простору імен ("Namespaced") будуть відповідати цьому правилу. "∗" означає, що обмежень області немає.
Примітка:
При використанні clientConfig.service, сертифікат сервера повинен бути дійсним для
<svc_name>.<svc_namespace>.svc.
Примітка:
Стандартний тайм-авт вебхуку — 10 секунд, ви можете встановити timeout, і рекомендується використовувати короткий тайм-авт для вебхуків. Якщо виклик вебхуку перевищує тайм-авт, запит обробляється відповідно до політики відмови вебхуку.
Коли сервер API отримує запит, що відповідає одному з rules, сервер API надсилає запит admissionReview до вебхуку, як зазначено в clientConfig.
Після створення конфігурації вебхуку, системі знадобиться кілька секунд, щоб визнати нову конфігурацію.
Автентифікація серверів API
Якщо вашим вебхукам для допуску потрібна автентифікація, ви можете налаштувати сервери API для використання базової автентифікації, токенів на предʼявника (bearer token) або сертифікатів для автентифікації себе у вебхуках. Налаштування складається з трьох кроків.
Під час запуску сервера API вкажіть розташування файлу конфігурації керування допуском за допомогою прапорця --admission-control-config-file.
У файлі конфігурації керування допуском вкажіть, де контролери MutatingAdmissionWebhook та ValidatingAdmissionWebhook повинні читати облікові дані. Облікові дані зберігаються у файлах kubeConfig (так, це та сама схема, що використовується kubectl), тому назва поля — kubeConfigFile. Ось приклад файлу конфігурації керування допуском:
# Застаріло у v1.17 на користь apiserver.config.k8s.io/v1apiVersion:apiserver.k8s.io/v1alpha1kind:AdmissionConfigurationplugins:- name:ValidatingAdmissionWebhookconfiguration:# Застаріло у v1.17 на користь apiserver.config.k8s.io/v1, kind=WebhookAdmissionConfigurationapiVersion:apiserver.config.k8s.io/v1alpha1kind:WebhookAdmissionkubeConfigFile:"<path-to-kubeconfig-file>"- name:MutatingAdmissionWebhookconfiguration:# Застаріло у v1.17 на користь apiserver.config.k8s.io/v1, kind=WebhookAdmissionConfigurationapiVersion:apiserver.config.k8s.io/v1alpha1kind:WebhookAdmissionkubeConfigFile:"<path-to-kubeconfig-file>"
apiVersion:v1kind:Configusers:# name повинно бути встановлено на DNS-імʼя служби або хост (включаючи порт) URL-адреси, з якою налаштовано взаємодію вебхуку.# Якщо для служб використовується порт, відмінний від 443, його необхідно включити до імені під час налаштування серверів API версії 1.16+.## Для вебхуку, налаштованого для взаємодії зі службою настандартному порті (443), вкажіть DNS-імʼя служби:# - name: webhook1.ns1.svc# user: ...## Для вебхуку, налаштованого для взаємодії зі службою на нестандартному порту (наприклад, 8443), вкажіть DNS-імʼя та порт служби у версії 1.16+:# - name: webhook1.ns1.svc:8443# user: ...# і, за бажанням, створіть другу секцію, використовуючи лише DNS-імʼя служби для сумісності з серверами API версії 1.15:# - name: webhook1.ns1.svc# user: ...## Для вебхуків, налаштованих для взаємодії з URL-адресою, вкажіть хост (і порт), вказані в URL-адресі вебхуку. Приклади:# Вебхук з `url: https://www.example.com`:# - name: www.example.com# user: ...## Вебхук з `url: https://www.example.com:443`:# - name: www.example.com:443# user: ...## Вебхук з `url: https://www.example.com:8443`:# - name: www.example.com:8443# user: ...#- name:'webhook1.ns1.svc'user:client-certificate-data:"<pem encoded certificate>"client-key-data:"<pem encoded key>"# Поле `name` підтримує використання * для підстановки сегментів префікса.- name:'*.webhook-company.org'user:password:"<password>"username:"<name>"# '*' є стандартним збігом.- name:'*'user:token:"<token>"
Звичайно, вам потрібно налаштувати сервер вебхуків для обробки цих запитів на автентифікацію.
Запит і відповідь вебхука
Запит
Вебхуки надсилаються як POST-запити з Content-Type: application/json, з об’єктом API AdmissionReview в API-групі admission.k8s.io, серіалізованим у JSON як тіло запиту.
Вебхуки можуть вказувати, які версії об’єктів AdmissionReview вони приймають, використовуючи поле admissionReviewVersions у своїй конфігурації:
admissionReviewVersions є обов’язковим полем при створенні конфігурацій вебхуків. Вебхуки повинні підтримувати принаймні одну версію AdmissionReview, яка зрозуміла поточному та попередньому API-серверу.
API-сервери надсилають першу версію AdmissionReview зі списку admissionReviewVersions, яку вони підтримують. Якщо жодна з версій у списку не підтримується API-сервером, створення конфігурації не буде дозволено. Якщо API-сервер виявляє конфігурацію вебхука, яка була створена раніше і не підтримує жодної з версій AdmissionReview, які API-сервер може надсилати, спроби виклику вебхука будуть невдалими та підлягатимуть політиці відмови.
Цей приклад показує дані, що містяться в об’єкті AdmissionReview для запиту на оновлення субресурсу scale для Deployment з групи apps/v1:
apiVersion:admission.k8s.io/v1kind:AdmissionReviewrequest:# Випадковий uid, що унікально ідентифікує цей виклик підтвердженняuid:705ab4f5-6393-11e8-b7cc-42010a800002# Повністю кваліфікована група/версія/тип вхідного об’єктаkind:group:autoscalingversion:v1kind:Scale# Повністю кваліфікована група/версія/тип ресурсу, що змінюєтьсяresource:group:appsversion:v1resource:deployments# субресурс, якщо запит стосується субресурсуsubResource:scale# Повністю кваліфікована група/версія/тип вхідного об’єкта в початковому запиті до API-сервера.# Це відрізняється від `kind`, лише якщо вебхук вказав `matchPolicy: Equivalent` і початковий запит до API-сервера був конвертований у версію, для якої зареєстровано вебхук.requestKind:group:autoscalingversion:v1kind:Scale# Повністю кваліфікована група/версія/тип ресурсу, що змінюється в початковому запиті до API-сервера.# Це відрізняється від `resource`, лише якщо вебхук вказав `matchPolicy: Equivalent` і початковий запит до API-сервера був конвертований у версію, для якої зареєстровано вебхук.requestResource:group:appsversion:v1resource:deployments# субресурс, якщо запит стосується субресурсу# Це відрізняється від `subResource`, лише якщо вебхук вказав `matchPolicy: Equivalent` і початковий запит до API-сервера був конвертований у версію, для якої зареєстровано вебхук.requestSubResource:scale# Ім’я ресурсу, що змінюєтьсяname:my-deployment# Простір імен ресурсу, що змінюється, якщо ресурс має простір імен (або є об’єктом Namespace)namespace:my-namespace# операція може бути CREATE, UPDATE, DELETE або CONNECToperation:UPDATEuserInfo:# Ім’я користувача автентифікованого користувача, що робить запит до API-сервераusername:admin# UID автентифікованого користувача, що робить запит до API-сервераuid:014fbff9a07c# Групові членства автентифікованого користувача, що робить запит до API-сервераgroups:- system:authenticated- my-admin-group# Додаткова довільна інформація, пов’язана з користувачем, що робить запит до API-сервера.# Це заповнюється шаром автентифікації API-сервера і повинно бути включено,# якщо будь-які перевірки SubjectAccessReview виконуються вебхуком.extra:some-key:- some-value1- some-value2# object є новим об’єктом, що підлягає допуску.# Це null для операцій DELETE.object:apiVersion:autoscaling/v1kind:Scale# oldObject є існуючим об’єктом.# Це null для операцій CREATE та CONNECT.oldObject:apiVersion:autoscaling/v1kind:Scale# options містить параметри операції, що підлягає допуску, як-от meta.k8s.io/v1 CreateOptions, UpdateOptions або DeleteOptions.# Це null для операцій CONNECT.options:apiVersion:meta.k8s.io/v1kind:UpdateOptions# dryRun вказує, що API-запит виконується в режимі dry run і не буде збережений.# Вебхуки з побічними ефектами повинні уникати здійснення цих побічних ефектів, коли dryRun дорівнює true.# Див. http://k8s.io/docs/reference/using-api/api-concepts/#make-a-dry-run-request для додаткової інформації.dryRun:False
Відповідь
Вебхуки відповідають зі статус-кодом HTTP 200, Content-Type: application/json та тілом, що містить об’єкт AdmissionReview (у тій же версії, що була надіслана), з заповненою секцією response, серіалізованою у JSON.
Мінімум, секція response повинна містити такі поля:
uid, скопійований з request.uid, що був надісланий до вебхука
allowed, встановлений або в true, або в false
Приклад мінімальної відповіді від вебхука для дозволу запиту:
При відхиленні запиту вебхук може налаштувати HTTP-код та повідомлення, яке повертається користувачеві, використовуючи поле status. Вказаний об’єкт статусу повертається користувачеві. Див. Довідник API для деталей про тип status. Приклад відповіді для заборони запиту з налаштуванням HTTP-коду та повідомлення, яке буде представлено користувачеві:
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"uid": "<значення з request.uid>",
"allowed": false,
"status": {
"code": 403,
"message": "Ви не можете це зробити, тому що сьогодні вівторок і ваше ім’я починається з літери А" }
}
}
При дозволі запиту, модифікуючий вебхук допуску може за бажанням модифікувати вхідний об’єкт. Це робиться за допомогою полів patch та patchType у відповіді. Єдиний підтримуваний тип patchType наразі — JSONPatch. Див. документацію JSON patch для додаткової інформації. Для patchType: JSONPatch, поле patch містить base64-кодований масив операцій JSON patch.
Як приклад, єдина операція patch, яка встановить spec.replicas, виглядає так: [{"op": "add", "path": "/spec/replicas", "value": 3}]
Base64-кодована, вона виглядатиме так: W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvcmVwbGljYXMiLCAidmFsdWUiOiAzfV0=
Отже, відповідь вебхука для додавання цієї мітки буде такою:
Вебхуки допуску можуть за бажанням повертати попереджувальні повідомлення, які повертаються клієнту, що зробив запит, у HTTP-заголовках Warning з кодом попередження 299. Попередження можуть бути надіслані з дозволеними або відхиленими відповідями на допуск.
Якщо ви реалізуєте вебхук, що повертає попередження:
Не включайте префікс "Warning:" у повідомлення
Використовуйте попереджувальні повідомлення для опису проблем, які клієнт, що робить API-запит, має виправити або про які має знати
За можливості, обмежуйте попередження до 120 символів
Увага:
Індивідуальні попереджувальні повідомлення довжиною понад 256 символів можуть бути скорочені API-сервером перед поверненням клієнтам. Якщо додано більше 4096 символів попереджувальних повідомлень (від усіх джерел), додаткові попередження ігноруються.
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"uid": "<значення з request.uid>",
"allowed": true,
"warnings": [
"зазначено дублюючі записи envvar з іменем MY_ENV",
"запит на пам’ять менший за 4 МБ зазначено для контейнера mycontainer, який не запуститься успішно" ]
}
}
Конфігурація вебхука
Для реєстрації вебхуків допуску створіть об’єкти API MutatingWebhookConfiguration або ValidatingWebhookConfiguration. Назва об’єкта MutatingWebhookConfiguration або ValidatingWebhookConfiguration має бути дійсним DNS-імʼям субдомену.
Кожна конфігурація може містити один або кілька вебхуків. Якщо в одній конфігурації вказано кілька вебхуків, кожен з них повинен мати унікальну назву. Це необхідно для полегшення відповідності логів аудиту та метрик активних конфігурацій.
Кожен вебхук визначає наступні параметри.
Відповідність запитів: правила
Кожен вебхук має вказувати список правил, що використовуються для визначення, чи повинен запит до API-сервера бути надісланий до вебхука. Кожне правило вказує одну або кілька операцій, груп API, версій API та ресурсів, а також область ресурсу:
operations отримує перелік з однієї або кількох операцій для порівняння. Можливі значення: "CREATE", "UPDATE", "DELETE", "CONNECT" або "*" для збігу зі всіма операціям.
apiGroups отримує перелік з однієї або кількох груп API для порівняння. "" означає ядро групи API. "*" відповідає всім групам API.
apiVersions отримує перелік з однієї або кількох версій API для порівняння. "*" відповідає всім версіям API.
resources отримує перелік з одного або кількох ресурсів для порівняння.
"*" відповідає всім ресурсам, але не субресурсам.
"*/*" відповідає всім ресурсам і субресурсам.
"pods/*" відповідає всім субресурсам Podʼів.
"*/status" відповідає всім субресурсам статусу.
scope вказує область для порівняння. Допустимі значення: "Cluster", "Namespaced" та "*". Субресурси відповідають області їх батьківського ресурсу. Стандартно "*".
"Cluster" означає, що тільки ресурси з кластерною областю відповідатимуть цьому правилу (об’єкти Namespace мають кластерну область).
"Namespaced" означає, що тільки ресурси з простору імен відповідатимуть цьому правилу.
"*" означає, що немає обмежень щодо області.
Якщо вхідний запит відповідає одному з: operations, apiGroups, apiVersions, resources та scope для будь-якого з правил вебхука, запит надсилається до вебхука.
Ось інші приклади правил, які можуть бути використані для визначення, які ресурси слід перехоплювати.
Відповідність запитам CREATE або UPDATE до apps/v1 та apps/v1beta1deployments і replicasets:
Вебхуки можуть за бажанням обмежувати, які запити перехоплюються, на основі міток обʼєктів, до яких вони будуть надіслані, вказуючи objectSelector. Якщо вказано, objectSelector оцінюється як для обʼєкта, так і для старого обʼєкта, які будуть надіслані до вебхука, і вважається відповідним, якщо будь-який з обʼєктів відповідає селектору.
Обʼєкт, що дорівнює null (oldObject у випадку створення або newObject у випадку видалення), або обʼєкт, який не може мати міток (наприклад, обʼєкт DeploymentRollback або PodProxyOptions), не вважається відповідним.
Використовуйте селектор обʼєктів тільки якщо вебхук є опціональним, тому що кінцеві користувачі можуть обійти вебхук допуску, встановлюючи мітки.
Цей приклад показує модифікуючий вебхук, який відповідатиме CREATE для будь-якого ресурсу (але не субресурсів) з міткою foo: bar:
Див. концепцію міток для більшої кількості прикладів селекторів міток.
Відповідність запитів: namespaceSelector
Вебхуки можуть за бажанням обмежувати, які запити на ресурси в межах простору імен перехоплюються, на основі міток простору імен, до якого вони належать, вказуючи namespaceSelector.
namespaceSelector вирішує, чи слід запускати вебхук для запиту на ресурс у межах простору імен (або обʼєкт Namespace), на основі того, чи відповідають мітки простору імен селектору. Якщо обʼєкт сам є простором імен, відповідність виконується за object.metadata.labels. Якщо обʼєкт є кластерним ресурсом, відмінним від Namespace, namespaceSelector не впливає.
Цей приклад показує модифікуючий вебхук, який відповідає CREATE для будь-якого ресурсу в межах простору імен, який не має мітки "runlevel" зі значенням "0" або "1":
Цей приклад показує валідаційний вебхук, який відповідає CREATE для будь-якого ресурсу в межах простору імен, асоційованого з "environment" зі значенням "prod" або "staging":
Див. концепцію міток для більшої кількості прикладів селекторів міток.
Відповідність запитів: matchPolicy
API сервери можуть робити обʼєкти доступними через кілька API груп або версій.
Наприклад, якщо вебхук визначає правило для певних API груп/версій (наприклад, apiGroups:["apps"], apiVersions:["v1","v1beta1"]), і запит робиться для зміни ресурсу через іншу API групу/версію (наприклад, extensions/v1beta1), запит не буде надіслано до вебхука.
matchPolicy дозволяє вебхуку визначити, як його rules використовуються для відповідності вхідним запитам. Допустимі значення — Exact або Equivalent.
Exact означає, що запит повинен бути перехоплений тільки в тому випадку, якщо він точно відповідає зазначеному правилу.
Equivalent означає, що запит повинен бути перехоплений, якщо він модифікує ресурс, зазначений в rules, навіть через іншу API групу або версію.
У наведеному вище прикладі, вебхук, зареєстрований тільки для apps/v1, може використовувати matchPolicy:
matchPolicy: Exact означає, що запит extensions/v1beta1 не буде надіслано до вебхука.
matchPolicy: Equivalent означає, що запит extensions/v1beta1 буде надіслано до вебхука (з обʼєктами, конвертованими до версії, яку вебхук визначив: apps/v1).
Вказування Equivalent рекомендовано і забезпечує, що вебхуки продовжують перехоплювати очікувані ресурси, коли оновлення включають нові версії ресурсу в API сервері.
Коли ресурс перестає обслуговуватись API сервером, він більше не вважається еквівалентним іншим версіям цього ресурсу, які все ще обслуговуються. Наприклад, extensions/v1beta1 розгортання були спочатку визнані застарілими, а потім видалені (у Kubernetes v1.16).
З моменту цього видалення, вебхук з правилом apiGroups:["extensions"], apiVersions:["v1beta1"], resources:["deployments"] не перехоплює розгортання, створені через API apps/v1. З цієї причини, вебхуки повинні віддавати перевагу реєстрації для стабільних версій ресурсів.
Цей приклад показує валідаційний вебхук, який перехоплює модифікації розгортань (незалежно від API групи або версії) і завжди отримує обʼєкт Deployment версії apps/v1:
matchPolicy для вебхуків допуску за замовчуванням дорівнює Equivalent.
Відповідність запитів: matchConditions
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.30 [stable] (стандартно увімкнено: true)
Ви можете визначити умови відповідності для вебхуків, якщо вам потрібна точніша фільтрація запитів. Ці умови корисні, якщо правила відповідності, objectSelectors та namespaceSelectors не надають необхідної фільтрації при викликах по HTTP. Умови відповідності є CEL виразами. Всі умови відповідності повинні оцінюватися як true для виклику вебхука.
Ось приклад, що ілюструє декілька різних способів використання умов відповідності:
apiVersion:admissionregistration.k8s.io/v1kind:ValidatingWebhookConfigurationwebhooks:- name:my-webhook.example.commatchPolicy:Equivalentrules:- operations:['CREATE','UPDATE']apiGroups:['*']apiVersions:['*']resources:['*']failurePolicy:'Ignore'# Fail-open (опційно)sideEffects:NoneclientConfig:service:namespace:my-namespacename:my-webhookcaBundle:'<omitted>'# Ви можете мати до 64 умов відповідності на вебхукmatchConditions:- name:'exclude-leases'# Кожна умова відповідності повинна мати унікальне імʼяexpression:'!(request.resource.group == "coordination.k8s.io" && request.resource.resource == "leases")'# Відповідність ресурсам, які не є lease.- name:'exclude-kubelet-requests'expression:'!("system:nodes" in request.userInfo.groups)'# Відповідність запитам, зробленим не користувачами вузлів.- name:'rbac'# Пропуск запитів RBAC, які обробляються другим вебхуком.expression:'request.resource.group != "rbac.authorization.k8s.io"'# Цей приклад ілюструє використання 'authorizer'. Перевірка авторизації дорожча за простий вираз, тому в цьому прикладі вона обмежена лише запитами RBAC, використовуючи другий вебхук. Обидва вебхуки можуть обслуговуватись одним кінцевим пунктом.- name:rbac.my-webhook.example.commatchPolicy:Equivalentrules:- operations:['CREATE','UPDATE']apiGroups:['rbac.authorization.k8s.io']apiVersions:['*']resources:['*']failurePolicy:'Fail'# Fail-closed (стандартно)sideEffects:NoneclientConfig:service:namespace:my-namespacename:my-webhookcaBundle:'<omitted>'# Ви можете мати до 64 умов відповідності на вебхукmatchConditions:- name:'breakglass'# Пропуск запитів, зроблених користувачами, авторизованими для 'breakglass' на цьому вебхуку.# Дієслово API 'breakglass' не повинно існувати за межами цієї перевірки.expression:'!authorizer.group("admissionregistration.k8s.io").resource("validatingwebhookconfigurations").name("my-webhook.example.com").check("breakglass").allowed()'
Примітка:
Ви можете визначити до 64 елементів у полі matchConditions для кожного вебхука.
Умови відповідності мають доступ до наступних CEL змінних:
object — Обʼєкт з вхідного запиту. Значення є null для DELETE запитів. Версія обʼєкта може бути конвертована на основі matchPolicy.
oldObject — Наявний обʼєкт. Значення є null для CREATE запитів.
request — Частина запиту AdmissionReview, виключаючи object та oldObject.
authorizer — CEL Authorizer. Може використовуватись для виконання перевірок авторизації для головного облікового запису (автентифікованого користувача) запиту. Дивіться Authz у документації бібліотеки Kubernetes CEL для додаткової інформації.
authorizer.requestResource — Скорочення для перевірки авторизації, налаштованої на ресурс запиту (група, ресурс, (субресурс), простір імен, імʼя).
Коли сервер API визначає, що запит повинен бути надісланий до вебхука, йому потрібно знати, як звʼязатися з вебхуком. Це визначається в розділі clientConfig конфігурації вебхука.
Вебхуки можуть викликатися через URL або посилання на сервіс, і можуть за бажанням включати власний набір CA для використання для перевірки TLS-зʼєднання.
URL
Поле url вказує місцезнаходження вебхука у стандартній формі URL (scheme://host:port/path).
Поле host не повинно вказувати на сервіс, що працює в кластері; використовуйте посилання на сервіс, вказуючи поле service. Хост може бути вирішений через зовнішній DNS на деяких серверах API (наприклад, kube-apiserver не може вирішувати DNS всередині кластера, оскільки це буде порушенням шарів). host також може бути IP-адресою.
Зверніть увагу, що використання localhost або 127.0.0.1 як host є ризикованим, якщо ви не забезпечите запуск цього вебхука на всіх хостах, які запускають сервер API, який може потребувати викликів до цього вебхука. Такі інсталяції, ймовірно, будуть непереносними або не будуть легко запускатися в новому кластері.
Схема повинна бути "https"; URL повинен починатися з "https://".
Спроба використання користувача або базової автентифікації (наприклад, user:password@) не дозволена. Фрагменти (#...) та параметри запиту (?...) також не дозволені.
Ось приклад конфігурації модифікуючого вебхука для виклику URL (і очікується, що TLS-сертифікат буде перевірено за допомогою системних коренів довіри, тому не вказується caBundle):
Розділ service всередині clientConfig є посиланням на сервіс для цього вебхука. Якщо вебхук працює всередині кластера, вам слід використовувати service замість url. Необхідно вказати простір імен та імʼя сервісу. Порт є необовʼязковим і стандартно дорівнює 443. Шлях є необовʼязковим і стандартно дорівнює "/".
Ось приклад конфігурації модифікуючого вебхука для виклику сервісу на порту "1234" за підшляхом "/my-path", і для перевірки TLS-зʼєднання проти ServerName my-service-name.my-service-namespace.svc з використанням власного набору CA:
Ви повинні замінити <CA_BUNDLE> у наведеному вище прикладі на дійсний набір CA, який є PEM-кодованим набором CA для перевірки сертифіката сервера вебхука.
Побічні ефекти
Вебхуки зазвичай працюють тільки з вмістом AdmissionReview, надісланого їм. Однак деякі вебхуки здійснюють зміни поза межами під час обробки запитів на допуск.
Вебхуки, які здійснюють зміни поза межами ("побічні ефекти"), повинні також мати механізм узгодження (наприклад, контролер), який періодично визначає фактичний стан системи та коригує дані поза межами, змінені вебхуком допуску, щоб відобразити реальність. Це тому, що виклик до вебхука допуску не гарантує, що прийнятий обʼєкт буде збережений таким, яким він є, або взагалі. Пізніші вебхуки можуть змінити вміст обʼєкта, може виникнути конфлікт під час запису в сховище, або сервер може вимкнутися до збереження обʼєкта.
Крім того, вебхуки з побічними ефектами повинні пропускати ці побічні ефекти, коли обробляються запити допуску з dryRun: true. Вебхук повинен явно вказати, що він не матиме побічних ефектів при запуску з dryRun, інакше запит dry-run не буде надіслано до вебхука, і API-запит замість цього не вдасться.
Вебхуки вказують, чи мають вони побічні ефекти, за допомогою поля sideEffects у конфігурації вебхука:
None: виклик вебхука не матиме побічних ефектів.
NoneOnDryRun: виклик вебхука може мати побічні ефекти, але якщо до вебхука надіслано запит з dryRun: true, вебхук придушить побічні ефекти (вебхук враховує dryRun).
Ось приклад конфігурації вебхука перевірки, який вказує, що він не має побічних ефектів при запитах з dryRun: true:
Оскільки вебхуки додають затримку до запитів API, вони повинні оцінюватися якомога швидше. timeoutSeconds дозволяє налаштувати, скільки часу сервер API повинен чекати на відповідь вебхука, перш ніж розглядати виклик як невдалий.
Якщо тайм-аут закінчується до того, як вебхук відповість, виклик вебхука буде проігноровано або API-запит буде відхилено відповідно до політики помилок.
Значення тайм-ауту повинно бути між 1 і 30 секунд.
Ось приклад конфігурації вебхука перевірки з кастомним тайм-аутом у 2 секунди:
Тайм-аут для вебхука допуску стандартно становить 10 секунд.
Політика повторного виклику
Одне впорядкування втулків модифікуючого допуску (включаючи вебхуки) не підходить для всіх випадків (див. приклад у https://issue.k8s.io/64333). Модифікуючий вебхук може додати нову підструктуру до обʼєкта (наприклад, додати container до pod), а інші модифікуючи втулки, які вже виконані, можуть мати вплив на ці нові структури (наприклад, встановити imagePullPolicy для всіх контейнерів).
Щоб дозволити втулкам модифікуючого допуску спостерігати за змінами, внесеними іншими втулками, вбудовані модифікуючи втулки допуску повторно запускаються, якщо модифікуючий вебхук змінює обʼєкт, і модифікуючи вебхуки можуть вказати reinvocationPolicy для контролю того, чи будуть вони повторно викликані.
reinvocationPolicy може бути встановлено на Never або IfNeeded. Стандартно встановлено у Never.
Never: вебхук не повинен викликатися більше одного разу в рамках однієї оцінки допуску.
IfNeeded: вебхук може бути викликаний знову в рамках оцінки допуску, якщо обʼєкт, що авторизується, змінюється іншими втулками допуску після початкового виклику вебхука.
Важливі моменти, на які слід звернути увагу:
Кількість додаткових викликів не гарантується як точно одна.
Якщо додаткові виклики призводять до подальших змін обʼєкта, не гарантується, що вебхуки будуть викликані знов.
Вебхуки, які використовують цей параметр, можуть бути переупорядковані для мінімізації кількості додаткових викликів.
Щоб перевірити обʼєкт після того, як всі модифікації гарантовано завершені, використовуйте вебхук допуску (рекомендується для вебхуків з побічними ефектами).
Ось приклад конфігурації модифікуючого вебхука, який вибирає повторний виклик, якщо пізніші втулки допуску змінюють обʼєкт:
Модифікуючи вебхуки повинні бути ідемпотентними, здатними успішно обробити обʼєкт, який вони вже авторизували і потенційно змінили. Це стосується всіх модифікуючих вебхуків допуску, оскільки будь-яка зміна, яку вони можуть внести в обʼєкт, вже могла існувати в обʼєкті, наданому користувачем, але це є особливо важливим для вебхуків, які вибирають повторний виклик.
Політика обробки помилок
failurePolicy визначає, як обробляються невизнані помилки та помилки тайм-ауту від вебхука допуску. Допустимі значення: Ignore або Fail.
Ignore означає, що помилка при виклику вебхука ігнорується, і запит API дозволяється продовжити.
Fail означає, що помилка при виклику вебхука призводить до невдачі допуску та відхилення запиту API.
Ось приклад конфігурації модифікуючого вебхука, налаштованого на відхилення запиту API, якщо виникають помилки під час виклику вебхука допуску:
Стандартна політика обробки помилок failurePolicy для вебхуків допуску Fail.
Моніторинг вебхуків авторизації
Сервер API надає способи моніторингу поведінки вебхуків допуску. Ці механізми моніторингу допомагають адміністраторам кластерів відповісти на запитання, як:
Який модифікуючий вебхук змінив обʼєкт у запиті API?
Яку зміну модифікуючий вебхук застосував до обʼєкта?
Які вебхуки часто відхиляють запити API? Яка причина відхилення?
Анотації аудиту модифікуючих вебхуків
Іноді корисно знати, який модифікуючий вебхук змінив обʼєкт у запиті API, і яку зміну вебхук застосував.
Сервер API Kubernetes виконує аудит кожного виклику модифікуючого вебхука. Кожен виклик генерує анотацію аудиту, яка відображає, чи був обʼєкт запиту змінений викликом, і, за необхідності, генерує анотацію із застосованим патчем з відповіді вебхука допуску. Анотації встановлюються в подію аудиту для даного запиту на даній стадії його виконання, яка потім попередньо обробляється відповідно до певної політики та записується в бекенд.
Рівень аудиту події визначає, які анотації будуть записані:
На рівні аудиту Metadata або вище записується анотація з ключем mutation.webhook.admission.k8s.io/round_{round idx}_index_{order idx} з JSON-наватаженням, яке вказує, що вебхук був викликаний для даного запиту і чи змінив він обʼєкт чи ні.
Наприклад, наступна анотація записується для вебхука, який повторно викликається. Вебхук є третім у ланцюгу модифікуючих вебхуків і не змінив обʼєкт запиту під час виклику.
# записана подія аудиту{"kind": "Event","apiVersion": "audit.k8s.io/v1","annotations": {"mutation.webhook.admission.k8s.io/round_1_index_2": "{\"configuration\":\"my-mutating-webhook-configuration.example.com\",\"webhook\":\"my-webhook.example.com\",\"mutated\": false}"# інші анотації...}# інші поля...}
# десеріалізоване значення анотації{"configuration": "my-mutating-webhook-configuration.example.com","webhook": "my-webhook.example.com","mutated": false}
Наступна анотація записується для вебхука, який викликається на першій стадії. Вебхук є першим у ланцюгу модифікуючих вебхуків і змінив обʼєкт запиту під час виклику.
# записана подія аудиту{"kind": "Event","apiVersion": "audit.k8s.io/v1","annotations": {"mutation.webhook.admission.k8s.io/round_0_index_0": "{\"configuration\":\"my-mutating-webhook-configuration.example.com\",\"webhook\":\"my-webhook-always-mutate.example.com\",\"mutated\": true}"# інші анотації...}# інші поля...}
# десеріалізоване значення анотації{"configuration": "my-mutating-webhook-configuration.example.com","webhook": "my-webhook-always-mutate.example.com","mutated": true}
На рівні аудиту Request або вище записується анотація з ключем patch.webhook.admission.k8s.io/round_{round idx}_index_{order idx} з JSON-навантаженням, яке вказує, що вебхук був викликаний для даного запиту і який патч був застосований до обʼєкта запиту.
Наприклад, наступна анотація записується для вебхука, який повторно викликається. Вебхук є четвертим у ланцюгу модифікуючих вебхуків і відповів JSON-патчем, який був застосований до обʼєкта запиту.
# записана подія аудиту{"kind": "Event","apiVersion": "audit.k8s.io/v1","annotations": {"patch.webhook.admission.k8s.io/round_1_index_3": "{\"configuration\":\"my-other-mutating-webhook-configuration.example.com\",\"webhook\":\"my-webhook-always-mutate.example.com\",\"patch\":[{\"op\":\"add\",\"path\":\"/data/mutation-stage\",\"value\":\"yes\"}],\"patchType\":\"JSONPatch\"}"# інші анотації...}# інші поля...}
Сервер API надає метрики Prometheus з точки доступу /metrics, які можна використовувати для моніторингу та діагностики стану сервера API. Наведені нижче метрики фіксують стан, повʼязаний з вебхуками допуску.
Лічильник відхилення запитів вебхука допуску сервера API
Іноді корисно знати, які вебхуки допуску часто відхиляють запити API, та причину відхилення.
Сервер API надає метрику лічильника Prometheus, яка фіксує відхилення вебхуків допуску. Метрики мають підписи, що ідентифікують причини відхилення запитів вебхуками:
name: назва вебхука, який відхилив запит.
operation: тип операції запиту, може бути одним із CREATE, UPDATE, DELETE та CONNECT.
type: тип вебхука допуску, може бути одним із admit та validating.
error_type: визначає, чи сталася помилка під час виклику вебхука, яка призвела до відхилення. Його значення може бути одним із:
calling_webhook_error: невизнані помилки або помилки тайм-ауту від вебхука допуску сталися, і політика помилки вебхука встановлена на Fail.
no_error: помилка не сталася. Вебхук відхилив запит з allowed: false у відповіді допуску. Підписи метрики rejection_code записують значення .status.code, встановлене в відповіді допуску.
apiserver_internal_error: сталася внутрішня помилка сервера API.
rejection_code: HTTP-код статусу, встановлений у відповіді допуску, коли вебхук відхилив запит.
Приклад метрик лічильника відхилення:
# HELP apiserver_admission_webhook_rejection_count [ALPHA] Лічильник відхилення вебхуків авторизації, ідентифікований за назвою та розділений для кожного типу авторизації (валідація чи допуск) та операції. Додаткові підписи вказують тип помилки (calling_webhook_error або apiserver_internal_error, якщо виникла помилка; no_error інакше) та, за потреби, ненульовий код відхилення, якщо вебхук відхилив запит із HTTP-кодом статусу (врахований сервером API, якщо код більший або рівний 400). Коди, більші за 600, обрізаються до 600, щоб обмежити кардинальність метрик.
# TYPE apiserver_admission_webhook_rejection_count counter
apiserver_admission_webhook_rejection_count{error_type="calling_webhook_error",name="always-timeout-webhook.example.com",operation="CREATE",rejection_code="0",type="validating"} 1
apiserver_admission_webhook_rejection_count{error_type="calling_webhook_error",name="invalid-admission-response-webhook.example.com",operation="CREATE",rejection_code="0",type="validating"} 1
apiserver_admission_webhook_rejection_count{error_type="no_error",name="deny-unwanted-configmap-data.example.com",operation="CREATE",rejection_code="400",type="validating"} 13
Найкращі практики та попередження
Ідемпотентність
Ідемпотентний вебхук допуску, що змінює дані, може успішно обробляти обʼєкт, який він вже допустив і, можливо, змінив. Допуск можна застосовувати кілька разів, не змінюючи результат поза початковою обробкою.
Для запиту CREATE Pod додається sidecar контейнер з імʼям foo-sidecar, суфіксований поточним часовим позначенням (наприклад, foo-sidecar-19700101-000000).
Для CREATE/UPDATE Pod відхиляються запити, якщо позначка "env" установлена, в іншому випадку додається позначка "env": "prod".
Для запиту CREATE Pod додається контейнер під назвою foo-sidecar без перевірки наявності контейнера foo-sidecar у специфікації Pod.
У першому випадку вебхук може додавати однаковий контейнер декілька разів до Pod, кожного разу з різним іменем контейнера. Аналогічно, вебхук може додавати дубльовані контейнери, якщо вони вже існують у Podʼах користувачів.
У другому випадку повторний виклик вебхука призведе до помилки вихідних даних вебхука.
У третьому випадку повторний виклик вебхука призведе до дублювання контейнерів у специфікації Pod, що робить запит недійсним та відхиленим сервером API.
Перехоплення всіх версій обʼєкта
Рекомендується, щоб вебхуки допуску завжди перехоплювали всі версії обʼєкта, встановлюючи .webhooks[].matchPolicy на Equivalent. Також рекомендується, щоб вебхуки допуску завжди реєструвалися для стабільних версій ресурсів. Невдала спроба перехопити всі версії обʼєкта може призвести до того, що політика допуску не буде застосовуватися до деяких версій запитів. Дивіться Відповідність запитів: matchPolicy для прикладів.
Доступність
Рекомендується, щоб вебхуки допуску оцінювалися якомога швидше (зазвичай за мілісекунди), оскільки вони збільшують затримку запиту API. Рекомендується використовувати невеликий таймаут для вебхуків. Дивіться Таймаути для докладнішої інформації.
Рекомендується, щоб вебхуки допуску використовували якусь форму балансування навантаження, щоб забезпечити високу доступність та вигоди в продуктивності. Якщо вебхук працює всередині кластера, ви можете запустити декілька вебхуків позаду служби, щоб скористатися балансуванням навантаження, яке підтримує ця служба.
Гарантування остаточного стану обʼєкта
Вебхуки допуску, які повинні гарантувати, що вони бачать остаточний стан обʼєкта, щоб застосовувати політику, повинні використовувати вебхук допуску для валідації, оскільки обʼєкти можуть бути змінені після перегляду модифікуючими вебхуками.
Наприклад, модифікуючий вебхук допуску налаштований на впровадження контейнера sidecar з імʼям "foo-sidecar" на кожний запит CREATE pod. Якщо необхідно, щоб контейнер був присутнім, також слід налаштувати вебхук допуску для перехоплення запитів CREATE pod, і перевірити, що контейнер з імʼям "foo-sidecar" з необхідною конфігурацією існує в обʼєкті, який має бути створений.
Уникнення блокування вебхуків у самостійно розміщених вебхуках
Вебхук, що працює всередині кластера, може призвести до блокування власного deployment, якщо він налаштований для перехоплення ресурсів, необхідних для запуску власних Podʼів.
Наприклад, модифікуючий вебхук допуску налаштований на допуск запитів на створення CREATE pod лише в тому випадку, якщо у pod встановлено певну мітку (наприклад, "env": "prod"). Сервер розгортання вебхука працює в deployment, яке не встановлює мітку "env". Коли вузол, на якому запущено Podʼи вебхука, стає непрацездатним, deployment вебхука спробує перепланувати Podʼи на інший вузол. Однак запити будуть відхилені існуючим сервером вебхука, оскільки мітка "env" не встановлена, і міграція не може відбутися.
Рекомендується виключати простір імен, де працює ваш вебхук, за допомогою namespaceSelector.
Побічні ефекти
Рекомендується, щоб вебхуки допуску уникати побічних ефектів, якщо це можливо, що означає, що вебхуки працюють тільки з вмістом AdmissionReview, надісланим до них, і не вносять зміни поза цими рамками. Поле .webhooks[].sideEffects має бути встановлене на None, якщо у вебхука немає жодних побічних ефектів.
Якщо побічні ефекти потрібні під час оцінки допуску, їх потрібно приглушити при обробці обʼєкта AdmissionReview з dryRun встановленим на true, і поле .webhooks[].sideEffects має бути встановлене на NoneOnDryRun. Дивіться Побічні ефекти для докладнішої інформації.
Уникнення операцій у просторі імен kube-system
Простір імен kube-system містить обʼєкти, створені компонентами панелі управління Kubernetes, наприклад, службові облікові записи для компонентів панелі управління, Podʼи такі як kube-dns. Ненавмисна зміна або відхилення запитів у просторі імен kube-system може призвести до того, що компоненти панелі управління перестануть працювати або будуть внесені невідомі зміни. Якщо ваші вебхуки допуску не мають на меті змінювати поведінку панелі управління Kubernetes, виключіть простір імен kube-system з перехоплення за допомогою namespaceSelector.
10 - Управління службовими обліковими записами
Службовий обліковий запис (ServiceAccount) надає ідентифікацію для процесів, що виконуються в Pod.
Процес всередині Pod може використовувати ідентифікацію свого повʼязаного службового облікового запису для автентифікації у API сервері кластера.
Цей посібник пояснює деякі концепції, повʼязані зі ServiceAccount. Також у посібнику розглядається, як отримати або відкликати токени, що представляють ServiceAccounts.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Щоб точно виконати ці кроки, переконайтеся, що у вас є простір імен під назвою examplens. Якщо ні, створіть його, виконавши команду:
kubectl create namespace examplens
Облікові записи користувачів та службові облікові записи
Kubernetes розрізняє поняття облікового запису користувача та службового облікового запису з кількох причин:
Облікові записи користувачів призначені для людей. Службові облікові записи призначені для процесів застосунків, які (для Kubernetes) виконуються в контейнерах, що є частиною Pod.
Облікові записи користувачів мають бути глобальними: імена повинні бути унікальними у всіх просторах імен кластера. Незалежно від того, який простір імен ви розглядаєте, певний обліковий запис користувача представляє того самого користувача. У Kubernetes службові облікові записи є привʼязаними до простору імен: два різні простори імен можуть містити ServiceAccountʼи з однаковими іменами.
Як правило, облікові записи користувачів кластера можуть синхронізуватися з корпоративною базою даних, де створення нового облікового запису користувача вимагає спеціальних привілеїв і повʼязане зі складними бізнес-процесами. Навпаки, створення службових облікових записів повинно бути легшим, дозволяючи користувачам кластера створювати службові облікові записи для конкретних завдань за запитом. Відділення створення ServiceAccount від кроків для реєстрації користувачів полегшує дотримання принципу найменших привілеїв для робочих навантажень.
Вимоги до аудиту для облікових записів користувачів (людей) та службових облікових записів можуть відрізнятися; розділення полегшує досягнення цих вимог.
Конфігураційний пакет для складної системи може містити визначення різних службових облікових записів для компонентів цієї системи. Оскільки службові облікові записи можуть створюватися без багатьох обмежень і мають імена, привʼязані до простору імен, така конфігурація зазвичай є переносимою.
Привʼязані токени службових облікових записів
Токени ServiceAccount можуть бути привʼязані до API обʼєктів, що існують у kube-apiserver. Їх можна використовувати для звʼязування дійсності токена з існуванням іншого API обʼєкта. Підтримувані типи обʼєктів наступні:
Pod (використовується для projected томів, див. нижче)
Secret (може використовуватися для відкликання токена шляхом видалення Secret)
Node (у версії v1.30 створення нових токенів, привʼязаних до вузлів, є альфа-функцією, використання наявних токенів, привʼязаних до вузлів, є бета-функцією)
Коли токен привʼязаний до обʼєкта, metadata.name і metadata.uid цього обʼєкта зберігаються як додаткові "приватні заявки" у виданому JWT.
Коли привʼязаний токен представляється kube-apiserver, автентифікатор службового облікового запису витягне і перевірить ці заявки. Якщо вказаний обʼєкт або ServiceAccount знаходяться в процесі видалення (наприклад, через завершувач), то протягом будь-якого моменту, через 60 секунд (або більше) після дати .metadata.deletionTimestamp, автентифікація з використанням цього токена буде неуспішною. Якщо обʼєкт, на який він посилається, більше не існує (або його metadata.uid не збігається), запит не буде автентифікований.
Додаткові метадані в токенах, повʼязаних з Pod
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.30 [beta] (стандартно увімкнено: true)
Коли токен службового облікового запису привʼязаний до обʼєкта Pod, додаткові метадані також вбудовуються в токен, що вказує на значення поля spec.nodeName повʼязаного Pod і uid цього вузла, якщо це можливо.
Ця інформація про вузол не перевіряється kube-apiserver, коли токен використовується для автентифікації. Вона включена, щоб інтегратори не повинні були отримувати обʼєкти API Pod або Node для перевірки повʼязаного імені вузла та uid при інспекції JWT.
Перевірка та інспекція приватних заявок
API TokenReview може використовуватися для перевірки та вилучення приватних заявок з токена:
Спочатку припустимо, що у вас є Pod з назвою test-pod і службовий обліковий запис з назвою my-sa.
Попри використання kubectl create -f для створення цього ресурсу, і визначення його схожим чином з іншими типами ресурсів у Kubernetes, TokenReview є спеціальним типом і kube-apiserver насправді не зберігає обʼєкт TokenReview в etcd. Тому kubectl get tokenreview не є допустимою командою.
Механізм томів привʼязаного токена службового облікового запису
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.22 [stable] (стандартно увімкнено: true)
...- name:kube-api-access-<random-suffix>projected:sources:- serviceAccountToken:path:token# має збігатися з шляхом, який очікує застосунок- configMap:items:- key:ca.crtpath:ca.crtname:kube-root-ca.crt- downwardAPI:items:- fieldRef:apiVersion:v1fieldPath:metadata.namespacepath:namespace
Цей фрагмент маніфесту визначає projected том, що складається з трьох джерел. У цьому випадку,
кожне джерело також представляє один шлях у цьому томі. Три джерела такі:
Джерело serviceAccountToken, яке містить токен, який kubelet отримує з kube-apiserver. Kubelet отримує токени з обмеженим терміном дії за допомогою API TokenRequest. Токен, наданий для TokenRequest, закінчується або при видаленні Pod, або після визначеного терміну дії (стандартно, це 1 година). Kubelet також оновлює цей токен перед тим, як термін його дії закінчиться. Токен привʼязаний до конкретного Pod і має kube-apiserver як свою аудиторію. Цей механізм замінив попередній механізм, який додавав том на основі Secret, де Secret представляв ServiceAccount для Pod, але не мав терміну дії.
Джерело configMap. ConfigMap містить набір даних центру сертифікації. Pod можуть використовувати ці сертифікати, щоб упевнитись, що вони підключаються до kube-apiserver вашого кластера (а не до проміжного блоку або випадково неправильно налаштованого колеги).
Джерело downwardAPI, яке шукає імʼя простору імен, що містить Pod, і надає цю інформацію про імʼя для коду застосунку, що виконується всередині Pod.
Будь-який контейнер у Pod, який монтує цей том, може отримати доступ до вищевказаної інформації.
Примітка:
Не існує якогось окремого механізму для анулювання токена, виданого через TokenRequest. Якщо ви більше не довіряєте привʼязаному токену службового облікового запису для Pod, ви можете видалити цей Pod. Видалення Pod анулює його привʼязані токени службових облікових записів.
Ручне управління Secret для ServiceAccounts
Версії Kubernetes до v1.22 автоматично створювали облікові дані для доступу до API Kubernetes. Цей старіший механізм був заснований на створенні токенів Secret, які потім могли бути змонтовані в запущені Podʼи.
У новіших версіях, включаючи Kubernetes v1.31, API облікові дані отримуються безпосередньо за допомогою TokenRequest, і монтуються в Podʼи за допомогою projected тому. Токени, отримані за допомогою цього методу, мають обмежений термін дії та автоматично анулюються, коли Pod, в який вони змонтовані, видаляється.
Ви все ще можете створити вручну Secret для збереження токена службового облікового запису; наприклад, якщо вам потрібен токен, який ніколи не закінчується.
Після того, як ви вручну створите Secret і звʼяжете його зі службовим обліковим записом, панель управління Kubernetes автоматично заповнює токен у цьому Secret.
Примітка:
Хоча існує ручний механізм для створення токена службового облікового запису з тривалим терміном дії, рекомендується використовувати TokenRequest для отримання токенів доступу до API з коротким терміном дії.
До версії 1.24 Kubernetes автоматично генерував токени на основі Secret для ServiceAccount. Щоб розрізнити автоматично згенеровані токени та створені вручну, Kubernetes перевіряє посилання з поля секретів ServiceAccount. Якщо Secret згадується в полі secrets, він вважається автоматично згенерованим застарілим токеном. В іншому випадку він вважається вручну створеним застарілим токеном. Наприклад:
apiVersion:v1kind:ServiceAccountmetadata:name:build-robotnamespace:defaultsecrets:- name:build-robot-secret# зазвичай НЕ присутній для вручну створеного токена
Починаючи з версії 1.29, застарілі токени службових облікових записів, які були згенеровані автоматично, будуть позначені як недійсні, якщо вони залишатимуться невикористаними протягом певного періоду часу (стандартно один рік). Токени, які продовжують залишатися невикористаними протягом цього визначеного періоду (знову ж таки, стандартно один рік), будуть згодом видалені панеллю управління.
Якщо користувачі використовують анульований автоматично згенерований токен, валідатор токенів:
додасть анотацію аудиту для пари ключ-значення authentication.k8s.io/legacy-token-invalidated: <secret name>/<namespace>,
оновить мітку Secret kubernetes.io/legacy-token-last-used з новою датою,
поверне помилку, вказуючи, що токен був анульований.
При отриманні цієї помилки валідації користувачі можуть оновити Secret, щоб видалити мітку kubernetes.io/legacy-token-invalid-since, щоб тимчасово дозволити використання цього токена.
Ось приклад автоматично згенерованого застарілого токена, який був позначений мітками kubernetes.io/legacy-token-last-used і kubernetes.io/legacy-token-invalid-since:
Контролер ServiceAccount керує ServiceAccount всередині просторів імен та забезпечує наявність ServiceAccount з іменем "default" у кожному активному просторі імен.
Контролер токенів
Контролер токенів службових облікових записів працює як частина kube-controller-manager. Цей контролер діє асинхронно. Він:
відстежує видалення ServiceAccount та видаляє всі відповідні Secretʼи токенів ServiceAccount.
відстежує додавання Secretʼу токенів ServiceAccount та забезпечує наявність відповідного ServiceAccount, додає токен до Secretʼу за потреби.
відстежує видалення Secretʼу та видаляє посилання з відповідного ServiceAccount за потреби.
Необхідно передати файл приватного ключа службового облікового запису контролеру токенів у kube-controller-manager, використовуючи прапорець --service-account-private-key-file. Приватний ключ використовується для підпису згенерованих токенів службових облікових записів. Аналогічно, необхідно передати відповідний публічний ключ у kube-apiserver, використовуючи прапорець --service-account-key-file. Публічний ключ буде використовуватися для перевірки токенів під час автентифікації.
Контролер допуску ServiceAccount
Зміна Podʼів здійснюється через втулок, що викликається Контролером допуску. Він є частиною сервера API. Цей контролер допуску діє синхронно для зміни Podʼів під час їх створення. Коли цей втулок активний (а він є стандартно активним у більшості дистрибутивів), то під час створення Pod він виконує наступні дії:
Якщо у Pod не встановлено значення .spec.serviceAccountName, контролер допуску встановлює імʼя ServiceAccount default для цього Pod.
Контролер допуску забезпечує наявність ServiceAccount, на який посилається Pod. Якщо не існує ServiceAccount з відповідним імʼям, контролер допуску відхиляє Pod. Ця перевірка застосовується навіть для default ServiceAccount.
Якщо поле automountServiceAccountToken у ServiceAccount або в Podʼі не встановлено в false:
контролер допуску змінює Pod, додаючи додатковий том, що містить токен для доступу до API.
контролер допуску додає volumeMount до кожного контейнера в Podʼі, пропускаючи контейнери, які вже мають визначений шлях для монтування тому /var/run/secrets/kubernetes.io/serviceaccount. Для Linux-контейнерів цей том монтується за адресою /var/run/secrets/kubernetes.io/serviceaccount; на Windows-вузлах монтування знаходиться ну еквівалентному шляху.
Якщо в специфікації Pod не містяться жодні imagePullSecrets, контролер допуску додає imagePullSecrets, копіюючи їх з ServiceAccount.
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.28 [stable] (стандартно увімкнено: true)
Цей контролер створює ConfigMap з назвою kube-system/kube-apiserver-legacy-service-account-token-tracking у просторі імен kube-system. ConfigMap фіксує мітку часу, коли система почала відстежувати застарілі токени службових облікових записів.
Очищувач токенів застарілих ServiceAccount
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.30 [stable] (стандартно увімкнено: true)
Очищувач токенів застарілих ServiceAccount працює як частина kube-controller-manager і перевіряє кожні 24 години, чи не використовувався будь-який автоматично згенерований застарілий токен службового облікового запису протягом визначеного часу. Якщо так, очищувач позначає ці токени як недійсні.
Очищувач працює, спершу перевіряючи ConfigMap, створений панеллю управління (за умови, що LegacyServiceAccountTokenTracking увімкнено). Якщо поточний час перевищує визначений час після дати в ConfigMap, очищувач переглядає список Secretʼів у кластері та оцінює кожен Secret, що має тип kubernetes.io/service-account-token.
Якщо Secret відповідає всім наступним умовам, очищувач позначає його як недійсний:
Secret створено автоматично, що означає що він двонаправлено згадується ServiceAccount.
Secret не змонтовано жодним Podʼом.
Secret не використовувався протягом визначеного часу з моменту створення або останнього використання.
Очищувач позначає Secret як недійсний, додаючи мітку kubernetes.io/legacy-token-invalid-since до Secret, з поточною датою. Якщо недійсний Secret не використовується протягом визначеного часу, очищувач видаляє його.
Примітка:
Усі визначені часи стандартно становлять один рік. Адміністратор кластера може налаштувати це значення через аргумент командного рядка --legacy-service-account-token-clean-up-period для компонента kube-controller-manager.
API TokenRequest
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.22 [stable]
Ви використовуєте субресур TokenRequest з ServiceAccount, щоб отримати токен з обмеженим часом дії для цього ServiceAccount. Вам не потрібно викликати його для отримання API-токена для використання в контейнері, оскільки kubelet налаштовує це для вас, використовуючи projected том.
Панель управління Kubernetes (зокрема, контролер допуску ServiceAccount) додає projected том до Podʼів, а kubelet забезпечує, що цей том містить токен, який дозволяє контейнерам автентифікуватися як відповідний ServiceAccount.
(Цей механізм замінив попередній механізм, який додавав том на основі Secret, де Secret представляв ServiceAccount для Pod, але не мав терміну дії.)
Ось приклад того, як це виглядає для запущеного Pod:
Цей фрагмент маніфесту визначає projected том, який обʼєднує інформацію з трьох джерел:
Джерело serviceAccountToken, що містить токен, який kubelet отримує від kube-apiserver. Kubelet отримує токени з обмеженим часом дії, використовуючи API TokenRequest. Токен, виданий для TokenRequest, спливає або коли Pod видаляється, або через визначений термін життя (стандартно — 1 година). Токен привʼязаний до конкретного Podʼа та має kube-apiserver як свою аудиторію.
Джерело configMap. ConfigMap містить пакет даних сертифікаційного центру. Podʼи можуть використовувати ці сертифікати, щоб переконатися, що вони підключаються до kube-apiserver вашого кластера (а не до проміжного блоку або випадково неправильно налаштованого колеги).
Джерело downwardAPI. Цей том downwardAPI робить імʼя простору імен, що містить Pod, доступним для коду програми, що працює всередині Podʼа.
Будь-який контейнер у Podʼі, що монтує цей том, може отримати доступ до вищезазначеної інформації.
Створення додаткових API токенів
Увага:
Створюйте довгострокові API токени тільки якщо механізм запиту токенів не підходить. Механізм запиту токенів надає токени з обмеженим часом дії; оскільки вони спливають, вони представляють менший ризик для інформаційної безпеки.
Для створення постійного API токена для ServiceAccount, створіть Secret типу kubernetes.io/service-account-token з анотацією, що посилається на ServiceAccount. Панель управління потім генерує довгостроковий токен і оновлює цей Secret з даними згенерованого токена.
Якщо ви запустите новий Pod у просторі імен examplens, він може використовувати Secret токену службового облікового запису myserviceaccount, який ви щойно створили.
API для сертифікатів та наборів довіри Kubernetes дозволяють автоматизувати створення облікових даних X.509, надаючи програмний інтерфейс для клієнтів API Kubernetes для запиту та отримання X.509 сертифікатів від Центру сертифікації (CA).
Також є експериментальна (альфа) підтримка розподілу наборів довіри.
Запити на підписання сертифікатів
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.19 [stable]
Ресурс CertificateSigningRequest (CSR) використовується для запиту підписання сертифіката від вказаного підписувача, після чого запит може бути схвалений або відхилений перед остаточним підписанням.
Процес підписання запиту
Ресурс типу CertificateSigningRequest дозволяє клієнту запросити видачу сертифіката X.509 на основі запиту на підписання. Обʼєкт CertificateSigningRequest містить PEM-кодований запит на підпис у форматі PKCS#10 у полі spec.request. CertificateSigningRequest вказує підписувача (одержувача, до якого робиться запит) за допомогою поля spec.signerName. Зверніть увагу, що після версії API certificates.k8s.io/v1 ключ spec.signerName є обовʼязковим. У Kubernetes v1.22 та пізніших версіях клієнти можуть за бажанням встановити поле spec.expirationSeconds, щоб запросити певний термін дії виданого сертифіката. Мінімальне допустиме значення для цього поля — 600, тобто десять хвилин.
Після створення CertificateSigningRequest його необхідно схвалити перед підписанням. Залежно від обраного підписувача, CertificateSigningRequest може бути автоматично схвалений контролером. В іншому випадку CertificateSigningRequest слід схвалити вручну через API REST (або client-go) або за допомогою команди kubectl certificate approve. Аналогічно CertificateSigningRequest також може бути відхилений, що повідомляє налаштованому підписувачу, що він не повинен підписати запит.
Для схвалених сертифікатів наступним кроком є підписання. Відповідний контролер підпису перевіряє, чи виконуються умови підписання, а потім створює сертифікат. Після цього контролер підпису оновлює CertificateSigningRequest, зберігаючи новий сертифікат у полі status.certificate наявного обʼєкта CertificateSigningRequest. Поле status.certificate CertificateSigningRequest може бути порожнім або містити сертифікат X.509, кодований у форматі PEM. Поле status.certificate CertificateSigningRequest залишається порожнім, доки підписувач не зробить це.
Після заповнення поля status.certificate запит вважається завершеним, і клієнти тепер можуть отримати PEM-дані підписаного сертифіката з ресурсу CertificateSigningRequest. Підписувачі також можуть відхилити підпис сертифіката, якщо умови схвалення не виконані.
Для зменшення кількості застарілих ресурсів CertificateSigningRequest в кластері періодично запускається контролер збору сміття. Він видаляє CertificateSigningRequests, які не змінювали стан протягом певного періоду:
Схвалені запити: автоматично видаляються після 1 години
Відхилені запити: автоматично видаляються після 1 години
Невдалі запити: автоматично видаляються після 1 години
Запити в очікуванні: автоматично видаляються після 24 годин
Усі запити: автоматично видаляються після того, як видача сертифіката закінчиться після спливання часу дії
Авторизація підпису сертифікатів
Для можливості створення запиту на підпис сертифіката та отримання будь-якого запиту на підпис сертифіката:
apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:name:csr-signerrules:- apiGroups:- certificates.k8s.ioresources:- certificatesigningrequestsverbs:- get- list- watch- apiGroups:- certificates.k8s.ioresources:- certificatesigningrequests/statusverbs:- update- apiGroups:- certificates.k8s.ioresources:- signersresourceNames:- example.com/my-signer-name# example.com/* може використовуватись для авторизації всіх підписувачів в домені 'example.com'verbs:- sign
Підписувачі
Підписувачі абстрактно представляють сутність або сутності, які можуть підписувати або вже підписали сертифікат.
Будь-який підписувач, який доступний за межами конкретного кластера, повинен надавати інформацію про те, як працює підписувач, щоб споживачі могли зрозуміти, що це означає для CertificateSigningRequests та (якщо це увімкнено) ClusterTrustBundles. Це охоплює:
Розподіл довіри: як розподіляються якорі довіри (CA-сертифікати або набори сертифікатів).
Дозволені субʼєкти: будь-які обмеження та поведінка, коли запитано недопустимий субʼєкт.
Дозволені розширення x509: включаючи IP subjectAltNames, DNS subjectAltNames, Email subjectAltNames, URI subjectAltNames тощо, та поведінка, коли запитано недопустиме розширення.
Дозволені використання ключів / розширені використання ключів: будь-які обмеження та поведінка, коли використання, відмінне від використання, визначеного підписувачем, вказане в CSR.
Термін дії / термін життя сертифіката: чи він фіксується підписувачем, настроюваний адміністратором, визначений полем spec.expirationSeconds CSR тощо, та поведінка, коли термін дії, визначений підписувачем, відрізняється від поля spec.expirationSeconds CSR.
Дозволені / заборонені прапорці CA: та поведінка, якщо CSR містить запит на отримання сертифіката CA, коли підписувач не пропускає його.
Зазвичай поле status.certificate обʼєкта CertificateSigningRequest містить один PEM-кодований сертифікат X.509, як тільки CSR схвалено, і сертифікат видається. Деякі підписувачі зберігають кілька сертифікатів у полі status.certificate. У цьому випадку документація для підписувача повинна вказувати значення додаткових сертифікатів; наприклад, це може бути сертифікат плюс проміжні сертифікати, які представляються під час рукостискання TLS.
Якщо ви хочете зробити якір довіри (кореневий сертифікат) доступним, це слід зробити окремо від CertificateSigningRequest та його поля status.certificate. Наприклад, ви можете використовувати ClusterTrustBundle.
Формат підпису PKCS#10 не має стандартного механізму для вказання терміну дії або терміну життя сертифіката. Термін дії або термін життя має бути встановлено через поле spec.expirationSeconds обʼєкта CSR. Вбудовані підписувачі використовують параметр конфігурації ClusterSigningDuration, який стандартно становить 1 рік, (прапорець командного рядка --cluster-signing-duration kube-controller-manager) в як стандартне значення, коли не вказано spec.expirationSeconds. Коли вказано spec.expirationSeconds, використовується мінімум з spec.expirationSeconds та ClusterSigningDuration.
Примітка:
Поле spec.expirationSeconds було додано в Kubernetes v1.22. У попередніх версіях Kubernetes це поле не враховується. API-сервери Kubernetes до v1.22 будуть мовчки видаляти це поле при створенні обʼєкта.
Підписувачі Kubernetes
Kubernetes надає вбудовані підписувачі для підпису сертифікатів, кожен з яких має широко відоме імʼя підписувача signerName:
kubernetes.io/kube-apiserver-client: підписує сертифікати, які мають вважатись сертифікатами клієнтів сервером API. Ніколи автоматично не затверджуються kube-controller-manager.
Розподіл довіри: підписані сертифікати мають вважатись клієнтськими сертифікатами для доступу до API-сервера. Набір ЦС не поширюється жодним іншим способом.
Дозволені субʼєкти: немає обмежень для субʼєктів, однак затверджувачі та підписувачі можуть відхилити запити на затвердження та підпис. Певні субʼєкти подібні до користувачів та груп на рівні кластера є різними поміж різними дистрибутивами, що вимагає додаткових перевірок перед затвердженням та підписуванням. Втулок допуску CertificateSubjectRestrictions є стандартно увімкненим для обмеження system:masters, але в кластері є не тільки субʼєкти рівня адміністраторів кластера.
Дозволені розширення x509: враховують subjectAltNames та використання ключів, відкидаючи інші розширення.
Використання дозволених ключів: мають включати ["client auth"]. Не мають містити використання ключів поза ["digital signature", "key encipherment", "client auth"].
Термін дії / термін життя сертифіката: для реалізації підписувача kube-controller-manager, встановлюється у мінімальне значення з --cluster-signing-duration або, якщо вказано, поля spec.expirationSeconds обʼєкта CSR.
Біт ЦС дозволено / заборонено: не дозволяється.
kubernetes.io/kube-apiserver-client-kubelet: підписує сертифікати, які мають вважатись сертифікатами клієнтів сервером API. Можуть бути автоматично затверджені kube-controller-manager.
Розподіл довіри: підписані сертифікати мають вважатись клієнтськими сертифікатами для доступу до API-сервера. Набір ЦС не поширюється жодним іншим способом.
Дозволені субʼєкти: організації є безумовно ["system:nodes"], загальні імена — "system:node:${NODE_NAME}".
Дозволені розширення x509: враховують розширення з використанням ключів, забороняють розширення subjectAltNames та відкидає інші розширення.
Дозволені використання ключів: ["key encipherment", "digital signature", "client auth"] або ["digital signature", "client auth"].
Термін дії / термін життя сертифіката: для реалізації підписувача kube-controller-manager, встановлюється у мінімальне значення з --cluster-signing-duration або, якщо вказано, поля spec.expirationSeconds обʼєкта CSR.
Біт ЦС дозволено / заборонено: не дозволяється.
kubernetes.io/kubelet-serving: підписує сертифікати, які мають вважатись сертифікатами, які обслуговуються kubelet, але не мають жодних гарантій. Ніколи автоматично не затверджуються kube-controller-manager.
Розподіл довіри: підписані сертифікати мають вважатись API сервером дійсними для обробки зʼєднань з kubelet. Набір ЦС не поширюється жодним іншим способом.
Дозволені субʼєкти: організації є безумовно ["system:nodes"], загальні імена — "system:node:${NODE_NAME}".
Дозволені розширення x509: враховують використання ключів та розширень DNSName/IPAddress subjectAltName extensions, забороняють розширення EmailAddress та URI subjectAltName, відкидають інші розширення. Принаймні один субʼєкт DNS чи IP повинен бути у subjectAltNames.
Дозволені використання ключів: ["key encipherment", "digital signature", "server auth"] або ["digital signature", "server auth"].
Термін дії / термін життя сертифіката: для реалізації підписувача kube-controller-manager, встановлюється у мінімальне значення з --cluster-signing-duration або, якщо вказано, поля spec.expirationSeconds обʼєкта CSR.
Біт ЦС дозволено / заборонено: не дозволяється.
kubernetes.io/legacy-unknown: не має гарантій довіри взагалі. Деякі сторонні дистрибутиви Kubernetes можуть використовувати сертифікати клієнтів, підписані ним. Стабільний API CertificateSigningRequest (версії certificates.k8s.io/v1 та пізніше) не дозволяють встановлювати signerName на kubernetes.io/legacy-unknown. Ніколи автоматично не затверджується kube-controller-manager.
Розподіл довіри: Немає. Для цього підписувача не існує стандартної довіри або розподілу в кластері Kubernetes.
Дозволені субʼєкти: будь-які
Дозволені розширення x509: враховуються subjectAltNames та використання ключів, відкидаються інші розширення.
Дозволені використання ключів: будь-які
Термін дії / термін життя сертифіката: для реалізації підписувача kube-controller-manager, встановлюється у мінімальне значення з --cluster-signing-duration або, якщо вказано, поля spec.expirationSeconds обʼєкта CSR.
Біт ЦС дозволено / заборонено: не дозволяється.
kube-controller-manager реалізує підписування панелю управління для кожного з вбудованих підписувачів. Збої для всіх цих операцій повідомляються лише в логах kube-controller-manager.
Примітка:
Поле spec.expirationSeconds було додано в Kubernetes v1.22. Раніше версії Kubernetes не враховували це поле. API-сервери Kubernetes до v1.22 будуть просто ігнорувати це поле під час створення обʼєкта.
Розподіл довіри відбувається поза рамками для цих підписувачів. Будь-яка довіра за межами описаного вище є строго випадковою. Наприклад, деякі дистрибутиви можуть приймати kubernetes.io/legacy-unknown як клієнтські сертифікати для kube-apiserver, але це не є стандартом. Жодне з цих використань не повʼязане з токенами секретів ServiceAccount .data[ca.crt]. Цей пакет CA гарантовано лише для верифікації зʼєднання з API-сервером за допомогою стандартного Service (kubernetes.default.svc).
Власні підписувачі
Ви можете ввести власних підписувачів, які матимуть схожі імена з префіксами, але такі, що вказують на ваш власний домен. Наприклад, якщо ви є представником проєкту з відкритими сирцями, який використовує доменне імʼя open-fictional.example, тоді ви можете використовувати issuer.open-fictional.example/service-mesh як імʼя підписувача.
Власний підписувач використовує API Kubernetes для випуску сертифікатів. Дивіться підписувачі на основі API для деталей.
Підписування
Підписування панеллю управління
Панель управління Kubernetes реалізує кожного з підписувачів Kubernetes як частину kube-controller-manager.
Примітка:
До Kubernetes v1.18, kube-controller-manager підписував будь-які CSRs, які були позначені як схвалені.
Примітка:
Поле spec.expirationSeconds було додано в Kubernetes v1.22. Раніше версії Kubernetes не враховували це поле. API-сервери Kubernetes до v1.22 будуть просто ігнорувати це поле під час створення обʼєкта.
Підписувачі на основі API
Користувачі REST API можуть підписувати CSRs, надсилаючи запит UPDATE до субресурсу status CSR, який потрібно підписати.
У рамках цього запиту поле status.certificate повинно бути встановлено, щоб містити підписаний сертифікат. Це поле містить один або більше сертифікатів, закодованих у форматі PEM.
Всі PEM блоки повинні мати мітку "CERTIFICATE", не містити заголовків, а закодовані дані повинні бути структурою сертифіката BER, закодованого в ASN.1, як описано в розділі 4 RFC5280.
Не-PEM вміст може зʼявлятися до або після блоків CERTIFICATE PEM і не перевіряється, щоб дозволити пояснювальний текст, як описано в розділі 5.2 RFC7468.
При кодуванні в JSON або YAML це поле закодоване в base-64. Запит на підпис сертифіката (CertificateSigningRequest), що містить приклад сертифіката вище, виглядатиме так:
Перед тим, як підписувач видасть сертифікат на основі запиту на підписання сертифіката (CertificateSigningRequest), підписувач зазвичай перевіряє, що видача для цього CSR була схвалена.
Автоматичне схвалення панелі управління
kube-controller-manager поставляється з вбудованим схвалювачем для сертифікатів з іменем підписувача kubernetes.io/kube-apiserver-client-kubelet, який делегує різні дозволи на CSRs для облікових даних вузлів до авторизації. kube-controller-manager надсилає ресурси SubjectAccessReview до API-сервера для перевірки авторизації на схвалення сертифіката.
Схвалення або відхилення за допомогою kubectl
Адміністратор Kubernetes (з відповідними дозволами) може вручну схвалювати (або відхиляти) запити на підписання сертифікатів (CertificateSigningRequests) за допомогою команд kubectl certificate approve та kubectl certificate deny.
Схвалення або відхилення за допомогою API Kubernetes
Користувачі REST API можуть схвалювати CSRs, надсилаючи запит UPDATE до субресурсу approval CSR, який потрібно схвалити. Наприклад, ви можете написати оператор, який слідкує за певним видом CSR, а потім надсилає UPDATE для їх схвалення.
Коли ви робите запит на схвалення або відхилення, встановіть або умову статусу Approved, або Denied залежно від визначеного стану:
Для схвалених CSR:
apiVersion:certificates.k8s.io/v1kind:CertificateSigningRequest...status:conditions:- lastUpdateTime:"2020-02-08T11:37:35Z"lastTransitionTime:"2020-02-08T11:37:35Z"message:Approved by my custom approver controllerreason:ApprovedByMyPolicy# Ви можете вказати тут будь-який рядокtype:Approved
Для відхилених CSR:
apiVersion:certificates.k8s.io/v1kind:CertificateSigningRequest...status:conditions:- lastUpdateTime:"2020-02-08T11:37:35Z"lastTransitionTime:"2020-02-08T11:37:35Z"message:Denied by my custom approver controllerreason:DeniedByMyPolicy# Ви можете вказати тут будь-який рядокtype:Denied
Зазвичай встановлюється в поле status.conditions.reason код причини, зручний для машинного зчитування, використовуючи TitleCase; це є умовністю, але ви можете встановити тут будь-яке значення. Якщо ви хочете додати примітку для читання людьми, використовуйте поле status.conditions.message.
Пакети довіри кластера
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.27 [alpha]
Примітка:
У Kubernetes 1.31 ви повинні ввімкнути функціональну можливістьClusterTrustBundleтагрупу APIcertificates.k8s.io/v1alpha1,
щоб використовувати цей API.
ClusterTrustBundles — це обʼєкт масштабу кластера для розподілу якорів довіри X.509 (кореневих сертифікатів) до робочих навантажень у кластері. Вони розроблені для гарної роботи з концепцією підписувача із запитів на підписання сертифікатів (CertificateSigningRequests).
Усі обʼєкти ClusterTrustBundle мають сувору валідацію вмісту їхнього поля trustBundle. Це поле повинно містити один або більше сертифікатів X.509, серіалізованих у DER, кожен з яких обгорнутий у блок PEM CERTIFICATE. Сертифікати повинні аналізуватися як дійсні сертифікати X.509.
Езотеричні функції PEM, такі як дані між блоками та заголовки всередині блоків, або відхиляються під час валідації обʼєкта, або можуть ігноруватися споживачами обʼєкта. Крім того, споживачі можуть перевпорядковувати сертифікати в пакеті за своїм власним довільним, але стабільним порядком.
Обʼєкти ClusterTrustBundle слід вважати загальнодоступними в межах кластера. Якщо ваш кластер використовує авторизацію RBAC, усі ServiceAccounts стандартно мають дозволи get, list та watch для всіх обʼєктів ClusterTrustBundle. Якщо ви використовуєте власний механізм авторизації та ввімкнули ClusterTrustBundles у своєму кластері, вам слід налаштувати еквівалентне правило для того, щоб ці обʼєкти були загальнодоступними в межах кластера, щоб вони працювали належним чином.
Якщо ви не маєте стандартного дозволу для отримання переліку пакетів довіри кластера у вашому кластері, ви можете діяти від імені службового облікового запису, до якого у вас є доступ, щоб побачити доступні ClusterTrustBundles:
kubectl get clustertrustbundles --as='system:serviceaccount:mynamespace:default'
ClusterTrustBundles, звʼязані з підписувачем
ClusterTrustBundles, звʼязані з підписувачем, асоціюються з імʼям підписувача, як тут:
apiVersion:certificates.k8s.io/v1alpha1kind:ClusterTrustBundlemetadata:name:example.com:mysigner:foospec:signerName:example.com/mysignertrustBundle:"<... PEM data ...>"
ClusterTrustBundles призначені для підтримки контролера, специфічного для підписувача в кластері, тому вони мають кілька функцій безпеки:
Щоб створити або оновити ClusterTrustBundle, звʼязаний з підписувачем, ви повинні мати дозвіл підтвердити підписувача (спеціальне дієслово авторизації attest, група API certificates.k8s.io; шлях ресурсу signers). Ви можете налаштувати авторизацію для конкретного імені ресурсу <signerNameDomain>/<signerNamePath> або відповідати шаблону, наприклад <signerNameDomain>/*.
ClusterTrustBundles, звʼязані з підписувачем, повинні бути названі з префіксом, отриманим з їхнього поля spec.signerName. Слеші (/) замінюються на двокрапки (:), а в кінці додається двокрапка. За цим слідує довільне імʼя. Наприклад, підписувач example.com/mysigner може бути звʼязаний з ClusterTrustBundle example.com:mysigner:<arbitrary-name>.
ClusterTrustBundles, звʼязані з підписувачем, зазвичай використовуються у робочих навантаженнях за допомогою комбінації селектора полів за іменем підписувача та окремого селектора міток.
ClusterTrustBundles, незвʼязані з підписувачем
ClusterTrustBundles, незвʼязані з підписувачем, мають порожнє поле spec.signerName, як це:
apiVersion:certificates.k8s.io/v1alpha1kind:ClusterTrustBundlemetadata:name:foospec:# signerName не вказано, тому поле порожнєtrustBundle:"<... PEM data ...>"
Вони призначені головним чином для випадків використання конфігурації кластера. Кожен ClusterTrustBundle, незвʼязаний з підписувачем, є незалежним обʼєктом, на відміну від звичайної групової поведінки ClusterTrustBundles, звʼязаних з підписувачем.
ClusterTrustBundles, незвʼязані з підписувачем, не мають вимоги щодо дієслова attest. Натомість, ви контролюєте доступ до них безпосередньо за допомогою звичайних механізмів, таких як контроль доступу на основі ролей.
Щоб відрізнити їх від ClusterTrustBundles, звʼязаних з підписувачем, назви ClusterTrustBundles, незвʼязаних з підписувачем, не повинні містити двокрапку (:).
Доступ до ClusterTrustBundles з Podʼів
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.29 [alpha]
Вміст ClusterTrustBundles може бути впроваджений у файлову систему контейнера, подібно до ConfigMaps та Secrets. Дивіться джерело projected томів clusterTrustBundle для отримання додаткової інформації.
Як видати сертифікат для користувача
Для того, щоб звичайний користувач міг автентифікуватися та викликати API, потрібно виконати кілька кроків. Спершу цей користувач повинен мати сертифікат, виданий кластером Kubernetes, а потім надати цей сертифікат API Kubernetes.
Створення приватного ключа
Наступні скрипти показують, як згенерувати приватний ключ PKI та CSR. Важливо встановити значення CN та O атрибута CSR. CN — це імʼя користувача, а O — це група, до якої належатиме цей користувач. Ви можете звернутися до RBAC по стандартні групи.
Створіть запит на підписання сертифікату (CertificateSigningRequest) і подайте його до кластера Kubernetes через kubectl. Нижче наведено скрипт для CertificateSigningRequest.
12 - Зіставлення PodSecurityPolicies зі стандартами безпеки Podʼів
Нижче наведено таблиці, що перераховують параметри конфігурації обʼєктів PodSecurityPolicy, чи поле змінює або перевіряє контейнери, та як значення конфігурації зіставляються з Стандартами безпеки Podʼів.
Для кожного параметра, до якого це застосовується, перераховані допустимі значення для Baseline та Restricted профілів. Все, що перебуває за межами допустимих значень для цих профілів, підпадає під Privileged профіль. "Немає думки" означає, що всі значення допустимі для всіх стандартів безпеки Podʼів.
Baseline: "runtime/default,"(Кома в кінці, щоб встановити unset)
Restricted: "runtime/default"(Без коми в кінці)
Значення localhost/* також дозволені як для Baseline, так і для Restricted.
13 - Автентифікація/авторизація kubelet
Огляд
HTTP-запити до HTTPS-точки доступу kubelet надають доступ до даних різного рівня чутливості та дозволяють виконувати операції з різними рівнями повноважень на вузлі та в контейнерах.
У цьому документі описано, як автентифікувати та авторизувати доступ до HTTPS-точки доступу kubelet.
Автентифікація kubelet
Стандартно запити до HTTPS-точки доступу kubelet, які не відхилені іншими налаштованими методами автентифікації, розглядаються як анонімні запити та отримують імʼя користувача system:anonymous та групу system:unauthenticated.
Щоб вимкнути анонімний доступ та надсилати відповіді 401 Unauthorized на невідомі запити:
запустіть kubelet з прапорцем --anonymous-auth=false
Щоб увімкнути автентифікацію за допомогою клієнтських сертифікатів X509 до HTTPS-точки доступу kubelet:
запустіть kubelet з прапорцем --client-ca-file, надаючи набір кореневих сертифікатів для перевірки клієнтських сертифікатів
запустіть apiserver з прапорцями --kubelet-client-certificate та --kubelet-client-key
Щоб увімкнути використання API-токенів на предʼявника (включаючи токени службових облікових записів) для автентифікації до HTTPS-точки доступу kubelet:
переконайтеся, що група API authentication.k8s.io/v1beta1 ввімкнена в apiserver
запустіть kubelet з прапорцями --authentication-token-webhook та --kubeconfig
kubelet викликає API TokenReview на налаштованому apiserver, щоб визначити інформацію про користувача з токенів на предʼявника
Авторизація kubelet
Будь-який запит, який успішно автентифікується (включаючи анонімний запит), потім авторизується. Стандартний режим авторизації — AlwaysAllow, який дозволяє всі запити.
Є багато можливих причин для розподілу доступу до API kubelet:
ввімкнено анонімну автентифікацію, але потрібно обмежити можливості анонімних користувачів викликати API kubelet
ввімкнено автентифікацію з використанням токенів на предʼявника, але потрібно обмежити можливості довільних користувачів API (наприклад, службові облікові записи) викликати API kubelet
ввімкнено автентифікацію за допомогою клієнтських сертифікатів, але дозволено використовувати API kubelet тільки деяким сертифікатам клієнтів, які підписані налаштованим кореневим сертифікатом
Щоб розділити доступ до API kubelet, делегуйте авторизацію apiserver:
переконайтеся, що група API authorization.k8s.io/v1beta1 ввімкнена в apiserver
запустіть kubelet з прапорцями --authorization-mode=Webhook та --kubeconfig
kubelet викликає API SubjectAccessReview на налаштованому apiserver, щоб визначити, чи авторизований кожний запит
Kubelet авторизує запити до API, використовуючи той самий підхід до атрибутів запиту, що й apiserver.
Дієслово визначається з HTTP-дії вхідного запиту:
HTTP-дія
Дієслово запиту
POST
create
GET, HEAD
get
PUT
update
PATCH
patch
DELETE
delete
Ресурс та субресурс визначаються з шляху вхідного запиту:
Kubelet API
Ресурс
Субресурс
/stats/*
nodes
stats
/metrics/*
nodes
metrics
/logs/*
nodes
log
/spec/*
nodes
spec
/checkpoint/*
nodes
checkpoint
всі інші
nodes
proxy
Атрибути простору імен та групи API завжди є порожніми рядками, а імʼя ресурсу завжди є імʼям обʼєкта Node kubelet.
При використанні цього режиму переконайтеся, що користувач, визначений прапорцями --kubelet-client-certificate та --kubelet-client-key, переданими до apiserver, має дозвіл наступних атрибутів:
verb=*, resource=nodes, subresource=proxy
verb=*, resource=nodes, subresource=stats
verb=*, resource=nodes, subresource=log
verb=*, resource=nodes, subresource=spec
verb=*, resource=nodes, subresource=metrics
14 - Початкове завантаження 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.
Файл токенів повинен виглядати як у наступному прикладі, де перші три значення можуть бути будь-якими, а імʼя групи в лапках повинно бути таким, як показано:
Додайте прапорець --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/v1kind:ClusterRoleBindingmetadata:name:create-csrs-for-bootstrappingsubjects:- kind:Groupname:system:bootstrappersapiGroup:rbac.authorization.k8s.ioroleRef:kind:ClusterRolename:system:node-bootstrapperapiGroup: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-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/v1kind:ClusterRoleBindingmetadata:name:auto-approve-csrs-for-groupsubjects:- kind:Groupname:system:bootstrappersapiGroup:rbac.authorization.k8s.ioroleRef:kind:ClusterRolename:system:certificates.k8s.io:certificatesigningrequests:nodeclientapiGroup:rbac.authorization.k8s.io
Щоб дозволити kubelet оновлювати власний клієнтський сертифікат, створіть ClusterRoleBinding, що звʼязує групу, в якій є членом повнофункціональний вузол, system:nodes, з ClusterRole, що
надає їй дозвіл, system:certificates.k8s.io:certificatesigningrequests:selfnodeclient:
# Затвердження запитів на оновлення CSR для групи "system:nodes"apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRoleBindingmetadata:name:auto-approve-renewals-for-nodessubjects:- kind:Groupname:system:nodesapiGroup:rbac.authorization.k8s.ioroleRef:kind:ClusterRolename:system:certificates.k8s.io:certificatesigningrequests:selfnodeclientapiGroup: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. Приклад файлу може виглядати наступним чином:
certificate-authority: шлях до файлу CA, використовується для перевірки сертифіката сервера, представленого kube-apiserver
server: URL до kube-apiserver
token: токен для використання
Формат токена не має значення, головне, щоб він відповідав очікуванням kube-apiserver. У наведеному прикладі ми використали початковий токен. Як зазначалося раніше, будь-який дійсний метод автентифікації може бути використаний, а не тільки токени.
Оскільки початковий kubeconfigє стандартним kubeconfig, ви можете використовувати kubectl для його створення. Щоб створити вищезазначений приклад файлу:
Під час запуску 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>.
15 - Правила перевірки допуску
СТАН ФУНКЦІОНАЛУ:Kubernetes v1.30 [stable]
Ця сторінка надає огляд правил перевірки допуску.
Що таке правила перевірки допуску?
Правила перевірки допуску пропонують декларативну, вбудовану альтернативу веб-хукам перевірки допуску.
Правила перевірки допуску використовують мову загальних виразів (Common Expression Language, CEL). Правила перевірки допуску мають високу налаштовуваність, що дозволяє авторам визначати правила, які можуть бути параметризовані та обмежені ресурсами за необхідності адміністраторами кластера.
Які ресурси складають правила
Зазвичай правило складається з трьох ресурсів:
ValidatingAdmissionPolicy описує абстрактну логіку правил (наприклад: "ці праивла переконуються, що певна мітка встановлена у певне значення").
ValidatingAdmissionPolicyBinding повʼязує вищезазначені ресурси разом і надає обмеження області дії. Якщо вам потрібно вимагати встановлення мітки owner для Pods, привʼязка визначає, де ви будете вказувати це обмеження.
Ресурс параметра надає інформацію для ValidatingAdmissionPolicy, щоб зробити його конкретним висловленням (наприклад, "мітка owner повинна бути встановлена на щось, що закінчується на .company.com"). Вбудований тип, такий як ConfigMap або CRD, визначає схему ресурсу параметра. Обʼєкти ValidatingAdmissionPolicy вказують, який Kind вони очікують для свого ресурсу параметру.
Для того щоб правила мали ефект, обовʼязково повинні бути визначені принаймні ValidatingAdmissionPolicy та відповідне ValidatingAdmissionPolicyBinding.
Якщо ValidatingAdmissionPolicy не потребує налаштування через параметри, просто залиште
spec.paramKind в ValidatingAdmissionPolicy не вказаним.
Початок роботи з правилами перевірки допуску
Правила перевірки допуску є частиною панелі управління кластера. Ви повинні писати та розгортати їх з великою обережністю. Нижче наведено інструкції щодо швидкого експерименту з правилами перевірки допуску.
spec.validations містить вирази CEL, які використовують Мову загальних виразів (CEL), щоб перевірити запит. Якщо вираз обчислюється як false, перевірка валідації застосовується згідно з полем spec.failurePolicy.
Примітка:
Ви можете швидко перевірити вирази CEL у пісочниці CEL.
Для налаштування правил перевірки допуску для використання в кластері потрібна привʼязка. Нижче наведено приклад ValidatingAdmissionPolicyBinding.:
Вище наведено простий приклад використання ValidatingAdmissionPolicy без налаштованого параметра.
Дії валідації
Кожний ValidatingAdmissionPolicyBinding повинен вказати одну або декілька validationActions, щоб визначити, як validations правила будуть застосовані.
Підтримувані validationActions:
Deny: Невдалий результат валідації призводить до відхиленого запиту.
Warn: Невдалий результат валідації повідомляється клієнту запиту як попередження.
Audit: Невдалий результат валідації включається в подію аудиту для запиту до API.
Наприклад, щоб одночасно попереджувати клієнтів про невдалий результат валідації та аудитувати невдалий результат валідації, використовуйте:
validationActions:[Warn, Audit]
Deny та Warn не можуть бути використані разом, оскільки ця комбінація надмірно дублює невдалий результат валідації як у тілі відповіді API, так і в HTTP заголовках попередження.
validation, який оцінюється як false, завжди застосовується відповідно до цих дій. Невдачі, визначені полем failurePolicy, застосовуються відповідно до цих дій тільки у випадку, якщо failurePolicy встановлено на Fail (або не вказано), інакше невдачі ігноруються.
Ресурси параметрів дозволяють відокремити конфігурацію правил від їх визначення. Правило може визначити paramKind, який визначає GVK ресурсу параметра, а потім привʼязка правила повʼязує його за іменем (через policyName) з певним ресурсом параметра через paramRef.
Якщо потрібна конфігурація параметра, наведено приклад ValidatingAdmissionPolicy з конфігурацією параметра.
Поле spec.paramKind ValidatingAdmissionPolicy вказує на вид використовуваних ресурсів для параметризації цього правила. У цьому прикладі це налаштовано за допомогою ресурсів ReplicaLimit. Зверніть увагу в цьому прикладі, як вираз CEL посилається на параметри через змінну CEL params, наприклад, params.maxReplicas. spec.matchConstraints вказує, для яких ресурсів ця правило призначена для валідації. Зверніть увагу, що як параметр можуть використовуватися і стандартні типи, такі як ConfigMap.
Поля spec.validations містять вирази CEL. Якщо вираз оцінюється як false, то валідаційна перевірка здійснюється відповідно до поля spec.failurePolicy.
Автор правил перевірки допуску відповідає за надання параметра CRD ReplicaLimit.
Для налаштування правил перевірки допуску для використання в кластері створюються привʼязка та ресурс параметра. Наведено приклад ValidatingAdmissionPolicyBinding який використовує кластерний параметр — той самий параметр буде використовуватися для валідації кожного запиту до ресурсу, який відповідає привʼязці:
Цей ресурс параметра правил обмежує Deployments до максимуму 3 репліки.
В правилі допуску може бути кілька привʼязок. Щоб привʼязати всі інші середовища до обмеження maxReplicas 100, створіть інший ValidatingAdmissionPolicyBinding:
apiVersion:admissionregistration.k8s.io/v1kind:ValidatingAdmissionPolicyBindingmetadata:name:"replicalimit-binding-nontest"spec:policyName:"replicalimit-policy.example.com"validationActions:[Deny]paramRef:name:"replica-limit-prod.example.com"namespace:"default"matchResources:namespaceSelector:matchExpressions:- key:environmentoperator:NotInvalues:- test
Зверніть увагу, що ця привʼязка застосовує різний параметр до ресурсів, які не знаходяться в середовищі test.
Для кожного запиту на допуск, сервер API оцінює вирази CEL кожної комбінації (правило, привʼязка, параметр), які відповідають запиту. Для того, щоб запит був прийнятий, він повинен пройти всі оцінки.
Якщо кілька привʼязок відповідають запиту, правило буде оцінено для кожної, і вони всі повинні пройти оцінку, щоб правило вважали пройденим.
Якщо кілька параметрів відповідають одній привʼязці, правила будуть оцінені для кожного параметра, і вони також повинні всі пройти, щоб привʼязка вважалася пройденою. Привʼязки можуть мати критерії відповідності, що перекриваються. Правило оцінюється для кожної відповідної комбінації привʼязка-параметр. Правило може бути оцінено навіть кілька разів, якщо йому відповідає кілька привʼязок, або одна привʼязка, яка відповідає кільком параметрам.
Обʼєкт params, який представляє ресурс параметра, не буде встановлений, якщо ресурс параметра не був привʼязаний, тому для правил, які потребують ресурсу параметра, може бути корисно додати перевірку, щоб забезпечити його привʼязку. Ресурс параметра не буде привʼязаний і params буде null, якщо paramKind правила або paramRef привʼязки не вказані.
Для випадків використання, що потребують конфігурації параметра, ми рекомендуємо додати перевірку параметра в spec.validations[0].expression:
- expression: "params != null"
message: "params missing but required to bind to this policy"
Необовʼязкові параметри
Буває зручно мати можливість мати необовʼязкові параметри як частину ресурсу параметра і валідувати їх лише в разі їх присутності. У CEL є has(), який перевіряє, чи існує переданий ключ. Крім того, CEL реалізує булеве скорочення. Якщо перша половина логічного ОБО відноситься до true, то друга половина не оцінюється (оскільки результат усього ОБО буде true в будь-якому випадку).
Поєднуючи ці дві можливості, ми можемо забезпечити можливість валідації необовʼязкових параметрів:
Тут спочатку ми перевіряємо, що необовʼязковий параметр присутній за допомогою !has(params.optionalNumber).
Якщо optionalNumber не був визначений, то вираз скорочується, оскільки
!has(params.optionalNumber) оцінюється як true.
Якщо optionalNumber був визначений, тоді друга половина CEL виразу буде
оцінена, і optionalNumber буде перевірений, щоб забезпечити, що він містить значення від 5 до 10 включно.
Параметри на рівні простору імен
Як автор ValidatingAdmissionPolicy та його ValidatingAdmissionPolicyBinding, ви можете вибрати, чи вказувати параметри на рівні кластера або на рівні простору імен. Якщо ви вказуєте namespace для paramRef привʼязки, панель управління шукає параметри лише в цьому просторі імен.
Проте, якщо namespace не вказано в ValidatingAdmissionPolicyBinding, сервер API може шукати відповідні параметри в просторі імен, до якого відноситься запит. Наприклад, якщо ви робите запит на зміну ConfigMap у просторі імен default, і існує відповідна ValidatingAdmissionPolicyBinding без вказаного namespace, то сервер API шукає обʼєкт параметра в default. Цей дизайн дозволяє конфігурувати правило, що залежить від простору імен ресурсу, який обробляється, для отримання більш точного контролю.
Селектор параметрів
Крім вказання параметра у привʼязці за допомогою name, ви можете вибрати замість цього вказати селектор міток, таким чином, всі ресурси paramKind правила та namespace параметра (якщо застосовується), які відповідають селектору міток, вибираються для оцінки. Див. селектор для отримання додаткової інформації про те, як селектори міток відбирають ресурси.
Якщо умову виконується для декількох параметрів, правила оцінюються для кожного знайденого параметра, а результати будуть оцінені разом через логічне І (AND).
Якщо надано namespace, для вибору допускаються лише обʼєкти paramKind у вказаному просторі імен. В іншому випадку, коли namespace порожній, а paramKind обмежений простором імен, використовується namespace, використаний у запиті для допуску.
Перевірка авторизації
Ми ввели перевірку авторизації для ресурсів параметрів. Очікується, що користувач матиме доступ на читання до ресурсів, на які посилається paramKind у ValidatingAdmissionPolicy та paramRef у ValidatingAdmissionPolicyBinding.
Зверніть увагу, що якщо ресурс у paramKind не вдасться знайти через restmapper, потрібен доступ на читання до всіх ресурсів груп.
Правило помилок
failurePolicy визначає, як обробляються неправильні конфігурації та вирази CEL, що викликають помилку в правилах перевірки допуску. Допустимі значення: Ignore або Fail.
Ignore означає, що помилка під час виклику ValidatingAdmissionPolicy ігнорується, і запит API може продовжуватися.
Fail означає, що помилка під час виклику ValidatingAdmissionPolicy призводить до відмови в прийнятті та відхилення запиту API.
Зверніть увагу, що failurePolicy визначається всередині ValidatingAdmissionPolicy:
spec.validations[i].expression представляє вираз, який буде оцінений за допомогою CEL. Для отримання додаткової інформації див. Специфікацію мови CEL. Вирази CEL мають доступ до вмісту запиту/відповіді допуску, організованого в змінні CEL, а також деяких інших корисних змінних:
'object' — Обʼєкт з вхідного запиту. Значення null для запитів DELETE.
'oldObject' — Наявний обʼєкт. Значення null для запитів CREATE.
'params' — Ресурс параметра, на який посилається привʼязка правила, яке оцінюється. Значення null, якщо ParamKind не вказано.
namespaceObject — Простір імен, як ресурс Kubernetes, до якого належить вхідний обʼєкт. Значення null, якщо вхідний обʼєкт має область видимості кластера.
authorizer — Авторизатор CEL. Може використовуватися для виконання перевірок авторизації для принципала (автентифікованого користувача) запиту. Див. AuthzSelectors та Authz в документації бібліотеки Kubernetes CEL для отримання додаткових відомостей.
authorizer.requestResource — Скорочення для перевірки авторизації, налаштоване з ресурсом запиту (група, ресурс, (субресурс), простір імен, імʼя).
apiVersion, kind, metadata.name і metadata.generateName завжди доступні з кореня обʼєкта. Інші властивості метаданих не доступні.
Рівність у масивах із типом списку 'set' або 'map' ігнорує порядок елементів, тобто [1, 2] == [2, 1]. Конкатенація у масивах з x-kubernetes-list-type використовує семантику типу списку:
'set': X + Y виконує обʼєднання, де позиції масиву всіх елементів в X зберігаються, а
неперетинаючися елементи в Y додаються, зберігаючи їх частковий порядок.
'map': X + Y виконує злиття, де позиції масиву всіх ключів в X зберігаються, але значення
перезаписуються значеннями в Y, коли множини ключів X і Y перетинаються. Елементи в Y з неперетинаючимися ключами додаються, зберігаючи їх частковий порядок.
spec.validation[i].reason представляє машинночитаний опис причини невдачі цієї валідації. Якщо це перша валідація в списку, яка завершується невдачею, ця причина, а також відповідний код відповіді HTTP використовуються у відповіді HTTP клієнту. Підтримувані зараз причини: Unauthorized, Forbidden, Invalid, RequestEntityTooLarge. Якщо не встановлено, StatusReasonInvalid використовується у відповіді клієнту.
Відповідність запитів: matchConditions
Ви можете визначити умови відповідності для ValidatingAdmissionPolicy, якщо вам потрібно дотримуватися детального фільтрування запитів. Ці умови корисні, якщо ви виявите, що правила відповідності, objectSelectors та namespaceSelectors все ще не забезпечують потрібного фільтрування. Умови відповідності — це вирази CEL. Усі умови відповідності повинні оцінюватися як true для ресурсу, який має бути оцінений.
Нижче наведено приклад, що ілюструє кілька різних використань умов відповідності:
apiVersion:admissionregistration.k8s.io/v1kind:ValidatingAdmissionPolicymetadata:name:"demo-policy.example.com"spec:failurePolicy:FailmatchConstraints:resourceRules:- apiGroups:["*"]apiVersions:["*"]operations:["CREATE","UPDATE"]resources:["*"]matchConditions:- name:'exclude-leases'# Імʼя кожної умови має бути унікальнимexpression:'!(request.resource.group == "coordination.k8s.io" && request.resource.resource == "leases")'# Шукати збіг із запитами non-lease.- name:'exclude-kubelet-requests'expression:'!("system:nodes" in request.userInfo.groups)'# Шукати збіг із запитами від користувачів, які не є користувачами вузла.- name:'rbac'# Оминати запити RBAC.expression:'request.resource.group != "rbac.authorization.k8s.io"'validations:- expression:"!object.metadata.name.contains('demo') || object.metadata.namespace == 'demo'"
Умови відповідності мають доступ до тих самих змінних CEL, що й вирази валідації.
У випадку помилки при оцінці умови відповідності правило не оцінюється. Рішення про відхилення запиту визначається наступним чином:
Якщо будь-яка умова відповідності оцінюється як false (незалежно від інших помилок), сервер API пропускає політику.
apiVersion:admissionregistration.k8s.io/v1kind:ValidatingAdmissionPolicymetadata:name:"demo-policy.example.com"spec:failurePolicy:FailmatchConstraints:resourceRules:- apiGroups:["apps"]apiVersions:["v1"]operations:["CREATE","UPDATE"]resources:["deployments"]validations:- key:"high-replica-count"expression:"object.spec.replicas > 50"messageExpression:"'Deployment spec.replicas set to ' + string(object.spec.replicas)"
Коли запит API перевіряється за цим правилом допуску, отримана подія аудиту буде виглядати так:
#Записанаподіяаудиту{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"annotations": {
"demo-policy.example.com/high-replica-count": "Deployment spec.replicas set to 128"#іншіанотації... }
#іншіполя...}
У цьому прикладі анотація буде включена лише тоді, коли spec.replicas у Deployment більше 50, в іншому випадку вираз CEL оцінюється як null, і анотація не буде включена.
Зверніть увагу, що ключі анотацій аудиту мають префікс з імʼям ValidatingAdmissionWebhook та /. Якщо інший контролер допуску, такий як вебхук допуску, використовує точно такий самий ключ анотації аудиту, то значення першого контролера допуску, який включає анотацію аудиту, буде включено в аудит-подію, а всі інші значення будуть ігноруватися.
Вираз повідомлення
Щоб повертати більш дружнє повідомлення, коли правило відхиляє запит, ми можемо використовувати вираз CEL для створення повідомлення з spec.validations[i].messageExpression. Подібно до виразу валідації, вираз повідомлення має доступ до object, oldObject, request, params та namespaceObject. На відміну від валідації, вираз повідомлення має повертати рядок.
Наприклад, щоб краще інформувати користувача про причину відхилення, коли правило посилається на параметр, ми можемо мати наступну валідацію:
apiVersion:admissionregistration.k8s.io/v1kind:ValidatingAdmissionPolicymetadata:name:"deploy-replica-policy.example.com"spec:paramKind:apiVersion:rules.example.com/v1kind:ReplicaLimitmatchConstraints:resourceRules:- apiGroups:["apps"]apiVersions:["v1"]operations:["CREATE","UPDATE"]resources:["deployments"]validations:- expression:"object.spec.replicas <= params.maxReplicas"messageExpression:"'object.spec.replicas must be no greater than ' + string(params.maxReplicas)"reason:Invalid
Після створення обʼєкту параметрів, який обмежує репліки до 3 та налаштування привʼязки, коли ми спробуємо створити Deployment з 5 репліками, ми отримаємо наступне повідомлення.
$ kubectl create deploy --image=nginx nginx --replicas=5error: failed to create deployment: deployments.apps "nginx" is forbidden: ValidatingAdmissionPolicy 'deploy-replica-policy.example.com' with binding 'demo-binding-test.example.com' denied request: object.spec.replicas must be no greater than 3
Це більш інформативно, ніж статичне повідомлення "занадто багато реплік".
Вираз повідомлення має перевагу над статичним повідомленням, визначеним у spec.validations[i].message, якщо обидва визначені. Однак, якщо вираз повідомлення не вдається оцінити, буде використано статичне повідомлення. Крім того, якщо вираз повідомлення оцінюється як багаторядковий рядок, результат оцінки буде відкинутий, і використовуватиметься статичне повідомлення, якщо воно присутнє. Зауважте, що статичне повідомлення перевіряється на відповідність багаторядковим рядкам.
Перевірка типів
Під час створення або оновлення визначення правил валідації процес валідації аналізує вирази, які він містить, та повідомляє про будь-які синтаксичні помилки, відхиляючи визначення, якщо виявлено помилки. Потім перевіряються змінні, на які є посилання, на наявність помилок типів, включаючи відсутні поля та плутанину типів, відносно відповідних типів spec.matchConstraints. Результат перевірки типів можна отримати з status.typeChecking. Наявність status.typeChecking вказує на завершення перевірки типів, а порожнє status.typeChecking означає, що помилок не виявлено.
apiVersion:admissionregistration.k8s.io/v1kind:ValidatingAdmissionPolicymetadata:name:"deploy-replica-policy.example.com"spec:matchConstraints:resourceRules:- apiGroups:["apps"]apiVersions:["v1"]operations:["CREATE","UPDATE"]resources:["deployments"]validations:- expression:"object.replicas > 1"# має бути "object.spec.replicas > 1"message:"must be replicated"reason:Invalid
apiVersion:admissionregistration.k8s.io/v1kind:ValidatingAdmissionPolicymetadata:name:"replica-policy.example.com"spec:matchConstraints:resourceRules:- apiGroups:["apps"]apiVersions:["v1"]operations:["CREATE","UPDATE"]resources:["deployments","replicasets"]validations:- expression:"object.replicas > 1"# має бути "object.spec.replicas > 1"message:"must be replicated"reason:Invalid
буде мати декілька типів та результат перевірки типів кожного типу у повідомленні про попередження.
Відсутнє зіставлення за шаблоном. Якщо spec.matchConstraints.resourceRules містить "*" у будь-якому з apiGroups, apiVersions або resources, типи, які відповідають "*", не будуть перевірені.
Кількість збігів типів обмежена до 10. Це робиться для запобігання використанню правил, що вручну вказує занадто багато типів, що може споживати занадто багато обчислювальних ресурсів. Порядок спадання групи, версії, а потім ресурсу, 11-а комбінація та після буде ігноруватися.
Перевірка типів не впливає на поведінку правил жодним чином. Навіть якщо під час перевірки типів виявляються помилки, політика буде продовжувати оцінюватися. Якщо під час оцінки виникають помилки, політика вибере свій результат.
Перевірка типів не застосовується до CRD, включаючи відповідні типи CRD та посилання на paramKind. Підтримка CRD зʼявиться у майбутній версії.
Склад змінних
Якщо вираз стає занадто складним або частина виразу повторно використовується та має високі обчислювальні витрати, ви можете винести частину виразів у змінні. Змінна — це вираз з назвою, на який можна посилатися пізніше в variables в інших виразах.
Змінна оцінюється ліниво (lazily), під час першого посилання на неї. Про будь-яку помилку, що виникає під час оцінки, буде повідомлено під час оцінки вказаного виразу, на який посилається змінна. Як результат, так і можлива помилка запамʼятовуються і лише один раз враховуються при оцінці під час виконання.
Порядок змінних важливий, оскільки змінна може посилатися на інші змінні, які визначені перед нею. Це упорядкування запобігає циклічним посиланням.
Наведено більш складний приклад змінних, що забезпечує відповідність імен репозиторіїв образів середовищу, визначеному у просторі імен.
# Це правило забезпечує виконання умови, що всі контейнери deployment повинні мати збіг репозиторієв образів з міткою середовища його простору імен.# За винятком deployment, позначених як "exempt", або будь-яких контейнерів, які не належать організації "example.com" (наприклад, загальні sidecar).# Наприклад, якщо у просторі імен є мітка {"environment": "staging"}, всі контейнери повинні мати репозиторій, який є або staging.example.com/*# або не містить "example.com" взагалі, якщо deployment має мітку {"exempt": "true"}.apiVersion:admissionregistration.k8s.io/v1kind:ValidatingAdmissionPolicymetadata:name:"image-matches-namespace-environment.policy.example.com"spec:failurePolicy:FailmatchConstraints:resourceRules:- apiGroups:["apps"]apiVersions:["v1"]operations:["CREATE","UPDATE"]resources:["deployments"]variables:- name:environmentexpression:"'environment' in namespaceObject.metadata.labels ? namespaceObject.metadata.labels['environment'] : 'prod'"- name:exemptexpression:"'exempt' in object.metadata.labels && object.metadata.labels['exempt'] == 'true'"- name:containersexpression:"object.spec.template.spec.containers"- name:containersToCheckexpression:"variables.containers.filter(c, c.image.contains('example.com/'))"validations:- expression:"variables.exempt || variables.containersToCheck.all(c, c.image.startsWith(variables.environment + '.'))"messageExpression:"'only ' + variables.environment + ' images are allowed in namespace ' + namespaceObject.metadata.name"
З правилом, привʼязаним до простору імен default, який має мітку environment: prod, спроба створити Deployment буде відхилена.
error: failed to create deployment: deployments.apps "invalid" is forbidden: ValidatingAdmissionPolicy 'image-matches-namespace-environment.policy.example.com' with binding 'demo-binding-test.example.com' denied request: only prod images are allowed in namespace default