Це багатосторінковий друкований вигляд цього розділу. Натисність щоб друкувати.
Налаштування Podʼів та контейнерів
- 1: Виділення ресурсів памʼяті для контейнерів та Podʼів
- 2: Виділення ресурсів CPU контейнерам та Podʼам
- 3: Налаштування GMSA для Windows Podʼів та контейнерів
- 4: Зміна обсягів CPU та памʼяті, призначених для контейнерів
- 5: Налаштування RunAsUserName для Podʼів та контейнерів Windows
- 6: Створення Podʼа Windows HostProcess
- 7: Налаштування якості обслуговування для Podʼів
- 8: Призначення розширених ресурсів контейнеру
- 9: Налаштування Podʼа для використання тому для зберігання
- 10: Налаштування Podʼа для використання PersistentVolume для зберігання
- 11: Налаштування Pod для використання projected тому для зберігання
- 12: Налаштування контексту безпеки для Podʼа або контейнера
- 13: Налаштування службових облікових записів для Podʼів
- 14: Отримання образів з приватного реєстру
- 15: Налаштування проб життєздатності, готовності та запуску
- 16: Призначення Podʼів на вузли
- 17: Призначення Podʼів на вузли за допомогою спорідненості вузла
- 18: Налаштування ініціалізації Podʼа
- 19: Обробники подій життєвого циклу контейнера
- 20: Налаштування Podʼів для використання ConfigMap
- 21: Поділ простору імен процесів між контейнерами у Podʼі
- 22: Використання простору імен користувача з Podʼом
- 23: Використання тому Image в Pod
- 24: Створення статичних Podʼів
- 25: Конвертація файлу Docker Compose в ресурси Kubernetes
- 26: Забезпечення стандартів безпеки Podʼів шляхом конфігурування вбудованого контролера допуску
- 27: Забезпечення стандартів безпеки Podʼів за допомогою міток простору імен
- 28: Міграція з PodSecurityPolicy до вбудованого контролера допуску PodSecurity
1 - Виділення ресурсів памʼяті для контейнерів та Podʼів
Ця сторінка показує, як вказати запити та ліміти памʼяті для контейнерів. Контейнери гарантовано матимуть стільки памʼяті, скільки вказано у запиті, і не отримають більше, ніж вказано у ліміті.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Кожен вузол у вашому кластері повинен мати принаймні 300 МіБ памʼяті.
Деякі кроки на цій сторінці вимагають запуску служби metrics-server у вашому кластері. Якщо у вас запущено metrics-server, ви можете пропустити ці кроки.
Якщо ви використовуєте Minikube, виконайте таку команду, щоб увімкнути metrics-server:
minikube addons enable metrics-server
Щоб перевірити, чи запущений metrics-server, або інший постачальник API ресурсів метрик (metrics.k8s.io
), виконайте таку команду:
kubectl get apiservices
Якщо API ресурсів метрик доступне, у виводі буде міститися посилання на metrics.k8s.io
.
NAME
v1beta1.metrics.k8s.io
Створення простору імен
Створіть простір імен, щоб ресурси, які ви створюєте у цьому завданні, були відокремлені від інших ресурсів у вашому кластері.
kubectl create namespace mem-example
Визначення запитів та лімітів памʼяті
Щоб вказати запит памʼяті для Контейнера, включіть поле resources:requests
у маніфесті ресурсів Контейнера. Для вказівки ліміти памʼяті включіть resources:limits
.
У цьому завданні ви створюєте Pod, який має один Контейнер. У Контейнера вказано запит памʼяті 100 МіБ і ліміти памʼяті 200 МіБ. Ось файл конфігурації для Podʼа:
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
requests:
memory: "100Mi"
limits:
memory: "200Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
Розділ args
у файлі конфігурації надає аргументи для Контейнера при його запуску. Аргументи "--vm-bytes", "150M"
вказують Контейнеру спробувати виділити 150 МіБ памʼяті.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example
Перевірте, що Контейнер Podʼа працює:
kubectl get pod memory-demo --namespace=mem-example
Перегляньте детальну інформацію про Pod:
kubectl get pod memory-demo --output=yaml --namespace=mem-example
Вивід показує, що один Контейнер у Podʼі має запит памʼяті 100 МіБ та ліміти памʼяті 200 МіБ.
...
resources:
requests:
memory: 100Mi
limits:
memory: 200Mi
...
Виконайте команду kubectl top
, щоб отримати метрики для Podʼа:
kubectl top pod memory-demo --namespace=mem-example
Вивід показує, що Pod використовує приблизно 162,900,000 байт памʼяті, що становить близько 150 МіБ. Це більше, ніж запит Podʼа на 100 МіБ, але в межах ліміти Podʼа на 200 МіБ.
NAME CPU(cores) MEMORY(bytes)
memory-demo <something> 162856960
Видаліть свій Pod:
kubectl delete pod memory-demo --namespace=mem-example
Перевищення лімітів памʼяті Контейнера
Контейнер може перевищити свій запит на памʼять, якщо на вузлі є вільна памʼять. Але Контейнер не може використовувати памʼяті більше, ніж його ліміт памʼяті. Якщо Контейнер використовує більше памʼяті, ніж його ліміт, Контейнер стає кандидатом на зупинку роботи. Якщо Контейнер продовжує використовувати памʼять поза своїм лімітом, він зупиняється. Якщо Контейнер може бути перезапущений, kubelet перезапускає його, як із будь-яким іншим типом відмови під час роботи.
У цьому завданні ви створюєте Pod, який намагається виділити більше памʼяті, ніж його ліміт. Ось файл конфігурації для Podʼа, який має один Контейнер з запитом памʼяті 50 МіБ та лімітом памʼяті 100 МіБ:
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-2
namespace: mem-example
spec:
containers:
- name: memory-demo-2-ctr
image: polinux/stress
resources:
requests:
memory: "50Mi"
limits:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
У розділі args
файлу конфігурації видно, що Контейнер спробує використати 250 МіБ памʼяті, що значно перевищує ліміт в 100 МіБ.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example
Перегляньте детальну інформацію про Pod:
kubectl get pod memory-demo-2 --namespace=mem-example
На цей момент Контейнер може працювати або бути знищеним. Повторіть попередню команду, доки Контейнер не буде знищено:
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 24s
Отримайте більш детальний огляд стану Контейнера:
kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example
Вивід показує, що Контейнер був знищений через вичерпання памʼяті (OOM):
lastState:
terminated:
containerID: 65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
exitCode: 137
finishedAt: 2017-06-20T20:52:19Z
reason: OOMKilled
startedAt: null
Контейнер у цьому завданні може бути перезапущений, тому kubelet перезапускає його. Повторіть цю команду кілька разів, щоб переконатися, що Контейнер постійно знищується та перезапускається:
kubectl get pod memory-demo-2 --namespace=mem-example
Вивід показує, що Контейнер знищується, перезапускається, знищується знову, знову перезапускається і так далі:
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 37s
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 1/1 Running 2 40s
Перегляньте детальну інформацію про історію Podʼа:
kubectʼ describe pod лімітомo-2 ʼ-namespace=mem-example
Вивід показує, що Контейнер починається і знову не вдається:
... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff Back-off restarting failed container
Перегляньте детальну інформацію про вузли вашого кластера:
kubectl describe nodes
Вивід містить запис про знищення Контейнера через умову вичерпання памʼяті:
Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child
Видаліть свій Pod:
kubectl delete pod memory-demo-2 --namespace=mem-example
Визначення запиту памʼяті, що є завеликим для вашого вузла
Запити та ліміт памʼяті повʼязані з Контейнерами, але корисно думати про Pod як про елемент, що має запит та ліміт памʼяті. Запит памʼяті для Podʼа — це сума запитів памʼяті для всіх Контейнерів у Podʼі. Аналогічно, ліміт памʼяті для Podʼа — це сума лімітів всіх Контейнерів у Podʼі.
Планування Podʼа ґрунтується на запитах. Pod планується кзапуску на вузлі лише у разі, якщо вузол має достатньо вільної памʼяті, щоб задовольнити запит памʼяті Podʼа.
У цьому завданні ви створюєте Pod, у якого запит памʼяті настільки великий, що перевищує можливості будь-якого вузла у вашому кластері. Ось файл конфігурації для Podʼа, у якого один Контейнер з запитом на 1000 ГіБ памʼяті, що, ймовірно, перевищує можливості будь-якого вузла у вашому кластері.
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-3
namespace: mem-example
spec:
containers:
- name: memory-demo-3-ctr
image: polinux/stress
resources:
requests:
memory: "1000Gi"
limits:
memory: "1000Gi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example
Перегляньте статус Podʼа:
kubectl get pod memory-demo-3 --namespace=mem-example
Вивід показує, що статус Podʼа — PENDING. Це означає, що Pod не заплановано для запуску на жодному вузлі, і він залишатиметься у стані PENDING безстроково:
kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 25s
Перегляньте детальну інформацію про Pod, включаючи події:
kubectl describe pod memory-demo-3 --namespace=mem-example
Вивід показує, що Контейнер не може бути запланований через нестачу памʼяті на вузлах:
Events:
... Reason Message
------ -------
... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3).
Одиниці памʼяті
Ресурс памʼяті вимірюється у байтах. Ви можете виразити памʼять як ціле число або ціле число з одним із наступних суфіксів: E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki. Наприклад, наступні значення приблизно однакові:
128974848, 129e6, 129M, 123Mi
Видаліть свій Pod:
kubectl delete pod memory-demo-3 --namespace=mem-example
Якщо ви не вказуєте ліміт памʼяті
Якщо ви не вказуєте ліміт памʼяті для Контейнера, відбувається одне з наступного:
Контейнер не має верхньої межі на кількість використаної памʼяті. Контейнер може використовувати всю доступну памʼять на вузлі, де він працює, що, своєю чергою, може спричинити активацію "OOM Killer". Крім того, в разі активації "OOM Kill" Контейнер без обмежень ресурсів матиме більше шансів на знищення.
Контейнер працює в просторі імен, який має стандартний ліміт памʼяті, і Контейнер автоматично отримує визначений стандартний ліміт. Адміністратори кластера можуть використовувати LimitRange для зазначення стандартного ліміту памʼяті.
Для чого вказувати запит та ліміт памʼяті
Налаштовуючи запити та ліміти памʼяті для Контейнерів, які працюють у вашому кластері, ви можете ефективно використовувати ресурси памʼяті, доступні на вузлах вашого кластера. Знижуючи запит памʼяті для Podʼа, ви даєте Podʼу хороший шанс на планування. Маючи ліміти памʼяті, який перевищує запит памʼяті, ви досягаєте двох цілей:
- Pod може мати періоди сплеску активності, коли він використовує доступну памʼять.
- Обсяг памʼяті, який Pod може використовувати під час сплесків, обмежений до якогось розумного значення.
Очищення
Видаліть простір імен. Це видалить всі Podʼи, які ви створили для цього завдання:
kubectl delete namespace mem-example
Що далі
Для розробників застосунків
Для адміністраторів кластера
Налаштування стандартних запитів та обмежень памʼяті для простору імен
Налаштування стандартних запитів та обмежень ЦП для простору імен
Налаштування мінімальних та максимальних обмежень памʼяті для простору імен
Налаштування мінімальних та максимальних обмежень ЦП для простору імен
Зміна розміру ресурсів ЦП та памʼяті, які призначені для Контейнерів
2 - Виділення ресурсів CPU контейнерам та Podʼам
Ця сторінка показує, як вказати запит та ліміт CPU для контейнера. Контейнери не можуть використовувати більше CPU, ніж налаштований ліміт. При наявності вільного часу процесора контейнера гарантується виділення стільки CPU, скільки він запитує.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Кожен вузол у вашому кластері повинен мати принаймні 1 CPU.
Деякі кроки на цій сторінці вимагають запуску служби metrics-server у вашому кластері. Якщо у вас запущено metrics-server, ви можете пропустити ці кроки.
Якщо ви використовуєте Minikube, виконайте таку команду, щоб увімкнути metrics-server:
minikube addons enable metrics-server
Щоб перевірити, чи запущений metrics-server, або інший постачальник API ресурсів метрик (metrics.k8s.io
), виконайте таку команду:
kubectl get apiservices
Якщо API ресурсів метрик доступне, у виводі буде міститися посилання на metrics.k8s.io
.
NAME
v1beta1.metrics.k8s.io
Створення простору імен
Створіть простір імен, щоб ресурси, які ви створюєте у цьому завданні, були відокремлені від інших ресурсів у вашому кластері.
kubectl create namespace cpu-example
Визначте запит ЦП та ліміт ЦП
Для вказання запиту ЦП для контейнера включіть поле resources:requests
в маніфест ресурсів Контейнера. Щоб вказати ліміт ЦП, включіть resources:limits
.
У цьому завданні ви створюєте Pod, у якого є один контейнер. Контейнер має запит на 0,5 CPU та ліміт 1 CPU. Ось файл конфігурації для Podʼа:
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr
image: vish/stress
resources:
limits:
cpu: "1"
requests:
cpu: "0.5"
args:
- -cpus
- "2"
Секція args
у файлі конфігурації надає аргументи для контейнера при його запуску. Аргумент -cpus "2"
каже Контейнеру спробувати використовувати 2 CPU.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit.yaml --namespace=cpu-example
Перевірте, що Pod працює:
kubectl get pod cpu-demo --namespace=cpu-example
Перегляньте детальну інформацію про Pod:
kubectl get pod cpu-demo --output=yaml --namespace=cpu-example
Вивід показує, що один контейнер у Podʼі має запит ЦП 500 міліCPU та ліміт ЦП 1 CPU.
resources:
limits:
cpu: "1"
requests:
cpu: 500m
Використовуйте kubectl top
, щоб отримати метрики для Podʼа:
kubectl top pod cpu-demo --namespace=cpu-example
У цьому прикладі виводу показано, що Pod використовує 974 міліCPU, що незначно менше, ніж ліміт 1 CPU, вказане в конфігурації Podʼа.
NAME CPU(cores) MEMORY(bytes)
cpu-demo 974m <something>
Нагадуємо, що, встановивши -cpu "2"
, ви налаштували контейнер на спробу використати 2 CPU, але контейнер може використовувати лише близько 1 CPU. Використання ЦП контейнером обмежується, оскільки контейнер намагається використовувати більше ресурсів ЦП, ніж його ліміт.
Примітка:
Інше можливе пояснення того, що використання ЦП менше 1.0, — це те, що на вузлі може не бути достатньо ресурсів ЦП. Пригадайте, що передумовами для цієї вправи є наявність у вашому кластері принаймні 1 CPU для використання. Якщо ваш контейнер запускається на вузлі з лише 1 CPU, контейнер не може використовувати більше ніж 1 CPU, незалежно від ліміту ЦП, вказаного для контейнера.Одиниці ЦП
Ресурс ЦП вимірюється в одиницях ЦП. Одна одиниця ЦП в Kubernetes еквівалентна:
- 1 AWS vCPU
- 1 GCP Core
- 1 Azure vCore
- 1 Hyperthread на процесорі Intel з гіперпотоками
Дозволені дробові значення. Контейнер, який запитує 0,5 ЦП, гарантовано отримує половину ЦП порівняно з контейнером, який запитує 1 ЦП. Ви можете використовувати суфікс m для позначення мілі. Наприклад, 100m ЦП, 100 міліЦП і 0,1 ЦП — це все одне й те саме. Точність, більша за 1m, не допускається.
ЦП завжди запитується як абсолютна кількість, ніколи як відносна кількість; 0.1 — це та сама кількість ЦП на одноядерному, двоядерному або 48-ядерному компʼютері.
Видаліть свій Pod:
kubectl delete pod cpu-demo --namespace=cpu-example
Визначте запит ЦП, який перевищує можливості ваших вузлів
Запити та ліміти ЦП повʼязані з контейнерами, але корисно вважати Pod таким, що має запит ЦП та ліміти. Запит ЦП для Podʼа — це сума запитів ЦП для всіх контейнерів у Podʼі. Так само, ліміти ЦП для Podʼа — це сума обмежень ЦП для всіх контейнерів у Podʼі.
Планування Podʼа базується на запитах. Pod буде запланований для запуску на вузлі тільки у випадку, якщо на вузлі є достатньо ресурсів ЦП для задоволення запиту ЦП Podʼа.
У цьому завданні ви створюєте Pod, який має запит ЦП такий великий, що він перевищує можливості будь-якого вузла у вашому кластері. Ось файл конфігурації для Podʼа, який має один контейнер. Контейнер запитує 100 ЦП, що ймовірно перевищить можливості будь-якого вузла у вашому кластері.
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo-2
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr-2
image: vish/stress
resources:
limits:
cpu: "100"
requests:
cpu: "100"
args:
- -cpus
- "2"
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit-2.yaml --namespace=cpu-example
Перегляньте статус Podʼа:
kubectl get pod cpu-demo-2 --namespace=cpu-example
Вивід показує, що статус Podʼа — Pending. Тобто Pod не був запланований для запуску на будь-якому вузлі, і він буде залишатися в стані Pending нескінченно:
NAME READY STATUS RESTARTS AGE
cpu-demo-2 0/1 Pending 0 7m
Перегляньте детальну інформацію про Pod, включаючи події:
kubectl describe pod cpu-demo-2 --namespace=cpu-example
Вивід показує, що контейнер не може бути запланований через недостатні ресурси ЦП на вузлах:
Events:
Reason Message
------ -------
FailedScheduling No nodes are available that match all of the following predicates:: Insufficient cpu (3).
Видаліть свій Pod:
kubectl delete pod cpu-demo-2 --namespace=cpu-example
Якщо ви не вказуєте ліміт ЦП
Якщо ви не вказуєте ліміт ЦП для контейнера, то застосовується одне з наступного:
Контейнер не має верхньої межі ресурсів ЦП, які він може використовувати. Контейнер може використовувати всі доступні ресурси ЦП на вузлі, на якому він працює.
Контейнер працює в просторі імен, який має стандартний ліміт ЦП, і контейнеру автоматично призначається цей стандартний ліміт. Адміністратори кластера можуть використовувати LimitRange для зазначення стандартних значень лімітів ЦП.
Якщо ви вказуєте ліміт ЦП, але не вказуєте запит ЦП
Якщо ви вказуєте ліміт ЦП для контейнера, але не вказуєте запит ЦП, Kubernetes автоматично призначає запит ЦП, який збігається з лімітом. Аналогічно, якщо контейнер вказує свій власний ліміт памʼяті, але не вказує запит памʼяті, Kubernetes автоматично призначає запит памʼяті, який збігається з лімітом.
Для чого вказувати запит та ліміт ЦП
Налаштувавши запити та ліміти ЦП контейнерів, що працюють у вашому кластері, ви можете ефективно використовувати доступні ресурси ЦП на вузлах вашого кластера. Зберігаючи низький запит ЦП для Podʼа, ви забезпечуєте хороші шанси на його планування. Маючи ліміти ЦП, який перевищує запит ЦП, ви досягаєте двох речей:
- Pod може мати періоди підвищеної активності, коли він використовує доступні ресурси ЦП.
- Кількість ресурсів ЦП, які Pod може використовувати під час такої активності, обмежена розумною кількістю.
Очищення
Видаліть ваш простір імен:
kubectl delete namespace cpu-example
Що далі
Для розробників застосунків
Для адміністраторів кластерів
- Налаштування стандартних запитів та лімітів памʼяті для простору імен
- Налаштування стандартних запитів та лімітів ЦП для простору імен
- Налаштування мінімальних та максимальних лімітів памʼяті для простору імен
- Налаштування мінімальних та максимальних лімітів ЦП для простору імен
- Налаштування квот на памʼять та ЦП для простору імен
- Налаштування квоти для Podʼів у просторі імен
- Налаштування квот для API-обʼєктів
- Зміна розміру ресурсів ЦП та памʼяті, призначених контейнерам
3 - Налаштування GMSA для Windows Podʼів та контейнерів
Kubernetes v1.18 [stable]
Ця сторінка показує, як налаштувати Group Managed Service Accounts (GMSA) для Podʼів та контейнерів, які будуть запущені на вузлах Windows. Group Managed Service Accounts це специфічний тип облікового запису Active Directory, який забезпечує автоматичне управління паролями, спрощене управління іменами служб (SPN) та можливість делегування управління іншим адміністраторам на кількох серверах.
У Kubernetes специфікації облікових даних GMSA налаштовуються на рівні кластера Kubernetes як Custom Resources. Windows Podʼи, також як і окремі контейнери в Podʼі, можуть бути налаштовані для використання GMSA для доменних функцій (наприклад, автентифікація Kerberos) при взаємодії з іншими службами Windows.
Перш ніж ви розпочнете
Вам необхідно мати кластер Kubernetes і інструмент командного рядка kubectl
, налаштований для керування з вашим кластером. Очікується, що в кластері будуть вузли Windows. Цей розділ охоплює набір початкових кроків, необхідних один раз для кожного кластера:
Встановлення CRD для GMSACredentialSpec
CustomResourceDefinition(CRD) для ресурсів специфікації облікових даних GMSA потрібно налаштувати на кластері, щоб визначити тип настроюваного ресурсу GMSACredentialSpec
. Завантажте GMSA CRD YAML і збережіть як gmsa-crd.yaml. Далі встановіть CRD за допомогою kubectl apply -f gmsa-crd.yaml
.
Встановлення вебхуків для перевірки користувачів GMSA
Два вебхуки потрібно налаштувати на кластері Kubernetes для заповнення та перевірки посилань на специфікації облікових даних GMSA на рівні Podʼа або контейнера:
Модифікаційний вебхук, який розширює посилання на GMSAs (за іменем зі специфікації Podʼа) до повної специфікації облікових даних у форматі JSON у специфікації Podʼа.
Валідаційний вебхук забезпечує, що всі посилання на GMSAs уповноважені для використання обліковим записом служби Podʼа.
Встановлення зазначених вище вебхуків та повʼязаних обʼєктів вимагає наступних кроків:
Створіть пару ключів сертифікатів (яка буде використовуватися для забезпечення звʼязку контейнера вебхука з кластером)
Встановіть Secret із вищезазначеним сертифікатом.
Створіть Deployment для основної логіки вебхука.
Створіть конфігурації валідаційного та модифікаційного вебхуків, посилаючись на Deployment.
Скрипт можна використовувати для розгортання та налаштування вебхуків GMSA та повʼязаних з ними обʼєктів, зазначених вище. Скрипт можна запускати з опцією --dry-run=server
, щоб ви могли переглянути зміни, які будуть внесені в ваш кластер.
YAML шаблон, що використовується скриптом, також може бути використаний для ручного розгортання вебхуків та повʼязаних обʼєктів (з відповідними замінами параметрів)
Налаштування GMSA та вузлів Windows в Active Directory
Перш ніж Podʼи в Kubernetes можуть бути налаштовані на використання GMSA, необхідно провести налаштування бажаних GMSA в Active Directory, як описано в документації Windows GMSA. Вузли робочих станцій Windows (які є частиною кластера Kubernetes) повинні бути налаштовані в Active Directory для доступу до секретних облікових даних, що повʼязані з бажаним GMSA, як описано в документації Windows GMSA.
Створення ресурсів GMSA Credential Spec
Після встановлення CRD GMSACredentialSpec (як описано раніше), можна налаштувати власні ресурси, що містять специфікації облікових даних GMSA. Специфікація облікових даних GMSA не містить конфіденційні або секретні дані. Це інформація, яку контейнерне середовище може використовувати для опису бажаної GMSA контейнера для Windows. Специфікації облікових даних GMSA можуть бути створені у форматі YAML за допомогою утиліти сценарію PowerShell.
Ось кроки для створення YAML-файлу специфікації облікових даних GMSA вручну у форматі JSON і подальше його конвертування:
Імпортуйте модуль CredentialSpec module:
ipmo CredentialSpec.psm1
.Створіть специфікацію облікових даних у форматі JSON за допомогою команди
New-CredentialSpec
. Щоб створити специфікацію облікових даних GMSA з іменем WebApp1, викличтеNew-CredentialSpec -Name WebApp1 -AccountName WebApp1 -Domain $(Get-ADDomain -Current LocalComputer)
.Використайте команду
Get-CredentialSpec
, щоб показати шлях до файлу JSON.Конвертуйте файл credspec з формату JSON у YAML та застосуйте необхідні заголовкові поля
apiVersion
,kind
,metadata
таcredspec
, щоб зробити його специфікацією GMSACredentialSpec, яку можна налаштувати в Kubernetes.
Наступна конфігурація YAML описує специфікацію облікових даних GMSA з іменем gmsa-WebApp1
:
apiVersion: windows.k8s.io/v1
kind: GMSACredentialSpec
metadata:
name: gmsa-WebApp1 # Це довільне імʼя, але воно буде використовуватися як посилання
credspec:
ActiveDirectoryConfig:
GroupManagedServiceAccounts:
- Name: WebApp1 # Імʼя користувача облікового запису GMSA
Scope: CONTOSO # Імʼя домену NETBIOS
- Name: WebApp1 # Імʼя користувача облікового запису GMSA
Scope: contoso.com # Імʼя домену DNS
CmsPlugins:
- ActiveDirectory
DomainJoinConfig:
DnsName: contoso.com # Імʼя домену DNS
DnsTreeName: contoso.com # Корінь імені домену DNS
Guid: 244818ae-87ac-4fcd-92ec-e79e5252348a # GUID для Domain
MachineAccountName: WebApp1 # Імʼя користувача облікового запису GMSA
NetBiosName: CONTOSO # Імʼя домену NETBIOS
Sid: S-1-5-21-2126449477-2524075714-3094792973 # SID для Domain
Вищезазначений ресурс специфікації облікових даних може бути збережений як gmsa-Webapp1-credspec.yaml
і застосований до кластера за допомогою: kubectl apply -f gmsa-Webapp1-credspec.yaml
.
Налаштування ролі кластера для включення RBAC у конкретні специфікації облікових даних GMSA
Для кожного ресурсу специфікації облікових даних GMSA потрібно визначити роль в кластері. Це авторизує дію use
("використовувати") на конкретному ресурсі GMSA певним субʼєктом, який, як правило, є службовим обліковим записом. Наведений нижче приклад показує роль в кластері, яка авторизує використання специфікації облікових даних gmsa-WebApp1
зверху. Збережіть файл як gmsa-webapp1-role.yaml і застосуйте його за допомогою kubectl apply -f gmsa-webapp1-role.yaml
.
# Створення ролі для читання credspec
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: webapp1-role
rules:
- apiGroups: ["windows.k8s.io"]
resources: ["gmsacredentialspecs"]
verbs: ["use"]
resourceNames: ["gmsa-WebApp1"]
Призначення ролі службовому обліковому запису для використання конкретних специфікацій облікових даних GMSA
Службовий обліковий запис (з якими будуть налаштовані Podʼи) повинен бути привʼязаний до ролі в кластері, створеної вище. Це авторизує службовий обліковий запис використовувати бажаний ресурс специфікації облікових даних GMSA. Нижче показано, як стандартний службовий обліковий запис привʼязується до ролі в кластера webapp1-role
для використання ресурсу специфікації облікових даних gmsa-WebApp1
, створеного вище.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: allow-default-svc-account-read-on-gmsa-WebApp1
namespace: default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: webapp1-role
apiGroup: rbac.authorization.k8s.io
Налаштування посилання на специфікацію облікових даних GMSA в специфікації Pod
Поле securityContext.windowsOptions.gmsaCredentialSpecName
у специфікації Pod використовується для вказівки посилань на бажані ресурси специфікації облікових даних GMSA в специфікаціях Pod. Це налаштовує всі контейнери в специфікації Pod на використання вказаного GMSA. Нижче наведено приклад специфікації Pod з анотацією, заповненою для посилання на gmsa-WebApp1
:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-webapp1
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
nodeSelector:
kubernetes.io/os: windows
Індивідуальні контейнери в специфікації Pod також можуть вказати бажану специфікацію облікових даних GMSA, використовуючи поле securityContext.windowsOptions.gmsaCredentialSpecName
на рівні окремого контейнера. Наприклад:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-Webapp1
nodeSelector:
kubernetes.io/os: windows
Під час застосування специфікацій Pod з заповненими полями GMSA (як описано вище) в кластері відбувається наступна послідовність подій:
Модифікаційний вебхук розвʼязує та розширює всі посилання на ресурси специфікації облікових даних GMSA до вмісту специфікації облікових даних GMSA.
Валідаційний вебхук переконується, що обліковий запис служби, повʼязаний з Pod, авторизований для дії
use
на вказаній специфікації облікових даних GMSA.Контейнерне середовище налаштовує кожен контейнер Windows із вказаною специфікацією облікових даних GMSA, щоб контейнер міг прийняти елемент GMSA в Active Directory та отримати доступ до служб в домені, використовуючи цей елемент.
Автентифікація на мережевих ресурсах за допомогою імені хосту або повного доменного імені
Якщо ви маєте проблеми з підключенням до SMB-ресурсів з Podʼів за допомогою імені хосту або повного доменного імені, але можете отримати доступ до ресурсів за їх адресою IPv4, переконайтеся, що встановлений наступний ключ реєстру на вузлах Windows.
reg add "HKLM\SYSTEM\CurrentControlSet\Services\hns\State" /v EnableCompartmentNamespace /t REG_DWORD /d 1
Після цього потрібно перестворити Podʼи, щоб вони врахували зміни в поведінці. Додаткову інформацію про те, як використовується цей ключ реєстру, можна знайти тут.
Усунення несправностей
Якщо у вас виникають труднощі з налаштуванням роботи GMSA в вашому середовищі, існують кілька кроків усунення несправностей, які ви можете виконати.
Спочатку переконайтеся, що credspec був переданий до Podʼа. Для цього вам потрібно виконати команду exec
в одному з ваших Podʼів і перевірити вивід команди nltest.exe /parentdomain
.
У наступному прикладі Pod не отримав credspec правильно:
kubectl exec -it iis-auth-7776966999-n5nzr powershell.exe
Результат команди nltest.exe /parentdomain
показує наступну помилку:
Getting parent domain failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
Якщо ваш Pod отримав credspec правильно, наступним кроком буде перевірка звʼязку з доменом. Спочатку, зсередини вашого Podʼа, виконайте nslookup, щоб знайти корінь вашого домену.
Це дозволить нам визначити 3 речі:
- Pod може досягти контролера домену (DC).
- Контролер домену (DC) може досягти Podʼа.
- DNS працює правильно.
Якщо тест DNS та комунікації успішний, наступним буде перевірка, чи Pod встановив захищений канал звʼязку з доменом. Для цього, знову ж таки, виконайте команду exec
в вашому Podʼі та запустіть команду nltest.exe /query
.
nltest.exe /query
Результат буде наступним:
I_NetLogonControl failed: Статус = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
Це говорить нам те, що з якоїсь причини Pod не зміг увійти в домен, використовуючи обліковий запис, вказаний у credspec. Ви можете спробувати полагодити захищений канал за допомогою наступного:
nltest /sc_reset:domain.example
Якщо команда успішна, ви побачите подібний вивід:
Flags: 30 HAS_IP HAS_TIMESERV
Trusted DC Name \\dc10.domain.example
Trusted DC Connection Status Status = 0 0x0 NERR_Success
The command completed successfully
Якщо дії вище виправили помилку, ви можете автоматизувати цей крок, додавши наступний виклик у час життєвого циклу до специфікації вашого Podʼа. Якщо це не виправило помилку, вам потрібно перевірити ваш credspec ще раз та підтвердити, що він правильний та повний.
image: registry.domain.example/iis-auth:1809v1
lifecycle:
postStart:
exec:
command: ["powershell.exe","-command","do { Restart-Service -Name netlogon } while ( $($Result = (nltest.exe /query); if ($Result -like '*0x0 NERR_Success*') {return $true} else {return $false}) -eq $false)"]
imagePullPolicy: IfNotPresent
Якщо ви додасте розділ lifecycle
до специфікації вашого Podʼа, Pod виконає вказані команди для перезапуску служби netlogon
до того, як команда nltest.exe /query
вийде без помилок.
4 - Зміна обсягів CPU та памʼяті, призначених для контейнерів
Kubernetes v1.27 [alpha]
(стандартно увімкнено: false)Ця сторінка передбачає, що ви обізнані з Якістю обслуговування для Podʼів Kubernetes.
Ця сторінка показує, як змінити обсяги CPU та памʼяті, призначені для контейнерів працюючого Podʼа без перезапуску самого Podʼа або його контейнерів. Вузол Kubernetes виділяє ресурси для Podʼа на основі його запитів
, і обмежує використання ресурсів Podʼа на основі лімітів
, вказаних у контейнерах Podʼа.
Зміна розподілу ресурсів для запущеного Podʼа вимагає, що функціональна можливість InPlacePodVerticalScaling
має бути увімкнено. Альтернативою може бути видалення Podʼа і ввімкнення параметра, щоб workload controller створив новий Pod з іншими вимогами до ресурсів.
Для зміни ресурсів Podʼа на місці:
- Ресурси
запитів
талімітів
контейнера є змінними для ресурсів CPU та памʼяті. - Поле
allocatedResources
уcontainerStatuses
статусу Podʼа відображає ресурси, виділені контейнерам Podʼа. - Поле
resources
уcontainerStatuses
статусу Podʼа відображає фактичні ресурсизапитів
талімітів
, які налаштовані на запущених контейнерах відповідно до звіту контейнерного середовища. - Поле
resize
у статусі Podʼа показує статус останнього запиту очікуваної зміни розміру. Воно може мати наступні значення:Proposed
: Це значення показує, що було отримано підтвердження запиту на зміну розміру та що запит був перевірений та зареєстрований.InProgress
: Це значення вказує, що вузол прийняв запит на зміну розміру та знаходиться у процесі застосування його до контейнерів Podʼа.Deferred
: Це значення означає, що запитаної зміни розміру наразі не можна виконати, і вузол буде спробувати її виконати пізніше. Зміна розміру може бути виконана, коли інші Podʼи покинуть і звільнять ресурси вузла.Infeasible
: це сигнал того, що вузол не може задовольнити запит на зміну розміру. Це може статися, якщо запит на зміну розміру перевищує максимальні ресурси, які вузол може виділити для Podʼа.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути не старішою ніж 1.27. Для перевірки версії введітьkubectl version
.Має бути увімкнено функціональну можливість InPlacePodVerticalScaling
для вашої панелі управління і для всіх вузлів вашого кластера.
Політики зміни розміру контейнера
Політики зміни розміру дозволяють більш детально керувати тим, як контейнери Podʼа змінюють свої ресурси CPU та памʼяті. Наприклад, застосунок з контейнера може використовувати ресурси CPU, змінені без перезапуску, але зміна памʼяті може вимагати перезапуску застосунку та відповідно контейнерів.
Для активації цього користувачам дозволяється вказати resizePolicy
у специфікації контейнера. Наступні політики перезапуску можна вказати для зміни розміру CPU та памʼяті:
NotRequired
: Змінити ресурси контейнера під час його роботи.RestartContainer
: Перезапустити контейнер та застосувати нові ресурси після перезапуску.
Якщо resizePolicy[*].restartPolicy
не вказано, воно стандартно встановлюється в NotRequired
.
Примітка:
ЯкщоrestartPolicy
Podʼа є Never
, політика зміни розміру контейнера повинна бути встановленою в NotRequired
для всіх контейнерів у Podʼі.У наведеному нижче прикладі Podʼа CPU контейнера може бути змінено без перезапуску, але змінювання памʼяті вимагає перезапуску контейнера.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-5
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr-5
image: nginx
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired
- resourceName: memory
restartPolicy: RestartContainer
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Примітка:
У вищенаведеному прикладі, якщо бажані запити або ліміти як для CPU, так і для памʼяті змінилися, контейнер буде перезапущено для зміни його памʼяті.Створення Podʼа із запитами та лімітами ресурсів
Ви можете створити Guaranteed або Burstable клас якості обслуговування Podʼу, вказавши запити та/або ліміти для контейнерів Podʼа.
Розгляньте наступний маніфест для Podʼа, який має один контейнер.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-5
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr-5
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Створіть Pod у просторі імен qos-example
:
kubectl create namespace qos-example
kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-5.yaml
Цей Pod класифікується як Pod класу якості обслуговування Guaranteed, і має запит 700 мілі CPU та 200 мегабайтів памʼяті.
Перегляньте детальну інформацію про Pod:
kubectl get pod qos-demo-5 --output=yaml --namespace=qos-example
Також погляньте, що значення resizePolicy[*].restartPolicy
типово встановлено в NotRequired
, що вказує, що CPU та памʼять можна змінити, поки контейнер працює.
spec:
containers:
...
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired
- resourceName: memory
restartPolicy: NotRequired
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
containerStatuses:
...
name: qos-demo-ctr-5
ready: true
...
allocatedResources:
cpu: 700m
memory: 200Mi
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
restartCount: 0
started: true
...
qosClass: Guaranteed
Оновлення ресурсів Podʼа
Скажімо, вимоги до CPU зросли, і тепер потрібно 0.8 CPU. Це можна вказати вручну, або визначити і застосувати програмно, наприклад, за допомогою таких засобів, як VerticalPodAutoscaler (VPA).
Примітка:
Хоча ви можете змінити запити та ліміти Podʼа, щоб виразити нові бажані ресурси, ви не можете змінити клас якості обслуговування, в якому був створений Pod.Тепер відредагуйте контейнер Podʼа, встановивши як запити, так і ліміти CPU на 800m
:
kubectl -n qos-example patch pod qos-demo-5 --patch '{"spec":{"containers":[{"name":"qos-demo-ctr-5", "resources":{"requests":{"cpu":"800m"}, "limits":{"cpu":"800m"}}}]}}'
Отримайте докладну інформацію про Pod після внесення змін.
kubectl get pod qos-demo-5 --output=yaml --namespace=qos-example
Специфікація Podʼа нижче показує оновлені запити та ліміти CPU.
spec:
containers:
...
resources:
limits:
cpu: 800m
memory: 200Mi
requests:
cpu: 800m
memory: 200Mi
...
containerStatuses:
...
allocatedResources:
cpu: 800m
memory: 200Mi
resources:
limits:
cpu: 800m
memory: 200Mi
requests:
cpu: 800m
memory: 200Mi
restartCount: 0
started: true
Зверніть увагу, що значення allocatedResources
були оновлені, щоб відображати нові бажані запити CPU. Це вказує на те, що вузол зміг забезпечити потреби у збільшених ресурсах CPU.
У статусі контейнера оновлені значення ресурсів CPU показують, що нові CPU ресурси були застосовані. Значення restartCount
контейнера залишається без змін, що вказує на те, що ресурси CPU контейнера були змінені без перезапуску контейнера.
Очищення
Видаліть ваш простір імен:
kubectl delete namespace qos-example
Для розробників застосунків
Для адміністраторів кластерів
5 - Налаштування RunAsUserName для Podʼів та контейнерів Windows
Kubernetes v1.18 [stable]
Ця сторінка показує, як використовувати параметр runAsUserName
для Podʼів та контейнерів, які будуть запущені на вузлах Windows. Це приблизно еквівалент параметра runAsUser
, який використовується для Linux, і дозволяє виконувати програми в контейнері від імені іншого імені користувача, ніж типово.
Перш ніж ви розпочнете
Вам потрібно мати кластер Kubernetes, а також інструмент командного рядка kubectl повинен бути налаштований для взаємодії з вашим кластером. Очікується, що в кластері будуть використовуватися вузли Windows, де будуть запускатися Podʼи з контейнерами, що виконують робочі навантаження у Windows.
Встановлення імені користувача для Podʼа
Щоб вказати імʼя користувача, з яким потрібно виконати процеси контейнера Podʼа, включіть поле securityContext
(PodSecurityContext) в специфікацію Podʼа, а всередині нього — поле windowsOptions
(WindowsSecurityContextOptions), що містить поле runAsUserName
.
Опції безпеки Windows, які ви вказуєте для Podʼа, застосовуються до всіх контейнерів та контейнерів ініціалізації у Podʼі.
Ось конфігураційний файл для Podʼа Windows зі встановленим полем runAsUserName
:
apiVersion: v1
kind: Pod
metadata:
name: run-as-username-pod-demo
spec:
securityContext:
windowsOptions:
runAsUserName: "ContainerUser"
containers:
- name: run-as-username-demo
image: mcr.microsoft.com/windows/servercore:ltsc2019
command: ["ping", "-t", "localhost"]
nodeSelector:
kubernetes.io/os: windows
Створіть Pod:
kubectl apply -f https://k8s.io/examples/windows/run-as-username-pod.yaml
Перевірте, що Контейнер Podʼа працює:
kubectl get pod run-as-username-pod-demo
Отримайте доступ до оболонки контейнера:
kubectl exec -it run-as-username-pod-demo -- powershell
Перевірте, що оболонка працює від імені відповідного користувача:
echo $env:USERNAME
Вивід повинен бути:
ContainerUser
Встановлення імені користувача для контейнера
Щоб вказати імʼя користувача, з яким потрібно виконати процеси контейнера, включіть поле securityContext
(SecurityContext) у маніфесті контейнера, а всередині нього — поле windowsOptions
(WindowsSecurityContextOptions), що містить поле runAsUserName
.
Опції безпеки Windows, які ви вказуєте для контейнера, застосовуються тільки до цього окремого контейнера, і вони перевизначають налаштування, зроблені на рівні Podʼа.
Ось конфігураційний файл для Podʼа, який має один Контейнер, а поле runAsUserName
встановлене на рівні Podʼа та на рівні Контейнера:
apiVersion: v1
kind: Pod
metadata:
name: run-as-username-container-demo
spec:
securityContext:
windowsOptions:
runAsUserName: "ContainerUser"
containers:
- name: run-as-username-demo
image: mcr.microsoft.com/windows/servercore:ltsc2019
command: ["ping", "-t", "localhost"]
securityContext:
windowsOptions:
runAsUserName: "ContainerAdministrator"
nodeSelector:
kubernetes.io/os: windows
Створіть Pod:
kubectl apply -f https://k8s.io/examples/windows/run-as-username-container.yaml
Перевірте, що Контейнер Podʼа працює:
kubectl get pod run-as-username-container-demo
Отримайте доступ до оболонки контейнера:
kubectl exec -it run-as-username-container-demo -- powershell
Перевірте, що оболонка працює від імені відповідного користувача (того, який встановлений на рівні контейнера):
echo $env:USERNAME
Вивід повинен бути:
ContainerAdministrator
Обмеження імен користувачів Windows
Для використання цієї функції значення, встановлене у полі runAsUserName
, повинно бути дійсним імʼям користувача. Воно повинно мати наступний формат: DOMAIN\USER
, де DOMAIN\
є необовʼязковим. Імена користувачів Windows регістронезалежні. Крім того, існують деякі обмеження стосовно DOMAIN
та USER
:
- Поле
runAsUserName
не може бути порожнім і не може містити керуючі символи (ASCII значення:0x00-0x1F
,0x7F
) DOMAIN
може бути або NetBios-імʼям, або DNS-імʼям, кожне з власними обмеженнями:- NetBios імена: максимум 15 символів, не можуть починатися з
.
(крапка), і не можуть містити наступні символи:\ / : * ? " < > |
- DNS-імена: максимум 255 символів, містять тільки буквено-цифрові символи, крапки та дефіси, і не можуть починатися або закінчуватися
.
(крапка) або-
(дефіс).
- NetBios імена: максимум 15 символів, не можуть починатися з
USER
може мати не більше 20 символів, не може містити тільки крапки або пробіли, і не може містити наступні символи:" / \ [ ] : ; | = , + * ? < > @
.
Приклади припустимих значень для поля runAsUserName
: ContainerAdministrator
, ContainerUser
, NT AUTHORITY\NETWORK SERVICE
, NT AUTHORITY\LOCAL SERVICE
.
Для отримання додаткової інформації про ці обмеження, перевірте тут та тут.
Що далі
6 - Створення Podʼа Windows HostProcess
Kubernetes v1.26 [stable]
Windows HostProcess контейнери дозволяють вам запускати контейнеризовані робочі навантаження на хості Windows. Ці контейнери працюють як звичайні процеси, але мають доступ до мережевого простору імен хосту, сховища та пристроїв, коли надані відповідні права користувача. Контейнери HostProcess можуть бути використані для розгортання мережевих втулків, сховищ конфігурацій, пристроїв, kube-proxy та інших компонентів на вузлах Windows без потреби у власних проксі або безпосереднього встановлення служб хосту.
Адміністративні завдання, такі як встановлення патчів безпеки, збір подій логів тощо, можна виконувати без потреби входу операторів кластера на кожен вузол Windows. Контейнери HostProcess можуть працювати як будь-який користувач, що доступний на хості або в домені машини хосту, що дозволяє адміністраторам обмежити доступ до ресурсів через дозволи користувача. Хоча і не підтримуються ізоляція файлової системи або процесу, при запуску контейнера на хості створюється новий том, щоб надати йому чисте та обʼєднане робоче середовище. Контейнери HostProcess також можуть бути побудовані на базі наявних образів базової системи Windows і не успадковують ті ж вимоги сумісності як контейнери Windows server, що означає, що версія базового образу не повинна відповідати версії хосту. Однак рекомендується використовувати ту ж версію базового образу, що й ваші робочі навантаження контейнерів Windows Server, щоб уникнути зайвого використання місця на вузлі. Контейнери HostProcess також підтримують монтування томів всередині тома контейнера.
Коли варто використовувати контейнери Windows HostProcess?
- Коли потрібно виконати завдання, які потребують мережевого простору імен хосту. Контейнери HostProcess мають доступ до мережевих інтерфейсів хосту та IP-адрес.
- Вам потрібен доступ до ресурсів на хості, таких як файлова система, події логів тощо.
- Встановлення конкретних драйверів пристроїв або служб Windows.
- Обʼєднання адміністративних завдань та політик безпеки. Це зменшує ступінь привілеїв, які потрібні вузлам Windows.
Перш ніж ви розпочнете
Цей посібник стосується конкретно Kubernetes v1.31. Якщо ви використовуєте іншу версію Kubernetes, перевірте документацію для цієї версії Kubernetes.
У Kubernetes 1.31 контейнери HostProcess є типово увімкненими. kubelet буде спілкуватися з containerd безпосередньо, передаючи прапорець hostprocess через CRI. Ви можете використовувати останню версію containerd (v1.6+) для запуску контейнерів HostProcess. Як встановити containerd.
Обмеження
Ці обмеження стосуються Kubernetes v1.31:
- Контейнери HostProcess вимагають середовища виконання контейнерів containerd 1.6 або вище, рекомендується використовувати containerd 1.7.
- Podʼи HostProcess можуть містити лише контейнери HostProcess. Це поточне обмеження ОС Windows; непривілейовані контейнери Windows не можуть спільно використовувати vNIC з простором імен IP хосту.
- Контейнери HostProcess запускаються як процес на хості та не мають жодного рівня ізоляції, окрім обмежень ресурсів, накладених на обліковий запис користувача HostProcess. Ізоляція ні файлової системи, ні ізоляції Hyper-V не підтримуються для контейнерів HostProcess.
- Монтування томів підтримуються і монтуватимуться як томом контейнера. Див. Монтування томів
- Стандартно для контейнерів HostProcess доступний обмежений набір облікових записів користувачів хосту. Див. Вибір облікового запису користувача.
- Обмеження ресурсів (диск, памʼять, кількість процесорів) підтримуються так само як і процеси на хості.
- Як іменовані канали, так і сокети Unix-домену не підтримуються і замість цього слід отримувати доступ до них через їх шлях на хості (наприклад, \\.\pipe\*)
Вимоги до конфігурації HostProcess Pod
Для активації Windows HostProcess Pod необхідно встановити відповідні конфігурації у конфігурації безпеки Podʼа. З усіх політик, визначених у Стандартах безпеки Pod, HostProcess Podʼи заборонені за базовою та обмеженою політиками. Тому рекомендується, щоб HostProcess Podʼи працювали відповідно до привілейованого профілю.
Під час роботи з привілейованою політикою, ось конфігурації, які потрібно встановити для активації створення HostProcess Pod:
Елемент | Політика |
---|---|
securityContext.windowsOptions.hostProcess | Windows Podʼи надають можливість запуску контейнерів HostProcess, які дозволяють привілейований доступ до вузла Windows. Дозволені значення
|
hostNetwork | Контейнери HostProcess Podʼи повинні використовувати мережевий простір хоста. Дозволені значення
|
securityContext.windowsOptions.runAsUserName | Необхідно вказати, яким користувачем має виконуватися контейнер HostProcess в специфікації Podʼа. Дозволені значення
|
runAsNonRoot | Оскільки контейнери HostProcess мають привілейований доступ до хоста, поле runAsNonRoot не може бути встановлене в true. Дозволені значення
|
Приклад маніфесту (частково)
spec:
securityContext:
windowsOptions:
hostProcess: true
runAsUserName: "NT AUTHORITY\\Local service"
hostNetwork: true
containers:
- name: test
image: image1:latest
command:
- ping
- -t
- 127.0.0.1
nodeSelector:
"kubernetes.io/os": windows
Монтування томів
Контейнери HostProcess підтримують можливість монтування томів у просторі томів контейнера. Поведінка монтування томів відрізняється залежно від версії контейнерного середовища containerd, яке використовується на вузлі.
Containerd v1.6
Застосунки, що працюють усередині контейнера, можуть отримувати доступ до підключених томів безпосередньо за допомогою відносних або абсолютних шляхів. Під час створення контейнера встановлюється змінна середовища $CONTAINER_SANDBOX_MOUNT_POINT
, яка містить абсолютний шлях хосту до тому контейнера. Відносні шляхи базуються на конфігурації .spec.containers.volumeMounts.mountPath
.
Для доступу до токенів облікового запису служби (наприклад) у контейнері підтримуються такі структури шляхів:
.\var\run\secrets\kubernetes.io\serviceaccount\
$CONTAINER_SANDBOX_MOUNT_POINT\var\run\secrets\kubernetes.io\serviceaccount\
Containerd v1.7 (та новіші версії)
Застосунки, які працюють усередині контейнера, можуть отримувати доступ до підключених томів безпосередньо через вказаний mountPath
тому (аналогічно Linux і не-HostProcess контейнерам Windows).
Для забезпечення зворотної сумісності зі старими версіями, доступ до томів також може бути здійснений через використання тих самих відносних шляхів, які були налаштовані у containerd v1.6.
Наприклад, для доступу до токенів службового облікового запису усередині контейнера ви можете використовувати один із таких шляхів:
c:\var\run\secrets\kubernetes.io\serviceaccount
/var/run/secrets/kubernetes.io/serviceaccount/
$CONTAINER_SANDBOX_MOUNT_POINT\var\run\secrets\kubernetes.io\serviceaccount\
Обмеження ресурсів
Обмеження ресурсів (диск, памʼять, кількість CPU) застосовуються до задачі і є загальними для всієї задачі. Наприклад, при обмеженні в 10 МБ памʼяті, памʼять, виділена для будь-якого обʼєкта задачі HostProcess, буде обмежена 10 МБ. Це така ж поведінка, як і в інших типах контейнерів Windows. Ці обмеження вказуються так само як і зараз для будь-якого середовища виконання контейнерів або оркестрування, яке використовується. Єдина відмінність полягає у розрахунку використання дискових ресурсів для відстеження ресурсів через відмінності у способі ініціалізації контейнерів HostProcess.
Вибір облікового запису користувача
Системні облікові записи
Типово контейнери HostProcess підтримують можливість запуску з одного з трьох підтримуваних облікових записів служб Windows:
Вам слід вибрати відповідний обліковий запис служби Windows для кожного контейнера HostProcess, спираючись на обмеження ступеня привілеїв, щоб уникнути випадкових (або навіть зловмисних) пошкоджень хосту. Обліковий запис служби LocalSystem має найвищий рівень привілеїв серед трьох і повинен використовуватися лише у разі абсолютної необхідності. Де це можливо, використовуйте обліковий запис служби LocalService, оскільки він має найнижчий рівень привілеїв серед цих трьох варіантів.
Локальні облікові записи
Якщо налаштовано, контейнери HostProcess також можуть запускатися як локальні облікові записи користувачів, що дозволяє операторам вузлів надавати деталізований доступ до робочих навантажень.
Для запуску контейнерів HostProcess як локального користувача, спершу на вузлі має бути створена локальна група користувачів, і імʼя цієї локальної групи користувачів повинно бути вказане у полі runAsUserName
у Deployment. Перед ініціалізацією контейнера HostProcess має бути створено новий ефемерний локальний обліковий запис користувача та приєднано його до вказаної групи користувачів, з якої запускається контейнер. Це надає кілька переваг, включаючи уникнення необхідності управління паролями для локальних облікових записів користувачів. Початковий контейнер HostProcess, що працює як службовий обліковий запис, може бути використаний для підготовки груп користувачів для подальших контейнерів HostProcess.
Примітка:
Запуск контейнерів HostProcess як локальних облікових записів користувачів вимагає containerd v1.7+Приклад:
Створіть локальну групу користувачів на вузлі (це може бути зроблено в іншому контейнері HostProcess).
net localgroup hpc-localgroup /add
Надайте доступ до потрібних ресурсів на вузлі локальній групі користувачів. Це можна зробити за допомогою інструментів, таких як icacls.
Встановіть
runAsUserName
на імʼя локальної групи користувачів для Podʼа або окремих контейнерів.securityContext: windowsOptions: hostProcess: true runAsUserName: hpc-localgroup
Заплануйте Pod!
Базовий образ для контейнерів HostProcess
Контейнери HostProcess можуть бути побудовані з будь-яких наявних базових образів контейнерів Windows.
Крім того, був створений новий базовий образ спеціально для контейнерів HostProcess! Для отримання додаткової інформації перегляньте проєкт windows-host-process-containers-base-image на github.
Розвʼязання проблем з контейнерами HostProcess
Контейнери HostProcess не запускаються, помилка
failed to create user process token: failed to logon user: Access is denied.: unknown
.Переконайтеся, що containerd працює як службовий обліковий запис
LocalSystem
абоLocalService
. Облікові записи користувачів (навіть адміністраторські облікові записи) не мають дозволів на створення токенів входу для будь-яких підтримуваних облікових записів користувачів.
7 - Налаштування якості обслуговування для Podʼів
Ця сторінка показує, як налаштувати Podʼи так, щоб їм були призначені певні класи якості обслуговування (QoS). Kubernetes використовує класи QoS для прийняття рішень про видалення Podʼів, коли використання ресурсів вузла збільшується.
Коли Kubernetes створює Pod, він призначає один з таких класів QoS для Podʼа:
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Також вам потрібно мати можливість створювати та видаляти простори імен.
Створення простору імен
Створіть простір імен, щоб ресурси, які ви створюєте у цьому завданні, були ізольовані від решти вашого кластера.
kubectl create namespace qos-example
Створення Podʼа, якому призначено клас QoS Guaranteed
Щоб Podʼа був наданий клас QoS Guaranteed:
- Кожний контейнер у Pod повинен мати ліміт памʼяті та запит памʼяті.
- Для кожного контейнера у Pod ліміт памʼяті повинен дорівнювати запиту памʼяті.
- Кожний контейнер у Pod повинен мати ліміт CPU та запит CPU.
- Для кожного контейнера у Pod ліміт CPU повинен дорівнювати запиту CPU.
Ці обмеження так само застосовуються до контейнерів ініціалізації і до контейнерів застосунків. Ефемерні контейнери не можуть визначати ресурси, тому ці обмеження не застосовуються до них.
Нижче подано маніфест для Podʼа з одним контейнером. Контейнер має ліміт памʼяті та запит памʼяті, обидва дорівнюють 200 MiB. Контейнер має ліміт CPU та запит CPU, обидва дорівнюють 700 міліCPU:
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod.yaml --namespace=qos-example
Перегляньте докладну інформацію про Pod:
kubectl get pod qos-demo --namespace=qos-example --output=yaml
Вивід показує, що Kubernetes призначив Podʼу клас QoS Guaranteed
. Також вивід підтверджує, що у контейнера Podʼа є запит памʼяті, який відповідає його ліміту памʼяті, і є запит CPU, який відповідає його ліміту CPU.
spec:
containers:
...
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
status:
qosClass: Guaranteed
Примітка:
Якщо контейнер вказує свій власний ліміт памʼяті, але не вказує запит памʼяті, Kubernetes автоматично призначає запит памʼяті, який відповідає ліміту. Так само, якщо контейнер вказує свій власний ліміт CPU, але не вказує запит CPU, Kubernetes автоматично призначає запит CPU, який відповідає ліміту.Очищення
Видаліть свій Pod:
kubectl delete pod qos-demo --namespace=qos-example
Створення Podʼа, якому призначено клас QoS Burstable
Podʼу надається клас QoS Burstable, якщо:
- Pod не відповідає критеріям для класу QoS
Guaranteed
. - Принаймні один контейнер у Podʼі має запит або ліміт памʼяті або CPU.
Нижче подано маніфест для Podʼа з одним контейнером. Контейнер має ліміт памʼяті 200 MiB та запит памʼяті 100 MiB.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
- name: qos-demo-2-ctr
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-2.yaml --namespace=qos-example
Перегляньте докладну інформацію про Pod:
kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml
Вивід показує, що Kubernetes призначив Podʼу клас QoS Burstable:
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: qos-demo-2-ctr
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
status:
qosClass: Burstable
Очищення
Видаліть свій Pod:
kubectl delete pod qos-demo-2 --namespace=qos-example
Створення Podʼа, якому призначено клас QoS BestEffort
Для того, щоб Podʼу був призначений клас QoS BestEffort
, контейнери у Podʼі не повинні мати жодних лімітів або запитів памʼяті чи CPU.
Нижче подано маніфест для Podʼа з одним контейнером. контейнер не має лімітів або запитів памʼяті чи CPU:
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- name: qos-demo-3-ctr
image: nginx
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-3.yaml --namespace=qos-example
Перегляньте докладну інформацію про Pod:
kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml
Вивід показує, що Kubernetes призначив Podʼа клас QoS BestEffort:
spec:
containers:
...
resources: {}
...
status:
qosClass: BestEffort
Очищення
Видаліть свій Pod:
kubectl delete pod qos-demo-3 --namespace=qos-example
Створення Podʼа з двома контейнерами
Нижче подано маніфест для Podʼа з двома контейнерами. Один контейнер вказує запит памʼяті 200 MiB. Інший контейнер не вказує жодних запитів або лімітів.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-4
namespace: qos-example
spec:
containers:
- name: qos-demo-4-ctr-1
image: nginx
resources:
requests:
memory: "200Mi"
- name: qos-demo-4-ctr-2
image: redis
Зверніть увагу, що цей Pod відповідає критеріям класу QoS Burstable
. Тобто, він не відповідає критеріям для класу QoS Guaranteed
, і один з його контейнерів має запит памʼяті.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-4.yaml --namespace=qos-example
Перегляньте докладну інформацію про Pod:
kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml
Вивід показує, що Kubernetes призначив Podʼу клас QoS Burstable
:
spec:
containers:
...
name: qos-demo-4-ctr-1
resources:
requests:
memory: 200Mi
...
name: qos-demo-4-ctr-2
resources: {}
...
status:
qosClass: Burstable
Отримання класу QoS Podʼа
Замість того, щоб бачити всі поля, ви можете переглянути лише поле, яке вам потрібно:
kubectl --namespace=qos-example get pod qos-demo-4 -o jsonpath='{ .status.qosClass}{"\n"}'
Burstable
Очищення
Видаліть ваш простір імен:
kubectl delete namespace qos-example
Що далі
Для розробників застосунків
Для адміністраторів кластера
8 - Призначення розширених ресурсів контейнеру
Kubernetes v1.31 [stable]
Ця сторінка показує, як призначити розширені ресурси контейнеру.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Перш ніж виконувати це завдання, виконайте завдання Оголошення розширених ресурсів для вузла. Це налаштує один з ваших вузлів для оголошення ресурсу "dongle".
Призначте розширений ресурс Podʼу
Щоб запитати розширений ресурс, включіть поле resources:requests
у ваш маніфест контейнера. Розширені ресурси повністю кваліфікуються будь-яким доменом поза *.kubernetes.io/
. Дійсні імена розширених ресурсів мають форму example.com/foo
, де example.com
замінено на домен вашої організації, а foo
— це описове імʼя ресурсу.
Нижче подано конфігураційний файл для Podʼа з одним контейнером:
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo
spec:
containers:
- name: extended-resource-demo-ctr
image: nginx
resources:
requests:
example.com/dongle: 3
limits:
example.com/dongle: 3
У конфігураційному файлі можна побачити, що контейнер запитує 3 розширених ресурси "dongle".
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod.yaml
Перевірте, що Pod працює:
kubectl get pod extended-resource-demo
Опишіть Pod:
kubectl describe pod extended-resource-demo
Виведений текст показує запити донглів:
Limits:
example.com/dongle: 3
Requests:
example.com/dongle: 3
Спроба створення другого Podʼа
Нижче наведено конфігураційний файл для Podʼа з одним контейнером. Контейнер запитує два розширені ресурси "dongle".
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo-2
spec:
containers:
- name: extended-resource-demo-2-ctr
image: nginx
resources:
requests:
example.com/dongle: 2
limits:
example.com/dongle: 2
Kubernetes не зможе задовольнити запит на два донгли, оскільки перший Pod використав три з чотирьох доступних донглів.
Спроба створити Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod-2.yaml
Опишіть Pod:
kubectl describe pod extended-resource-demo-2
Текст виводу показує, що Pod не може бути запланованим, оскільки немає вузла, на якому було б доступно 2 донгли:
Conditions:
Type Status
PodScheduled False
...
Events:
...
... Warning FailedScheduling pod (extended-resource-demo-2) failed to fit in any node
fit failure summary on nodes : Insufficient example.com/dongle (1)
Перегляньте статус Podʼа:
kubectl get pod extended-resource-demo-2
Текст виводу показує, що Pod було створено, але не заплановано для виконання на вузлі. Він має статус Pending:
NAME READY STATUS RESTARTS AGE
extended-resource-demo-2 0/1 Pending 0 6m
Очищення
Видаліть Podʼи, які ви створили для цього завдання:
kubectl delete pod extended-resource-demo
kubectl delete pod extended-resource-demo-2
Для розробників застосунків
- Призначення ресурсів памʼяті для контейнерів та Podʼів
- Призначення ресурсів CPU для контейнерів та Podʼів
Для адміністраторів кластера
9 - Налаштування Podʼа для використання тому для зберігання
Ця сторінка показує, як налаштувати Pod для використання тому для зберігання.
Файлова система контейнера існує лише поки існує сам контейнер. Отже, коли контейнер завершує роботу та перезавантажується, зміни в файловій системі втрачаються. Для більш стійкого зберігання, яке не залежить від контейнера, ви можете використовувати том. Це особливо важливо для застосунків, що зберігають стан, таких як бази даних і сховища ключ-значення (наприклад, Redis).
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Налаштування тому для Podʼа
У цьому завданні ви створюєте Pod, який запускає один контейнер. У цьому Podʼі є том типу emptyDir, який існує протягом усього життєвого циклу Podʼа, навіть якщо контейнер завершиться та перезапуститься. Ось конфігураційний файл для Podʼа:
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
emptyDir: {}
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/storage/redis.yaml
Перевірте, що контейнер Podʼа працює, а потім спостерігайте за змінами в Podʼі:
kubectl get pod redis --watch
Вивід буде подібний до цього:
NAME READY STATUS RESTARTS AGE redis 1/1 Running 0 13s
В іншому терміналі отримайте доступ до оболонки запущеного контейнера:
kubectl exec -it redis -- /bin/bash
У вашій оболонці перейдіть до
/data/redis
, а потім створіть файл:root@redis:/data# cd /data/redis/ root@redis:/data/redis# echo Hello > test-file
У вашій оболонці виведіть список запущених процесів:
root@redis:/data/redis# apt-get update root@redis:/data/redis# apt-get install procps root@redis:/data/redis# ps aux
Вивід буде схожий на це:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND redis 1 0.1 0.1 33308 3828 ? Ssl 00:46 0:00 redis-server *:6379 root 12 0.0 0.0 20228 3020 ? Ss 00:47 0:00 /bin/bash root 15 0.0 0.0 17500 2072 ? R+ 00:48 0:00 ps aux
У вашій оболонці завершіть процес Redis:
root@redis:/data/redis# kill <pid>
де
<pid>
— це ідентифікатор процесу Redis (PID).У вашому початковому терміналі спостерігайте за змінами в Podʼі Redis. В кінцевому результаті ви побачите щось подібне:
NAME READY STATUS RESTARTS AGE redis 1/1 Running 0 13s redis 0/1 Completed 0 6m redis 1/1 Running 1 6m
На цьому етапі контейнер завершився та перезапустився. Це тому, що Pod Redis має restartPolicy Always
.
Отримайте доступ до оболонки в перезапущеному контейнері:
kubectl exec -it redis -- /bin/bash
У вашій оболонці перейдіть до
/data/redis
та перевірте, щоtest-file
все ще там.root@redis:/data/redis# cd /data/redis/ root@redis:/data/redis# ls test-file
Видаліть Pod, який ви створили для цього завдання:
kubectl delete pod redis
Що далі
Дивіться Volume.
Дивіться Pod.
Крім локального сховища на диску, яке надає
emptyDir
, Kubernetes підтримує багато різних рішень для мережевого сховища, включаючи PD на GCE та EBS на EC2, які бажані для критичних даних та будуть обробляти деталі, такі як монтування та розмонтування пристроїв на вузлах. Дивіться Volumes для отримання додаткової інформації.
10 - Налаштування Podʼа для використання PersistentVolume для зберігання
Ця сторінка показує, як налаштувати Pod для використання PersistentVolumeClaim для зберігання. Ось короткий опис процесу:
Ви, як адміністратор кластера, створюєте PersistentVolume на основі фізичного сховища. Ви не повʼязуєте том з жодним Podʼом.
Ви, як розробник / користувач кластера, створюєте PersistentVolumeClaim, який автоматично привʼязується до відповідного PersistentVolume.
Ви створюєте Pod, який використовує вищезгаданий PersistentVolumeClaim для зберігання.
Перш ніж ви розпочнете
Вам потрібно мати кластер Kubernetes, який має лише один вузол, і kubectl повинен бути налаштований на спілкування з вашим кластером. Якщо у вас ще немає кластера з одним вузлом, ви можете створити його, використовуючи Minikube.
Ознайомтеся з матеріалом в Постійні томи.
Створіть файл index.html на вашому вузлі
Відкрийте оболонку на єдиному вузлі вашого кластера. Спосіб відкриття оболонки залежить від того, як ви налаштували ваш кластер. Наприклад, якщо ви використовуєте Minikube, ви можете відкрити оболонку до вашого вузла, введенням minikube ssh
.
У вашій оболонці на цьому вузлі створіть теку /mnt/data
:
# Це передбачає, що ваш вузол використовує "sudo" для запуску команд
# як суперкористувач
sudo mkdir /mnt/data
У теці /mnt/data
створіть файл index.html
:
# Це також передбачає, що ваш вузол використовує "sudo" для запуску команд
# як суперкористувач
sudo sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html"
Примітка:
Якщо ваш вузол використовує інструмент для доступу суперкористувача, відмінний відsudo
, ви зазвичай можете зробити це, якщо заміните sudo
на імʼя іншого інструмента.Перевірте, що файл index.html
існує:
cat /mnt/data/index.html
Виведення повинно бути:
Hello from Kubernetes storage
Тепер ви можете закрити оболонку вашого вузла.
Створення PersistentVolume
У цьому завданні ви створюєте hostPath PersistentVolume. Kubernetes підтримує hostPath для розробки та тестування на одновузловому кластері. PersistentVolume типу hostPath використовує файл або теку на вузлі для емуляції мережевого сховища.
В операційному кластері ви не використовували б hostPath. Замість цього адміністратор кластера створив би мережевий ресурс, такий як постійний диск Google Compute Engine, розділ NFS або том Amazon Elastic Block Store. Адміністратори кластера також можуть використовувати StorageClasses для динамічного налаштування.
Ось файл конфігурації для PersistentVolume типу hostPath:
apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
Файл конфігурації вказує, що том знаходиться в /mnt/data
на вузлі кластера. Конфігурація також вказує розмір 10 гібібайт та режим доступу ReadWriteOnce
, що означає, що том може бути підключений як для читання-запису лише одним вузлом. Визначається імʼя StorageClass manual
для PersistentVolume, яке буде використовуватися для привʼязки запитів PersistentVolumeClaim до цього PersistentVolume.
Примітка:
У цьому прикладі використовується режим доступуReadWriteOnce
для спрощення. Для
операційного застосування проєкт Kubernetes рекомендує використовувати режим доступу ReadWriteOncePod
.Створіть PersistentVolume:
kubectl apply -f https://k8s.io/examples/pods/storage/pv-volume.yaml
Перегляньте інформацію про PersistentVolume:
kubectl get pv task-pv-volume
Вивід показує, що PersistentVolume має STATUS
Available
. Це означає, що він ще не був привʼязаний до PersistentVolumeClaim.
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Available manual 4s
Створення PersistentVolumeClaim
Наступним кроком є створення PersistentVolumeClaim. Podʼи використовують PersistentVolumeClaim для запиту фізичного сховища. У цій вправі ви створюєте PersistentVolumeClaim, який запитує том не менше трьох гібібайт, який може забезпечити доступ до читання-запису не більше одного вузла за раз.
Ось файл конфігурації для PersistentVolumeClaim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
Створіть PersistentVolumeClaim:
kubectl apply -f https://k8s.io/examples/pods/storage/pv-claim.yaml
Після створення PersistentVolumeClaim панель управління Kubernetes шукає PersistentVolume, який відповідає вимогам заявки. Якщо панель управління знаходить відповідний PersistentVolume з тим самим StorageClass, вона привʼязує заявку до тому.
Знову подивіться на PersistentVolume:
kubectl get pv task-pv-volume
Тепер вивід показує STATUS
як Bound
.
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Bound default/task-pv-claim manual 2m
Подивіться на PersistentVolumeClaim:
kubectl get pvc task-pv-claim
Вивід показує, що PersistentVolumeClaim привʼязаний до вашого PersistentVolume,
task-pv-volume
.
NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE
task-pv-claim Bound task-pv-volume 10Gi RWO manual 30s
Створення Podʼа
Наступним кроком є створення Podʼа, який використовує ваш PersistentVolumeClaim як том.
Ось файл конфігурації для Podʼа:
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
Зверніть увагу, що файл конфігурації Podʼа вказує PersistentVolumeClaim, але не вказує PersistentVolume. З погляду Podʼа, заявка є томом.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/storage/pv-pod.yaml
Перевірте, що контейнер у Podʼі працює:
kubectl get pod task-pv-pod
Відкрийте оболонку для контейнера, що працює у вашому Podʼі:
kubectl exec -it task-pv-pod -- /bin/bash
У вашій оболонці перевірте, що nginx обслуговує файл index.html
з тому hostPath:
# Обовʼязково запустіть ці 3 команди всередині кореневої оболонки, яка є результатом
# виконання "kubectl exec" на попередньому кроці
apt update
apt install curl
curl http://localhost/
Вивід показує текст, який ви записали у файл index.html
у томі hostPath:
Hello from Kubernetes storage
Якщо ви бачите це повідомлення, ви успішно налаштували Pod для використання зберігання з PersistentVolumeClaim.
Очищення
Видаліть Pod, PersistentVolumeClaim та PersistentVolume:
kubectl delete pod task-pv-pod
kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume
Якщо у вас ще не відкрито оболонку до вузла у вашому кластері, відкрийте нову оболонку так само як ви робили це раніше.
У оболонці на вашому вузлі видаліть файл і теку, які ви створили:
# Це передбачає, що ваш вузол використовує "sudo" для виконання команд
# з правами суперкористувача
sudo rm /mnt/data/index.html
sudo rmdir /mnt/data
Тепер ви можете закрити оболонку доступу до вашого вузла.
Монтування одного PersistentVolume у два місця
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- name: test
image: nginx
volumeMounts:
# a mount for site-data
- name: config
mountPath: /usr/share/nginx/html
subPath: html
# another mount for nginx config
- name: config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: config
persistentVolumeClaim:
claimName: test-nfs-claim
Ви можете виконати монтування томуу двох місцях у вашому контейнері nginx:
/usr/share/nginx/html
для статичного вебсайту/etc/nginx/nginx.conf
для стандартної конфігурації
Контроль доступу
Зберігання даних із використанням ідентифікатора групи (GID) дозволяє запис лише для Podʼів, які використовують той самий GID. Невідповідність або відсутність GID призводить до помилок доступу. Щоб зменшити необхідність координації з користувачами, адміністратор може анотувати PersistentVolume з GID. Після цього GID автоматично додається до будь-якого Podʼа, який використовує цей PersistentVolume.
Використовуйте анотацію pv.beta.kubernetes.io/gid
наступним чином:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
annotations:
pv.beta.kubernetes.io/gid: "1234"
Коли Pod використовує PersistentVolume з анотацією GID, анотований GID застосовується до всіх контейнерів у Podʼі так само як GID, зазначені у контексті безпеки Podʼа. Кожен GID, незалежно від того, чи походить він з анотації PersistentVolume або специфікації Podʼа, застосовується до першого процесу, запущеного в кожному контейнері.
Примітка:
Коли Pod використовує PersistentVolume, GID, асоційовані з PersistentVolume, не відображаються на самому ресурсі Podʼа.Що далі
- Дізнайтеся більше про PersistentVolumes.
- Прочитайте документ проєктування постійного сховища.
Довідка
11 - Налаштування Pod для використання projected тому для зберігання
Ця сторінка показує, як використовувати projected
том, щоб змонтувати декілька наявних джерел томів у одну теку. Наразі можна проєктувати томи типів secret
, configMap
, downwardAPI
, та serviceAccountToken
.
Примітка:
serviceAccountToken
не є типом тому.Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Налаштування projected тому для Pod
У цьому завданні ви створите Secrets із локальних файлів для імені користувача та пароля. Потім ви створите Pod, який запускає один контейнер, використовуючи projected
том для монтування секретів у спільну теку.
Ось файл конфігурації для Pod:
apiVersion: v1
kind: Pod
metadata:
name: test-projected-volume
spec:
containers:
- name: test-projected-volume
image: busybox:1.28
args:
- sleep
- "86400"
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: user
- secret:
name: pass
Створіть Secrets:
# Створіть файли, що містять імʼя користувача та пароль: echo -n "admin" > ./username.txt echo -n "1f2d1e2e67df" > ./password.txt # Запакуйте ці файли у секрети: kubectl create secret generic user --from-file=./username.txt kubectl create secret generic pass --from-file=./password.txt
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/storage/projected.yaml
Перевірте, що контейнер Pod запущено, а потім слідкуйте за змінами в Podʼі:
kubectl get --watch pod test-projected-volume
Вивід буде виглядати так:
NAME READY STATUS RESTARTS AGE test-projected-volume 1/1 Running 0 14s
В іншому терміналі отримайте оболонку до запущеного контейнера:
kubectl exec -it test-projected-volume -- /bin/sh
У вашій оболонці перевірте, що тека
projected-volume
містить ваші projected джерела:ls /projected-volume/
Очищення
Видаліть Pod та Secrets:
kubectl delete pod test-projected-volume
kubectl delete secret user pass
Що далі
- Дізнайтеся більше про
projected
томи. - Прочитайте документ про проєктування all-in-one volume.
12 - Налаштування контексту безпеки для Podʼа або контейнера
Контекст безпеки визначає параметри привілеїв та контролю доступу для Podʼа або контейнера. Налаштування контексту безпеки включають, але не обмежуються:
Дискреційний контроль доступу: Дозвіл на доступ до обʼєкта, такого як файл, базується на ідентифікаторі користувача (UID) та ідентифікаторі групи (GID).
Security Enhanced Linux (SELinux): Обʼєкти призначаються мітки безпеки.
Виконання з привілеями або без них.
Linux Capabilities: Надає процесу деякі привілеї, але не всі привілеї користувача root.
AppArmor: Використовуйте профілі програм для обмеження можливостей окремих програм.
Seccomp: Фільтрує системні виклики процесу.
allowPrivilegeEscalation
: Контролює, чи може процес отримувати більше привілеїв, ніж його батьківський процес. Ця логічна величина безпосередньо контролює, чи встановлюється прапорецьno_new_privs
для процесу контейнера.allowPrivilegeEscalation
завжди true, коли контейнер:- запущений з привілеями, або
- має
CAP_SYS_ADMIN
readOnlyRootFilesystem
: Підключає кореневу файлову систему контейнера тільки для читання.
Вищевказані пункти не є повним набором налаштувань контексту безпеки,докладну інформацію див. у SecurityContext для повного переліку.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Встановлення контексту безпеки для Pod
Щоб вказати параметри безпеки для Podʼа, включіть поле securityContext
в специфікацію Pod. Поле securityContext
є обʼєктом PodSecurityContext. Параметри безпеки, які ви вказуєте для Pod, застосовуються до всіх контейнерів в Podʼі. Ось файл конфігурації для Podʼа з securityContext
та томом emptyDir
:
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
supplementalGroups: [4000]
volumes:
- name: sec-ctx-vol
emptyDir: {}
containers:
- name: sec-ctx-demo
image: busybox:1.28
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- name: sec-ctx-vol
mountPath: /data/demo
securityContext:
allowPrivilegeEscalation: false
У файлі конфігурації поле runAsUser
вказує, що для будь-яких контейнерів в Podʼі, всі процеси виконуються з ідентифікатором користувача 1000. Поле runAsGroup
вказує основний ідентифікатор групи 3000 для усіх процесів у контейнерах Pod. Якщо це поле відсутнє, основний ідентифікатор групи контейнерів буде root(0). Будь-які створені файли також належатимуть користувачу 1000 та групі 3000 при вказанні runAsGroup
. Оскільки вказано поле fsGroup
, всі процеси контейнера також належать до додаткової групи ідентифікатора 2000. Власником тому /data/demo
та всіх створених файлів у цьому томі буде груповий ідентифікатор 2000. Додатково, коли вказане поле supplementalGroups
, всі процеси контейнера також є частиною вказаних груп. Якщо це поле пропущене, це означає, що воно порожнє.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/security/security-context.yaml
Перевірте, що контейнер Pod запущений:
kubectl get pod security-context-demo
Отримайте оболонку до запущеного контейнера:
kubectl exec -it security-context-demo -- sh
У вашій оболонці перелічіть запущені процеси:
ps
Виведений результат показує, що процеси виконуються від імені користувача 1000, що є значенням runAsUser
:
PID USER TIME COMMAND
1 1000 0:00 sleep 1h
6 1000 0:00 sh
...
У вашій оболонці перейдіть до /data
, та виведіть список тек:
cd /data
ls -l
Виведений результат показує, що тека /data/demo
має ідентифікатор групи 2000, що є значенням fsGroup
.
drwxrwsrwx 2 root 2000 4096 Jun 6 20:08 demo
У вашій оболонці перейдіть до /data/demo
, та створіть файл:
cd demo
echo hello > testfile
Виведіть список файлів у теці /data/demo
:
ls -l
Виведений результат показує, що testfile
має ідентифікатор групи 2000, що є значенням fsGroup
.
-rw-r--r-- 1 1000 2000 6 Jun 6 20:08 testfile
Виконайте наступну команду:
id
Результат буде схожий на цей:
uid=1000 gid=3000 groups=2000,3000,4000
З результату видно, що gid
дорівнює 3000, що є таким самим, як поле runAsGroup
. Якби поле runAsGroup
було пропущено, gid
залишився б 0 (root), і процес зміг би взаємодіяти з файлами, які належать групі root(0) та групам, які мають необхідні права групи для групи root (0). Ви також можете побачити, що groups
містить ідентифікатори груп, які вказані в fsGroup
і supplementalGroups
, поряд з gid
.
Вийдіть з оболонки:
exit
Неявні членства груп, визначені в /etc/group
в контейнерному образі
Стандартно Kubernetes обʼєднує інформацію про групи з Podʼа з інформацією, визначеною в /etc/group
в контейнерному образі.
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
supplementalGroups: [4000]
containers:
- name: sec-ctx-demo
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: [ "sh", "-c", "sleep 1h" ]
securityContext:
allowPrivilegeEscalation: false
Цей контекст безпеки Podʼа містить runAsUser
, runAsGroup
та supplementalGroups
. Проте ви можете побачити, що фактичні додаткові групи, що прикріплені до процесу контейнера, включатимуть ідентифікатори груп, які походять з /etc/group
всередині контейнерного образу.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/security/security-context-5.yaml
Перевірте, чи контейнер Pod запущений:
kubectl get pod security-context-demo
Отримайте оболонку для запущеного контейнера:
kubectl exec -it security-context-demo -- sh
Перевірте ідентичність процесу:
$ id
Вивід буде схожий на:
uid=1000 gid=3000 groups=3000,4000,50000
Ви можете побачити, що groups
включає ідентифікатор групи 50000
. Це тому, що користувач (uid=1000
), який визначений в образі, належить до групи (gid=50000
), яка визначена в /etc/group
всередині контейнерного образу.
Перевірте /etc/group
в контейнерному образі:
$ cat /etc/group
Ви побачите, що uid 1000
належить до групи 50000
.
...
user-defined-in-image:x:1000:
group-defined-in-image:x:50000:user-defined-in-image
Вийдіть з оболонки:
exit
Примітка:
Неявно обʼєднані додаткові групи можуть викликати проблеми з безпекою, особливо при доступі до томів (див. kubernetes/kubernetes#112879 для деталей). Щоб уникнути цього, перегляньте розділ нижче.Налаштування SupplementalGroups для Podʼа
Kubernetes v1.31 [alpha]
(стандартно увімкнено: false)Цю функцію можна увімкнути, встановивши функціональну можливість SupplementalGroupsPolicy
для kubelet та kube-apiserver, а також налаштувавши поле .spec.securityContext.supplementalGroupsPolicy
для Podʼа.
Поле supplementalGroupsPolicy
визначає політику для розрахунку додаткових груп для процесів контейнера в Podʼі. Для цього поля є два дійсних
значення:
Merge
: Членство в групах, визначене в/etc/group
для основного користувача контейнера, буде обʼєднано. Це є стандартною політикою, якщо не зазначено інше.Strict
: Тільки ідентифікатори груп у поляхfsGroup
,supplementalGroups
абоrunAsGroup
прикріплюються як додаткові групи для процесів контейнера. Це означає, що жодне членство в групах з/etc/group
для основного користувача контейнера не буде обʼєднано.
Коли функція увімкнена, вона також надає ідентичність процесу, прикріплену до першого процесу контейнера в полі .status.containerStatuses[].user.linux
. Це буде корисно для виявлення, чи прикріплені неявні ідентифікатори груп.
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
supplementalGroups: [4000]
supplementalGroupsPolicy: Strict
containers:
- name: sec-ctx-demo
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: [ "sh", "-c", "sleep 1h" ]
securityContext:
allowPrivilegeEscalation: false
Цей маніфест Podʼа визначає supplementalGroupsPolicy=Strict
. Ви можете побачити, що жодне членство в групах, визначене в /etc/group
, не обʼєднується в додаткові групи для процесів контейнера.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/security/security-context-6.yaml
Перевірте, що контейнер Podʼа працює:
kubectl get pod security-context-demo
Перевірте ідентичність процесу:
kubectl exec -it security-context-demo -- id
Вивід буде подібним до цього:
uid=1000 gid=3000 groups=3000,4000
Перегляньте статус Podʼа:
kubectl get pod security-context-demo -o yaml
Ви можете побачити, що поле status.containerStatuses[].user.linux
надає ідентичність процесу, прикріплену до першого процесу контейнера.
...
status:
containerStatuses:
- name: sec-ctx-demo
user:
linux:
gid: 3000
supplementalGroups:
- 3000
- 4000
uid: 1000
...
Примітка:
Зверніть увагу, що значення в поліstatus.containerStatuses[].user.linux
є першою прикріпленою ідентичністю процесу до першого процесу контейнера в контейнері. Якщо контейнер має достатні привілеї для здійснення системних викликів, повʼязаних з ідентичністю процесу (наприклад, setuid(2)
, setgid(2)
або setgroups(2)
та ін.), процес контейнера може змінити свою ідентичність. Отже, реальна ідентичність процесу буде динамічною.Реалізації
Відомо, що наступні середовища виконання контейнерів підтримують контроль додаткових груп з тонкою настройкою.
На рівні CRI:
- containerd, починаючи з v2.0
- CRI-O, починаючи з v1.31
Ви можете перевірити, чи підтримується функція в статусі вузла.
apiVersion: v1
kind: Node
...
status:
features:
supplementalGroupsPolicy: true
Налаштування політики зміни дозволів та прав власності тому для Pod
Kubernetes v1.23 [stable]
Типово Kubernetes рекурсивно змінює права власності та дозволи для вмісту кожного тому так, щоб вони відповідали значенню fsGroup
, вказаному в securityContext
Podʼа при підключенні цього тому. Для великих томів перевірка та зміна власності та дозволів може займати багато часу, сповільнюючи запуск Podʼів. Ви можете використовувати поле fsGroupChangePolicy
в securityContext
для контролю способу, яким Kubernetes перевіряє та керує власністю та дозволами для тому.
fsGroupChangePolicy — fsGroupChangePolicy
визначає поведінку зміни власності та дозволів тому перед тим, як він буде використаний в Pod. Це поле застосовується лише до типів томів, які підтримують контроль власності та дозволів за допомогою fsGroup
. Це поле має два можливі значення:
- OnRootMismatch: Змінювати дозволи та права власності тільки у випадку, якщо дозволи та права кореневої теки не відповідають очікуваним дозволам тому. Це може допомогти скоротити час зміни власності та дозволів тому.
- Always: Завжди змінювати дозволи та права власності тому під час підключення.
Наприклад:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
fsGroupChangePolicy: "OnRootMismatch"
Делегування зміни прав власності та дозволів тому до драйвера CSI
Kubernetes v1.26 [stable]
Якщо ви розгортаєте драйвер Container Storage Interface (CSI), який підтримує VOLUME_MOUNT_GROUP
NodeServiceCapability
, процес встановлення права власності та дозволів файлу на основі fsGroup
, вказаного в securityContext
, буде виконуватися драйвером CSI, а не Kubernetes. У цьому випадку, оскільки Kubernetes не виконує жодної зміни права власності та дозволів, fsGroupChangePolicy
не набуває чинності, і згідно з вказаним CSI, очікується, що драйвер монтує том з наданим fsGroup
, що призводить до отримання тому, який є доступними для читаання/запису для fsGroup
.
Встановлення контексту безпеки для контейнера
Для вказання параметрів безпеки для контейнера, включіть поле securityContext
в маніфест контейнера. Поле securityContext
є обʼєктом SecurityContext. Параметри безпеки, які ви вказуєте для контейнера, застосовуються тільки до окремого контейнера, і вони перевизначають налаштування, зроблені на рівні Podʼа, коли є перетин. Налаштування контейнера не впливають на томи Podʼів.
Ось файл конфігурації для Podʼа з одним контейнером. Як Pod, так і контейнер мають поле securityContext
:
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-2
spec:
securityContext:
runAsUser: 1000
containers:
- name: sec-ctx-demo-2
image: gcr.io/google-samples/hello-app:2.0
securityContext:
runAsUser: 2000
allowPrivilegeEscalation: false
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/security/security-context-2.yaml
Перевірте, що контейнер Pod запущений:
kubectl get pod security-context-demo-2
Отримайте оболонку до запущеного контейнера:
kubectl exec -it security-context-demo-2 -- sh
У вашій оболонці перегляньте запущені процеси:
ps aux
Виведений результат показує, що процеси виконуються від імені користувача 2000. Це значення
runAsUser
, вказане для контейнера. Воно перевизначає значення 1000, вказане для Pod.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
2000 1 0.0 0.0 4336 764 ? Ss 20:36 0:00 /bin/sh -c node server.js
2000 8 0.1 0.5 772124 22604 ? Sl 20:36 0:00 node server.js
...
Вийдіть з оболонки:
exit
Встановлення можливостей для контейнера
За допомогою можливостей Linux, ви можете надати певні привілеї процесу, не надаючи всі привілеї користувачеві з правами root. Щоб додати або видалити можливості Linux для контейнера, включіть поле capabilities
в розділ securityContext
маніфесту контейнера.
Спочатку подивімося, що відбувається, коли ви не включаєте поле capabilities
. Ось файл конфігурації, який не додає або не видаляє жодних можливостей контейнера:
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-3
spec:
containers:
- name: sec-ctx-3
image: gcr.io/google-samples/hello-app:2.0
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/security/security-context-3.yaml
Перевірте, що контейнер Pod запущений:
kubectl get pod security-context-demo-3
Отримайте оболонку до запущеного контейнера:
kubectl exec -it security-context-demo-3 -- sh
У вашій оболонці перегляньте запущені процеси:
ps aux
Виведений результат показує ідентифікатори процесів (PID) для контейнера:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4336 796 ? Ss 18:17 0:00 /bin/sh -c node server.js
root 5 0.1 0.5 772124 22700 ? Sl 18:17 0:00 node server.js
У вашій оболонці перегляньте статус для процесу 1:
cd /proc/1
cat status
Виведений результат показує bitmap можливостей для процесу:
...
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
...
Запамʼятайте bitmap можливостей, а потім вийдіть з оболонки:
exit
Далі, запустіть контейнер, який є такий самий, як попередній контейнер, за винятком того, що він має додаткові можливості.
Ось файл конфігурації для Pod, який запускає один контейнер. Конфігурація додає можливості CAP_NET_ADMIN
та CAP_SYS_TIME
:
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-4
spec:
containers:
- name: sec-ctx-4
image: gcr.io/google-samples/hello-app:2.0
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/security/security-context-4.yaml
Отримайте оболонку до запущеного контейнера:
kubectl exec -it security-context-demo-4 -- sh
У вашій оболонці перегляньте можливості для процесу 1:
cd /proc/1
cat status
Виведений результат показує бітову карту можливостей для процесу:
...
CapPrm: 00000000aa0435fb
CapEff: 00000000aa0435fb
...
Порівняйте можливості двох контейнерів:
00000000a80425fb
00000000aa0435fb
У bitmap можливостей першого контейнера біти 12 і 25 не встановлені. У другому контейнері, біти 12 і 25 встановлені. Біт 12 — це CAP_NET_ADMIN
, а біт 25 — це CAP_SYS_TIME
. Дивіться capability.h для визначень констант можливостей.
Примітка:
Константи можливостей Linux мають формуCAP_XXX
. Але коли ви перелічуєте можливості у маніфесті вашого контейнера, вам необхідно пропустити частину CAP_
константи. Наприклад, для додавання CAP_SYS_TIME
, включіть SYS_TIME
у ваш список можливостей.Встановлення профілю Seccomp для контейнера
Щоб встановити профіль Seccomp для контейнера, включіть поле seccompProfile
в розділ securityContext
вашого маніфесту Pod або контейнера. Поле seccompProfile
є обʼєктом SeccompProfile, який складається з type
та localhostProfile
. Допустимі варіанти для type
включають RuntimeDefault
, Unconfined
та Localhost
. localhostProfile
повинен бути встановлений лише якщо type: Localhost
. Він вказує шлях до попередньо налаштованого профілю на вузлі, повʼязаного з розташуванням налаштованого профілю Seccomp kubelet (налаштованого за допомогою прапорця --root-dir
).
Ось приклад, який встановлює профіль Seccomp до стандартного профілю контейнера вузла:
...
securityContext:
seccompProfile:
type: RuntimeDefault
Ось приклад, який встановлює профіль Seccomp до попередньо налаштованого файлу за шляхом <kubelet-root-dir>/seccomp/my-profiles/profile-allow.json
:
...
securityContext:
seccompProfile:
type: Localhost
localhostProfile: my-profiles/profile-allow.json
Налаштування профілю AppArmor для контейнера
Щоб налаштувати профіль AppArmor для контейнера, включіть поле appArmorProfile
в секцію securityContext
вашого контейнера. Поле appArmorProfile
є обʼєктом AppArmorProfile, що складається з type
та localhostProfile
. Дійсні опції для type
включають RuntimeDefault
(стандартно), Unconfined
і Localhost
. localhostProfile
слід встановлювати тільки якщо type
є Localhost
. Це вказує на назву попередньо налаштованого профілю на вузлі. Профіль повинен бути завантажений на всіх вузлах, які підходять для Podʼа, оскільки ви не знаєте, де буде розгорнуто Pod. Підходи до налаштування власних профілів обговорюються в Налаштування вузлів з профілями.
Примітка: Якщо containers[*].securityContext.appArmorProfile.type
явно встановлено на RuntimeDefault
, то Pod не буде допущено, якщо AppArmor не включено на вузлі. Однак, якщо containers[*].securityContext.appArmorProfile.type
не зазначено, то стандартне значення (що також є RuntimeDefault
) буде застосовано тільки якщо вузол має увімкнений AppArmor. Якщо вузол має вимкнений AppArmor, Pod буде допущено, але контейнер не буде обмежено профілем RuntimeDefault
.
Ось приклад, який встановлює профіль AppArmor на стандартний профіль контейнерного середовища вузла:
...
containers:
- name: container-1
securityContext:
appArmorProfile:
type: RuntimeDefault
Ось приклад, який встановлює профіль AppArmor на попередньо налаштований профіль
з назвою k8s-apparmor-example-deny-write
:
...
containers:
- name: container-1
securityContext:
appArmorProfile:
type: Localhost
localhostProfile: k8s-apparmor-example-deny-write
Для отримання додаткової інформації дивіться Обмеження доступу контейнера до ресурсів з AppArmor.
Призначення міток SELinux контейнеру
Щоб призначити мітки SELinux контейнеру, включіть поле seLinuxOptions
в розділ securityContext
вашого маніфесту Podʼа або контейнера. Поле seLinuxOptions
є обʼєктом SELinuxOptions. Ось приклад, який застосовує рівень SELinux:
...
securityContext:
seLinuxOptions:
level: "s0:c123,c456"
Примітка:
Для призначення міток SELinux модуль безпеки SELinux повинен бути завантажений в операційну систему хосту.Ефективне переозначення обʼєктів SELinux в томах
Kubernetes v1.28 [beta]
(стандартно увімкнено: true)Примітка:
У Kubernetes v1.27 було введено обмежену ранню форму такої поведінки, яка була застосовна тільки до томів (та PersistentVolumeClaims), які використовують режим доступу ReadWriteOncePod
.
Як альфа-функціонал, ви можете увімкнути функціональну можливість SELinuxMount
, щоб розширити це поліпшення продуктивності на інші види PersistentVolumeClaims, як пояснено докладніше нижче.
Стандартно, контейнерне середовище рекурсивно призначає мітку SELinux для всіх файлів на всіх томах Pod. Щоб прискорити цей процес, Kubernetes може миттєво змінити мітку SELinux тому за допомогою параметра монтування -o context=<мітка>
.
Щоб скористатися цим прискоренням, мають бути виконані всі ці умови:
- Функціональні можливості
ReadWriteOncePod
таSELinuxMountReadWriteOncePod
повинні бути увімкнені. - Pod повинен використовувати PersistentVolumeClaim з відповідними
accessModes
та функціональною можливстю:- Або том має
accessModes: ["ReadWriteOncePod"]
, і властивість включенняSELinuxMountReadWriteOncePod
увімкнена. - Або том може використовувати будь-які інші режими доступу та обидва
SELinuxMountReadWriteOncePod
таSELinuxMount
повинні бути увімкнені.
- Або том має
- Pod (або всі його контейнери, які використовують PersistentVolumeClaim) повинні мати встановлені параметри
seLinuxOptions
. - Відповідний PersistentVolume повинен бути або:
- Том, який використовує старі типи томів
iscsi
,rbd
абоfc
. - Або том, який використовує драйвер CSI CSI. Драйвер CSI повинен оголосити, що він підтримує монтування з
-o context
, встановившиspec.seLinuxMount: true
у його екземплярі CSIDriver.
- Том, який використовує старі типи томів
Для будь-яких інших типів томів переозначення SELinux відбувається іншим шляхом: контейнерне середовище рекурсивно змінює мітку SELinux для всіх inodes (файлів і тек) у томі. Чим більше файлів і тек у томі, тим довше відбувається це переозначення.
Управління доступом до файлової системи /proc
Kubernetes v1.12 [alpha]
(стандартно увімкнено: false)Для середовищ виконання, які слідують специфікації виконання OCI, контейнери типово запускаються у режимі, де є кілька шляхів, які промасковані та доступні тільки для читання. Результатом цього є те, що в межах простору імен монтування контейнера присутні ці шляхи, і вони можуть працювати подібно до того, якби контейнер був ізольованим хостом, але процес контейнера не може записувати до них. Список промаскованих і доступних тільки для читання шляхів такий:
Промасковані шляхи:
/proc/asound
/proc/acpi
/proc/kcore
/proc/keys
/proc/latency_stats
/proc/timer_list
/proc/timer_stats
/proc/sched_debug
/proc/scsi
/sys/firmware
/sys/devices/virtual/powercap
Шляхи доступні тільки для читання:
/proc/bus
/proc/fs
/proc/irq
/proc/sys
/proc/sysrq-trigger
Для деяких Podʼів вам може знадобитися обійти стандартний шлях маскування. Найбільш поширений контекст, коли це потрібно, — це спроба запуску контейнерів у межах контейнера Kubernetes (у межах Podʼа).
Поле procMount
в securityContext
дозволяє користувачеві запитати, щоб /proc
контейнера був Unmasked
, або міг бути підмонтований для читання-запису контейнерним процесом. Це також стосується /sys/firmware
, який не знаходиться в /proc
.
...
securityContext:
procMount: Unmasked
Примітка:
ВстановленняprocMount
в Unmasked потребує, щоб значення spec.hostUsers
в специфікації Pod було false
. Іншими словами: контейнер, який бажає мати Unmasked /proc
або Unmasked /sys
, також повинен бути у просторі імен користувача. У версіях Kubernetes v1.12 по v1.29 це вимога не дотримувалася.Обговорення
Контекст безпеки для Pod застосовується до Контейнерів Pod і також до Томів Pod при необхідності. Зокрема, fsGroup
та seLinuxOptions
застосовуються до Томів наступним чином:
fsGroup
: Томи, які підтримують управління власністю, модифікуються так, щоб бути власністю та доступними для запису за GID, вказаним уfsGroup
. Докладніше див. Документ із проєктування управління власністю томів.seLinuxOptions
: Томи, які підтримують мітку SELinux, переозначаються так, щоб бути доступними за міткою, вказаною уseLinuxOptions
. Зазвичай вам потрібно лише встановити розділlevel
. Це встановлює мітку Multi-Category Security (MCS), яку отримують всі Контейнери у Pod, а також Томи.
Попередження:
Після вказання мітки MCS для Pod всі Pod з такою міткою можуть отримати доступ до Тома. Якщо вам потрібен захист між Podʼами, вам слід призначити унікальну мітку MCS для кожного Pod.Очищення
Видаліть Pod:
kubectl delete pod security-context-demo
kubectl delete pod security-context-demo-2
kubectl delete pod security-context-demo-3
kubectl delete pod security-context-demo-4
Що далі
- PodSecurityContext
- SecurityContext
- Посібник з налаштування втулків CRI
- Документ проєктування контекстів безпеки
- Документ проєктування управління власністю
- Допуск PodSecurity
- Документ проєктування AllowPrivilegeEscalation
- Для отримання додаткової інформації про механізми безпеки в Linux дивіться Огляд функцій безпеки ядра Linux (Примітка: деяка інформація може бути застарілою)
- Дізнайтеся більше про Простори імен користувачів для Linux контейнерів.
- Промасковані шляхи в специфікації OCI Runtime
13 - Налаштування службових облікових записів для Podʼів
Kubernetes пропонує два відмінні способи автентифікації для клієнтів, які працюють у межах вашого кластера або мають взаємозвʼязок з панеллю управління вашого кластера для автентифікації в API-сервері.
Службовий обліковий запис надає ідентичність процесам, які працюють у Podʼі, і відповідає обʼєкту ServiceAccount. Коли ви автентифікуєтеся в API-сервері, ви ідентифікуєте себе як певного користувача. Kubernetes визнає поняття користувача, але сам Kubernetes не має API User.
Це завдання стосується Службових облікових записів, які існують в API Kubernetes. Керівництво показує вам деякі способи налаштування Службових облікових записів для Podʼів.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Використання стандартного службового облікового запису для доступу до API-сервера
Коли Podʼи звертаються до API-сервера, вони автентифікуються як певний Службовий обліковий запис (наприклад, default
). В кожному просторі імен завжди є принаймні один Службовий обліковий запис.
У кожному просторі імен Kubernetes завжди міститься принаймні один Службовий обліковий запис: стандартний службовий обліковий запис для цього простору імен, з назвою default
. Якщо ви не вказуєте Службовий обліковий запис при створенні Podʼа, Kubernetes автоматично призначає Службовий обліковий запис з назвою default
у цьому просторі імен.
Ви можете отримати деталі для Podʼа, який ви створили. Наприклад:
kubectl get pods/<імʼя_пода> -o yaml
У виводі ви побачите поле spec.serviceAccountName
. Kubernetes автоматично встановлює це значення, якщо ви не вказали його при створенні Podʼа.
Застосунок, який працює усередині Podʼа, може отримати доступ до API Kubernetes, використовуючи автоматично змонтовані облікові дані службового облікового запису. Для отримання додаткової інформації див. доступ до кластера.
Коли Pod автентифікується як Службовий обліковий запис, його рівень доступу залежить від втулка авторизації та політики, які використовуються.
Облікові дані API автоматично відкликаються, коли Pod видаляється, навіть якщо є завершувачі. Зокрема, облікові дані API відкликаються через 60 секунд після встановленого на Pod значення .metadata.deletionTimestamp
(час видалення зазвичай дорівнює часу, коли запит на видалення був прийнятий плюс період належного завершення роботи Pod).
Відмова від автоматичного монтування облікових даних API
Якщо ви не бажаєте, щоб kubelet автоматично монтував облікові дані API ServiceAccount, ви можете відмовитися від такої стандартної поведінки. Ви можете відмовитися від автоматичного монтування облікових даних API у /var/run/secrets/kubernetes.io/serviceaccount/token
для службового облікового запису, встановивши значення automountServiceAccountToken: false
у ServiceAccount:
Наприклад:
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
automountServiceAccountToken: false
...
Ви також можете відмовитися від автоматичного монтування облікових даних API для певного Podʼа:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: build-robot
automountServiceAccountToken: false
...
Якщо як ServiceAccount, так і .spec
Podʼа вказують значення для automountServiceAccountToken
, специфікація Podʼа має перевагу.
Використання більше ніж одного ServiceAccount
У кожному просторі імен є принаймні один ServiceAccount: типовий ServiceAccount, який називається default
. Ви можете переглянути всі ресурси ServiceAccount у вашому поточному просторі імен за допомогою:
kubectl get serviceaccounts
Вихідні дані схожі на наступні:
NAME SECRETS AGE
default 1 1d
Ви можете створити додаткові обʼєкти ServiceAccount таким чином:
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
Імʼя обʼєкта ServiceAccount повинно бути дійсним DNS-піддоменним імʼям.
Якщо ви отримуєте повний дамп обʼєкта ServiceAccount, подібний до цього:
kubectl get serviceaccounts/build-robot -o yaml
Вихідні дані схожі на наступні:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2019-06-16T00:12:34Z
name: build-robot
namespace: default
resourceVersion: "272500"
uid: 721ab723-13bc-11e5-aec2-42010af0021e
Ви можете використовувати розширення дозволів для встановлення дозволів на облікові записи служб.
Щоб використовувати не-стандартний обліковий запис, встановіть поле spec.serviceAccountName
Podʼа на імʼя ServiceAccount, який ви хочете використовувати.
Ви можете встановити лише поле serviceAccountName
при створенні Podʼа або в шаблоні для нового Podʼа. Ви не можете оновлювати поле .spec.serviceAccountName
Podʼа, який вже існує.
Примітка:
Поле.spec.serviceAccount
є застарілою альтернативою для .spec.serviceAccountName
. Якщо ви хочете видалити поля з ресурсу робочого навантаження, встановіть обидва поля явно пустими у шаблоні Pod.Очищення
Якщо ви спробували створити ServiceAccount build-robot
з прикладу вище, ви можете видалити його виконавши:
kubectl delete serviceaccount/build-robot
Вручну створіть API-токен для ServiceAccount
Припустимо, у вас вже є службовий обліковий запис з назвою "build-robot", як зазначено вище.
Ви можете отримати тимчасовий API-токен для цього ServiceAccount за допомогою kubectl
:
kubectl create token build-robot
Вихідні дані з цієї команди — це токен, який ви можете використовувати для автентифікації цього ServiceAccount. Ви можете запросити певний час дії токена, використовуючи аргумент командного рядка --duration
для kubectl create token
(фактичний час дії виданого токену може бути коротшим або навіть довшим).
Kubernetes v1.31 [beta]
(стандартно увімкнено: true)Коли увімкнено функції ServiceAccountTokenNodeBinding
і ServiceAccountTokenNodeBindingValidation
, а також використовується kubectl
версії 1.31 або пізнішої, можна створити токен службового облікового запису, який безпосередньо привʼязаний до Node.
kubectl create token build-robot --bound-object-kind Node --bound-object-name node-001 --bound-object-uid 123...456
Токен буде чинний до закінчення його терміну дії або до видалення відповідного вузла чи службового облікового запису.
Примітка:
У версіях Kubernetes до v1.22 автоматично створювалися довгострокові облікові дані для доступу до API Kubernetes. Цей старий механізм базувався на створенні Secret токенів, які потім можна було монтувати в запущені контейнери. У більш пізніх версіях, включаючи Kubernetes v1.31, облікові дані API отримуються безпосередньо за допомогою TokenRequest API, і вони монтуються в контейнери за допомогою projected тому. Токени, отримані за допомогою цього методу, мають обмежений термін дії та автоматично анулюються, коли контейнер, у який вони монтувалися, видаляється.
Ви все ще можете вручну створити Secret токен службового облікового запису; наприклад, якщо вам потрібен токен, який ніколи не закінчується. Однак рекомендується використовувати TokenRequest для отримання токена для доступу до API.
Вручну створіть довговічний API-токен для ServiceAccount
Якщо ви бажаєте отримати API-токен для службового облікового запису, ви створюєте новий Secret з особливою анотацією kubernetes.io/service-account.name
.
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: build-robot-secret
annotations:
kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
Якщо ви переглянете Secret використовуючи:
kubectl get secret/build-robot-secret -o yaml
ви побачите, що тепер Secret містить API-токен для ServiceAccount "build-robot".
Через анотацію, яку ви встановили, панель управління автоматично генерує токен для цього службового облікового запису і зберігає їх у відповідному Secret. Крім того, панель управління також очищає токени для видалених облікових записів служб.
kubectl describe secrets/build-robot-secret
Вивід схожий на такий:
Name: build-robot-secret
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: build-robot
kubernetes.io/service-account.uid: da68f9c6-9d26-11e7-b84e-002dc52800da
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1338 байтів
namespace: 7 байтів
token: ...
Примітка:
Зміст token
тут пропущений.
При здійсненні перегляду вмісту Secret kubernetes.io/service-account-token
уважно відносьтеся, щоб не відображати його будь-де, де його може побачити сторонній спостерігач.
При видаленні ServiceAccount, який має відповідний Secret, панель управління Kubernetes автоматично очищає довговічний токен з цього Secret.
Примітка:
Якщо ви переглянете ServiceAccount використовуючи:
kubectl get serviceaccount build-robot -o yaml
Ви не побачите Secret build-robot-secret
у полях API-обʼєктів службового облікового запису .secrets
, оскільки це поле заповнюється лише автоматично згенерованими Secret.
Додайте ImagePullSecrets до ServiceAccount
Спочатку створіть imagePullSecret. Потім перевірте, чи він був створений. Наприклад:
Створіть imagePullSecret, як описано в Вказування ImagePullSecrets в контейнері.
kubectl create secret docker-registry myregistrykey --docker-server=<імʼя реєстру> \ --docker-username=ІМ'Я_КОРИСТУВАЧА --docker-password=ПАРОЛЬ_ДЛЯ_DOCKER \ --docker-email=ЕЛЕКТРОННА_ПОШТА_ДЛЯ_DOCKER
Перевірте, чи він був створений.
kubectl get secrets myregistrykey
Вивід схожий на такий:
NAME TYPE DATA AGE myregistrykey kubernetes.io/.dockerconfigjson 1 1д
Додайте imagePullSecret до ServiceAccount
Далі, змініть типовий обліковий запис служби для цього простору імен так, щоб він використовував цей Secret як imagePullSecret.
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
Ви можете досягти того ж самого результату, відредагувавши обʼєкт вручну:
kubectl edit serviceaccount/default
Вивід файлу sa.yaml
буде схожий на такий:
Вибраний вами текстовий редактор відкриється з конфігурацією, що схожа на цю:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2021-07-07T22:02:39Z
name: default
namespace: default
resourceVersion: "243024"
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
За допомогою вашого редактора видаліть рядок з ключем resourceVersion
, додайте рядки для imagePullSecrets:
та збережіть це. Залиште значення uid
таким же, як ви його знайшли.
Після внесення змін, відредагований ServiceAccount виглядатиме схоже на це:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2021-07-07T22:02:39Z
name: default
namespace: default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
imagePullSecrets:
- name: myregistrykey
Перевірте, що imagePullSecrets встановлені для нових Podʼів
Тепер, коли створюється новий Pod у поточному просторі імен і використовується типовий ServiceAccount, у новому Podʼі автоматично встановлюється поле spec.imagePullSecrets
:
kubectl run nginx --image=<імʼя реєстру>/nginx --restart=Never
kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'
Вивід:
myregistrykey
Проєцювання токенів ServiceAccount
Kubernetes v1.20 [stable]
Примітка:
Для включення та використання проєкції запиту токена вам необхідно вказати кожен з наступних аргументів командного рядка для kube-apiserver
:
--service-account-issuer
- визначає ідентифікатор емітента токена службового облікового запису. Ви можете вказати аргумент
--service-account-issuer
аргумент кілька разів, це може бути корисно, щоб увімкнути зміну емітента без переривання роботи. Коли цей прапорець вказано кілька разів, перший використовується для генерації токенів та всі використовуються для визначення прийнятних емітентів. Вам потрібно використовувати Kubernetes v1.22 або пізніше, щоб мати можливість вказати--service-account-issuer
кілька разів. --service-account-key-file
- вказує шлях до файлу, який містить PEM-кодований X.509 приватний або публічний ключі (RSA або ECDSA), які використовуються для перевірки токенів ServiceAccount. Вказаний файл може містити кілька ключів, а прапорець може бути вказаний кілька разів з різними файлами. Якщо вказано кілька разів, токени, підписані будь-яким із вказаних ключів, вважаються сервером Kubernetes API дійсними.
--service-account-signing-key-file
- вказує шлях до файлу, який містить поточний приватний ключ емітента токенів службового облікового запису. Емітент підписує видані ID токени з цим приватним ключем.
--api-audiences
(може бути опущено)- визначає аудиторії для токенів ServiceAccount. Автентифікатор токенів службових облікових записів перевіряє, що токени, використані в API, привʼязані принаймні до однієї з цих аудиторій. Якщо
api-audiences
вказано кілька разів, токени для будь-якої з вказаних аудиторій вважаються сервером Kubernetes API дійсними. Якщо ви вказали аргумент командного рядка--service-account-issuer
, але не встановили--api-audiences
, панель управління типово має одноелементний список аудиторій, що містить лише URL емітента.
Kubelet також може проєцювати токен ServiceAccount в Pod. Ви можете вказати бажані властивості токена, такі як аудиторія та тривалість дії. Ці властивості не конфігуруються для типового токена ServiceAccount. Токен також стане недійсним щодо API, коли будь-який з Podʼів або ServiceAccount буде видалено.
Ви можете налаштувати цю поведінку для spec
Podʼа за допомогою типу projected тому, що називається ServiceAccountToken
.
Токен з цього projected тому — JSON Web Token (JWT). JSON-вміст цього токена слідує чітко визначеній схемі — приклад вмісту для токена, повʼязаного з Pod:
{
"aud": [ # відповідає запитаним аудиторіям або стандартним аудиторіям API-сервера, якщо явно не запитано
"https://kubernetes.default.svc"
],
"exp": 1731613413,
"iat": 1700077413,
"iss": "https://kubernetes.default.svc", # відповідає першому значенню, переданому прапорцю --service-account-issuer
"jti": "ea28ed49-2e11-4280-9ec5-bc3d1d84661a", # Функція ServiceAccountTokenJTI повинна бути активована для того, щоб вимагати присутності цього запиту
"kubernetes.io": {
"namespace": "kube-system",
"node": { # Функція ServiceAccountTokenPodNodeInfo повинна бути активована для того, щоб API-сервер додавав цей запит посилання на вузол
"name": "127.0.0.1",
"uid": "58456cb0-dd00-45ed-b797-5578fdceaced"
},
"pod": {
"name": "coredns-69cbfb9798-jv9gn",
"uid": "778a530c-b3f4-47c0-9cd5-ab018fb64f33"
},
"serviceaccount": {
"name": "coredns",
"uid": "a087d5a0-e1dd-43ec-93ac-f13d89cd13af"
},
"warnafter": 1700081020
},
"nbf": 1700077413,
"sub": "system:serviceaccount:kube-system:coredns"
}
Запуск Podʼа з використанням проєцювання токену службового облікового запису
Щоб надати Podʼу токен з аудиторією vault
та терміном дії дві години, ви можете визначити маніфест Podʼа, схожий на цей:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /var/run/secrets/tokens
name: vault-token
serviceAccountName: build-robot
volumes:
- name: vault-token
projected:
sources:
- serviceAccountToken:
path: vault-token
expirationSeconds: 7200
audience: vault
Створіть Pod:
kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml
Kubelet буде: запитувати та зберігати токен від імені Podʼа; робити токен доступним для Podʼа за налаштованим шляхом до файлу; і оновлювати токен поблизу його закінчення. Kubelet активно запитує ротацію для токена, якщо він старший, ніж 80% від загального часу життя (TTL), або якщо токен старший, ніж 24 години.
Застосунок відповідає за перезавантаження токена при його ротації. Зазвичай для застосунку достатньо завантажувати токен за розкладом (наприклад: один раз кожні 5 хвилин), без відстеження фактичного часу закінчення.
Виявлення емітента службового облікового запису
Kubernetes v1.21 [stable]
Якщо ви увімкнули проєцювання токенів для ServiceAccounts у вашому кластері, то ви також можете скористатися функцією виявлення. Kubernetes надає спосіб клієнтам обʼєднуватись як постачальник ідентифікаційних даних, щоб одна або кілька зовнішніх систем могли діяти як сторона, що їм довіряє.
Примітка:
URL емітента повинен відповідати Специфікації виявлення OIDC. На практиці це означає, що він повинен використовувати схему https
, і має обслуговувати конфігурацію постачальника OpenID за адресою {емітент-облікового-запису}/.well-known/openid-configuration
.
Якщо URL не відповідає, точки доступу виявлення емітента ServiceAccount не зареєстровані або недоступні.
Якщо увімкнено, Kubernetes API-сервер публікує документ конфігурації постачальника OpenID через HTTP. Документ конфігурації публікується за адресою /.well-known/openid-configuration
. Документ конфігурації OpenID постачальника іноді називається документом виявлення. Kubernetes API-сервер також публікує повʼязаний набір ключів JSON Web (JWKS), також через HTTP, за адресою /openid/v1/jwks
.
Примітка:
Відповіді, що обслуговуються за адресами/.well-known/openid-configuration
та /openid/v1/jwks
, призначені для сумісності з OIDC, але не є строго сумісними з OIDC. Ці документи містять лише параметри, необхідні для виконання перевірки токенів службових облікових записів Kubernetes.Кластери, які використовують RBAC, включають типову роль кластера з назвою system:service-account-issuer-discovery
. Типовий ClusterRoleBinding надає цю роль групі system:serviceaccounts
, до якої неявно належать всі ServiceAccounts. Це дозволяє Podʼам, які працюють у кластері, отримувати доступ до документа виявлення службового облікового запису через їх змонтований токен службового облікового запису. Адміністратори також можуть вибрати привʼязку ролі до system:authenticated
або system:unauthenticated
залежно від їх вимог до безпеки та зовнішніх систем, з якими вони мають намір обʼєднуватись.
Відповідь JWKS містить публічні ключі, які може використовувати залежна сторона для перевірки токенів службових облікових записів Kubernetes. Залежні сторони спочатку запитують конфігурацію постачальника OpenID, а потім використовують поле jwks_uri
у відповіді, щоб знайти JWKS.
У багатьох випадках API-сервери Kubernetes не доступні через глобальну мережу, але публічні точки доступу, які обслуговують кешовані відповіді від API-сервера, можуть бути доступні для користувачів або постачальників послуг. У таких випадках можливо перевизначити jwks_uri
в конфігурації постачальника OpenID, щоб вона вказувала на глобальну точку доступу, а не на адресу API-сервера, передаючи прапорець --service-account-jwks-uri
до API-сервера. Як і URL емітента, URI JWKS повинен використовувати схему https
.
Що далі
Дивіться також:
- Прочитайте Посібник адміністратора кластера щодо службових облікових записів
- Дізнайтеся про Авторизацію в Kubernetes
- Дізнайтеся про Secret
- або, як розподіляти облікові дані безпечно за допомогою Secret
- але також майте на увазі, що використання Secret для автентифікації як службового облікового запису є застарілим. Рекомендований альтернативний метод — проєціювання токенів службового облікового запису.
- Дізнайтеся про projected томи.
- Для ознайомлення з OIDC discovery, прочитайте Попередній перегляд пропозиції щодо підпису токена службового облікового запису щодо покращення Kubernetes
- Прочитайте Специфікацію виявлення OIDC
14 - Отримання образів з приватного реєстру
Ця сторінка показує, як створити Pod, що використовує Secret для отримання образу з приватного реєстру або сховища контейнерних образів. Існує багато приватних реєстрів, які використовуються. У цьому завданні використовується Docker Hub як приклад реєстру.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для виконання цієї вправи вам потрібно мати інструмент командного рядка
docker
, а також ідентифікатор Docker, та пароль до якого ви знаєте.Якщо ви використовуєте інший приватний контейнерний реєстр, вам потрібен інструмент командного рядка для цього реєстру та будь-яка інформація для входу в реєстр.
Увійдіть до Docker Hub
На вашому компʼютері вам необхідно автентифікуватися в реєстрі, щоб отримати приватний образ.
Використовуйте інструмент docker
, щоб увійти до Docker Hub. Докладніше про це дивіться у розділі log in на сторінці Docker ID accounts.
docker login
Коли буде запитано, введіть свій ідентифікатор Docker, а потім обрані вами облікові дані (токен доступу чи пароль до вашого Docker ID).
Процес входу створює або оновлює файл config.json
, який містить токен авторизації. Ознайомтеся з тим, як Kubernetes інтерпретує цей файл.
Перегляньте файл config.json
:
cat ~/.docker/config.json
Вивід містить секцію, подібну до цієї:
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "c3R...zE2"
}
}
}
Примітка:
Якщо ви використовуєте сховище облікових даних Docker, ви не побачите цей записauth
, а замість нього буде запис credsStore
з назвою сховища як значення. У цьому випадку ви можете створити Secret безпосередньо. Дивіться Створення Secret, за допомогою вводу облікових даних в командному рядку.Створення Secret на основі наявних облікових даних
Кластер Kubernetes використовує Secret типу kubernetes.io/dockerconfigjson
для автентифікації в контейнерному реєстрі для отримання приватного образу.
Якщо ви вже виконали команду docker login
, ви можете скопіювати ці облікові дані в Kubernetes:
kubectl create secret generic regcred \
--from-file=.dockerconfigjson=<шлях/до/.docker/config.json> \
--type=kubernetes.io/dockerconfigjson
Якщо вам потрібно більше контролю (наприклад, встановити простір імен чи мітку для нового Secret), то ви можете налаштувати Secret перед збереженням його. Переконайтеся, що:
- встановлено назву елемента даних як
.dockerconfigjson
- файл конфігурації Docker закодовано у base64, а потім вставлено цей рядок без розривів як значення для поля
data[".dockerconfigjson"]
- встановлено
type
якkubernetes.io/dockerconfigjson
Приклад:
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
namespace: awesomeapps
data:
.dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==
type: kubernetes.io/dockerconfigjson
Якщо ви отримали повідомлення про помилку error: no objects passed to create
, це може означати, що закодований у base64 рядок є недійсним. Якщо ви отримали повідомлення про помилку, подібне до Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...
, це означає, що закодований у base64 рядок у даних успішно декодувався, але не може бути розпізнаний як файл .docker/config.json
.
Створення Secret, за допомогою вводу облікових даних в командному рядку
Створіть цей Secret, назвавши його regcred
:
kubectl create secret docker-registry regcred \
--docker-server=<your-registry-server> \
--docker-username=<your-name> \
--docker-password=<your-pword> \
--docker-email=<your-email>
де:
<your-registry-server>
— це повна доменна назва вашого приватного реєстру Docker. Використовуйтеhttps://index.docker.io/v1/
для DockerHub.<your-name>
— це ваше імʼя користувача Docker.<your-pword>
— це ваш пароль Docker.<your-email>
— це ваша електронна адреса Docker.
Ви успішно встановили ваші облікові дані Docker у кластері як Secret під назвою regcred
.
Примітка:
Ввід секретів у командному рядку може зберігатися в історії вашої оболонки в незахищеному вигляді, і ці секрети також можуть бути видимими для інших користувачів на вашому компʼютері протягом часу, коли виконуєтьсяkubectl
.Перегляд Secret regcred
Щоб зрозуміти вміст Secret regcred
, який ви створили, спочатку перегляньте Secret у форматі YAML:
kubectl get secret regcred --output=yaml
Вивід подібний до такого:
apiVersion: v1
kind: Secret
metadata:
...
name: regcred
...
data:
.dockerconfigjson: eyJodHRwczovL2luZGV4L ... J0QUl6RTIifX0=
type: kubernetes.io/dockerconfigjson
Значення поля .dockerconfigjson
— це представлення в base64 ваших облікових даних Docker.
Щоб зрозуміти, що знаходиться у полі .dockerconfigjson
, конвертуйте дані Secret в читабельний формат:
kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
Вивід подібний до такого:
{"auths":{"your.private.registry.example.com":{"username":"janedoe","password":"xxxxxxxxxxx","email":"jdoe@example.com","auth":"c3R...zE2"}}}
Щоб зрозуміти, що знаходиться у полі auth
, конвертуйте дані, закодовані в base64, у читабельний формат:
echo "c3R...zE2" | base64 --decode
Вивід, імʼя користувача та пароль, зʼєднані через :
, подібний до такого:
janedoe:xxxxxxxxxxx
Зверніть увагу, що дані Secret містять токен авторизації, аналогічний вашому локальному файлу ~/.docker/config.json
.
Ви успішно встановили ваші облікові дані Docker як Secret з назвою regcred
у кластері.
Створення Pod, який використовує ваш Secret
Нижче подано опис для прикладу Pod, який потребує доступу до ваших облікових даних Docker у regcred
:
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: regcred
Завантажте вищезазначений файл на свій компʼютер:
curl -L -o my-private-reg-pod.yaml https://k8s.io/examples/pods/private-reg-pod.yaml
У файлі my-private-reg-pod.yaml
замініть <your-private-image>
на шлях до образу у приватному реєстрі, наприклад:
your.private.registry.example.com/janedoe/jdoe-private:v1
Для отримання образу з приватного реєстру Kubernetes потрібні облікові дані. Поле imagePullSecrets
у файлі конфігурації вказує, що Kubernetes повинен отримати облікові дані з Secret з назвою regcred
.
Створіть Pod, який використовує ваш Secret, і перевірте, що Pod працює:
kubectl apply -f my-private-reg-pod.yaml
kubectl get pod private-reg
Примітка:
Щоб використовувати Secret для отримання образів для Pod (або Deployment, або іншого обʼєкта, який має шаблон Pod, який ви використовуєте), вам потрібно переконатися, що відповідний Secret існує в правильному просторі імен. Простір імен для використання — той самий, де ви визначили Pod.Також, якщо запуск Podʼа не вдається і ви отримуєте статус ImagePullBackOff
, перегляньте події Pod:
kubectl describe pod private-reg
Якщо ви побачите подію з причиною, встановленою на FailedToRetrieveImagePullSecret
, Kubernetes не може знайти Secret із назвою (regcred
, у цьому прикладі). Якщо ви вказали, що Pod потребує облікових даних для отримання образів, kubelet перевіряє, чи може він отримати доступ до цього Secret, перед тим як спробувати отримати образ.
Переконайтеся, що вказаний вами Secret існує і що його назва вірно вказана.
Events:
... Reason ... Message
------ -------
... FailedToRetrieveImagePullSecret ... Unable to retrieve some image pull secrets (<regcred>); attempting to pull the image may not succeed.
Що далі
- Дізнайтеся більше про Secret
- або перегляньте посилання на API для Secret
- Дізнайтеся більше про використання приватного реєстру.
- Дізнайтеся більше про додавання Secrets для отримання образів до службового облікового запису.
- Подивіться kubectl create secret docker-registry.
- Подивіться поле
imagePullSecrets
у визначеннях контейнерів Pod
15 - Налаштування проб життєздатності, готовності та запуску
Ця сторінка показує, як налаштувати проби життєздатності, готовності та запуску для контейнерів.
Для отримання додаткової інформації про проби див. Проби життєздатності, готовності та запуску
Kubelet використовує проби життєздатності для визначення моменту перезапуску контейнера. Наприклад, проби життєздатності можуть виявити проблеми, коли застосунок працює, але не може досягти результату. Перезапуск контейнера в такому стані може допомогти зробити застосунок більш доступним, попри помилки.
Загальний шаблон для проб життєздатності — використовує ту саму недорогу HTTP-точку доступу, що й для проб готовності, але з більшим значенням failureThreshold. Це гарантує, що Pod може спостерігатись як не готовий впродовж певного часу перед тим, як примусово завершити його роботу.
Kubelet використовує проби готовності для визначення моменту, коли контейнер готовий приймати трафік. Одним з використань цього сигналу є контроль за тим, які Podʼи використовуються як бекенди для Service. Pod вважається готовим, коли його стан Ready
є true. Коли Pod не готовий, його видаляють з балансувальників навантаження Serviceʼів. Стан Ready
у Pod є false, коли стан Ready
у його Node не є true, коли один з readinessGates
Pod є хибним, або коли принаймні один з його контейнерів не готовий.
Kubelet використовує проби запуску для визначення моменту запуску застосунку контейнера. Якщо така проба налаштована, проби життєздатності та готовності не починають працювати, поки вона не успішна, щоб переконатися, що ці проби не перешкоджають запуску застосунку. Це може бути використано для впровадження перевірки життєздатності для повільних контейнерів, що дозволяє уникати їхнього вимкнення kubelet перед тим, як вони будуть готові до роботи.
Увага:
Проби життєздатності можуть бути потужним засобом відновлення після відмов застосунків, але їх слід використовувати обережно. Проби життєздатності повинні бути налаштовані ретельно, щоб вони дійсно вказували на незворотню відмову застосунку, наприклад, на застрягання.Примітка:
Неправильна реалізація проб життєздатності може призвести до каскадних відмов. Це призводить до перезапуску контейнера при великому навантаженні; невдалих запитів клієнтів через зменшення масштабованості вашого застосунку; та збільшеного навантаження на інші Podʼи через невдалі Podʼи. Розумійте різницю між пробами готовності та життєздатності та коли застосовувати їх для вашого застосунку.Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Визначте команду життєздатності
Багато застосунків, що працюють протягом тривалого часу, зрештою переходять у непрацездатний стан і не можуть відновитися, крім як знову бути перезапущеними. Kubernetes надає проби життєздатності для виявлення та виправлення таких ситуацій.
У цьому завданні ви створите Pod, який запускає контейнер на основі образу registry.k8s.io/busybox
. Ось файл конфігурації для Podʼа:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: registry.k8s.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
У файлі конфігурації можна побачити, що у Podʼа є один Container
. Поле periodSeconds
вказує, що kubelet повинен виконувати пробу життєздатності кожні 5 секунд. Поле initialDelaySeconds
повідомляє kubelet, що він повинен зачекати 5 секунд перед виконанням першої проби. Для виконання проби kubelet виконує команду cat /tmp/healthy
у цільовому контейнері. Якщо команда успішно виконується, вона повертає 0, і kubelet вважає контейнер живим і справним. Якщо команда повертає ненульове значення, kubelet примусово зупиняє контейнер і перезапускає його.
Під час запуску контейнера виконується ця команда:
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600"
Протягом перших 30 секунд життя контейнера існує файл /tmp/healthy
. Таким чином, протягом перших 30 секунд команда cat /tmp/healthy
повертає код успіху. Після 30 секунд cat /tmp/healthy
повертає код невдачі.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml
Протягом 30 секунд перегляньте події Podʼа:
kubectl describe pod liveness-exec
Виведений текст показує, що жодна проба життєздатності ще не зазнав невдачі:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 11s default-scheduler Successfully assigned default/liveness-exec to node01
Normal Pulling 9s kubelet, node01 Pulling image "registry.k8s.io/busybox"
Normal Pulled 7s kubelet, node01 Successfully pulled image "registry.k8s.io/busybox"
Normal Created 7s kubelet, node01 Created container liveness
Normal Started 7s kubelet, node01 Started container liveness
Після 35 секунд знову перегляньте події Podʼа:
kubectl describe pod liveness-exec
У нижній частині виводу є повідомлення про те, що проби життєздатності зазнали невдачі, і непрацездатні контейнери були примусово зупинені та перезапущені.
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 57s default-scheduler Successfully assigned default/liveness-exec to node01
Normal Pulling 55s kubelet, node01 Pulling image "registry.k8s.io/busybox"
Normal Pulled 53s kubelet, node01 Successfully pulled image "registry.k8s.io/busybox"
Normal Created 53s kubelet, node01 Created container liveness
Normal Started 53s kubelet, node01 Started container liveness
Warning Unhealthy 10s (x3 over 20s) kubelet, node01 Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal Killing 10s kubelet, node01 Container liveness failed liveness probe, will be restarted
Почекайте ще 30 секунд та перевірте, що контейнер був перезапущений:
kubectl get pod liveness-exec
Виведений текст показує, що RESTARTS
було збільшено. Зауважте, що лічильник RESTARTS
збільшується, як тільки непрацездатний контейнер знову переходить у стан виконання:
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
Визначення HTTP-запиту життєздатності
Ще один вид проб життєздатності використовує HTTP GET-запит. Ось файл конфігурації для Podʼа, який запускає контейнер на основі образу registry.k8s.io/e2e-test-images/agnhost
.
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: registry.k8s.io/e2e-test-images/agnhost:2.40
args:
- liveness
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
У файлі конфігурації можна побачити, що у Podʼа є один контейнер. Поле periodSeconds
вказує, що kubelet повинен виконувати пробу життєздатності кожні 3 секунди. Поле initialDelaySeconds
повідомляє kubelet, що він повинен зачекати 3 секунди перед виконанням першої проби. Для виконання проби kubelet надсилає HTTP GET-запит на сервер, який працює в контейнері та слухає порт 8080. Якщо обробник для шляху /healthz
сервера повертає код успіху, kubelet вважає контейнер живим і справним. Якщо обробник повертає код невдачі, ubelet примусово зупиняє контейнер і перезапускає його.
Будь-який код, більший або рівний 200 і менший за 400, вказує на успіх. Будь-який інший код вказує на невдачу.
Ви можете переглянути вихідний код сервера в server.go.
Протягом перших 10 секунд, коли контейнер живий, обробник /healthz
повертає статус 200. Після цього обробник повертає статус 500.
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
Kubelet починає виконувати перевірку стану справності через 3 секунди після запуску контейнера. Таким чином, перші кілька перевірок стану справності будуть успішними. Але після 10 секунд перевірки стану справності будуть невдалими, і kubelet зупинить та перезапустить контейнер.
Щоб спробувати перевірку стану справності через HTTP, створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml
Через 10 секунд перегляньте події Podʼа, щоб перевірити, що проби життєздатності зазнали невдачі, і контейнер був перезапущений:
kubectl describe pod liveness-http
У випусках після v1.13 налаштування локального HTTP-проксі не впливають на пробу життєздатності через HTTP.
Визначення проби життєздатності через TCP-сокет
Третій тип проби життєздатності використовує TCP сокет. З цією конфігурацією kubelet спробує відкрити зʼєднання з вашим контейнером на вказаному порту. Якщо він може встановити зʼєднання, контейнер вважається справним, якщо ні — це вважається невдачею.
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: registry.k8s.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
Як можна побачити, конфігурація для перевірки TCP досить схожа на перевірку через HTTP. У цьому прикладі використовуються як проби готовності, так і життєздатності. Kubelet надішле першу пробу життєздатності через 15 секунд після запуску контейнера. Ця проба спробує підʼєднатися до контейнера goproxy
на порту 8080. Якщо проба на життєздатність не спрацює, контейнер буде перезапущено. Kubelet продовжить виконувати цю перевірку кожні 10 секунд.
Крім проби життєздатності, ця конфігурація включає пробу готовності. Kubelet запустить першу пробу готовності через 15 секунд після запуску контейнера. Аналогічно проби життєздатності, це спроба підʼєднатися до контейнера goproxy
на порту 8080. Якщо проба пройде успішно, Pod буде позначений як готовий і отримає трафік від сервісів. Якщо перевірка готовності не вдасться, то Pod буде позначений як не готовий і не отримає трафік від жодного з сервісів.
Щоб спробувати перевірку життєздатності через TCP, створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml
Через 15 секунд перегляньте події Podʼа, щоб перевірити, що проби життєздатності:
kubectl describe pod goproxy
Визначення проби життєздатності через gRPC
Kubernetes v1.27 [stable]
Якщо ваш застосунок реалізує Протокол gRPC перевірки стану справності, цей приклад показує, як налаштувати Kubernetes для його використання для перевірок життєздатності застосунку. Так само ви можете налаштувати проби готовності та запуску.
Ось приклад маніфесту:
apiVersion: v1
kind: Pod
metadata:
name: etcd-with-grpc
spec:
containers:
- name: etcd
image: registry.k8s.io/etcd:3.5.1-0
command: [ "/usr/local/bin/etcd", "--data-dir", "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"]
ports:
- containerPort: 2379
livenessProbe:
grpc:
port: 2379
initialDelaySeconds: 10
Для використання проби gRPC має бути налаштований port
. Якщо ви хочете розрізняти проби різних типів та проби для різних функцій, ви можете використовувати поле service
. Ви можете встановити service
у значення liveness
та вказати вашій точці доступу gRPC перевірки стану справності відповідати на цей запит інакше, ніж коли ви встановлюєте service
у значення readiness
. Це дозволяє використовувати ту саму точку доступу для різних видів перевірки стану справності контейнера замість прослуховування двох різних портів. Якщо ви хочете вказати свою власну назву сервісу та також вказати тип проби, Kubernetes рекомендує використовувати імʼя, яке складається з цих двох частин. Наприклад: myservice-liveness
(використовуючи -
як роздільник).
Примітка:
На відміну від проб HTTP або TCP, ви не можете вказати порт перевірки стану справності за іменем, але не можете налаштувати власне імʼя для хосту.Проблеми конфігурації (наприклад: неправильний порт чи Service, нереалізований протокол перевірки стану справності) вважаються невдачею проби, подібно до проб через HTTP та TCP.
Щоб спробувати перевірку життєздатності через gRPC, створіть Pod за допомогою наступної команди. У наведеному нижче прикладі, Pod etcd налаштований для використання проби життєздатності через gRPC.
kubectl apply -f https://k8s.io/examples/pods/probe/grpc-liveness.yaml
Через 15 секунд перегляньте події Podʼа, щоб перевірити, що перевірка життєздатності не зазнала невдачі:
kubectl describe pod etcd-with-grpc
При використанні проби через gRPC, є кілька технічних деталей, на які варто звернути увагу:
- Проби запускаються для IP-адреси Podʼа або його імені хосту. Обовʼязково налаштуйте вашу кінцеву точку gRPC для прослуховування IP-адреси Podʼа.
- Проби не підтримують жодних параметрів автентифікації (наприклад,
-tls
). - Немає кодів помилок для вбудованих проб. Усі помилки вважаються невдачами проби.
- Якщо
ExecProbeTimeout
feature gate встановлено уfalse
, grpc-health-probe не дотримується налаштуванняtimeoutSeconds
(яке стандартно становить 1 с), тоді як вбудована проба зазнає невдачі через тайм-аут.
Використання іменованого порту
Ви можете використовувати іменований port
для проб HTTP та TCP. Проби gRPC не підтримують іменовані порти.
Наприклад:
ports:
- name: liveness-port
containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
Захист контейнерів, що повільно запускаються за допомогою проб запуску
Іноді вам доводиться мати справу з застосунками, які вимагають додаткового часу запуску при їх першій ініціалізації. У таких випадках може бути складно налаштувати параметри проби життєздатності без компромісів щодо швидкої відповіді на затримки, які мотивували використання такої проби. Рішення полягає в тому, щоб налаштувати пробу запуску з тою самою командою, перевіркою через HTTP або TCP, з failureThreshold * periodSeconds
, достатньо довгим, щоб покрити найгірший випадок щодо часу запуску.
Отже, попередній приклад стане:
ports:
- name: liveness-port
containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 10
startupProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 30
periodSeconds: 10
Завдяки пробі запуску застосунок матиме максимум 5 хвилин (30 * 10 = 300 с), щоб завершити свій запуск. Як тільки проба запуску вдалася один раз, проба життєздатності бере роль на себе, щоб забезпечити швидку відповідь на затримки роботи контейнера. Якщо проба запуску ніколи не вдається, контейнер буде зупинений після 300 с і підпадатиме під restartPolicy
Podʼа.
Визначення проб готовності
Іноді застосунки тимчасово не можуть обслуговувати трафік. Наприклад, застосунок може потребувати завантаження великих даних або конфігураційних файлів під час запуску, або залежати від зовнішніх служб після запуску. У таких випадках ви не хочете примусово припиняти роботу застосунку, але ви також не хочете надсилати йому запити. Kubernetes надає проби готовності для виявлення та помʼякшення таких ситуацій. Pod з контейнерами, які повідомляють, що вони не готові, не отримують трафіку через Service Kubernetes.
Примітка:
Проби готовності працюють у контейнері протягом його всього життєвого циклу.Увага:
Проби готовності та життєздатності не залежать одна від одної для успішного виконання. Якщо ви хочете зачекати перед виконанням проби готовності, вам слід використовуватиinitialDelaySeconds
або startupProbe
.Проби готовності налаштовуються аналогічно пробам життєздатності. Єдина відмінність полягає в тому, що ви використовуєте поле readinessProbe
замість поля livenessProbe
.
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
Конфігурація для проб готовності через HTTP та TCP також залишається ідентичною конфігурації пробам життєздатності.
Проби готовності та життєздатності можуть використовуватися паралельно для того самого контейнера. Використання обох може забезпечити, що трафік не досягне контейнера, який не готовий до нього, та що контейнери будуть перезапускатися у разі виникнення несправностей.
Налаштування проб
Проби мають кілька полів, які можна використовувати для більш точного керування поведінкою перевірок запуску, життєздатності та готовності:
initialDelaySeconds
: Кількість секунд після запуску контейнера, перед тим як будуть запущені перевірки запуску, життєздатності або готовності. Якщо визначено пробу запуску, проби життєздатності та готовності не починаються, поки проба запуску не вдалася. Якщо значенняperiodSeconds
більше, ніжinitialDelaySeconds
, то значенняinitialDelaySeconds
буде проігнороване. Стандартно — 0 секунд. Мінімальне значення — 0.periodSeconds
: Як часто (у секундах) виконувати пробу. Стандартно — 10 секунд. Мінімальне значення — 1. Поки контейнер не має статусу Ready,ReadinessProbe
може бути виконаний у час, відмінний від налаштованого інтервалуperiodSeconds
. Це робиться для того, щоб пришвидшити готовність Podʼа.timeoutSeconds
: Кількість секунд, після яких проба завершиться по тайм-ауту. Стандартно — 1 секунда. Мінімальне значення — 1.successThreshold
: Мінімальна послідовна кількість успіхів для того, щоб проба вважалася успішною після невдачі. Стандартно — 1. Має бути 1 для проб життєздатності та запуску. Мінімальне значення — 1.failureThreshold
: Після того, як проба не вдаєтьсяfailureThreshold
разів поспіль, Kubernetes вважає, що загальна перевірка невдала: контейнер не готовий/справний. У випадку проби запуску або життєздатності, якщо принаймніfailureThreshold
проб зазнали невдачі, Kubernetes розглядає контейнер як несправний та виконує перезапуск для цього конкретного контейнера. Kubelet дотримується налаштуванняterminationGracePeriodSeconds
для цього контейнера. Для невдалих проб готовності kubelet продовжує запускати контейнер, який не пройшов перевірку, і також продовжує запускати додаткові проби; через те, що перевірка не пройшла, kubelet встановлює умовуReady
для Podʼа у значенняfalse
.terminationGracePeriodSeconds
: налаштуйте період-допуск для kubelet, щоб чекати між тригером вимкнення невдалих контейнерів та примусовим зупиненням контейнера середовищем виконання. Стандартно — значення успадковується від рівня Podʼа дляterminationGracePeriodSeconds
(якщо не вказано, то 30 секунд), а мінімальне значення — 1. Див. terminationGracePeriodSeconds на рівні проби для більш детальної інформації.
Увага:
Неправильна реалізація проб готовності може призвести до зростання кількості процесів в контейнері та вичерпання ресурсів, якщо це не буде виправлено.HTTP проби
HTTP проби мають додаткові поля, які можна встановити в httpGet
:
host
: Імʼя хосту для підключення, стандартно — IP-адреса Podʼа. Ймовірно, ви захочете встановити "Host" вhttpHeaders
замість цього.scheme
: Схема для підключення до хосту (HTTP або HTTPS). Стандартно — "HTTP".path
: Шлях до доступу на HTTP сервері. Стандартно — "/".httpHeaders
: Власні заголовки, що встановлюються у запиті. HTTP дозволяє повторювані заголовки.port
: Імʼя або номер порту для доступу до контейнера. Номер повинен бути в діапазоні від 1 до 65535.
Для HTTP проби kubelet надсилає HTTP-запит на вказаний порт та шлях, щоб виконати перевірку. Kubelet надсилає пробу до IP-адреси Podʼа, якщо адреса не перевизначена необовʼязковим полем host
у httpGet
. Якщо поле scheme
встановлено на HTTPS
, kubelet надсилає запит HTTPS, пропускаючи перевірку сертифіката. У більшості сценаріїв ви не хочете встановлювати поле host
. Ось один сценарій, коли ви його встановлюєте. Припустимо, що контейнер слухає на 127.0.0.1, а поле hostNetwork
Podʼа встановлене на true. Тоді host
у httpGet
повинен бути встановлений на 127.0.0.1. Якщо ваш Pod спирається на віртуальні хости, що, ймовірно, є більш поширеним випадком, ви не повинні використовувати host
, але краще встановити заголовок Host
в httpHeaders
.
Для HTTP проби kubelet надсилає два заголовки запиту, крім обовʼязкового заголовка Host
:
User-Agent
: Стандартне значення —kube-probe/1.31
, де1.31
— версія kubelet.Accept
: Стандартне значення —*/*
.
Ви можете перевизначити стандартне значення цих двох заголовків, визначивши httpHeaders
для проби. Наприклад:
livenessProbe:
httpGet:
httpHeaders:
- name: Accept
value: application/json
startupProbe:
httpGet:
httpHeaders:
- name: User-Agent
value: MyUserAgent
Ви також можете видалити ці два заголовки, визначивши їх з порожнім значенням.
livenessProbe:
httpGet:
httpHeaders:
- name: Accept
value: ""
startupProbe:
httpGet:
httpHeaders:
- name: User-Agent
value: ""
Примітка:
Коли kubelet перевіряє Pod за допомогою HTTP, він виконує переадресацію тільки в тому випадку, якщо переадресація відбувається на той самий хост. Якщо kubelet отримує 11 або більше переадресувань під час перевірки, проба вважається успішною і створюється відповідна подія:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 29m default-scheduler Successfully assigned default/httpbin-7b8bc9cb85-bjzwn to daocloud
Normal Pulling 29m kubelet Pulling image "docker.io/kennethreitz/httpbin"
Normal Pulled 24m kubelet Successfully pulled image "docker.io/kennethreitz/httpbin" in 5m12.402735213s
Normal Created 24m kubelet Created container httpbin
Normal Started 24m kubelet Started container httpbin
Warning ProbeWarning 4m11s (x1197 over 24m) kubelet Readiness probe warning: Probe terminated redirects
Якщо kubelet отримує переадресацію, де імʼя хосту відрізняється від запиту, результат проби вважається успішним, і kubelet створює подію для повідомлення про збій переадресації.
TCP проби
Для TCP-проби kubelet встановлює зʼєднання проби на вузлі, а не в Podʼі, що означає, що ви не можете використовувати імʼя сервісу в параметрі host
, оскільки kubelet не може його розпізнати.
terminationGracePeriodSeconds
на рівні проб
Kubernetes 1.25 [stable]
У версіях 1.25 і вище користувачі можуть вказувати terminationGracePeriodSeconds
на рівні проби в рамках специфікації проби. Коли одночасно встановлені terminationGracePeriodSeconds
на рівні Podʼа і на рівні проби, kubelet використовуватиме значення на рівні проби.
При встановленні terminationGracePeriodSeconds
слід звернути увагу на наступне:
Kubelet завжди враховує поле
terminationGracePeriodSeconds
на рівні проби, якщо воно присутнє в Podʼі.Якщо у вас є поточні Podʼи, де поле
terminationGracePeriodSeconds
встановлене і ви більше не бажаєте використовувати індивідуальні терміни відповідного завершення роботи для проб, вам слід видалити ці Podʼи.
Наприклад:
spec:
terminationGracePeriodSeconds: 3600 # на рівні Podʼа
containers:
- name: test
image: ...
ports:
- name: liveness-port
containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 60
# Перевизначити `terminationGracePeriodSeconds` на рівні Podʼа #
terminationGracePeriodSeconds: 60
terminationGracePeriodSeconds
на рівні проби не може бути встановлене для проб готовності. Воно буде відхилене API-сервером.
Що далі
- Дізнайтеся більше про Проби в контейнерах.
Також ви можете прочитати API-посилання на:
- Pod, і зокрема:
16 - Призначення Podʼів на вузли
Ця сторінка показує, як призначити Pod Kubernetes на певний вузол в кластері Kubernetes.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Додайте мітку до вузла
Виведіть список вузлів у вашому кластері разом з їхніми мітками:
kubectl get nodes --show-labels
Вивід буде схожий на такий:
NAME STATUS ROLES AGE VERSION LABELS worker0 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker0 worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1 worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
Виберіть один з ваших вузлів і додайте до нього мітку:
kubectl label nodes <your-node-name> disktype=ssd
де
<your-node-name>
— це імʼя вашого обраного вузла.Перевірте, що ваш обраний вузол має мітку
disktype=ssd
:kubectl get nodes --show-labels
Вивід буде схожий на такий:
NAME STATUS ROLES AGE VERSION LABELS worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0 worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1 worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
У попередньому виводі можна побачити, що вузол
worker0
має міткуdisktype=ssd
.
Створіть Pod, який буде призначений на ваш обраний вузол
Цей файл конфігурації Podʼа описує Pod, який має селектор вузла disktype: ssd
. Це означає, що Pod буде призначений на вузол, який має мітку disktype=ssd
.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
Використайте файл конфігурації, щоб створити Pod, який буде призначений на ваш обраний вузол:
kubectl apply -f https://k8s.io/examples/pods/pod-nginx.yaml
Перевірте, що Pod працює на вашому обраному вузлі:
kubectl get pods --output=wide
Вивід буде схожий на такий:
NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 13s 10.200.0.4 worker0
Створіть Pod, який буде призначений на конкретний вузол
Ви також можете призначити Pod на один конкретний вузол, встановивши nodeName
.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: foo-node # призначення Podʼу конкретному вузлу
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Використовуйте файл конфігурації, щоб створити Pod, який буде призначений тільки на foo-node
.
Що далі
- Дізнайтеся більше про мітки та селектори.
- Дізнайтеся більше про вузли.
17 - Призначення Podʼів на вузли за допомогою спорідненості вузла
На цій сторінці показано, як призначити Pod Kubernetes на певний вузол за допомогою спорідненості вузла в кластері Kubernetes.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути не старішою ніж v1.10. Для перевірки версії введітьkubectl version
.Додайте мітку до вузла
Виведіть список вузлів у вашому кластері разом з їхніми мітками:
kubectl get nodes --show-labels
Вивід буде схожий на такий:
NAME STATUS ROLES AGE VERSION LABELS worker0 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker0 worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1 worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
Виберіть один з ваших вузлів і додайте до нього мітку:
kubectl label nodes <your-node-name> disktype=ssd
де
<your-node-name>
— це імʼя вашого обраного вузла.Перевірте, що ваш обраний вузол має мітку
disktype=ssd
:kubectl get nodes --show-labels
Вивід буде схожий на такий:
NAME STATUS ROLES AGE VERSION LABELS worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0 worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1 worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
У попередньому виводі можна побачити, що вузол
worker0
має міткуdisktype=ssd
.
Розмістіть Pod, використовуючи потрібну спорідненість вузла
Цей маніфест описує Pod, який має спорідненість вузла requiredDuringSchedulingIgnoredDuringExecution
, disktype: ssd
. Це означає, що Pod буде розміщений лише на вузлі, який має мітку disktype=ssd
.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Застосуйте маніфест, щоб створити Pod, який буде розміщений на вашому обраному вузлі:
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-required-affinity.yaml
Перевірте, що Pod працює на вашому обраному вузлі:
kubectl get pods --output=wide
Вивід буде схожий на такий:
NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 13s 10.200.0.4 worker0
Розмістіть Pod, використовуючи бажану спорідненість вузла
Цей маніфест описує Pod, який має бажану спорідненість вузла preferredDuringSchedulingIgnoredDuringExecution
, disktype: ssd
. Це означає, що Pod надасть перевагу вузлу, який має мітку disktype=ssd
.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Застосуйте маніфест, щоб створити Pod, який буде розміщений на вашому обраному вузлі:
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-preferred-affinity.yaml
Перевірте, що Pod працює на вашому обраному вузлі:
kubectl get pods --output=wide
Вивід буде схожий на такий:
NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 13s 10.200.0.4 worker0
Що далі
Дізнайтеся більше про Спорідненість вузла.
18 - Налаштування ініціалізації Podʼа
На цій сторінці показано, як використовувати Init Container для ініціалізації Podʼа перед запуском контейнера застосунку.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Створіть Pod, який має Init Container
У цьому завданні ви створите Pod, який має один контейнер застосунку та один Init Container. Контейнер ініціалізації виконується до завершення перед тим, як розпочне виконання контейнер застосунку.
Ось файл конфігурації для Podʼа:
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# Цей контейр виконуєть під час ініціалізації podʼу
initContainers:
- name: install
image: busybox:1.28
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://info.cern.ch
volumeMounts:
- name: workdir
mountPath: "/work-dir"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
У файлі конфігурації ви бачите, що в Podʼі є Том, який обидва контейнери (ініціалізації та застосунку) спільно використовують.
Контейнер ініціалізації монтує спільний Том у /work-dir
, а контейнер застосунку монтує спільний Том у /usr/share/nginx/html
. Контейнер ініціалізації виконує наступну команду, а потім завершується:
wget -O /work-dir/index.html http://info.cern.ch
Зверніть увагу, що контейнер ініціалізації записує файл index.html
в кореневу теку сервера nginx.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/init-containers.yaml
Перевірте, що контейнер nginx працює:
kubectl get pod init-demo
Вивід показує, що контейнер nginx працює:
NAME READY STATUS RESTARTS AGE
init-demo 1/1 Running 0 1m
Отримайте доступ до оболонки в контейнері nginx, що працює в Podʼі init-demo
:
kubectl exec -it init-demo -- /bin/bash
У своїй оболонці надішліть запит GET на сервер nginx:
root@nginx:~# apt-get update
root@nginx:~# apt-get install curl
root@nginx:~# curl localhost
Вивід показує, що nginx обслуговує вебсторінку, яку записав контейнер ініціалізації:
<html><head></head><body><header>
<title>http://info.cern.ch</title>
</header>
<h1>http://info.cern.ch - home of the first website</h1>
...
<li><a href="http://info.cern.ch/hypertext/WWW/TheProject.html">Browse the first website</a></li>
...
Що далі
- Дізнайтеся більше про спілкування між контейнерами, що працюють в одному Podʼі.
- Дізнайтеся більше про Контейнери ініціалізації.
- Дізнайтеся більше про Томи.
- Дізнайтеся більше про Налагодження контейнерів ініціалізації
19 - Обробники подій життєвого циклу контейнера
Ця сторінка показує, як прикріплювати обробники до подій життєвого циклу контейнера. Kubernetes підтримує події postStart та preStop. Kubernetes надсилає подію postStart безпосередньо після того, як контейнер стартує, і він надсилає подію preStop безпосередньо перед завершенням роботи контейнера. Контейнер може вказати один обробник для кожної події.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Визначте обробники postStart та preStop
У цьому завдані ви створите Pod, який має один контейнер. У контейнері встановлені обробники для подій postStart та preStop.
Ось файл конфігурації для Podʼа:
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"]
У файлі конфігурації ви бачите, що команда postStart записує файл message
в теку /usr/share
контейнера. Команда preStop відповідним чином вимикає nginx. Це корисно, якщо контейнер перериває роботу через помилку.
Створіть Pod:
kubectl apply -f https://k8s.io/examples/pods/lifecycle-events.yaml
Перевірте, що контейнер у Podʼі працює:
kubectl get pod lifecycle-demo
Отримайте доступ до оболонки контейнера, який працює в Podʼі:
kubectl exec -it lifecycle-demo -- /bin/bash
У своїй оболонці перевірте, що обробник postStart створив файл message
:
root@lifecycle-demo:/# cat /usr/share/message
Вивід показує текст, записаний обробником postStart:
Hello from the postStart handler
Обговорення
Kubernetes надсилає подію postStart безпосередньо після створення контейнера. Проте, немає гарантії, що обробник postStart буде викликаний перед тим, як буде викликано точку входу контейнера. Обробник postStart працює асинхронно відносно коду контейнера, але керування Kubernetes блокується до завершення обробника postStart. Статус контейнера не встановлюється як RUNNING до завершення обробника postStart.
Kubernetes надсилає подію preStop безпосередньо перед завершенням роботи контейнера. Керування Kubernetes контейнером блокується до завершення обробника preStop, якщо тайм-аут оновлення Podʼа не закінчився. Докладніше див. Життєвий цикл Podʼа.
Примітка:
Kubernetes надсилає подію preStop лише тоді, коли Pod або контейнер у Podʼі завершується. Це означає, що обробник preStop не викликається, коли Pod завершує роботу. Про це обмеження дізнайтеся більше в розділі Контейнерні обробники.Що далі
- Дізнайтеся більше про обробників життєвого циклу контейнера.
- Дізнайтеся більше про життєвий цикл Podʼа.
Довідка
- Життєвий цикл
- Контейнер
- Дивіться
terminationGracePeriodSeconds
в Spec Podʼа
20 - Налаштування Podʼів для використання ConfigMap
Велика кількість застосунків покладаються на налаштування, які використовуються під час їх ініціалізації та виконання. В більшості випадків ці налаштування можна визначити за допомогою конфігураційних параметрів. Kubernetes надає можливість додавати конфігураційні параметри до Podʼів за допомогою обʼєктів ConfigMap.
Концепція ConfigMap дозволяє виокремити конфігураційні параметри з образу контейнера, що робить застосунок більш переносним. Наприклад, ви можете завантажити та використовувати один й той самий образ контейнера для використання контейнера для потреб локальної розробки, тестування системи, або в операційному середовищі.
Ця сторінка надає ряд прикладів, які демонструють як створювати ConfigMap та налаштувати Podʼи для використання даних, що містяться в ConfigMap.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
У вас має бути встановлено wget
. Якщо ви використовуєте інший інструмент, такий як curl
, замініть команди wget
на відповідні команди для вашого інструменту.
Створення ConfigMap
Ви можете скористатись або kubectl create configmap
або генератором ConfigMap в kustomization.yaml
для створення ConfigMap.
Створення ConfigMap за допомогою kubectl create configmap
Скористайтесь командою kubectl create configmap
, щоб створити ConfigMap з тек, файлів, або літералів:
kubectl create configmap <map-name> <data-source>
де, <map-name> — це імʼя ConfigMap, а <data-source> — це тека, файл чи літерал з даними, які ви хочете включити в ConfigMap. Імʼя обʼєкта ConfigMap повинно бути вірним імʼям субдомену DNS.
Коли ви створюєте ConfigMap на основі файлу, ключ в <data-source> визначається імʼям файлу, а значення — вмістом файлу.
Ви можете використовувати kubectl describe
або kubectl get
для отримання інформації про ConfigMap.
Створення ConfigMap з тек
Ви можете використовувати kubectl create configmap
, щоб створити ConfigMap з кількох файлів у тій самій теці. Коли ви створюєте ConfigMap на основі теки, kubectl ідентифікує файли, імʼя яких є допустимим ключем у теці, та пакує кожен з цих файлів у новий ConfigMap. Всі записи теки, окрім звичайних файлів, ігноруються (наприклад: підтеки, символьні посилання, пристрої, канали тощо).
Примітка:
Імʼя кожного файлу, яке використовується для створення ConfigMap, має складатися лише з прийнятних символів, а саме: літери (A
до Z
та a
до z
), цифри (0
до 9
), '-', '_', або '.'. Якщо ви використовуєте kubectl create configmap
з текою, де імʼя будь-якого файлу містить неприйнятний символ, команда kubectl
може завершитись з помилкою.
Команда kubectl
не виводить повідомлення про помилку, коли зустрічає недопустиме імʼя файлу.
Створіть локальну теку:
mkdir -p configure-pod-container/configmap/
Тепер завантажте приклад конфігурації та створіть ConfigMap:
# Завантажте файли у теку `configure-pod-container/configmap/`
wget https://kubernetes.io/examples/configmap/game.properties -O configure-pod-container/configmap/game.properties
wget https://kubernetes.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties
# Створіть ConfigMap
kubectl create configmap game-config --from-file=configure-pod-container/configmap/
Вказана вище команда упаковує кожен файл, у цьому випадку game.properties
та ui.properties
у теці configure-pod-container/configmap/
у ConfigMap game-config. Ви можете показати деталі ConfigMap за допомогою наступної команди:
kubectl describe configmaps game-config
Вивід буде приблизно таким:
Name: game-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
Файли game.properties
та ui.properties
у теці configure-pod-container/configmap/
представлені у секції data
ConfigMap.
kubectl get configmaps game-config -o yaml
Вивід буде приблизно таким:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2022-02-18T18:52:05Z
name: game-config
namespace: default
resourceVersion: "516"
uid: b4952dc3-d670-11e5-8cd0-68f728db1985
data:
game.properties: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
Створення ConfigMaps з файлів
Ви можете використовувати kubectl create configmap
для створення ConfigMap з окремого файлу або з декількох файлів.
Наприклад,
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties
створить наступний ConfigMap:
kubectl describe configmaps game-config-2
де вивід буде схожий на це:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Ви можете вказати аргумент --from-file
кілька разів, щоб створити ConfigMap із кількох джерел даних.
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties --from-file=configure-pod-container/configmap/ui.properties
Можете переглянути деталі ConfigMap game-config-2
за допомогою наступної команди:
kubectl describe configmaps game-config-2
Вивід буде схожий на це:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
Використовуйте опцію --from-env-file
для створення ConfigMap з env-файлу, наприклад:
# Env-файли містять список змінних оточення.
# На ці синтаксичні правила слід звертати увагу:
# Кожен рядок у env-файлі повинен бути у форматі VAR=VAL.
# Рядки, які починаються з # (тобто коментарі), ігноруються.
# Порожні рядки ігноруються.
# Особливого врахування лапок немає (тобто вони будуть частиною значення у ConfigMap).
# Завантажте приклад файлів у теку `configure-pod-container/configmap/`
wget https://kubernetes.io/examples/configmap/game-env-file.properties -O configure-pod-container/configmap/game-env-file.properties
wget https://kubernetes.io/examples/configmap/ui-env-file.properties -O configure-pod-container/configmap/ui-env-file.properties
# Env-файл `game-env-file.properties` виглядає так
cat configure-pod-container/configmap/game-env-file.properties
enemies=aliens
lives=3
allowed="true"
# Цей коментар та порожній рядок вище ігноруються
kubectl create configmap game-config-env-file \
--from-env-file=configure-pod-container/configmap/game-env-file.properties
створить ConfigMap. Перегляньте ConfigMap:
kubectl get configmap game-config-env-file -o yaml
вивід буде схожий на:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2019-12-27T18:36:28Z
name: game-config-env-file
namespace: default
resourceVersion: "809965"
uid: d9d1ca5b-eb34-11e7-887b-42010a8002b8
data:
allowed: '"true"'
enemies: aliens
lives: "3"
Починаючи з Kubernetes v1.23, kubectl
підтримує аргумент --from-env-file
, який може бути вказаний кілька разів для створення ConfigMap із кількох джерел даних.
kubectl create configmap config-multi-env-files \
--from-env-file=configure-pod-container/configmap/game-env-file.properties \
--from-env-file=configure-pod-container/configmap/ui-env-file.properties
створить наступний ConfigMap:
kubectl get configmap config-multi-env-files -o yaml
де вивід буде схожий на це:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2019-12-27T18:38:34Z
name: config-multi-env-files
namespace: default
resourceVersion: "810136"
uid: 252c4572-eb35-11e7-887b-42010a8002b8
data:
allowed: '"true"'
color: purple
enemies: aliens
how: fairlyNice
lives: "3"
textmode: "true"
Визначення ключа для створення ConfigMap з файлу
Ви можете визначити ключ, відмінний від імені файлу, який буде використаний у розділі data
вашого ConfigMap під час використання аргументу --from-file
:
kubectl create configmap game-config-3 --from-file=<my-key-name>=<path-to-file>
де <my-key-name>
— це ключ, який ви хочете використовувати в ConfigMap, а <path-to-file>
— це місцезнаходження файлу джерела даних, яке ключ має представляти.
Наприклад:
kubectl create configmap game-config-3 --from-file=game-special-key=configure-pod-container/configmap/game.properties
створить наступний ConfigMap:
kubectl get configmaps game-config-3 -o yaml
де вивід буде схожий на це:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2022-02-18T18:54:22Z
name: game-config-3
namespace: default
resourceVersion: "530"
uid: 05f8da22-d671-11e5-8cd0-68f728db1985
data:
game-special-key: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Створення ConfigMaps з літеральних значень
Ви можете використовувати kubectl create configmap
з аргументом --from-literal
, щоб визначити літеральне значення з командного рядка:
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
Ви можете передати декілька пар ключ-значення. Кожна пара, надана у командному рядку, представлена як окремий запис у розділі data
ConfigMap.
kubectl get configmaps special-config -o yaml
Вивід буде схожий на це:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2022-02-18T19:14:38Z
name: special-config
namespace: default
resourceVersion: "651"
uid: dadce046-d673-11e5-8cd0-68f728db1985
data:
special.how: very
special.type: charm
Створення ConfigMap за допомогою генератора
Ви також можете створити ConfigMap за допомогою генераторів, а потім застосувати його для створення обʼєкта на API сервері кластера. Ви повинні вказати генератори у файлі kustomization.yaml
в межах теки.
Генерація ConfigMaps з файлів
Наприклад, для створення ConfigMap з файлів configure-pod-container/configmap/game.properties
:
# Створіть файл kustomization.yaml з ConfigMapGenerator
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-4
options:
labels:
game-config: config-4
files:
- configure-pod-container/configmap/game.properties
EOF
Застосуйте теку kustomization для створення обʼєкта ConfigMap:
kubectl apply -k .
configmap/game-config-4-m9dm2f92bt created
Ви можете перевірити, що ConfigMap був створений так:
kubectl get configmap
NAME DATA AGE
game-config-4-m9dm2f92bt 1 37s
а також:
kubectl describe configmaps game-config-4-m9dm2f92bt
Name: game-config-4-m9dm2f92bt
Namespace: default
Labels: game-config=config-4
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","data":{"game.properties":"enemies=aliens\nlives=3\nenemies.cheat=true\nenemies.cheat.level=noGoodRotten\nsecret.code.p...
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Events: <none>
Зверніть увагу, що до згенерованої назви ConfigMap додано суфікс хешування вмісту. Це забезпечує генерацію нового ConfigMap кожного разу, коли вміст змінюється.
Визначення ключа для використання при генерації ConfigMap з файлу
Ви можете визначити ключ, відмінний від імені файлу, для використання у генераторі ConfigMap. Наприклад, для генерації ConfigMap з файлів configure-pod-container/configmap/game.properties
з ключем game-special-key
:
# Створіть файл kustomization.yaml з ConfigMapGenerator
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-5
options:
labels:
game-config: config-5
files:
- game-special-key=configure-pod-container/configmap/game.properties
EOF
Застосуйте теки kustomization для створення обʼєкта ConfigMap.
kubectl apply -k .
configmap/game-config-5-m67dt67794 created
Генерація ConfigMap з літералів
У цьому прикладі показано, як створити ConfigMap
з двох пар ключ/значення: special.type=charm
та special.how=very
, використовуючи Kustomize та kubectl. Для досягнення цього, ви можете вказати генератор ConfigMap
. Створіть (або замініть) kustomization.yaml
, щоб мати наступний вміст:
---
# Вміст kustomization.yaml для створення ConfigMap з літералів
configMapGenerator:
- name: special-config-2
literals:
- special.how=very
- special.type=charm
Застосуйте теку kustomization для створення обʼєкта ConfigMap:
kubectl apply -k .
configmap/special-config-2-c92b5mmcf2 created
Проміжна очистка
Перед продовженням, очистіть деякі з ConfigMaps, які ви створили:
kubectl delete configmap special-config
kubectl delete configmap env-config
kubectl delete configmap -l 'game-config in (config-4,config-5)'
Тепер, коли ви вивчили, як визначати ConfigMaps, ви можете перейти до наступного розділу і дізнатися, як використовувати ці обʼєкти з Pod.
Визначення змінних середовища контейнера за допомогою даних з ConfigMap
Визначення змінної середовища контейнера за допомогою даних з одного ConfigMap
Визначте змінну середовища як пару ключ-значення в ConfigMap:
kubectl create configmap special-config --from-literal=special.how=very
Присвойте значення
special.how
, визначене в ConfigMap, змінній середовищаSPECIAL_LEVEL_KEY
у специфікації Pod.apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: registry.k8s.io/busybox command: [ "/bin/sh", "-c", "env" ] env: # Визначення змінної середовища - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: # ConfigMap, що містить значення, яке потрібно присвоїти SPECIAL_LEVEL_KEY name: special-config # Вказує ключ, повʼязаний зі значенням key: special.how restartPolicy: Never
Створіть Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-single-configmap-env-variable.yaml
Тепер вивід Podʼа містить змінну середовища
SPECIAL_LEVEL_KEY=very
.
Визначення змінних середовища контейнера з даних з кількох ConfigMaps
Так само як у попередньому прикладі, спочатку створіть ConfigMaps. Ось маніфест, який ви будете використовувати:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
Створіть ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmaps.yaml
Визначте змінні середовища у специфікації Pod.
apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: registry.k8s.io/busybox command: [ "/bin/sh", "-c", "env" ] env: - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how - name: LOG_LEVEL valueFrom: configMapKeyRef: name: env-config key: log_level restartPolicy: Never
Створіть Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-multiple-configmap-env-variable.yaml
Тепер виведення Pod містить змінні середовища
SPECIAL_LEVEL_KEY=very
таLOG_LEVEL=INFO
.Як тільки ви готові перейти далі, видаліть цей Pod та ConfigMaps:
kubectl delete pod dapi-test-pod --now kubectl delete configmap special-config kubectl delete configmap env-config
Налаштування всіх пар ключ-значення в ConfigMap як змінних середовища контейнера
Створіть ConfigMap, який містить кілька пар ключ-значення.
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: SPECIAL_LEVEL: very SPECIAL_TYPE: charm
Створіть ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
Використовуйте
envFrom
, щоб визначити всі дані ConfigMap як змінні середовища контейнера. Ключ з ConfigMap стає іменем змінної середовища в Pod.apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: registry.k8s.io/busybox command: [ "/bin/sh", "-c", "env" ] envFrom: - configMapRef: name: special-config restartPolicy: Never
Створіть Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-envFrom.yaml
Тепер виведення Pod містить змінні середовища
SPECIAL_LEVEL=very
таSPECIAL_TYPE=charm
.Як тільки ви готові перейти далі, видаліть цей Pod:
kubectl delete pod dapi-test-pod --now
Використання змінних середовища, визначених у ConfigMap, у командах Pod
Ви можете використовувати змінні середовища, визначені у ConfigMap, у розділі command
та args
контейнера за допомогою синтаксису підстановки Kubernetes $(VAR_NAME)
.
Наприклад, у наступному маніфесті Pod:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/echo", "$(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never
Створіть цей Pod, запустивши:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-env-var-valueFrom.yaml
Цей Pod видає наступний вивід від контейнера test-container
:
kubectl logs dapi-test-pod
very charm
Як тільки ви готові перейти далі, видаліть цей Pod:
kubectl delete pod dapi-test-pod --now
Додавання даних ConfigMap до тому
Як пояснено у розділі Створення ConfigMap з файлів, коли ви створюєте ConfigMap, використовуючи --from-file
, імʼя файлу стає ключем, збереженим у розділі data
ConfigMap. Вміст файлу стає значенням ключа.
Приклади в цьому розділі відносяться до ConfigMap з іменем special-config
:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
Створіть ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
Заповнення тому даними, збереженими в ConfigMap
Додайте імʼя ConfigMap у розділ volumes
специфікації Pod. Це додасть дані ConfigMap до теки, вказаної як volumeMounts.mountPath
(у цьому випадку, /etc/config
). Розділ command
перераховує файли теки з іменами, що відповідають ключам у ConfigMap.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
# Надає назву ConfigMap, що містить файли, які ви бажаєте
# додати до контейнера
name: special-config
restartPolicy: Never
Створіть Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume.yaml
Коли Pod працює, команда ls /etc/config/
виводить наступне:
SPECIAL_LEVEL
SPECIAL_TYPE
Текстові дані показуються у вигляді файлів з використанням кодування символів UTF-8. Щоб використовувати інше кодування символів, скористайтеся binaryData
(див. обʼєкт ConfigMap для докладніших відомостей).
Примітка:
Якщо в теці/etc/config
образу контейнера є будь-які файли, то змонтований том робить ці файли образу недоступними.Якщо ви готові перейти до наступного кроку, видаліть цей Pod:
kubectl delete pod dapi-test-pod --now
Додавання конфігурації ConfigMap до певного шляху у томі
Використовуйте поле path
, щоб вказати бажаний шлях до файлів для конкретних елементів ConfigMap. У цьому випадку елемент SPECIAL_LEVEL
буде змонтовано у томі config-volume
за адресою /etc/config/keys
.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh","-c","cat /etc/config/keys" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: SPECIAL_LEVEL
path: keys
restartPolicy: Never
Створіть pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume-specific-key.yaml
Коли pod запущено, команда cat /etc/config/keys
видасть наведений нижче вивід:
very
Увага:
Як і раніше, усі попередні файли у теці/etc/config/
буде видалено.Видаліть цей Pod:
kubectl delete pod dapi-test-pod --now
Спроєцюйте ключі на конкретні шляхи та встановлюйте права доступу до файлів
Ви можете спроєцювати ключі на конкретні шляхи. Зверніться до відповідного розділу в Посібнику Secret для ознайомлення з синтаксисом. Ви можете встановлювати права доступу POSIX для ключів. Зверніться до відповідного розділу в Посібнику Secret ознайомлення з синтаксисом.
Необовʼязкові посилання
Посилання на ConfigMap може бути позначене як необовʼязкове. Якщо ConfigMap не існує, змонтований том буде порожнім. Якщо ConfigMap існує, але посилання на ключ не існує, шлях буде відсутній під точкою монтування. Дивіться Опціональні ConfigMaps для отримання додаткових відомостей.
Змонтовані ConfigMap оновлюються автоматично
Коли змонтований ConfigMap оновлюється, спроєцьований вміст врешті-решт оновлюється також. Це стосується випадку, коли ConfigMap, на який посилатися необовʼязково, зʼявляється після того, як Pod вже почав працювати.
Kubelet перевіряє, чи змонтований ConfigMap є актуальним під час кожної періодичної синхронізації. Однак він використовує свій локальний кеш на основі TTL для отримання поточного значення ConfigMap. В результаті загальна затримка від моменту оновлення ConfigMap до моменту, коли нові ключі проєцюються у Pod може бути таким, як період синхронізації kubelet (стандартно — 1 хвилина) + TTL кешу ConfigMaps (стандартно — 1 хвилина) в kubelet. Ви можете викликати негайне оновлення, оновивши одну з анотацій Podʼа.
Примітка:
Контейнери, які використовують ConfigMap як том subPath не отримуватимуть оновлення ConfigMap.Розуміння ConfigMap та Podʼів
Ресурс ConfigMap API зберігає конфігураційні дані у вигляді пар ключ-значення. Дані можуть бути використані в Podʼах або надавати конфігураційні дані для системних компонентів, таких як контролери. ConfigMap схожий на Secret, але надає засоби для роботи з рядками, що не містять конфіденційної інформації. Користувачі та системні компоненти можуть зберігати конфігураційні дані в ConfigMap.
Примітка:
ConfigMaps повинні посилатися на файли властивостей, а не заміняти їх. Подумайте про ConfigMap як щось подібне до теки/etc
в Linux та її вмісту. Наприклад, якщо ви створюєте Том Kubernetes з ConfigMap, кожен елемент даних у ConfigMap представлений окремим файлом у томі.Поле data
у ConfigMap містить дані конфігурації. Як показано у прикладі нижче, це може бути простим (наприклад, окремі властивості, визначені за допомогою --from-literal
) або складним (наприклад, файли конфігурації або JSON-фрагменти, визначені за допомогою --from-file
).
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: example-config
namespace: default
data:
# приклад простої властивості, визначеної за допомогою --from-literal
example.property.1: hello
example.property.2: world
# приклад складної властивості, визначеної за допомогою --from-file
example.property.file: |-
property.1=value-1
property.2=value-2
property.3=value-3
Коли kubectl
створює ConfigMap з вхідних даних, які не є ASCII або UTF-8, цей інструмент поміщає їх у поле binaryData
ConfigMap, а не в data
. Як текстові, так і бінарні дані можуть бути поєднані в одному ConfigMap.
Якщо ви хочете переглянути ключі binaryData
(і їх значення) в ConfigMap, ви можете виконати kubectl get configmap -o jsonpath='{.binaryData}' <імʼя>
.
Podʼи можуть завантажувати дані з ConfigMap, що використовують як data
, так і binaryData
.
Опціональні ConfigMaps
Ви можете позначити посилання на ConfigMap як опціональне в специфікації Pod. Якщо ConfigMap не існує, конфігурація, для якої вона надає дані в Pod (наприклад: змінна середовища, змонтований том), буде пустою. Якщо ConfigMap існує, але посилання на ключ не існує, дані також будуть пустими.
Наприклад, наступна специфікація Pod позначає змінну середовища з ConfigMap як опціональну:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: ["/bin/sh", "-c", "env"]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: a-config
key: akey
optional: true # позначає змінну як опціональну
restartPolicy: Never
Якщо ви запустите цей Pod, і ConfigMap з імʼям a-config
не існує, вивід буде пустим. Якщо ви запустите цей Pod, і ConfigMap з імʼям a-config
існує, але в цьому ConfigMap немає ключа з імʼям akey
, вивід також буде пустим. Якщо ж ви задасте значення для akey
в ConfigMap a-config
, цей Pod надрукує це значення і потім завершить роботу.
Ви також можете позначити томи та файли, надані ConfigMap, як опціональні. Kubernetes завжди створює шляхи для монтування томів, навіть якщо зазначений ConfigMap або ключ не існують. Наприклад, наступна специфікація Pod позначає том, який посилається на ConfigMap, як опціональний:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: ["/bin/sh", "-c", "ls /etc/config"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: no-config
optional: true # позначає ConfigMap як опціональний
restartPolicy: Never
Обмеження
Ви повинні створити обʼєкт
ConfigMap
до того, як ви посилатиметесь на нього в специфікації Pod. Альтернативно, позначте посилання на ConfigMap якoptional
в специфікації Pod (див. Опціональні ConfigMaps). Якщо ви посилаєтесь на ConfigMap, який не існує, і ви не позначите посилання якoptional
, Podʼи не запуститься. Аналогічно, посилання на ключі, які не існують в ConfigMap, також перешкоджатимуть запуску Podʼа, якщо ви не позначите посилання на ключі якoptional
.Якщо ви використовуєте
envFrom
для визначення змінних середовища з ConfigMaps, ключі, які вважаються недійсними, будуть пропущені. Podʼу буде дозволено запускатися, але недійсні імена будуть записані в лог подій (InvalidVariableNames
). Повідомлення логу містить кожен пропущений ключ. Наприклад:kubectl get events
Вивід буде схожий на цей:
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE 0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames {kubelet, 127.0.0.1} Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names.
ConfigMaps знаходяться в конкретному Namespace. Podʼи можуть посилатися лише на ConfigMaps, які знаходяться в тому ж контексті, що і сам Pod.
Ви не можете використовувати ConfigMaps для статичних Podʼів, оскільки kubelet їх не підтримує.
Очищення
Вилучить ConfigMaps та Pod, які ви створили, використовуючи наступні команди:
kubectl delete configmaps/game-config configmaps/game-config-2 configmaps/game-config-3 \
configmaps/game-config-env-file
kubectl delete pod dapi-test-pod --now
# Можливо, ви вже видалили наступний набір
kubectl delete configmaps/special-config configmaps/env-config
kubectl delete configmap -l 'game-config in (config-4,config-5)'
Видаліть файл kustomization.yaml
, який ви створили для генерації ConfigMap:
rm kustomization.yaml
Якщо ви створили ntre configure-pod-container
і вже не потребуєте її, вам слід також її видалити або перемістити в кошик або місце для видалених файлів.
rm -rf configure-pod-container
Що далі
- Ознайомтесь з прикладом налаштування Redis за допомогою ConfigMap.
- Ознайомтесь з прикладом оновлення конфігурації через ConfigMap.
21 - Поділ простору імен процесів між контейнерами у Podʼі
На цій сторінці показано, як налаштувати поділ простору імен процесів для Podʼа. Коли поділ простору імен процесів увімкнено, процеси в контейнері стають видимими для всіх інших контейнерів у тому ж Podʼі.
Ви можете використовувати цю функцію для налаштування контейнерів, що взаємодіють один з одним, таких як контейнер sidecar обробника логу, або для дослідження образів контейнера, які не містять інструментів для налагодження, наприклад, оболонки.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Налаштування Podʼа
Поділ простору імен процесів увімкнено за допомогою поля shareProcessNamespace
в розділі .spec
Podʼа. Наприклад:
Створіть Pod
nginx
у вашому кластері:kubectl apply -f https://k8s.io/examples/pods/share-process-namespace.yaml
Приєднайтеся до контейнера
shell
та запустіть командуps
:kubectl exec -it nginx -c shell -- /bin/sh
Якщо ви не бачите символу командного рядка, спробуйте натиснути клавішу Enter. У оболонці контейнера:
# виконайте це всередині контейнера "shell" ps ax
Вивід схожий на такий:
PID USER TIME COMMAND 1 root 0:00 /pause 8 root 0:00 nginx: master process nginx -g daemon off; 14 101 0:00 nginx: worker process 15 root 0:00 sh 21 root 0:00 ps ax
Ви можете відправляти сигнали процесам в інших контейнерах. Наприклад, відправте SIGHUP
до nginx
, щоб перезапустити робочий процес. Для цього потрібна можливість SYS_PTRACE
.
# виконайте це всередині контейнера "shell"
kill -HUP 8 # змініть "8" на відповідний PID лідера процесу nginx, якщо потрібно
ps ax
Вивід схожий на такий:
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
15 root 0:00 sh
22 101 0:00 nginx: worker process
23 root 0:00 ps ax
Навіть можливо отримати доступ до файлової системи іншого контейнера, використовуючи посилання /proc/$pid/root
.
# виконайте це всередині контейнера "shell"
# змініть "8" на PID процесу Nginx, якщо потрібно
head /proc/8/root/etc/nginx/nginx.conf
Вивід схожий на такий:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
Розуміння поділу простору імен процесів
Podʼи ділять багато ресурсів, тому логічно, що вони також будуть ділитися простором імен процесів. Деякі контейнери можуть очікувати ізоляції від інших, тому важливо розуміти відмінності:
Процес контейнера вже не має PID 1. Деякі контейнери відмовляються запускатися без PID 1 (наприклад, контейнери, що використовують
systemd
) або виконують команди типуkill -HUP 1
для відправлення сигналу процесу контейнера. У Podʼах зі спільним простором імен процесівkill -HUP 1
відправить сигнал пісочниці Podʼа (/pause
у вищезазначеному прикладі).Процеси видимі іншим контейнерам у Podʼі. Це включає всю інформацію, доступну у
/proc
, таку як паролі, що були передані як аргументи або змінні середовища. Ці дані захищені лише звичайними правами Unix.Файлові системи контейнерів видимі іншим контейнерам у Podʼі через посилання
/proc/$pid/root
. Це полегшує налагодження, але також означає, що секрети файлової системи захищені лише правами файлової системи.
22 - Використання простору імен користувача з Podʼом
Kubernetes v1.30 [beta]
(стандартно увімкнено: false)Ця сторінка показує, як налаштувати простір імен користувача для Podʼів. Це дозволяє ізолювати користувача, що працює всередині контейнера, від того, який працює на хості.
Процес, що працює як root у контейнері, може працювати як інший (не root) користувач на хості; іншими словами, процес має повні привілеї для операцій всередині простору імен користувача, але не має привілеїв для операцій за межами простору імен.
Ви можете використовувати цю функцію, щоб зменшити шкоду, яку скомпрометований контейнер може завдати хосту або іншим Podʼам на тому ж вузлі. Є кілька уразливостей безпеки, оцінених як ВИСОКІ або КРИТИЧНІ, які не були використовні при активному використанні просторів імен користувача. Очікується, що простори імен користувача захистять від деяких майбутніх уразливостей також.
Без використання просторів імен користувача контейнер, що працює як root, у випадку втечі з контейнера має привілеї root на вузлі. І якщо деякі можливості були надані контейнеру, то ці можливості також дійсні на хості. Цього не відбувається, коли використовуються простори імен користувача.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути не старішою ніж v1.25. Для перевірки версії введітьkubectl version
.- ОС вузла повинна бути Linux
- Ви повинні мати можливість виконувати команди на хості
- Ви повинні мати можливість виконувати команди у Podʼах
- Вам потрібно увімкнути функціональну можливість
UserNamespacesSupport
Примітка:
Feature gate для увімкнення просторів імен користувача раніше називавсяUserNamespacesStatelessPodsSupport
, коли підтримувалися лише Podʼи без збереження стану. Тільки Kubernetes v1.25 по v1.27 визнають UserNamespacesStatelessPodsSupport
.Кластер, який ви використовуєте, обовʼязково повинен містити принаймні один вузол, який відповідає вимогам щодо використання просторів імен користувача з Podʼами.
Якщо у вас є суміш вузлів і лише деякі з них надають підтримку просторів імен користувача для Podʼів, вам також потрібно забезпечити те, що Podʼи з просторами імен користувача будуть заплановані на відповідні вузли.
Запуск Podʼа, що використовує простір імен користувача
Простір імен користувача для Podʼа вимкається, встановленням поля hostUsers
в .spec
на false
. Наприклад:
apiVersion: v1
kind: Pod
metadata:
name: userns
spec:
hostUsers: false
containers:
- name: shell
command: ["sleep", "infinity"]
image: debian
Створіть Pod у вашому кластері:
kubectl apply -f https://k8s.io/examples/pods/user-namespaces-stateless.yaml
Приєднайтеся до контейнера і виконайте
readlink /proc/self/ns/user
:kubectl attach -it userns bash
Виконайте цю команду:
read
link /proc/self/ns/user
Вивід схожий на:
user:[4026531837]
Також виконайте:
cat /proc/self/uid_map
Вивід схожий на:
0 833617920 65536
Потім відкрийте оболонку на хості та виконайте ті ж самі команди.
Команда readlink
показує простір імен користувача, в якому працює процес. Він повинен бути різним, коли ви виконуєте його на хості і всередині контейнера.
Останнє число у файлі uid_map
всередині контейнера повинно бути 65536, на хості це число повинно бути більшим.
Якщо ви запускаєте kubelet всередині простору імен користувача, вам потрібно порівняти вивід команди в Pod з виводом, отриманим на хості:
readlink /proc/$pid/ns/user
замінивши $pid
на PID kubelet.
23 - Використання тому Image в Pod
Kubernetes v1.31 [alpha]
(стандартно увімкнено: false)Ця сторінка демонструє, як налаштувати Pod для використання томів image. Це дозволяє монтувати вміст з OCI реєстрів всередині контейнерів.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути v1.31. Для перевірки версії введітьkubectl version
.- Середовище виконання контейнерів має підтримувати функцію томів image.
- Вам потрібно мати можливість виконувати команди на хості.
- Вам потрібно мати можливість підключатися до pod.
- Вам потрібно увімкнути функціональну можливість
ImageVolume
.
Запуск Podʼа, що використовує том image
Том image для Podʼа активується шляхом налаштування поля volumes.[*].image
у .spec
на дійсне посилання та використання його в volumeMounts
контейнера. Наприклад:
apiVersion: v1
kind: Pod
metadata:
name: image-volume
spec:
containers:
- name: shell
command: ["sleep", "infinity"]
image: debian
volumeMounts:
- name: volume
mountPath: /volume
volumes:
- name: volume
image:
reference: quay.io/crio/artifact:v1
pullPolicy: IfNotPresent
Створіть Pod у вашому кластері:
kubectl apply -f https://k8s.io/examples/pods/image-volumes.yaml
Приєднайтесь до контейнера:
kubectl attach -it image-volume bash
Перевірте вміст файлу в томі:
cat /volume/dir/file
Вивід буде подібний до:
1
Ви також можете перевірити інший файл з іншим шляхом:
cat /volume/file
Вивід буде подібний до:
2
Додатково
24 - Створення статичних Podʼів
Статичні Podʼи керуються безпосередньо демоном kubelet на конкретному вузлі, без спостереження за ними з боку API сервера. На відміну від Podʼів, які керуються панеллю управління (наприклад, Deployment}), kubelet спостерігає за кожним статичним Podʼом (і перезапускає його у разі невдачі).
Статичні Podʼи завжди привʼязані до одного Kubelet на конкретному вузлі.
Kubelet автоматично намагається створити дзеркальний Pod на сервері Kubernetes API для кожного статичного Podʼа. Це означає, що Podʼи, які запущені на вузлі, є видимими на сервері API, але не можуть бути керовані звідти. Назви Podʼів будуть мати суфікс з іменем хосту вузла відділеним дефісом.
Примітка:
Якщо ви використовуєте кластеризований Kubernetes і використовуєте статичні Podʼи для запуску Podʼа на кожному вузлі, вам, ймовірно, слід використовувати DaemonSet замість цього.Примітка:
spec
статичного Podʼа не може посилатися на інші обʼєкти API (наприклад, ServiceAccount, ConfigMap, Secret, тощо).Примітка:
Статичні Podʼи не підтримують Ефемерні контейнери.Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.На цій сторінці передбачається, що ви використовуєте CRI-O для запуску Podʼів, а також що ваші вузли працюють під управлінням операційної системи Fedora. Інструкції для інших дистрибутивів або встановлень Kubernetes можуть відрізнятися.
Створення статичного Podʼа
Ви можете налаштувати статичний Pod з використанням файлу конфігурації, що зберігається в файловій системі або файлу конфігурації, що зберігається на вебсервері.
Статичний Pod з файлової системи
Маніфести — це стандартні визначення Podʼів у форматі JSON або YAML в певній теці. Використовуйте поле staticPodPath: <тека>
у конфігураційному файлі kubelet, який періодично сканує теку і створює/видаляє статичні Podʼи, коли у цій теці зʼявляються/зникають файли YAML/JSON. Зверніть увагу, що kubelet ігнорує файли, що починаються з крапки при скануванні вказаної теки.
Наприклад, так можна запустити простий вебсервер як статичний Pod:
Виберіть вузол, на якому ви хочете запустити статичний Pod. У цьому прикладі це
my-node1
.ssh my-node1
Виберіть теку, наприклад
/etc/kubernetes/manifests
, і помістіть туди визначення Podʼа вебсервера, наприклад,/etc/kubernetes/manifests/static-web.yaml
:# Виконайте цю команду на вузлі, де працює kubelet mkdir -p /etc/kubernetes/manifests/ cat <<EOF >/etc/kubernetes/manifests/static-web.yaml apiVersion: v1 kind: Pod metadata: name: static-web labels: role: myrole spec: containers: - name: web image: nginx ports: - name: web containerPort: 80 protocol: TCP EOF
Налаштуйте kubelet на тому вузлі, щоб встановити значення
staticPodPath
в конфігураційному файлі kubelet. Див. Встановлення параметрів kubelet через конфігураційний файл для отримання додаткової інформації.Альтернативний і застарілий метод полягає в налаштуванні kubelet на тому вузлі, щоб він шукав маніфести статичного Podʼа локально, використовуючи аргумент командного рядка. Щоб використовувати застарілий підхід, запустіть kubelet з аргументом
--pod-manifest-path=/etc/kubernetes/manifests/
.Перезапустіть kubelet. У Fedora ви виконаєте:
# Виконайте цю команду на вузлі, де працює kubelet systemctl restart kubelet
Маніфест Podʼа, розміщений на вебсервері
Kubelet періодично завантажує файл, вказаний аргументом --manifest-url=<URL>
,
і розглядає його як файл JSON/YAML, який містить визначення Podʼів.
Подібно до того, як працюють маніфести, розміщені в файловій системі, kubelet
перевіряє маніфест за розкладом. Якщо відбулися зміни в списку статичних
Podʼів, kubelet застосовує їх.
Щоб скористатися цим підходом:
Створіть YAML-файл і збережіть його на веб-сервері, щоб ви могли передати URL цього файлу kubelet.
apiVersion: v1 kind: Pod metadata: name: static-web labels: role: myrole spec: containers: - name: web image: nginx ports: - name: web containerPort: 80 protocol: TCP
Налаштуйте kubelet на обраному вузлі для використання цього веб-маніфесту, запустивши його з аргументом
--manifest-url=<URL-маніфесту>
. У Fedora відредагуйте/etc/kubernetes/kubelet
, щоб додати цей рядок:KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --manifest-url=<URL-маніфесту>"
Перезапустіть kubelet. У Fedora ви виконаєте:
# Виконайте цю команду на вузлі, де працює kubelet systemctl restart kubelet
Спостереження за поведінкою статичного Podʼа
Після запуску kubelet автоматично запускає всі визначені статичні Podʼи. Оскільки ви визначили статичний Pod і перезапустили kubelet, новий статичний Pod вже має бути запущений.
Ви можете переглянути запущені контейнери (включно зі статичними Podʼами), виконавши (на вузлі):
# Виконайте цю команду на вузлі, де працює kubelet
crictl ps
Вивід може бути наступним:
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
129fd7d382018 docker.io/library/nginx@sha256:... 11 minutes ago Running web 0 34533c6729106
Примітка:
crictl
виводить URI образу та контрольну суму SHA-256. NAME
буде виглядати більш подібним до: docker.io/library/nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
.Ви можете побачити дзеркальний Pod на сервері API:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 2m
Примітка:
Переконайтеся, що kubelet має дозвіл на створення дзеркального Podʼа на сервері API. якщо — ні, запит на створення буде відхилено сервером API.Мітки зі статичного Podʼа передаються в дзеркальний Pod. Ви можете використовувати ці мітки як зазвичай через селектори, і т.д.
Якщо ви спробуєте використовувати kubectl
для видалення дзеркального Podʼа з сервера API, kubelet не видаляє статичний Pod:
kubectl delete pod static-web-my-node1
pod "static-web-my-node1" deleted
Ви побачите, що Pod все ще працює:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 4s
Поверніться на вузол, де працює kubelet, і спробуйте вручну зупинити контейнер. Ви побачите, що після певного часу kubelet помітить це та автоматично перезапустить Pod:
# Виконайте ці команди на вузлі, де працює kubelet
crictl stop 129fd7d382018 # замініть на ID вашого контейнера
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
89db4553e1eeb docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
Після того як ви визначите потрібний контейнер, ви можете отримати журнал для цього контейнера за допомогою crictl
:
# Виконайте ці команди на вузлі, де працює контейнер
crictl logs <container_id>
10.240.0.48 - - [16/Nov/2022:12:45:49 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.48 - - [16/Nov/2022:12:45:50 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.48 - - [16/Nove/2022:12:45:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
Щоб дізнатися більше про те, як налагоджувати за допомогою crictl
, відвідайте Налагодження вузлів Kubernetes за допомогою crictl.
Динамічне додавання та видалення статичних Podʼів
Запущений kubelet періодично сканує налаштовану теку (/etc/kubernetes/manifests
у нашому прикладі) на предмет змін та додає/видаляє Podʼи при появі/зникненні файлів в цій теці.
# Це передбачає, що ви використовуєте файлову конфігурацію статичних Podʼів
# Виконайте ці команди на вузлі, де працює контейнер
#
mv /etc/kubernetes/manifests/static-web.yaml /tmp
sleep 20
crictl ps
# Ви бачите, що ніякий контейнер nginx не працює
mv /tmp/static-web.yaml /etc/kubernetes/manifests/
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
f427638871c35 docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
Що далі
- Створення статичних файлів маніфестів Podʼів для компонентів панелі управління
- Створення статичного файлу маніфесту Podʼа для локального etcd
- Налагодження вузлів Kubernetes за допомогою
crictl
- Дізнайтеся більше про
crictl
. - Зіставлення команд
docker
CLI зcrictl
. - Налаштування екземплярів etcd як статичних Podʼів, керованих kubelet
25 - Конвертація файлу Docker Compose в ресурси Kubernetes
Що таке Kompose? Це інструмент конвертації для всього, що стосується композиції (зокрема Docker Compose) в ресурси систем оркестрування (Kubernetes або OpenShift).
Додаткову інформацію можна знайти на вебсайті Kompose за адресою http://kompose.io.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Встановлення Kompose
Є кілька способів встановлення Kompose. Наш спосіб - завантаження бінарного файлу з останнього релізу GitHub.
Kompose випускається через GitHub кожні три тижні, ви можете переглянути всі поточні релізи на сторінці релізів GitHub.
# Linux
curl -L https://github.com/kubernetes/kompose/releases/download/v1.34.0/kompose-linux-amd64 -o kompose
# macOS
curl -L https://github.com/kubernetes/kompose/releases/download/v1.34.0/kompose-darwin-amd64 -o kompose
# Windows
curl -L https://github.com/kubernetes/kompose/releases/download/v1.34.0/kompose-windows-amd64.exe -o kompose.exe
chmod +x kompose
sudo mv ./kompose /usr/local/bin/kompose
Також ви можете завантажити архів.
Встановлення за допомогою go get
витягує дані з гілки master з останніми змінами розробки.
go get -u github.com/kubernetes/kompose
Kompose є в репозиторії EPEL для CentOS. Якщо у вас ще немає встановленого та увімкненого репозиторію EPEL, ви можете зробити це, виконавши sudo yum install epel-release
.
Якщо у вас увімкнений репозиторій EPEL у вашій системі, ви можете встановити Kompose як будь-який інший пакунок.
sudo yum -y install kompose
Kompose є в репозиторіях Fedora 24, 25 та 26. Ви можете встановити його, як і будь-який інший пакунок.
sudo dnf -y install kompose
У macOS ви можете встановити останній реліз за допомогою Homebrew:
brew install kompose
Використання Kompose
За кілька кроків ми переведемо вас з Docker Compose до Kubernetes. Вам потрібен лише наявний файл docker-compose.yml
.
Перейдіть до теки, що містить ваш файл
docker-compose.yml
. Якщо у вас його немає, ви можете випробувати використовуючи цей.services: redis-leader: container_name: redis-leader image: redis ports: - "6379" redis-replica: container_name: redis-replica image: redis ports: - "6379" command: redis-server --replicaof redis-leader 6379 --dir /tmp web: container_name: web image: quay.io/kompose/web ports: - "8080:8080" environment: - GET_HOSTS_FROM=dns labels: kompose.service.type: LoadBalancer
Щоб конвертувати файл
docker-compose.yml
у файли, які можна використовувати зkubectl
, запустітьkompose convert
, а потімkubectl apply -f <output file>
.kompose convert
Вивід подібний до:
INFO Kubernetes file "redis-leader-service.yaml" created INFO Kubernetes file "redis-replica-service.yaml" created INFO Kubernetes file "web-tcp-service.yaml" created INFO Kubernetes file "redis-leader-deployment.yaml" created INFO Kubernetes file "redis-replica-deployment.yaml" created INFO Kubernetes file "web-deployment.yaml" created
kubectl apply -f web-tcp-service.yaml,redis-leader-service.yaml,redis-replica-service.yaml,web-deployment.yaml,redis-leader-deployment.yaml,redis-replica-deployment.yaml
Вивід подібний до:
deployment.apps/redis-leader created deployment.apps/redis-replica created deployment.apps/web created service/redis-leader created service/redis-replica created service/web-tcp created
Ваші розгортання, що працюють в Kubernetes.
Доступ до вашого застосунку.
Якщо ви вже використовуєте
minikube
для вашого процесу розробки:minikube service web-tcp
В іншому випадку, подивімось, яку IP використовує ваш Service!
kubectl describe svc web-tcp
Name: web-tcp Namespace: default Labels: io.kompose.service=web-tcp Annotations: kompose.cmd: kompose convert kompose.service.type: LoadBalancer kompose.version: 1.33.0 (3ce457399) Selector: io.kompose.service=web Type: LoadBalancer IP Family Policy: SingleStack IP Families: IPv4 IP: 10.102.30.3 IPs: 10.102.30.3 Port: 8080 8080/TCP TargetPort: 8080/TCP NodePort: 8080 31624/TCP Endpoints: 10.244.0.5:8080 Session Affinity: None External Traffic Policy: Cluster Events: <none>
Якщо ви використовуєте хмарного постачальника, ваша IP буде вказана поруч з
LoadBalancer Ingress
.curl http://192.0.2.89
Прибирання.
Після завершення тестування розгортання прикладного застосунку просто запустіть наступну команду в вашій оболонці, щоб видалити використані ресурси.
kubectl delete -f web-tcp-service.yaml,redis-leader-service.yaml,redis-replica-service.yaml,web-deployment.yaml,redis-leader-deployment.yaml,redis-replica-deployment.yaml
Посібник користувача
Kompose підтримує двох провайдерів: OpenShift і Kubernetes. Ви можете вибрати відповідного постачальника, використовуючи глобальну опцію --provider
. Якщо постачальник не вказаний, буде встановлено Kubernetes.
kompose convert
Kompose підтримує конвертацію файлів Docker Compose версій V1, V2 і V3 в обʼєкти Kubernetes та OpenShift.
Приклад kompose convert
для Kubernetes
kompose --file docker-voting.yml convert
WARN Unsupported key networks - ignoring
WARN Unsupported key build - ignoring
INFO Kubernetes file "worker-svc.yaml" created
INFO Kubernetes file "db-svc.yaml" created
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "result-svc.yaml" created
INFO Kubernetes file "vote-svc.yaml" created
INFO Kubernetes file "redis-deployment.yaml" created
INFO Kubernetes file "result-deployment.yaml" created
INFO Kubernetes file "vote-deployment.yaml" created
INFO Kubernetes file "worker-deployment.yaml" created
INFO Kubernetes file "db-deployment.yaml" created
ls
db-deployment.yaml docker-compose.yml docker-gitlab.yml redis-deployment.yaml result-deployment.yaml vote-deployment.yaml worker-deployment.yaml
db-svc.yaml docker-voting.yml redis-svc.yaml result-svc.yaml vote-svc.yaml worker-svc.yaml
Ви також можете надати кілька файлів docker-compose одночасно:
kompose -f docker-compose.yml -f docker-guestbook.yml convert
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "mlbparks-service.yaml" created
INFO Kubernetes file "mongodb-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "mlbparks-deployment.yaml" created
INFO Kubernetes file "mongodb-deployment.yaml" created
INFO Kubernetes file "mongodb-claim0-persistentvolumeclaim.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
ls
mlbparks-deployment.yaml mongodb-service.yaml redis-slave-service.jsonmlbparks-service.yaml
frontend-deployment.yaml mongodb-claim0-persistentvolumeclaim.yaml redis-master-service.yaml
frontend-service.yaml mongodb-deployment.yaml redis-slave-deployment.yaml
redis-master-deployment.yaml
Коли надається кілька файлів docker-compose, конфігурація обʼєднується. Будь-яка конфігурація, яка є спільною, буде перевизначена наступним файлом.
Приклад kompose convert
для OpenShift
kompose --provider openshift --file docker-voting.yml convert
WARN [worker] Service cannot be created because of missing port.
INFO OpenShift file "vote-service.yaml" created
INFO OpenShift file "db-service.yaml" created
INFO OpenShift file "redis-service.yaml" created
INFO OpenShift file "result-service.yaml" created
INFO OpenShift file "vote-deploymentconfig.yaml" created
INFO OpenShift file "vote-imagestream.yaml" created
INFO OpenShift file "worker-deploymentconfig.yaml" created
INFO OpenShift file "worker-imagestream.yaml" created
INFO OpenShift file "db-deploymentconfig.yaml" created
INFO OpenShift file "db-imagestream.yaml" created
INFO OpenShift file "redis-deploymentconfig.yaml" created
INFO OpenShift file "redis-imagestream.yaml" created
INFO OpenShift file "result-deploymentconfig.yaml" created
INFO OpenShift file "result-imagestream.yaml" created
Також підтримує створення buildconfig для директиви build в сервісі. Стандартно використовується віддалений репозиторій для поточної гілки git як джерело репозиторію, та поточну гілку як гілку джерела для збірки. Ви можете вказати інше джерело репозиторію та гілку джерела, використовуючи опції --build-repo
та --build-branch
відповідно.
kompose --provider openshift --file buildconfig/docker-compose.yml convert
WARN [foo] Service cannot be created because of missing port.
INFO OpenShift Buildconfig using git@github.com:rtnpro/kompose.git::master as source.
INFO OpenShift file "foo-deploymentconfig.yaml" created
INFO OpenShift file "foo-imagestream.yaml" created
INFO OpenShift file "foo-buildconfig.yaml" created
Примітка:
Якщо ви вручну публікуєте артефакти OpenShift за допомогоюoc create -f
, вам потрібно забезпечити, щоб ви публікували артефакт imagestream перед артефактом buildconfig, щоб уникнути цієї проблеми OpenShift: https://github.com/openshift/origin/issues/4518 .Альтернативні конвертації
Типово kompose
перетворює файли у форматі yaml на обʼєкти Kubernetes Deployments та Services. У вас є альтернативна опція для генерації json за допомогою -j
. Також, ви можете альтернативно згенерувати обʼєкти Replication Controllers, Daemon Sets, або Helm чарти.
kompose convert -j
INFO Kubernetes file "redis-svc.json" created
INFO Kubernetes file "web-svc.json" created
INFO Kubernetes file "redis-deployment.json" created
INFO Kubernetes file "web-deployment.json" created
Файли *-deployment.json
містять обʼєкти Deployment.
kompose convert --replication-controller
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-replicationcontroller.yaml" created
INFO Kubernetes file "web-replicationcontroller.yaml" created
Файли *-replicationcontroller.yaml
містять обʼєкти Replication Controller. Якщо ви хочете вказати кількість реплік (стандартно 1), використовуйте прапорець --replicas
: kompose convert --replication-controller --replicas 3
.
kompose convert --daemon-set
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-daemonset.yaml" created
INFO Kubernetes file "web-daemonset.yaml" created
Файли *-daemonset.yaml
містять обʼєкти DaemonSet.
Якщо ви хочете згенерувати чарт для використання з Helm, виконайте:
kompose convert -c
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-deployment.yaml" created
INFO Kubernetes file "redis-deployment.yaml" created
chart created in "./docker-compose/"
tree docker-compose/
docker-compose
├── Chart.yaml
├── README.md
└── templates
├── redis-deployment.yaml
├── redis-svc.yaml
├── web-deployment.yaml
└── web-svc.yaml
Структура чарту спрямована на надання каркаса для створення ваших чартів Helm.
Мітки
kompose
підтримує специфічні для Kompose мітки в файлі docker-compose.yml
, щоб явно визначити поведінку сервісу при конвертації.
kompose.service.type
визначає тип сервісу, який потрібно створити.Наприклад:
version: "2" services: nginx: image: nginx dockerfile: foobar build: ./foobar cap_add: - ALL container_name: foobar labels: kompose.service.type: nodeport
kompose.service.expose
визначає, чи потрібно сервісу бути доступним ззовні кластера чи ні. Якщо значення встановлено на "true", постачальник автоматично встановлює точку доступу, і для будь-якого іншого значення, значення встановлюється як імʼя хосту. Якщо в сервісі визначено кілька портів, вибирається перший.- Для постачальника Kubernetes створюється ресурс Ingress, припускається, що контролер Ingress вже налаштований.
- Для постачальника OpenShift створюється маршрут.
Наприклад:
version: "2" services: web: image: tuna/docker-counter23 ports: - "5000:5000" links: - redis labels: kompose.service.expose: "counter.example.com" redis: image: redis:3.0 ports: - "6379"
Наразі підтримуються наступні варіанти:
Ключ | Значення |
---|---|
kompose.service.type | nodeport / clusterip / loadbalancer |
kompose.service.expose | true / hostname |
Примітка:
Міткаkompose.service.type
повинна бути визначена лише з ports
, інакше kompose
завершиться невдачею.Перезапуск
Якщо ви хочете створити звичайні Podʼи без контролерів, ви можете використовувати конструкцію restart
у docker-compose, щоб визначити це. Дивіться таблицю нижче, щоб побачити, що відбувається при значенні restart
.
docker-compose restart | створений обʼєкт | restartPolicy Podʼа |
---|---|---|
"" | обʼєкт контролера | Always |
always | обʼєкт контролера | Always |
on-failure | Капсула | OnFailure |
no | Капсула | Never |
Примітка:
Обʼєкт контролера може бутиdeployment
або replicationcontroller
.Наприклад, сервіс pival
стане Podʼом нижче. Цей контейнер обчислює значення pi
.
version: '2'
services:
pival:
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restart: "on-failure"
Попередження про конфігурації Deployment
Якщо в Docker Compose файлі вказано том для сервісу, стратегія Deployment (Kubernetes) або DeploymentConfig (OpenShift) змінюється на "Recreate" замість "RollingUpdate" (типово). Це робиться для того, щоб уникнути одночасного доступу кількох екземплярів сервісу до тому.
Якщо в Docker Compose файлі імʼя сервісу містить _
(наприклад, web_service
), то воно буде замінено на -
, і імʼя сервісу буде перейменовано відповідно (наприклад, web-service
). Kompose робить це, оскільки "Kubernetes" не дозволяє _
в імені обʼєкта.
Зверніть увагу, що зміна назви сервісу може зіпсувати деякі файли docker-compose
.
Версії Docker Compose
Kompose підтримує версії Docker Compose: 1, 2 та 3. Ми маємо обмежену підтримку версій 2.1 та 3.2 через їх експериментальний характер.
Повний список сумісності між усіма трьома версіями перераховано у нашому документі з конвертації, включаючи список всіх несумісних ключів Docker Compose.
26 - Забезпечення стандартів безпеки Podʼів шляхом конфігурування вбудованого контролера допуску
Kubernetes надає вбудований контролер допуску, щоб забезпечити дотримання стандартів безпеки Podʼів. Ви можете налаштувати цей контролер допуску, щоб встановити глобальні стандартні значення та винятки.
Перш ніж ви розпочнете
Після альфа-релізу в Kubernetes v1.22, Pod Security Admission став стандартно доступним в Kubernetes v1.23, у вигляді бета. Починаючи з версії 1.25, Pod Security Admissio доступний загалом.
Для перевірки версії введіть kubectl version
.
Якщо у вас не запущено Kubernetes 1.31, ви можете перемикнутися на перегляд цієї сторінки в документації для версії Kubernetes, яку ви використовуєте.
Налаштування контролера допуску
Примітка:
Конфігураціяpod-security.admission.config.k8s.io/v1
потребує v1.25+. Для v1.23 та v1.24, використовуйте v1beta1. Для v1.22, використовуйте v1alpha1.apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1 # див. примітку про сумісність
kind: PodSecurityConfiguration
# Стандартні значення, які застосовуються, коли мітка режиму не встановлена.
#
# Значення мітки рівня повинні бути одним з:
# - "privileged" (станадртно)
# - "baseline"
# - "restricted"
#
# Значення мітки версії повинні бути одним з:
# - "latest" (станадртно)
# - конкретна версія, наприклад "v1.31"
defaults:
enforce: "privileged"
enforce-version: "latest"
audit: "privileged"
audit-version: "latest"
warn: "privileged"
warn-version: "latest"
exemptions:
# Масив імен користувачів для виключення.
usernames: []
# Масив імен класів виконання для виключення.
runtimeClasses: []
# Масив просторів імен для виключення.
namespaces: []
Примітка:
Вищезазначений маніфест потрібно вказати через--admission-control-config-file
для kube-apiserver.27 - Забезпечення стандартів безпеки Podʼів за допомогою міток простору імен
Простори імен можуть бути позначені, щоб забезпечити стандарти безпеки Podʼів. Три політики privileged, baseline та restricted широко охоплюють спектр безпеки та реалізуються за допомогою контролера допуску безпеки Podʼа.
Перш ніж ви розпочнете
Pod Security Admission був доступний в Kubernetes v1.23, у вигляді бета. Починаючи з версії 1.25, Pod Security Admission доступний загалом.
Для перевірки версії введіть kubectl version
.
Вимога стандарту безпеки Pod baseline
за допомогою міток простору імен
Цей маніфест визначає Простір імен my-baseline-namespace
, який:
- Блокує будь-які Podʼи, які не відповідають вимогам політики
baseline
. - Генерує попередження для користувача та додає анотацію аудиту до будь-якого створеного Podʼа, який не відповідає вимогам політики
restricted
. - Фіксує версії політик
baseline
таrestricted
на v1.31.
apiVersion: v1
kind: Namespace
metadata:
name: my-baseline-namespace
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/enforce-version: v1.31
# Ми встановлюємо ці рівні за нашим _бажаним_ `enforce` рівнем.
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: v1.31
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: v1.31
Додавання міток до наявних просторів імен за допомогою kubectl label
Примітка:
Коли мітка політикиenforce
(або версії) додається або змінюється, втулок допуску буде тестувати кожен Pod в просторі імен на відповідність новій політиці. Порушення повертаються користувачу у вигляді попереджень.Корисно застосувати прапорець --dry-run
при початковому оцінюванні змін профілю безпеки для просторів імен. Перевірки стандарту безпеки Pod все ще будуть виконуватися в режимі dry run, що дозволяє отримати інформацію про те, як нова політика буде обробляти наявні Podʼи, без фактичного оновлення політики.
kubectl label --dry-run=server --overwrite ns --all \
pod-security.kubernetes.io/enforce=baseline
Застосування до всіх просторів імен
Якщо ви тільки починаєте зі Pod Security Standards, відповідний перший крок — налаштувати всі простори імен з анотаціями аудиту для строгого рівня, такого як baseline
:
kubectl label --overwrite ns --all \
pod-security.kubernetes.io/audit=baseline \
pod-security.kubernetes.io/warn=baseline
Зверніть увагу, що це не встановлює рівень примусового виконання, щоб можна було відрізняти простори імен, для яких не було явно встановлено рівень примусового виконання. Ви можете перелічити простори імен без явно встановленого рівня примусового виконання за допомогою цієї команди:
kubectl get namespaces --selector='!pod-security.kubernetes.io/enforce'
Застосування до конкретного простору імен
Ви також можете оновити конкретний простір імен. Ця команда додає політику enforce=restricted
до простору імен my-existing-namespace
, закріплюючи версію обмеженої політики на v1.31.
kubectl label --overwrite ns my-existing-namespace \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=v1.31
28 - Міграція з PodSecurityPolicy до вбудованого контролера допуску PodSecurity
Ця сторінка описує процес міграції з PodSecurityPolicy до вбудованого контролера допуску PodSecurity. Це можна зробити ефективно за допомогою комбінації запуску dry-run та режимів audit
та warn
, хоча це стає складнішим, якщо використовуються мутуючі PSP.
Перш ніж ви розпочнете
Версія вашого Kubernetes сервера має бути не старішою ніж v1.22.
Для перевірки версії введіть kubectl version
.
Якщо ви використовуєте відмінну від 1.31 версію Kubernetes, вам можливо захочеться перейти до перегляду цієї сторінки у документації для версії Kubernetes, яку ви фактично використовуєте.
Ця сторінка передбачає, що ви вже знайомі з основними концепціями Pod Security Admission.
Загальний підхід
Існує кілька стратегій для міграції з PodSecurityPolicy до Pod Security Admission. Наведені нижче кроки — це один з можливих шляхів міграції, з метою мінімізації ризиків виробничої перерви та пробілів у безпеці.
- Вирішіть, чи Pod Security Admission відповідає вашому випадку використання.
- Перегляньте дозволи простору імен.
- Спростіть та стандартизуйте PodSecurityPolicies.
- Оновіть простори імен
- Визначте відповідний рівень безпеки Podʼа.
- Перевірте рівень безпеки Podʼів.
- Застосуйте рівень безпеки Podʼів.
- Оминіть PodSecurityPolicy.
- Перегляньте процеси створення просторів імен.
- Вимкніть PodSecurityPolicy.
0. Вирішіть, чи Pod Security Admission підходить для вас
Pod Security Admission був розроблений для задоволення найбільш поширених потреб у безпеці з коробки, а також для забезпечення стандартного набору рівнів безпеки у всіх кластерах. Однак він менш гнучкий, ніж PodSecurityPolicy. Зокрема, наступні функції підтримуються за допомогою PodSecurityPolicy, але не за допомогою Pod Security Admission:
- Встановлення типових обмежень безпеки — Pod Security Admission є немутуючим контролером допуску, що означає, що він не буде змінювати Podʼи перед їх перевіркою. Якщо ви покладалися на цей аспект PodSecurityPolicy, вам доведеться або модифікувати ваші робочі навантаження, щоб вони відповідали обмеженням безпеки Podʼів, або використовувати Мутуючий вебхук допуску для внесення цих змін. Дивіться Спрощення та стандартизація PodSecurityPolicies нижче для детальнішої інформації.
- Докладний контроль над визначенням політики — Pod Security Admission підтримує тільки 3 стандартні рівні. Якщо вам потрібно більше контролю над конкретними обмеженнями, вам доведеться використовувати Вебхук допуску з перевіркою для виконання цих політик.
- Деталізація політики на рівні підпросторів імен — PodSecurityPolicy дозволяє вам призначати різні політики різним обліковим записам служб або користувачам, навіть в межах одного простору імен. Цей підхід має багато підводних каменів і не рекомендується, але якщо вам все одно потрібна ця функція, вам потрібно буде використовувати сторонній вебхук. Виняток становить випадок, коли вам потрібно повністю виключити певних користувачів або RuntimeClasses, у цьому випадку Pod Security Admission все ж надає деякі статичні конфігурації для виключень.
Навіть якщо Pod Security Admission не відповідає всім вашим потребам, він був розроблений для доповнення інших механізмів контролю політики, і може бути корисним допоміжним засобом, який працює нарівно з іншими вебхуками допуску.
1. Перегляньте дозволи простору імен
Pod Security Admission керується мітками в просторах імен. Це означає, що будь-хто, хто може оновлювати (або накладати патчі, або створювати) простір імен, також може змінювати рівень безпеки Podʼів для цього простору імен, що може бути використано для обходу більш обмеженої політики. Перш ніж продовжувати, переконайтеся, що ці дозволи на простір імен мають лише довірені, привілейовані користувачі. Не рекомендується надавати ці могутні дозволи користувачам, які не повинні мати підвищені привілеї, але якщо вам доведеться це зробити, вам потрібно буде використовувати вебхук допуску, щоб накласти додаткові обмеження на встановлення міток безпеки Podʼів на обʼєкти Namespace.
2. Спрощення та стандартизація PodSecurityPolicies
На цьому етапі зменште кількість мутуючих PodSecurityPolicies і видаліть параметри, що виходять за межі Pod Security Standards. Зміни, рекомендовані тут, слід внести в офлайн-копію оригіналу PodSecurityPolicy, який ви змінюєте. Клонована PSP повинна мати іншу назву, яка в алфавітному порядку стоїть перед оригінальною (наприклад, додайте 0
до її назви). Не створюйте нові політики в Kubernetes зараз — це буде розглянуто в розділі Впровадження оновлених політик нижче.
2.а. Видалення явно мутуючих полів
Якщо PodSecurityPolicy змінює Podʼи, то ви можете опинитись з Podʼами, які не відповідають вимогам рівня безпеки Podʼів, коли ви нарешті вимкнете PodSecurityPolicy. Щоб уникнути цього, вам слід усунути всі мутації PSP перед переходом. На жаль, PSP чітко не розділяє мутуючі та валідуючі поля, тому цей перехід не є простим.
Ви можете почати з видалення полів, які є явно мутуючими та не мають жодного впливу на політику валлідації. Ці поля (також перераховані в довіднику Перенесення PodSecurityPolicies у Pod Security Standards) включають:
.spec.defaultAllowPrivilegeEscalation
.spec.runtimeClass.defaultRuntimeClassName
.metadata.annotations['seccomp.security.alpha.kubernetes.io/defaultProfileName']
.metadata.annotations['apparmor.security.beta.kubernetes.io/defaultProfileName']
.spec.defaultAddCapabilities
— хоча це технічно мутуюче і валідуюче поле, його слід обʼєднати з.spec.allowedCapabilities
, яке виконує ту саму валідацію без мутації.
Увага:
Видалення цих полів може призвести до відсутності необхідних конфігурацій у робочих навантаженнях і спричинити проблеми. Дивіться Впровадження оновлених політик нижче, щоб отримати поради про те, як безпечно впроваджувати ці зміни.2.б. Вилучення параметрів, що не підпадають під Pod Security Standards
Існують кілька полів в PodSecurityPolicy, які не входять до складу Pod Security Standards. Якщо вам потрібно забезпечити ці опції, вам доведеться доповнити Pod Security Admission за допомогою вебхуків допуску, що не входить в рамки цього посібника.
Спочатку ви можете видалити явно валідуючі поля, які не охоплюються Pod Security Standards. Ці поля (також перераховані в довіднику Перенесення PodSecurityPolicies у Pod Security Standards з поміткою "no opinion") включають:
.spec.allowedHostPaths
.spec.allowedFlexVolumes
.spec.allowedCSIDrivers
.spec.forbiddenSysctls
.spec.runtimeClass
Ви також можете видалити наступні поля, які стосуються управління групами POSIX / UNIX.
Увага:
Якщо хоча б одне з них використовує стратегіюMustRunAs
, вони можуть бути мутуючими! Вилучення цих полів може призвести до того, що робочі навантаження не встановлюватимуть необхідні групи та спричинити проблеми. Дивіться Впровадження оновлених політик нижче, щоб отримати поради щодо безпечного впровадження цих змін..spec.runAsGroup
.spec.supplementalGroups
.spec.fsGroup
Залишені мутуючі поля потрібні для належної підтримки Pod Security Standards і будуть оброблені в окремому порядку:
.spec.requiredDropCapabilities
— Потрібно видалитиALL
щоб зробити профіль Restricted..spec.seLinux
— (Тільки мутуюче з правиломMustRunAs
) потрібно для забезпечення вимог SELinux для профілів Baseline & Restricted..spec.runAsUser
— (Не мутує з правиломRunAsAny
) потрібно для забезпеченняRunAsNonRoot
для профілю Restricted..spec.allowPrivilegeEscalation
— (Тільки мутується, якщо встановленоfalse
) потрібно для профілю Restricted.
2.в. Впровадження оновлених PSP
Далі ви можете впровадити оновлені політики у ваш кластер. Вам слід діяти обережно, оскільки видалення мутуючих опцій може призвести до того, що робочі навантаження пропустять необхідну конфігурацію.
Для кожної оновленої PodSecurityPolicy:
Визначте, які Podʼи працюють під оригінальною PSP. Це можна зробити за допомогою анотації
kubernetes.io/psp
. Наприклад, використовуючи kubectl:PSP_NAME="original" # Встановіть назву PSP, яку ви перевіряєте kubectl get pods --all-namespaces -o jsonpath="{range .items[?(@.metadata.annotations.kubernetes\.io\/psp=='$PSP_NAME')]}{.metadata.namespace} {.metadata.name}{'\n'}{end}"
Порівняйте ці робочі навантаження з оригінальною специфікацією Podаʼа, щоб визначити, чи змінила PodSecurityPolicy Pod. Для Podʼів, створених за ресурсами робочого навантаження, ви можете порівняти Pod з PodTemplate в ресурсі контролера. Якщо будь-які зміни виявлені, оригінальний Pod або PodTemplate слід оновити з необхідною конфігурацією. Поля для перегляду:
.metadata.annotations['container.apparmor.security.beta.kubernetes.io/*']
(замініть * на назву кожного контейнера).spec.runtimeClassName
.spec.securityContext.fsGroup
.spec.securityContext.seccompProfile
.spec.securityContext.seLinuxOptions
.spec.securityContext.supplementalGroups
- У контейнерів, під
.spec.containers[*]
та.spec.initContainers[*]
:.securityContext.allowPrivilegeEscalation
.securityContext.capabilities.add
.securityContext.capabilities.drop
.securityContext.readOnlyRootFilesystem
.securityContext.runAsGroup
.securityContext.runAsNonRoot
.securityContext.runAsUser
.securityContext.seccompProfile
.securityContext.seLinuxOptions
Створіть нові PodSecurityPolicies. Якщо будь-які Roles або ClusterRoles надають
use
на всі PSP, це може призвести до використання нових PSP замість їх мутуючих аналогів.Оновіть вашу авторизацію, щоб дозволити доступ до нових PSP. У RBAC це означає оновлення будь-яких Roles або ClusterRoles, які надають дозвіл
use
на оригінальну PSP, щоб також надати його оновленому PSP.Перевірте: після деякого часу повторно виконайте команду з кроку 1, щоб переглянути, чи використовуються будь-які Podʼи за оригінальними PSP. Зверніть увагу, що Podʼи повинні бути перестворені після того, як нові політики будуть впроваджені, перш ніж їх можна буде повністю перевірити.
(опціонально) Після того, як ви перевірили, що оригінальні PSP більше не використовуються, ви можете їх видалити.
3. Оновлення просторів імен
Наступні кроки потрібно виконати для кожного простору імен у кластері. Команди, на які посилаються в цих кроках, використовують змінну $NAMESPACE
для посилання на простір імен, який оновлюється.
3.а. Визначення відповідного рівня безпеки Podʼа
Почніть з ознайомлення зі Стандартами безпеки Podʼа та з трьома різними рівнями цих стандартів.
Існує кілька способів вибору рівня безпеки Podʼа для вашого простору імен:
За вимогами безпеки для простору імен — Якщо ви знайомі з очікуваним рівнем доступу для простору імен, ви можете вибрати відповідний рівень, базуючись на цих вимогах, подібно до підходу, який можна застосувати в новому кластері.
За поточними PodSecurityPolicies — Використовуючи довідник Перенесення PodSecurityPolicies у Pod Security Standards, ви можете віднести кожен PSP до рівня стандарту безпеки Podʼа. Якщо ваші PSP не базуються на Pod Security Standards, вам може знадобитися вирішити, обирати рівень, який є принаймні таким же дозвільним, як PSP, або рівень, який є принаймні таким же обмежувальним. Які PSP використовуються для Podʼів у даному просторі імен, ви можете побачити за допомогою цієї команди:
kubectl get pods -n $NAMESPACE -o jsonpath="{.items[*].metadata.annotations.kubernetes\.io\/psp}" | tr " " "\n" | sort -u
За поточними Podʼами — Використовуючи стратегії з розділу Перевірка рівня безпеки Podʼа, ви можете перевірити рівні Baseline і Restricted, щоб побачити, чи є вони достатньо дозвільними для наявних робочих навантажень, і вибрати найменш привілейований валідний рівень.
Увага:
Опції 2 і 3 вище базуються на поточних Podʼах і можуть не враховувати робочі навантаження, які в цей момент не запущені, такі як CronJobs, робочі навантаження з масштабуванням до нуля або інші робочі навантаження, які ще не були розгорнуті.3.б. Перевірка рівня безпеки Podʼа
Після того як ви обрали рівень безпеки Podʼа для простору імен (або якщо ви пробуєте кілька), добре було б спершу його протестувати (цей крок можна пропустити, якщо використовується рівень Privileged). Безпека Podʼа включає кілька інструментів для тестування та безпечного впровадження профілів.
Спочатку ви можете виконати пробний запуск політики, який оцінить Podʼи, що вже працюють у просторі імен, відносно застосованої політики, не впроваджуючи нову політику в дію:
# $LEVEL - рівень для пробного запуску, або "baseline", або "restricted".
kubectl label --dry-run=server --overwrite ns $NAMESPACE pod-security.kubernetes.io/enforce=$LEVEL
Ця команда поверне попередження для будь-яких наявних Podʼів, які не відповідають запропонованому рівню.
Другий варіант краще підходить для виявлення робочих навантажень, які в цей момент не запущені: режим аудиту. Коли запущено в режимі аудиту (на відміну від примусового впровадження), Podʼи, які порушують рівень політики, реєструються у логах аудиту, які можна переглянути пізніше після деякого часу, але вони не заборонені. Режим попередження працює подібно, але надсилає попередження користувачу негайно. Ви можете встановити рівень аудиту для простору імен за допомогою цієї команди:
kubectl label --overwrite ns $NAMESPACE pod-security.kubernetes.io/audit=$LEVEL
Якщо будь-який з цих підходів призведе до несподіваних порушень, вам потрібно буде або оновити робочі навантаження, що їх спричиняють, щоб відповідати вимогам політики, або послабити рівень безпеки простору імен Pod.
3.в. Впровадження рівня безпеки Podʼа
Коли ви переконаєтеся, що обраний рівень може бути безпечно впроваджений для простору імен, ви можете оновити простір імен, щоб впровадити бажаний рівень:
kubectl label --overwrite ns $NAMESPACE pod-security.kubernetes.io/enforce=$LEVEL
3.г. Оминання політики безпеки Pod
Наостанок, ви можете ефективно оминути PodSecurityPolicy на рівні простору імен, привʼязавши повністю привілейовану PSP до всіх облікових записів служб у просторі імен.
# Наступні команди, які виконуються на рівні кластера, потрібні лише один раз.
kubectl apply -f privileged-psp.yaml
kubectl create clusterrole privileged-psp --verb use --resource podsecuritypolicies.policy --resource-name privileged
# Вимкнення на рівні простору імен
kubectl create -n $NAMESPACE rolebinding disable-psp --clusterrole privileged-psp --group system:serviceaccounts:$NAMESPACE
Оскільки привілейована PSP не є мутуючою, а контролер прийняття рішення PSP завжди віддає перевагу немутуючим PSP, це гарантує, що Podʼи в цьому просторі імен більше не змінюються або не обмежуються PodSecurityPolicy.
Перевага вимкнення PodSecurityPolicy на рівні простору імен полягає в тому, що у разі виникнення проблеми ви можете легко скасувати зміну, видаливши RoleBinding. Просто переконайтеся, що попередньо наявні PodSecurityPolicy все ще застосовуються!
# Скасування вимкнення PodSecurityPolicy.
kubectl delete -n $NAMESPACE rolebinding disable-psp
4. Перегляд процесів створення просторів імен
Тепер, коли поточні простори імен оновлено для забезпечення прийняття рішень щодо Pod Security Admission, вам слід переконатися, що ваші процеси та/або політики для створення нових просторів імен оновлено, щоб гарантувати застосування відповідного профілю безпеки Pod для нових просторів імен.
Ви також можете статично налаштувати контролер Pod Security Admission для встановлення типового рівня впровадження, аудиту та/або попередження для просторів імен без міток. Див. Налаштування контролера допуску для отримання додаткової інформації.
5. Вимкнення PodSecurityPolicy
Нарешті, ви готові вимкнути PodSecurityPolicy. Для цього вам потрібно змінити конфігурацію допуску сервера API: Як я можу вимкнути контролер допуску?.
Щоб перевірити, що контролер допуску PodSecurityPolicy більше не активний, ви можете вручну запустити тест, видаючи себе за користувача без доступу до будь-яких PodSecurityPolicies (див. приклад PodSecurityPolicy), або перевірити логи сервера API. При запуску сервер API виводить рядки логу, що перераховують завантажені втулки контролера допуску:
I0218 00:59:44.903329 13 plugins.go:158] Loaded 16 mutating admission controller(s) successfully in the following order: NamespaceLifecycle,LimitRanger,ServiceAccount,NodeRestriction,TaintNodesByCondition,Priority,DefaultTolerationSeconds,ExtendedResourceToleration,PersistentVolumeLabel,DefaultStorageClass,StorageObjectInUseProtection,RuntimeClass,DefaultIngressClass,MutatingAdmissionWebhook.
I0218 00:59:44.903350 13 plugins.go:161] Loaded 14 validating admission controller(s) successfully in the following order: LimitRanger,ServiceAccount,PodSecurity,Priority,PersistentVolumeClaimResize,RuntimeClass,CertificateApproval,CertificateSigning,CertificateSubjectRestriction,DenyServiceExternalIPs,ValidatingAdmissionWebhook,ResourceQuota.
Ви маєте побачити PodSecurity
(у списку контролерів допуску для перевірки валідності), і жоден зі списків не повинен містити PodSecurityPolicy
.
Після того, як ви впевнені, що контролер допуску PSP вимкнуто (і після достатнього часу, щоб бути впевненим, що вам не потрібно буде відкочувати зміни), ви вільні видалити ваші PodSecurityPolicies та будь-які повʼязані Roles, ClusterRoles, RoleBindings та ClusterRoleBindings (просто переконайтеся, що вони не надають будь-яких інших неповʼязаних дозволів).