Це багатосторінковий друкований вигляд цього розділу. Натисність щоб друкувати.
Конфігурація
Pod
ів.1 - Поради щодо конфігурації
Цей документ виділяє та консолідує найкращі практики конфігурації, які представлені в документації користувача, документації для початківців та прикладах.
Це живий документ. Якщо ви подумаєте про щось, що не включено до цього списку, але може бути корисним іншим користувачам, будь ласка, не соромтеся подати тікет або надіслати PR.
Загальні поради щодо конфігурації
При створенні конфігурацій вкажіть останню стабільну версію API.
Файли конфігурації повинні зберігатися у системі контролю версій, перш ніж бути перенесеними в кластер. Це дозволяє швидко відкочувати зміну конфігурації у разі необхідності. Це також сприяє перестворенню та відновленню кластера.
Пишіть файли конфігурації за допомогою YAML, а не JSON. Хоча ці формати можна використовувати взаємозамінно практично в усіх сценаріях, YAML зазвичай є більш зручним для користувачів.
Гуртуйте повʼязані обʼєкти в один файл, якщо це має сенс. Одним файлом часто легше керувати, ніж кількома. Podʼивіться на файл guestbook-all-in-one.yaml як приклад використання цього синтаксису.
Також зверніть увагу, що багато команд
kubectl
можна виконувати з теками. Наприклад, ви можете застосуватиkubectl apply
в теці з файлами конфігурації.Не вказуйте типові значення без потреби: проста, мінімальна конфігурація зменшить ймовірність помилок.
Додайте описи обʼєктів в анотації, щоб забезпечити кращий самоаналіз.
Примітка:
У специфікації булевих значень в YAML 1.2 була введена переломну зміну у порівнянні з YAML 1.1. Це відома проблема в Kubernetes. YAML 1.2 визнає лише true та false як дійсні булеві значення, тоді як YAML 1.1 також приймає yes, no, on, та off як булеві значення. Хоча Kubernetes використовує YAML парсери, які в основному сумісні з YAML 1.1, однак використання yes або no замість true або false у маніфесті YAML може призвести до непередбачених помилок або поведінки. Щоб уникнути цієї проблеми, рекомендується завжди використовувати true або false для булевих значень у маніфестах YAML, та використовувати лапки для будь-яких рядків, які можуть бути сплутані з булевими значеннями, таких як "yes" або "no".
Крім булевих значень, є додаткові зміни у специфікаціях між версіями YAML. Будь ласка, зверніться до Зміни в специфікації YAML документації для отримання повного списку.
"Чисті" Podʼи проти ReplicaSets, Deployments та Jobs
Не використовуйте "чисті" Podʼи (тобто Podʼи, не повʼязані з ReplicaSet або Deployment), якщо можна уникнути цього. "Чисті" Podʼи не будуть переплановані в разі відмови вузла.
Використання Deployment, який як створює ReplicaSet для забезпечення того, що потрібна кількість Podʼів завжди доступна, так і вказує стратегію для заміни Podʼів (таку як RollingUpdate), майже завжди є переважним варіантом на відміну від створення Podʼів безпосередньо, за винятком деяких явних сценаріїв
restartPolicy: Never
. Також може бути прийнятним використання Job.
Services
Створіть Service перед створенням відповідного робочого навантаження (Deployments або ReplicaSets), і перед будь-якими створенням робочих навантажень, які мають до нього доступ. Коли Kubernetes запускає контейнер, він надає змінні середовища, які вказують на всі Serviceʼи, які працювали під час запуску контейнера. Наприклад, якщо існує Service з іменем
foo
, то всі контейнери отримають наступні змінні у своєму початковому середовищі:FOO_SERVICE_HOST=<хост, на якому працює Service> FOO_SERVICE_PORT=<порт, на якому працює Service>
Це передбачає вимоги щодо черговості — будь-який
Service
, до якогоPod
хоче отримати доступ, повинен бути створений перед створенням цьогоPod
ʼу, бо змінні середовища не будуть заповнені. DNS не має такого обмеження.Необовʼязкова (хоча настійно рекомендована) надбудова для кластера — це DNS-сервер. DNS-сервер спостерігає за Kubernetes API за появою нових
Serviceʼів
та створює набір DNS-записів для кожного з них. Якщо DNS було активовано в усьому кластері, то всіPodʼи
повинні мати можливість автоматичного використовувати назвиServiceʼів
.Не вказуйте
hostPort
для Podʼа, якщо це не є абсолютно необхідним. Коли ви привʼязуєте Pod доhostPort
, це обмежує місця, де може бути запланований Pod, оскільки кожна комбінація <hostIP
,hostPort
,protocol
> повинна бути унікальною. Якщо ви не вказуєте явноhostIP
таprotocol
, Kubernetes використовуватиме0.0.0.0
як типовийhostIP
таTCP
як типовийprotocol
.Якщо вам потрібен доступ до порту лише для налагодження, ви можете використовувати apiserver proxy або
kubectl port-forward
.Якщо вам дійсно потрібно використовувати порт Подʼа на вузлі, розгляньте можливість використання NodePort Service перед використанням
hostPort
.Уникайте використання
hostNetwork
, з тих самих причин, що йhostPort
.Використовуйте headless Service (які мають
ClusterIP
None
) для виявлення Service, коли вам не потрібен балансувальник навантаженняkube-proxy
.
Використання міток
Визначайте та використовуйте мітки, які ідентифікують семантичні атрибути вашого застосунку або Deployment, такі як
{ app.kubernetes.io/name: MyApp, tier: frontend, phase: test, deployment: v3 }
. Ви можете використовувати ці мітки для вибору відповідних Podʼів для інших ресурсів; наприклад, Service, який вибирає всі Podʼи зtier: frontend
, або всі складовіphase: test
зapp.kubernetes.io/name: MyApp
. Подивіться застосунок гостьова книга для прикладів застосування такого підходу.Service може охоплювати кілька Deploymentʼів, пропускаючи мітки, специфічні для релізу, від його селектора. Коли вам потрібно оновити робочий Service без простою, використовуйте Deployment.
Бажаний стан обʼєкта описується Deploymentʼом, і якщо зміни до його специфікації будуть застосовані, контролер Deployment змінює фактичний стан на бажаний з контрольованою швидкістю.
Використовуйте загальні мітки Kubernetes для загальних випадків використання. Ці стандартизовані мітки збагачують метадані таким чином, що дозволяють інструментам, включаючи
kubectl
та інфопанель (dashboard), працювати в сумісний спосіб.Ви можете маніпулювати мітками для налагодження. Оскільки контролери Kubernetes (такі як ReplicaSet) та Service отримують збіг з Podʼами за допомогою міток селектора, видалення відповідних міток з Podʼа зупинить його від обробки контролером або від обслуговування трафіку Serviceʼом. Якщо ви видалите мітки наявного Podʼа, його контролер створить новий Pod, щоб зайняти його місце. Це корисний спосіб налагоджувати раніше "справний" Pod в "карантинному" середовищі. Щоб інтерактивно видаляти або додавати мітки, використовуйте
kubectl label
.
Використання kubectl
Використовуйте
kubectl apply -f <directory>
. Виконання цієї команди шукає конфігурацію Kubernetes у всіх файлах.yaml
,.yml
та.json
у<directory>
та передає її доapply
.Використовуйте селектори міток для операцій
get
таdelete
замість конкретних назв обʼєктів. Подивіться розділи про селектори міток та ефективне використання міток.Використовуйте
kubectl create deployment
таkubectl expose
, щоб швидко створити Deployment з одним контейнером та Service. Подивіться Використання Service для доступу до застосунку в кластері для прикладу.
2 - ConfigMaps
ConfigMap це обʼєкт API, призначений для зберігання неконфіденційних даних у вигляді пар ключ-значення. Podʼи можуть використовувати ConfigMap як змінні середовища, аргументи командного рядка чи файли конфігурації у томі.
ConfigMap дозволяє відділити конфігурацію, специфічну для середовища, від образів контейнерів, щоб ваші застосунки були легко переносимими.
Увага:
ConfigMap не забезпечує конфіденційності або шифрування. Якщо дані, які ви хочете зберегти, конфіденційні, використовуйте Secret замість ConfigMap, або використовуйте додаткові (зовнішні) інструменти для збереження ваших даних в таємниці.Мотивація
Використовуйте ConfigMap для визначення конфігураційних даних окремо від коду застосунку.
Наприклад, уявіть, що ви розробляєте застосунок, який ви можете запускати на своєму власному компʼютері (для розробки) і в хмарі (для обробки реального трафіку). Ви пишете код, який переглядає змінну середовища з назвою DATABASE_HOST
. Локально ви встановлюєте цю змінну як localhost
. У хмарі ви встановлюєте її так, щоб вона посилалася на Service, який надає доступ до компонент бази даних вашому кластеру. Це дозволяє вам отримати образ контейнера, який працює в хмарі, і в разі потреби налагоджувати той самий код локально.
Примітка:
ConfigMap не призначено для зберігання великих обсягів даних. Дані, збережені в ConfigMap, не можуть перевищувати 1 MiB. Якщо потрібно зберегти налаштування, які перевищують це обмеження, варто розглянути можливість монтування тому або використання окремої бази даних або файлової служби.Обʼєкт ConfigMap
ConfigMap — це обʼєкт API, який дозволяє зберігати конфігураційні дані для використання іншими обʼєктами. На відміну від більшості обʼєктів Kubernetes, у яких є spec
, ConfigMap має поля data
та binaryData
. Ці поля приймають пари ключ-значення як свої значення. Обидва поля data
і binaryData
є необовʼязковими. Поле data
призначене для зберігання рядків UTF-8, тоді як поле binaryData
призначене для зберігання бінарних даних у вигляді рядків, закодованих у base64.
Назва ConfigMap повинна бути дійсним піддоменом DNS.
Кожний ключ у полі data
або binaryData
повинен складатися з алфавітно-цифрових символів, -
, _
або .
. Ключі, збережені в data
, не повинні перетинатися з ключами у полі binaryData
.
Починаючи з версії v1.19, ви можете додати поле immutable
до визначення ConfigMap,
щоб створити незмінний ConfigMap.
ConfigMaps та Podʼи
Ви можете написати spec
Podʼа, який посилається на ConfigMap і конфігурує контейнер(и) в цьому Podʼі на основі даних з ConfigMap. Pod і ConfigMap повинні бути в тому самому namespace.
Ось приклад ConfigMap, який має деякі ключі з одними значеннями, та інші ключі, де значення виглядає як фрагмент формату конфігурації.
apiVersion: v1
kind: ConfigMap
metadata:
name: game-demo
data:
# ключі у вигляді властивостей; кожен ключ зіставляється з простим значенням
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
# ключі у формі файлів
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
Є чотири різних способи використання ConfigMap для конфігурації контейнера всередині Podʼа:
- В команді та аргументах контейнера
- В змінних середовища для контейнера
- Додайте файл до тому тільки для читання, щоб застосунок міг його читати
- Напишіть код для виконання всередині Podʼа, який використовує Kubernetes API для читання ConfigMap
Ці різні методи підходять для різних способів моделювання даних, які споживаються. Для перших трьох методів kubelet використовує дані з ConfigMap при запуску контейнер(ів) для Podʼа.
Четвертий метод означає, що вам потрібно написати код для читання ConfigMap та його даних. Однак, оскільки ви використовуєте прямий доступ до Kubernetes API, ваш застосунок може підписатися на отримання оновлень, коли змінюється ConfigMap, і реагувати на це. Завдяки прямому доступу до Kubernetes API цей технічний підхід також дозволяє вам отримувати доступ до ConfigMap в іншому namespace.
Ось приклад Podʼа, який використовує значення з game-demo
для конфігурації Podʼа:
apiVersion: v1
kind: Pod
metadata:
name: configmap-demo-pod
spec:
containers:
- name: demo
image: alpine
command: ["sleep", "3600"]
env:
# Визначення змінної середовища
- name: PLAYER_INITIAL_LIVES # Зверніть увагу, що регістр відрізняється тут
# від назви ключа в ConfigMap.
valueFrom:
configMapKeyRef:
name: game-demo # ConfigMap, з якого отримується це значення.
key: player_initial_lives # Ключ для отримання значення.
- name: UI_PROPERTIES_FILE_NAME
valueFrom:
configMapKeyRef:
name: game-demo
key: ui_properties_file_name
volumeMounts:
- name: config
mountPath: "/config"
readOnly: true
volumes:
# Ви встановлюєте томи на рівні Pod, а потім монтуєте їх в контейнери всередині цього Pod
- name: config
configMap:
# Вкажіть назву ConfigMap, який ви хочете змонтувати.
name: game-demo
# Масив ключів з ConfigMap, які треба створити як файли
items:
- key: "game.properties"
path: "game.properties"
- key: "user-interface.properties"
path: "user-interface.properties"
ConfigMap не розрізняє значення властивостей з окремих рядків та багаторядкові файлоподібні значення. Важливо, як Podʼи та інші обʼєкти використовують ці значення.
У цьому прикладі визначення тому та монтування його всередину контейнера demo
як /config
створює два файли, /config/game.properties
та /config/user-interface.properties
, навіть якщо в ConfigMap є чотири ключі. Це тому, що визначення Podʼа вказує на масив items
в розділі volumes
. Якщо ви взагалі опустите масив items
, кожен ключ у ConfigMap стане файлом з тією ж навою, що й ключ, і ви отримаєте 4 файли.
Використання ConfigMap
ConfigMap можуть бути змонтовані як томи з даними. ConfigMap також можуть бути використані іншими частинами системи, не піддаючись безпосередньому впливу Podʼа. Наприклад, ConfigMap можуть містити дані, які повинні використовуватися іншими частинами системи для конфігурації.
Найпоширеніший спосіб використання ConfigMap — це конфігурація налаштувань для контейнерів, які запускаються в Podʼі в тому ж namespace. Ви також можете використовувати ConfigMap окремо.
Наприклад, ви можете зустріти надбудови або оператори, які налаштовують свою поведінку на основі ConfigMap.
Використання ConfigMaps як файлів в Pod
Щоб використовувати ConfigMap в томі в Podʼі:
- Створіть ConfigMap або використовуйте наявний. Декілька Podʼів можуть посилатися на один ConfigMap.
- Змініть ваше визначення Podʼа, щоб додати том в
.spec.volumes[]
. Назвіть том будь-яким імʼям, та встановіть поле.spec.volumes[].configMap.name
для посилання на ваш обʼєкт ConfigMap. - Додайте
.spec.containers[].volumeMounts[]
до кожного контейнера, який потребує ConfigMap. Вкажіть.spec.containers[].volumeMounts[].readOnly = true
та.spec.containers[].volumeMounts[].mountPath
в невикористану назву каталогу, де ви хочете, щоб зʼявився ConfigMap. - Змініть ваш образ або командний рядок так, щоб програма шукала файли у цьому каталозі. Кожен ключ в ConfigMap
data
стає імʼям файлу вmountPath
.
Ось приклад Podʼа, який монтує ConfigMap в том:
apiVersion: v1
kind:ʼPod {#configmap-object}
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
configMap:
name: myconfigmap
Кожен ConfigMap, який ви хочете використовувати, слід зазначити в .spec.volumes
.
Якщо в Podʼі є кілька контейнерів, то кожен контейнер потребує свого власного блоку volumeMounts
, але потрібно лише одне полу .spec.volumes
на ConfigMap.
Змонтовані ConfigMaps оновлюються автоматично
Коли ConfigMap, що наразі використовується в томі, оновлюється, ключі, що зіставляються, в кінцевому підсумку також оновлюються. Kubelet перевіряє, чи змонтований ConfigMap є свіжим під час кожної синхронізації. Однак Kubelet використовує свій локальний кеш для отримання поточного значення ConfigMap. Тип кешу настроюється за допомогою поля configMapAndSecretChangeDetectionStrategy
в структурі KubeletConfiguration. ConfigMap можна поширити за допомогою watch (типово), на основі ttl або шляхом перенаправлення всіх запитів безпосередньо до сервера API. Отже, загальна затримка від моменту оновлення ConfigMap до моменту коли нові ключі зʼявляться в Pod може становити стільки, скільки й періодична затримка kubelet + затримка поширення кешу, де затримка поширення кешу залежить від обраного типу кешу (вона дорівнює затримці поширення watch, ttl кешу або нулю відповідно).
ConfigMap, що використовуються як змінні оточення, не оновлюються автоматично і потребують перезапуску Podʼа.
Примітка:
Контейнер, який використовує ConfigMap як том з монтуванням subPath, не отримує оновлення ConfigMap.Використання ConfigMaps як змінних середовища
Щоб використовувати ConfigMap у змінних середовища в Podʼі:
- Для кожного контейнера у вашій специфікації Podʼа додайте змінну середовища для кожного ключа ConfigMap, який ви хочете використовувати, до поля
env[].valueFrom.configMapKeyRef
. - Змініть ваш образ та/або командний рядок так, щоб програма шукала значення у вказаних змінних середовища.
Ось приклад визначення ConfigMap як змінної середовища Podʼа:
Цей ConfigMap (myconfigmap.yaml) містить дві властивості: username та access_level:
apiVersion: v1
kind: ConfigMap
metadata:
name: myconfigmap
data:
username: k8s-admin
access_level: "1"
Наступна команда створить обʼєкт ConfigMap:
kubectl apply -f myconfigmap.yaml
Наступний Pod використовує вміст ConfigMap як змінні середовища:
apiVersion: v1
kind: Pod
metadata:
name: env-configmap
spec:
containers:
- name: app
command: ["/bin/sh", "-c", "printenv"]
image: busybox:latest
envFrom:
- configMapRef:
name: myconfigmap
Поле envFrom
вказує Kubernetes створити змінні середовища з джерел, вкладених у нього. Внутрішній configMapRef
посилається на ConfigMap за його імʼям і вибирає всі його пари ключ-значення. Додайте Pod до свого кластера, а потім перегляньте його логи, щоб побачити виведення команди printenv. Це має підтвердити, що дві пари ключ-значення з ConfigMap були встановлені як змінні середовища:
kubectl apply -f env-configmap.yaml
kubectl logs pod/ env-configmap
Вивід буде подібний до цього:
...
username: "k8s-admin"
access_level: "1"
...
Іноді Pod не потребуватиме доступу до всіх значень у ConfigMap. Наприклад, можна мати інший Pod, який використовує тільки значення username з ConfigMap. Для цього випадку можна використовувати синтаксис env.valueFrom
, який дозволяє вибирати окремі ключі в ConfigMap. Імʼя змінної середовища також може відрізнятися від ключа в ConfigMap. Наприклад:
apiVersion: v1
kind: Pod
metadata:
name: env-configmap
spec:
containers:
- name: envars-test-container
image: nginx
env:
- name: CONFIGMAP_USERNAME
valueFrom:
configMapKeyRef:
name: myconfigmap
key: username
У Podʼі, створеному з цього маніфесту, ви побачите, що змінна середовища CONFIGMAP_USERNAME
встановлена на значення username
з ConfigMap. Інші ключі з даних ConfigMap не будуть скопійовані у середовище.
Важливо зауважити, що діапазон символів, дозволених для назв змінних середовища в Podʼах, обмежений. Якщо будь-які ключі не відповідають правилам, ці ключі не будуть доступні вашому контейнеру, хоча Pod може бути запущений.
Незмінні ConfigMap
Kubernetes v1.21 [stable]
Функція Kubernetes Immutable Secrets та ConfigMaps надає опцію встановлення індивідуальних Secret та ConfigMap як незмінних. Для кластерів, що інтенсивно використовують ConfigMap (принаймні десятки тисяч унікальних монтувань ConfigMap до Podʼів), запобігання змінам їх даних має наступні переваги:
- захищає від випадкових (або небажаних) оновлень, які можуть призвести до відмов застосунків
- покращує продуктивність кластера шляхом значного зниження навантаження на kube-apiserver, закриваючи спостереження за ConfigMap, які позначені як незмінні.
Ви можете створити незмінний ConfigMap, встановивши поле immutable
в true
.
Наприклад:
apiVersion: v1
kind: ConfigMap
metadata:
...
data:
...
immutable: true
Після того як ConfigMap позначено як незмінний, змінити цю властивість або змінити вміст поля data
або binaryData
неможливо. Ви можете лише видалити та створити ConfigMap знову. Тому що поточні Podʼи підтримують точку монтування для видаленого ConfigMap, рекомендується перестворити ці Podʼи.
Що далі
- Дізнайтеся більше про Secret.
- Прочитайте про Налаштування Podʼа для використання ConfigMap.
- Дізнайтеся про зміну ConfigMap (або будь-якого іншого обʼєкту Kubernetes)
- Прочитайте про 12-факторні застосунки, щоб зрозуміти мотивацію для відокремлення коду від конфігурації.
3 - Secrets
Secret — це обʼєкт, який містить невелику кількість конфіденційних даних, таких як пароль, токен або ключ. Така інформація також може бути включена до специфікації Pod або в образ контейнера. Використання Secret означає, що вам не потрібно включати конфіденційні дані у ваш код.
Оскільки Secret можуть бути створені незалежно від Podʼів, які їх використовують, існує менше ризику того, що Secret (і його дані) буде викрито під час процесу створення, перегляду та редагування Podʼів. Kubernetes та програми, які працюють у вашому кластері, також можуть вживати додаткових заходів безпеки щодо Secretʼів, наприклад, уникання запису конфіденційних даних у енергонезалежне сховище.
Secretʼи схожі на ConfigMap, але призначені для зберігання конфіденційних даних.
Увага:
Керовані Kubernetes Secretʼи, стандартно, зберігаються незашифрованими у базі даних API-сервера (etcd). Будь-хто з доступом до API може отримати або змінити Secret, так само як будь-хто з доступом до etcd. Крім того, будь-хто, хто має дозвіл на створення Podʼа у просторі імен, може використовувати цей доступ для читання будь-якого Secretʼу у цьому просторі імен; це включає і непрямий доступ, такий як можливість створення Deployment.
Щоб безпечно використовувати Secretʼи, виконайте принаймні наступні кроки:
- Увімкніть шифрування у стані спокою для Secret.
- Увімкніть або налаштуйте правила RBAC з найменшими правами доступу до Secret.
- Обмежте доступ до Secret для конкретних контейнерів.
- Розгляньте використання зовнішніх постачальників сховища для Secret.
Для отримання додаткових рекомендацій щодо керування та покращення безпеки ваших Secret, ознайомтесь з Належними практиками для Secret Kubernetes.
Дивіться Інформаційна безпека для Secret для отримання додаткових відомостей.
Застосування Secretʼів
Ви можете використовувати Secrets для таких цілей:
- Встановлення змінних оточення для контейнера.
- Надання облікових даних, таких як SSH-ключі або паролі, Podʼам.
- Дозвіл kubelet отримувати образи контейнера з приватних реєстрів.
Панель управління Kubernetes також використовує Secretʼи; наприклад, Secret токену реєстрації вузлів — це механізм, що допомагає автоматизувати реєстрацію вузлів.
Сценарій використання: dotfiles у томі Secret
Ви можете зробити ваші дані "прихованими", визначивши ключ, який починається з крапки. Цей ключ являє собою dotfile або "прихований" файл. Наприклад, коли наступний Secret підключається до тому secret-volume
, том буде містити один файл, з назвою .secret-file
, і контейнер dotfile-test-container
матиме цей файл присутнім у шляху /etc/secret-volume/.secret-file
.
Примітка:
Файли, які починаються з крапок, приховані від виводуls -l
; для того, щоб побачити їх під час перегляду вмісту каталогу використовуйте ls -la
.apiVersion: v1
kind: Secret
metadata:
name: dotfile-secret
data:
.secret-file: dmFsdWUtMg0KDQo=
---
apiVersion: v1
kind: Pod
metadata:
name: secret-dotfiles-pod
spec:
volumes:
- name: secret-volume
secret:
secretName: dotfile-secret
containers:
- name: dotfile-test-container
image: registry.k8s.io/busybox
command:
- ls
- "-l"
- "/etc/secret-volume"
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
Сценарій використання: Secret видимий для одного контейнера в Pod
Припустимо, що у вас є програма, яка потребує обробки HTTP-запитів, виконання складної бізнес-логіки та підписування деяких повідомлень HMAC. Оскільки у неї складна логіка застосунків, може бути непоміченою вразливість на віддалене читання файлів з сервера, що може дати доступ до приватного ключа зловмиснику.
Це можна розділити на два процеси у двох контейнерах: контейнер інтерфейсу, який обробляє взаємодію з користувачем та бізнес-логіку, але не може бачити приватний ключ; і контейнер що перевіряє підписи, який може бачити приватний ключ, та відповідає на прості запити на підпис від фронтенду (наприклад, через мережу localhost).
З цим розділеним підходом зловмиснику зараз потрібно обманути сервер застосунків, щоб зробити щось досить довільне, що може бути складніше, ніж змусити його прочитати файл.
Альтернативи Secretʼам
Замість використання Secret для захисту конфіденційних даних, ви можете вибрати з альтернатив.
Ось деякі з варіантів:
- Якщо ваш хмарно-орієнтований компонент потребує автентифікації від іншого застосунку, який, ви знаєте, працює в межах того ж кластера Kubernetes, ви можете використовувати ServiceAccount та його токени, щоб ідентифікувати вашого клієнта.
- Існують сторонні інструменти, які ви можете запускати, як в межах, так і поза вашим кластером, які керують чутливими даними. Наприклад, Service, до якого Podʼи мають доступ через HTTPS, який використовує Secret, якщо клієнт правильно автентифікується (наприклад, з токеном ServiceAccount).
- Для автентифікації ви можете реалізувати спеціальний підписувач для сертифікатів X.509, і використовувати CertificateSigningRequests, щоб дозволити цьому спеціальному підписувачу видавати сертифікати Podʼам, які їх потребують.
- Ви можете використовувати втулок пристрою, щоб використовувати апаратне забезпечення шифрування, яке локалізоване на вузлі, для певного Podʼа. Наприклад, ви можете розмістити довірені Podʼи на вузлах, які надають Trusted Platform Module.
Ви також можете комбінувати два або більше з цих варіантів, включаючи варіант використання Secret самостійно.
Наприклад: реалізуйте (або розгорніть) оператор, що отримує тимчасові токени сеансів від зовнішнього Service, а потім створює Secretʼи на основі цих тимчасових токенів. Podʼи, що працюють у вашому кластері, можуть використовувати токени сеансів, а оператор забезпечує їхню дійсність. Це розподілення означає, що ви можете запускати Podʼи, які не знають точних механізмів створення та оновлення цих токенів сеансів.
Типи Secret
При створенні Secret ви можете вказати його тип, використовуючи поле type
ресурсу Secret, або певні еквівалентні прапорці командного рядка kubectl
(якщо вони доступні). Тип Secret використовується для сприяння програмному обробленню даних Secret.
Kubernetes надає кілька вбудованих типів для деяких типових сценаріїв використання. Ці типи відрізняються за умовами перевірки та обмеженнями, які Kubernetes накладає на них.
Вбудований Тип | Використання |
---|---|
Opaque | довільні користувацькі дані |
kubernetes.io/service-account-token | токен ServiceAccount |
kubernetes.io/dockercfg | серіалізований файл ~/.dockercfg |
kubernetes.io/dockerconfigjson | серіалізований файл ~/.docker/config.json |
kubernetes.io/basic-auth | облікові дані для базової автентифікації |
kubernetes.io/ssh-auth | облікові дані для SSH автентифікації |
kubernetes.io/tls | дані для TLS клієнта або сервера |
bootstrap.kubernetes.io/token | дані bootstrap token |
Ви можете визначити та використовувати власний тип Secret, присвоївши непорожній рядок як значення type
обʼєкту Secret (порожній рядок розглядається як тип Opaque
).
Kubernetes не накладає жодних обмежень на назву типу. Однак, якщо ви використовуєте один з вбудованих типів, ви повинні задовольнити всі вимоги, визначені для цього типу.
Якщо ви визначаєте тип Secret, призначений для загального використання, дотримуйтесь домовленостей та структуруйте тип Secret так, щоб він мав ваш домен перед назвою, розділений знаком /
. Наприклад: cloud-hosting.example.net/cloud-api-credentials
.
Opaque Secrets
Opaque
— це стандартний тип Secret, якщо ви не вказуєте явно тип у маніфесті Secret. При створенні Secret за допомогою kubectl
вам потрібно використовувати команду generic
, щоб вказати тип Secret Opaque
. Наприклад, наступна команда створює порожній Secret типу Opaque
:
kubectl create secret generic empty-secret
kubectl get secret empty-secret
Вивід виглядає наступним чином:
NAME TYPE DATA AGE
empty-secret Opaque 0 2m6s
У стовпчику DATA
показується кількість елементів даних, збережених у Secret. У цьому випадку 0
означає, що ви створили порожній Secret.
Secret токенів ServiceAccount
Тип Secret kubernetes.io/service-account-token
використовується для зберігання
токену, який ідентифікує ServiceAccount. Це старий механізм, який забезпечує довгострокові облікові дані ServiceAccount для Podʼів.
У Kubernetes v1.22 та пізніших рекомендований підхід полягає в тому, щоб отримати короткостроковий, токен ServiceAccount який автоматично змінюється за допомогою API [TokenRequest
](/docs/reference/kubernetes-api/authentication-resources/ token-request-v1/) замість цього. Ви можете отримати ці короткострокові токени, використовуючи наступні методи:
- Викликайте API
TokenRequest
або використовуйте клієнт API, такий якkubectl
. Наприклад, ви можете використовувати командуkubectl create token
. - Запитуйте монтований токен в томі projected у вашому маніфесті Podʼа. Kubernetes створює токен і монтує його в Pod. Токен автоматично анулюється, коли Pod, в якому він монтується, видаляється. Докладні відомості див. в розділі Запуск Podʼа за допомогою токена ServiceAccount.
Примітка:
Ви повинні створювати Secret токена ServiceAccount лише в тому випадку, якщо ви не можете використовувати APITokenRequest
для отримання токена, і вам прийнятно з погляду безпеки зберігання постійного токена доступу у читабельному обʼєкті API. Для інструкцій див. Створення довгострокового API-токена для ServiceAccount вручну.При використанні цього типу Secret вам потрібно переконатися, що анотація kubernetes.io/service-account.name
встановлена на наявне імʼя ServiceAccount. Якщо ви створюєте як Secret, так і обʼєкти ServiceAccount, ви повинні спочатку створити обʼєкт ServiceAccount.
Після створення Secret контролер Kubernetes заповнює деякі інші поля, такі як анотація kubernetes.io/service-account.uid
, та ключ token
в полі data
, який заповнюється токеном автентифікації.
У наступному прикладі конфігурації оголошується Secret токена ServiceAccount:
apiVersion: v1
kind: Secret
metadata:
name: secret-sa-sample
annotations:
kubernetes.io/service-account.name: "sa-name"
type: kubernetes.io/service-account-token
data:
extra: YmFyCg==
Після створення Secret дочекайтеся, коли Kubernetes заповнить ключ token
в полі data
.
Для отримання додаткової інформації про роботу ServiceAccounts перегляньте документацію по ServiceAccount. Ви також можете перевірити поле automountServiceAccountToken
та поле serviceAccountName
у Pod
для отримання інформації про посилання на облікові дані ServiceAccount з Podʼів.
Secret конфігурації Docker
Якщо ви створюєте Secret для зберігання облікових даних для доступу до реєстру образів контейнерів, ви повинні використовувати одне з наступних значень type
для цього Secret:
kubernetes.io/dockercfg
: збереже серіалізований~/.dockercfg
, який є старим форматом налаштування командного рядка Docker. У поліdata
Secret міститься ключ.dockercfg
, значення якого — це вміст файлу~/.dockercfg
, закодованого у форматі base64.kubernetes.io/dockerconfigjson
: збереже серіалізований JSON, який слідує тим же правилам формату, що й файл~/.docker/config.json
, який є новим форматом для~/.dockercfg
. У поліdata
Secret має міститися ключ.dockerconfigjson
, значення якого – це вміст файлу~/.docker/config.json
, закодованого у форматі base64.
Нижче наведено приклад для Secret типу kubernetes.io/dockercfg
:
apiVersion: v1
kind: Secret
metadata:
name: secret-dockercfg
type: kubernetes.io/dockercfg
data:
.dockercfg: |
eyJhdXRocyI6eyJodHRwczovL2V4YW1wbGUvdjEvIjp7ImF1dGgiOiJvcGVuc2VzYW1lIn19fQo=
Примітка:
Якщо ви не хочете виконувати кодування у формат base64, ви можете вибрати використання поляstringData
замість цього.При створенні Secret конфігурації Docker за допомогою маніфесту, API сервер перевіряє, чи існує відповідний ключ у полі data
, і перевіряє, чи надане значення можна розпізнати як дійсний JSON. API сервер не перевіряє, чи є цей JSON фактично файлом конфігурації Docker.
Ви також можете використовувати kubectl
для створення Secret для доступу до реєстру контейнерів, наприклад, коли у вас немає файлу конфігурації Docker:
kubectl create secret docker-registry secret-tiger-docker \
--docker-email=tiger@acme.example \
--docker-username=tiger \
--docker-password=pass1234 \
--docker-server=my-registry.example:5000
Ця команда створює Secret типу kubernetes.io/dockerconfigjson
.
Отримайте поле .data.dockerconfigjson
з цього нового Secret та розкодуйте дані:
kubectl get secret secret-tiger-docker -o jsonpath='{.data.*}' | base64 -d
Вихід еквівалентний наступному JSON-документу (який також є дійсним файлом конфігурації Docker):
{
"auths": {
"my-registry.example:5000": {
"username": "tiger",
"password": "pass1234",
"email": "tiger@acme.example",
"auth": "dGlnZXI6cGFzczEyMzQ="
}
}
}
Увага:
Значення auth
закодовано у формат base64; воно зашифроване, але не є Secretним. Будь-хто, хто може прочитати цей Secret, може дізнатися токен доступу до реєстру.
Рекомендується використовувати постачальників облікових записів для динамічного і безпечного надання Secretʼів на запит.
Secret базової автентифікації
Тип kubernetes.io/basic-auth
наданий для зберігання облікових даних, необхідних для базової автентифікації. При використанні цього типу Secret, поле data
Secret повинно містити один з двох наступних ключів:
username
: імʼя користувача для автентифікаціїpassword
: пароль або токен для автентифікації
Обидва значення для цих ключів закодовані у формат base64. Ви також можете надати чіткий текст, використовуючи поле stringData
у маніфесті Secret.
Наступний маніфест є прикладом Secret для базової автентифікації:
apiVersion: v1
kind: Secret
metadata:
name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
username: admin # обовʼязкове поле для kubernetes.io/basic-auth
password: t0p-Secret # обовʼязкове поле для kubernetes.io/basic-auth
Примітка:
ПолеstringData
для Secret не дуже підходить для застосування на боці сервера.Тип Secret для базової автентифікації наданий лише для зручності. Ви можете створити тип Opaque
для облікових даних, які використовуються для базової автентифікації. Однак використання визначеного та публічного типу Secret (kubernetes.io/basic-auth
) допомагає іншим людям зрозуміти призначення вашого Secret та встановлює домовленості для очікуваних назв ключів.
Secret для автентифікації SSH
Вбудований тип kubernetes.io/ssh-auth
наданий для зберігання даних, що використовуються в автентифікації SSH. При використанні цього типу Secret, вам потрібно вказати пару ключ-значення ssh-privatekey
в полі data
(або stringData
) як SSH-автентифікаційні дані для використання.
Наступний маніфест є прикладом Secret, який використовується для автентифікації SSH з використанням пари публічного/приватного ключів:
apiVersion: v1
kind: Secret
metadata:
name: secret-ssh-auth
type: kubernetes.io/ssh-auth
data:
# в цьомум прикладі поле data скорочене
ssh-privatekey: |
UG91cmluZzYlRW1vdGljb24lU2N1YmE=
Тип Secret для автентифікації SSH наданий лише для зручності. Ви можете створити тип Opaque
для облікових даних, які використовуються для автентифікації SSH. Однак використання визначеного та публічного типу Secret (kubernetes.io/ssh-auth
) допомагає іншим людям зрозуміти призначення вашого Secret та встановлює домовленості для очікуваних назв ключів. API Kubernetes перевіряє, чи встановлені необхідні ключі для Secret цього типу.
Увага:
Приватні ключі SSH не встановлюють довіру між клієнтом SSH та сервером хосту самі по собі. Для зменшення ризику атак "man-in-the-middle" потрібен додатковий спосіб встановлення довіри, наприклад, файлknown_hosts
, доданий до ConfigMap.TLS Secrets
Тип Secret kubernetes.io/tls
призначений для зберігання сертифіката та його повʼязаного ключа, які зазвичай використовуються для TLS.
Одним з поширених використань TLS Secret є налаштування шифрування під час передачі для
Ingress, але ви також можете використовувати його з іншими ресурсами або безпосередньо у вашій роботі. При використанні цього типу Secret ключі tls.key
та tls.crt
повинні бути надані в полі data
(або stringData
) конфігурації Secret, хоча сервер API фактично не перевіряє значення кожного ключа.
Як альтернативу використанню stringData
, ви можете використовувати поле data
для надання сертифіката та приватного ключа у вигляді base64-кодованого тексту. Докладніше див. Обмеження для назв і даних Secret.
Наступний YAML містить приклад конфігурації TLS Secret:
apiVersion: v1
kind: Secret
metadata:
name: secret-tls
type: kubernetes.io/tls
data:
# значення закодовані в форматі base64, що приховує їх, але НЕ забезпечує
# жодного рівня конфіденційності
tls.crt: |
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNVakNDQWJzQ0FnMytNQTBHQ1NxR1NJYjNE
UUVCQlFVQU1JR2JNUXN3Q1FZRFZRUUdFd0pLVURFT01Bd0cKQTFVRUNCTUZWRzlyZVc4eEVEQU9C
Z05WQkFjVEIwTm9kVzh0YTNVeEVUQVBCZ05WQkFvVENFWnlZVzVyTkVSRQpNUmd3RmdZRFZRUUxF
dzlYWldKRFpYSjBJRk4xY0hCdmNuUXhHREFXQmdOVkJBTVREMFp5WVc1ck5FUkVJRmRsCllpQkRR
VEVqTUNFR0NTcUdTSWIzRFFFSkFSWVVjM1Z3Y0c5eWRFQm1jbUZ1YXpSa1pDNWpiMjB3SGhjTk1U
TXcKTVRFeE1EUTFNVE01V2hjTk1UZ3dNVEV3TURRMU1UTTVXakJMTVFzd0NRWURWUVFHREFKS1VE
RVBNQTBHQTFVRQpDQXdHWEZSdmEzbHZNUkV3RHdZRFZRUUtEQWhHY21GdWF6UkVSREVZTUJZR0Ex
VUVBd3dQZDNkM0xtVjRZVzF3CmJHVXVZMjl0TUlHYU1BMEdDU3FHU0liM0RRRUJBUVVBQTRHSUFE
Q0JoQUo5WThFaUhmeHhNL25PbjJTbkkxWHgKRHdPdEJEVDFKRjBReTliMVlKanV2YjdjaTEwZjVN
Vm1UQllqMUZTVWZNOU1vejJDVVFZdW4yRFljV29IcFA4ZQpqSG1BUFVrNVd5cDJRN1ArMjh1bklI
QkphVGZlQ09PekZSUFY2MEdTWWUzNmFScG04L3dVVm16eGFLOGtCOWVaCmhPN3F1TjdtSWQxL2pW
cTNKODhDQXdFQUFUQU5CZ2txaGtpRzl3MEJBUVVGQUFPQmdRQU1meTQzeE15OHh3QTUKVjF2T2NS
OEtyNWNaSXdtbFhCUU8xeFEzazlxSGtyNFlUY1JxTVQ5WjVKTm1rWHYxK2VSaGcwTi9WMW5NUTRZ
RgpnWXcxbnlESnBnOTduZUV4VzQyeXVlMFlHSDYyV1hYUUhyOVNVREgrRlowVnQvRGZsdklVTWRj
UUFEZjM4aU9zCjlQbG1kb3YrcE0vNCs5a1h5aDhSUEkzZXZ6OS9NQT09Ci0tLS0tRU5EIENFUlRJ
RklDQVRFLS0tLS0K
# У цьому прикладі, дані не є справжнім приватним ключем в форматі PEM
tls.key: |
RXhhbXBsZSBkYXRhIGZvciB0aGUgVExTIGNydCBmaWVsZA==
Тип TLS Secret наданий лише для зручності. Ви можете створити тип Opaque
для облікових даних, які використовуються для TLS-автентифікації. Однак використання визначеного та публічного типу Secret (kubernetes.io/tls
) допомагає забезпечити однорідність формату Secret у вашому проєкті. Сервер API перевіряє, чи встановлені необхідні ключі для Secret цього типу.
Для створення TLS Secret за допомогою kubectl
використовуйте підкоманду tls
:
kubectl create secret tls my-tls-secret \
--cert=path/to/cert/file \
--key=path/to/key/file
Пара публічного/приватного ключа повинна бути створена заздалегідь. Публічний ключ сертифіката для --cert
повинен бути закодований у .PEM форматі і повинен відповідати наданому приватному ключу для --key
.
Secret bootstrap-токенів
Тип Secret bootstrap.kubernetes.io/token
призначений для токенів, що використовуються під час процесу ініціалізації вузла. Він зберігає токени, які використовуються для підпису відомих ConfigMaps.
Secret токена ініціалізації зазвичай створюється в просторі імен kube-system
і називається у формі bootstrap-token-<token-id>
, де <token-id>
— це 6-символьний
рядок ідентифікатора токена.
Як Kubernetes маніфест, Secret токена ініціалізації може виглядати наступним чином:
apiVersion: v1
kind: Secret
metadata:
name: bootstrap-token-5emitj
namespace: kube-system
type: bootstrap.kubernetes.io/token
data:
auth-extra-groups: c3lzdGVtOmJvb3RzdHJhcHBlcnM6a3ViZWFkbTpkZWZhdWx0LW5vZGUtdG9rZW4=
expiration: MjAyMC0wOS0xM1QwNDozOToxMFo=
token-id: NWVtaXRq
token-secret: a3E0Z2lodnN6emduMXAwcg==
usage-bootstrap-authentication: dHJ1ZQ==
usage-bootstrap-signing: dHJ1ZQ==
У Secret токена ініціалізації вказані наступні ключі в data
:
token-id
: Випадковий рядок з 6 символів як ідентифікатор токена. Обовʼязковий.token-secret
: Випадковий рядок з 16 символів як сам Secret токена. Обовʼязковий.description
: Рядок, що призначений для користувачів, що описує, для чого використовується токен. Необовʼязковий.expiration
: Абсолютний час UTC, відповідно до RFC3339, що вказує, коли дія токена має бути закінчена. Необовʼязковий.usage-bootstrap-<usage>
: Логічний прапорець, який вказує додаткове використання для токена ініціалізації.auth-extra-groups
: Список імен груп, розділених комами, які будуть автентифікуватися як додатково до групиsystem:bootstrappers
.
Ви також можете надати значення в полі stringData
Secret без їх base64 кодування:
apiVersion: v1
kind: Secret
metadata:
# Зверніть увагу, як названий Secret
name: bootstrap-token-5emitj
# Зазвичай, Secret з bootstrap token знаходиться в просторі імен kube-system
namespace: kube-system
type: bootstrap.kubernetes.io/token
stringData:
auth-extra-groups: "system:bootstrappers:kubeadm:default-node-token"
expiration: "2020-09-13T04:39:10Z"
# Цей ідентифікатор токена використовується в назві
token-id: "5emitj"
token-secret: "kq4gihvszzgn1p0r"
# Цей токен може бути використаний для автентифікації
usage-bootstrap-authentication: "true"
# і він може бути використаний для підпису
usage-bootstrap-signing: "true"
Примітка:
ПолеstringData
для Secret погано працює на боці сервера.Робота з Secret
Створення Secret
Є кілька способів створення Secret:
Обмеження щодо імен і даних Secret
Імʼя обʼєкта Secret повинно бути дійсним імʼям DNS-піддомену.
Ви можете вказати поля data
і/або stringData
при створенні файлу конфігурації для Secret. Поля data
і stringData
є необовʼязковими. Значення для всіх ключів у полі data
повинні бути base64-кодованими рядками. Якщо перетворення у рядок base64 не є бажаним, ви можете вибрати поле stringData
, яке приймає довільні рядки як значення.
Ключі data
і stringData
повинні складатися з буквено-цифрових символів, -
, _
або .
. Усі пари ключ-значення в полі stringData
внутрішньо обʼєднуються в поле data
. Якщо ключ зустрічається як у полі data
, так і у полі stringData
, значення, вказане у полі stringData
, має пріоритет.
Обмеження розміру
Індивідуальні Secretʼи обмежені розміром 1 МБ. Це зроблено для того, щоб уникнути створення дуже великих Secret, які можуть вичерпати памʼять API-сервера та kubelet. Однак створення багатьох менших Secret також може вичерпати памʼять. Ви можете використовувати квоту ресурсів для обмеження кількості Secret (або інших ресурсів) в просторі імен.
Редагування Secret
Ви можете редагувати наявний Secret, якщо він не є незмінним. Для редагування Secret скористайтеся одним із наступних методів:
Ви також можете редагувати дані у Secret за допомогою інструменту Kustomize. Проте цей метод створює новий обʼєкт Secret
з відредагованими даними.
Залежно від того, як ви створили Secret, а також від того, як Secret використовується в ваших Podʼах, оновлення існуючих обʼєктів Secret
автоматично поширюються на Podʼи, які використовують дані. Для отримання додаткової інформації звертайтеся до розділу Використання Secret як файлів у Podʼі.
Використання Secret
Secret можна монтувати як томи даних або використовувати як змінні оточення для використання контейнером в Podʼі. Secret також можна використовувати іншими частинами системи, не надаючи прямого доступу до Podʼа. Наприклад, Secret можуть містити автентифікаційні дані, які інші частини системи повинні використовувати для взаємодії зовнішніми системами від вашого імені.
Джерела томів Secret перевіряються на наявність для того, щоб переконатися, що вказано посилання на обʼєкт дійсно вказує на обʼєкт типу Secret. Тому Secret повинен бути створений перед будь-якими Podʼами, які залежать від нього.
Якщо Secret не може бути отриманий (можливо, через те, що він не існує, або через тимчасову відсутність зʼєднання з сервером API), kubelet періодично повторює спробу запуску цього Podʼа. Крім того, kubelet також реєструє подію для цього Podʼа, включаючи деталі проблеми отримання Secret.
Необовʼязкові Secret
Коли ви посилаєтеся на Secret у Podʼі, ви можете позначити Secret як необовʼязковий, як у наступному прикладі. Якщо необовʼязковий Secret не існує, Kubernetes ігнорує його.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
optional: true
Типово Secret є обовʼязковими. Жоден з контейнерів Podʼа не розпочне роботу, доки всі обовʼязкові Secret не будуть доступні.
Якщо Pod посилається на певний ключ у необовʼязковому Secret і цей Secret існує, але відсутній зазначений ключ, Pod не запускається під час старту.
Використання Secret у вигляді файлів у Pod
Якщо ви хочете отримати доступ до даних з Secret у Podʼі, один із способів зробити це — це дозволити Kubernetes робити значення цього Secret доступним як файл у файловій системі одного або декількох контейнерів Podʼа.
Щоб це зробити, дивіться Створення Podʼа, який має доступ до секретних даних через Volume.
Коли том містить дані з Secret, а цей Secret оновлюється, Kubernetes відстежує це і оновлює дані в томі, використовуючи підхід з подальшою згодою.
Примітка:
Контейнер, який використовує Secret як том subPath, не отримує автоматичних оновлень Secret.Kubelet зберігає кеш поточних ключів та значень для Secret, які використовуються у томах для Podʼів на цьому вузлі. Ви можете налаштувати спосіб, яким kubelet виявляє зміни від кешованих значень. Поле configMapAndSecretChangeDetectionStrategy
в конфігурації kubelet контролює стратегію, яку використовує kubelet. Стандартною стратегією є Watch
.
Оновлення Secret можуть бути передані за допомогою механізму спостереження за API (стандартно), на основі кешу з визначеним часом життя або отримані зі API-сервера кластера в кожнному циклі синхронізації kubelet.
Як результат, загальна затримка від моменту оновлення Secret до моменту, коли нові ключі зʼявляються в Podʼі, може бути такою ж тривалою, як період синхронізації kubelet + затримка розповсюдження кешу, де затримка розповсюдження кешу залежить від обраного типу кешу (перший у списку це затримка розповсюдження спостереження, налаштований TTL кешу або нуль для прямого отримання).
Використання Secret як змінних оточення
Для використання Secret в змінних оточення в Podʼі:
- Для кожного контейнера у вашому описі Podʼа додайте змінну оточення для кожного ключа Secret, який ви хочете використовувати, у поле
env[].valueFrom.secretKeyRef
. - Змініть свій образ і/або командний рядок так, щоб програма шукала значення у вказаних змінних оточення.
Для отримання інструкцій дивіться Визначення змінних оточення контейнера за допомогою даних Secret.
Важливо зауважити, що діапазон символів, дозволених для назв змінних середовища в Podʼах, обмежений. Якщо будь-які ключі не відповідають правилам, ці ключі не будуть доступні вашому контейнеру, хоча Pod може бути запущений.
Використання Secret для витягування образів контейнерів
Якщо ви хочете отримувати образи контейнерів з приватного репозиторію, вам потрібен спосіб автентифікації для kubelet на кожному вузлі для доступу до цього репозиторію. Ви можете налаштувати Secret для витягування образів для досягнення цієї мети. Ці Secret налаштовані на рівні Pod.
Використання imagePullSecrets
Поле imagePullSecrets
є списком посилань на Secret в тому ж просторі імен. Ви можете використовувати imagePullSecrets
, щоб передати Secret, який містить пароль Docker (або іншого) репозиторію образів, в kubelet. Kubelet використовує цю інформацію для витягування приватного образу від імені вашого Podʼа. Для отримання додаткової інформації про поле imagePullSecrets
, дивіться PodSpec API.
Ручне вказання imagePullSecret
Ви можете дізнатися, як вказати imagePullSecrets
, переглянувши документацію про образи контейнерів.
Організація автоматичного приєднання imagePullSecrets
Ви можете вручну створити imagePullSecrets
та посилатися на них з ServiceAccount. Будь-які Podʼи, створені з цим ServiceAccount або створені з цим ServiceAccount, отримають своє поле imagePullSecrets
, встановлене на відповідне для сервісного облікового запису. Дивіться Додавання ImagePullSecrets до Service Account для детального пояснення цього процесу.
Використання Secret зі статичними Podʼами
Ви не можете використовувати ConfigMaps або Secrets зі статичними Podʼами.
Незмінні Secret
Kubernetes v1.21 [stable]
Kubernetes дозволяє вам позначати певні Secret (і ConfigMaps) як незмінні. Запобігання змінам даних існуючого Secret має наступні переваги:
- захищає вас від випадкових (або небажаних) оновлень, які можуть призвести до відмов застосунків
- (для кластерів, що широко використовують Secret — щонайменше десятки тисяч унікальних монтувань Secret у Podʼи), перехід до незмінних Secret покращує продуктивність вашого кластера шляхом значного зменшення навантаження на kube-apiserver. kubeletʼу не потрібно підтримувати [watch] за будь-якими Secret, які позначені як незмінні.
Позначення Secret як незмінного
Ви можете створити незмінний Secret, встановивши поле immutable
в true
. Наприклад,
apiVersion: v1
kind: Secret
metadata: ...
data: ...
immutable: true
Ви також можете оновити будь-який наявний змінний Secret, щоб зробити його незмінним.
Примітка:
Як тільки Secret або ConfigMap позначений як незмінний, цю зміну неможливо скасувати чи змінити зміст поляdata
. Ви можете тільки видалити і знову створити Secret. Наявні Podʼи зберігають точку монтування для видаленого Secret — рекомендується перестворити ці Podʼи.Інформаційна безпека для Secret
Хоча ConfigMap і Secret працюють схоже, Kubernetes застосовує додаткові заходи захисту для обʼєктів Secret.
Secret часто містять значення, які охоплюють широкий спектр важливостей, багато з яких можуть викликати ескалації всередині Kubernetes (наприклад, токени облікових записів служби) та зовнішніх систем. Навіть якщо окремий застосунок може мати на меті використання Secret, з якими він очікує взаємодіяти, інші застосунки в тому ж просторі імен можуть зробити ці припущення недійсними.
Secret буде відправлений на вузол тільки у випадку, якщо на цьому вузлі є Pod, якому він потрібен. Для монтування Secret Podʼи kubelet зберігає копію даних у tmpfs
, щоб конфіденційні дані не записувалися у носії з довгостроковим зберіганням. Коли Pod, який залежить від Secret, видаляється, kubelet видаляє свою локальну копію конфіденційних даних з Secret.
У Podʼі може бути кілька контейнерів. Типово контейнери, які ви визначаєте, мають доступ тільки до службового стандартного облікового запису та повʼязаного з ним Secret. Вам потрібно явно визначити змінні середовища або відобразити том у контейнері, щоб надати доступ до будь-якого іншого Secret.
Може бути Secret для кількох Podʼів на тому ж вузлі. Проте тільки Secretʼи, які запитує Pod, можливо бачити всередині його контейнерів. Таким чином, один Pod не має доступу до Secretʼів іншого Podʼа.
Налаштування доступу за принципом найменшого дозволу до Secret
Щоб посилити заходи безпеки навколо Secrets, використовуйте окремі простори імен для ізоляції доступу до змонтованих секретів.
Попередження:
Будь-які контейнери, які працюють з параметромprivileged: true
на вузлі, можуть отримати доступ до всіх Secret, що використовуються на цьому вузлі.Що далі
- Для настанов щодо керування та покращення безпеки ваших Secret перегляньте Рекомендаціх щодо Secret в Kubernetes.
- Дізнайтеся, як керувати Secret за допомогою
kubectl
- Дізнайтеся, як керувати Secret за допомогою конфігураційного файлу
- Дізнайтеся, як керувати Secret за допомогою kustomize
- Прочитайте довідник API для
Secret
.
4 - Керування ресурсами Podʼів та Контейнерів
Коли ви визначаєте Pod, ви можете додатково вказати, скільки кожного ресурсу потребує контейнер. Найпоширеніші ресурси для вказання — це процесор та памʼять (RAM); є й інші.
Коли ви вказуєте запит ресурсів для контейнерів в Podʼі, kube-scheduler використовує цю інформацію для вибору вузла, на який розмістити Pod. Коли ви вказуєте обмеження ресурсів для контейнера, kubelet забезпечує виконання цих обмежень, щоб запущений контейнер не міг використовувати більше цього ресурсу, ніж обмеження, яке ви встановили. Крім того, kubelet резервує принаймні ту кількість запитуваних ресурсів спеціально для використання цим контейнером.
Запити та обмеження
Якщо вузол, на якому запущений Pod, має достатньо вільного ресурсу, то можливе (і дозволено), щоб контейнер використовував більше ресурсу, ніж його запит
для цього ресурсу вказує.
Наприклад, якщо ви встановите запит memory
256 МіБ для контейнера, і цей контейнер буде в Pod, запланованому на вузол з 8 ГіБ памʼяті та без інших Pod, то контейнер може спробувати використати більше оперативної памʼяті.
Обмеження, то вже інша справа. Обидва обмеження cpu
та memory
застосовуються kubletʼом (та середовищем виконання контейнерів), і, зрештою, застосовуються ядром. На вузлах Linux, ядро накладає обмеження за допомогою cgroups. Поведінка застосування обмежень cpu
та memory
відрізняється.
Застосування обмеження cpu
виконується через зниження частоти доступу до процесора. Коли контейенер надближається до свого обмеження, ядро обмежує доступ до процесора, відповідно до обмеженнь контейнера. Тож, обмеження cpu
є жорстким обмеженням, що застосовує ядро.
Застосування обмеження memory
виконується ядром за допомогою припинення процесів через механізм браку памʼяті (OOM — Out Of Memory kills). Якщо контейнер намагається використати більше памʼяті, ніж його обмеження, ядро може припинити його роботу. Однак, припинення роботи контейнера відбувається тільки тоді, коли ядро виявляє тиск на памʼять. Це означає, що обмеження memory
застосовується реактивно. Контенер може використовувати більше памʼяті, ніж його обмеження, однак, якщо він перевищує ліміт, то його робота може бути припинена.
Примітка:
Альфа версіяMemoryQoS
є спробою додати більш витісняюче обмеження для памʼяті (на противагу реактивному обмеженню пам'яті за допомогою OOM killer). Однак роботу в цьому напрямку зупинено через можливу ситуацію з блокуванням, яку може спричинити контейнер із високим споживанням пам’яті.Примітка:
Якщо ви вказали обмеження для ресурсу, але не вказали жодного запиту, і жодний механізм часу входу не застосував стандартного значення запиту для цього ресурсу, то Kubernetes скопіює обмеження яке ви вказали та використовує його як запитане значення для ресурсу.Типи ресурсів
ЦП та памʼять кожен є типом ресурсу. Тип ресурсу має базові одиниці вимірювання. ЦП представляє обчислювальні ресурси та вказується в одиницях ЦП Kubernetes. Памʼять вказується в байтах. Для робочих завдань на Linux ви можете вказати huge page ресурсів. Huge page є функцією, специфічною для Linux, де ядро вузла виділяє блоки памʼяті, що значно більше, ніж розмір стандартної сторінки.
Наприклад, у системі, де розмір стандартної сторінки становить 4 КіБ, ви можете вказати обмеження hugepages-2Mi: 80Mi
. Якщо контейнер намагається виділити більше ніж 40 2МіБ великих сторінок (всього 80 МіБ), то це виділення не вдасться.
Примітка:
Ви не можете перевищити ресурсиhugepages-*
. Це відрізняється від ресурсів memory
та cpu
.ЦП та памʼять спільно називаються обчислювальними ресурсами або ресурсами. Обчислювальні ресурси – це вимірювальні величини, які можна запитувати, виділяти та використовувати. Вони відрізняються від ресурсів API. Ресурси API, такі як Pod та Service, є обʼєктами, які можна читати та змінювати за допомогою сервера API Kubernetes.
Запити та обмеження ресурсів для Podʼа та контейнера
Для кожного контейнера ви можете вказати обмеження та запити ресурсів, включаючи наступне:
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.limits.hugepages-<size>
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
spec.containers[].resources.requests.hugepages-<size>
Хоча ви можете вказувати запити та обмеження тільки для окремих контейнерів, також корисно думати про загальні запити та обмеження ресурсів для Podʼа. Для певного ресурсу запит/обмеження ресурсів Podʼа — це сума запитів/обмежень цього типу для кожного контейнера в Podʼі.
Специфікація ресурсів на рівні Podʼів
Kubernetes v1.32 [alpha]
(стандартно увімкнено: false)Починаючи з Kubernetes 1.32, ви також можете вказувати запити на ресурси та ліміти на рівні Pod. На рівні Pod, Kubernetes 1.32 підтримує запити на ресурси або ліміти лише для певних типів ресурсів: cpu
та/або memory
. Наразі ця можливість знаходиться у альфа-версії і з увімкненою функцією Kubernetes дозволяє вам декларувати загальний бюджет ресурсів для Pod, що є особливо корисним при роботі з великою кількістю контейнерів, де може бути важко точно визначити індивідуальні потреби у ресурсах. Крім того, це дає змогу контейнерам в рамках Podʼа ділитися один з одним ресурсами, що простоюють, покращуючи використання ресурсів.
Для Podʼа ви можете вказати ліміти ресурсів і запити на процесор і памʼять, включивши наступне:
spec.resources.limits.cpu
spec.resources.limits.memory
spec.resources.requests.cpu
spec.resources.requests.memory
Одиниці виміру ресурсів в Kubernetes
Одиниці виміру ресурсів процесора
Обмеження та запити ресурсів процесора вимірюються в одиницях cpu. У Kubernetes 1 одиниця CPU еквівалентна 1 фізичному ядру процесора або 1 віртуальному ядру, залежно від того, чи є вузол фізичним хостом або віртуальною машиною, яка працює всередині фізичної машини.
Допускаються дробові запити. Коли ви визначаєте контейнер з spec.containers[].resources.requests.cpu
встановленою на 0.5
, ви просите вдвічі менше часу CPU порівняно з тим, якщо ви запросили 1.0
CPU. Для одиниць ресурсів процесора вираз кількості 0.1
еквівалентний виразу 100m
, що може бути прочитано як "сто міліпроцесорів". Деякі люди кажуть "сто міліядер", і це розуміється так само.
Ресурс CPU завжди вказується як абсолютна кількість ресурсу, ніколи як відносна кількість. Наприклад, 500m
CPU представляє приблизно ту саму обчислювальну потужність, не важливо чи цей контейнер працює на одноядерній, двоядерній або 48-ядерній машині.
Примітка:
Kubernetes не дозволяє вказувати ресурси CPU з точністю вище 1m
або 0.001
CPU. Щоб уникнути випадкового використання неприпустимої кількості CPU, корисно вказувати одиниці CPU, використовуючи форму міліCPU замість десяткової форми при використанні менше ніж 1 одиниця CPU.
Наприклад, у вас є Pod, який використовує 5m
або 0.005
CPU, і ви хочете зменшити його ресурси CPU. Використовуючи десяткову форму, важко помітити, що 0.0005
CPU є неприпустимим значенням, тоді як використовуючи форму міліCPU, легше помітити, що 0.5m
є неприпустимим значенням.
Одиниці виміру ресурсів памʼяті
Обмеження та запити для memory
вимірюються в байтах. Ви можете вказувати памʼять як звичайне ціле число або як число з плаваючою комою, використовуючи один з наступних суфіксів кількості: E, P, T, G, M, k. Ви також можете використовувати еквіваленти степенів двійки: Ei, Pi, Ti, Gi, Mi, Ki. Наприклад, наступне приблизно представляє те ж саме значення:
128974848, 129e6, 129M, 128974848000m, 123Mi
Звертайте увагу на регістр суфіксів. Якщо ви запитуєте 400m
памʼяті, це запит на 0.4 байта. Той, хто вводить це, ймовірно, мав на увазі запросити 400 мебібайтів (400Mi
)
або 400 мегабайтів (400M
).
Приклад ресурсів контейнера
У наступному Podʼі є два контейнери. Обидва контейнери визначені з запитом на 0,25 CPU і 64 МіБ (226 байт) памʼяті. Кожен контейнер має обмеження в 0,5 CPU та 128 МіБ памʼяті. Можна сказати, що у Podʼі є запит на 0,5 CPU та 128 МіБ памʼяті, та обмеження в 1 CPU та 256 МіБ памʼяті.
---
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: app
image: images.my-company.example/app:v4
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: log-aggregator
image: images.my-company.example/log-aggregator:v6
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Приклад ресурсів Podʼа
Kubernetes v1.32 [alpha]
(стандартно увімкнено: false)Наступний Pod має явний запит на 1 CPU та 100 MiB памʼяті, а також явний ліміт на 1 CPU та 200 MiB памʼяті. Контейнер pod-resources-demo-ctr-1
має явні запити та обмеження. Однак, контейнер pod-resources-demo-ctr-2
буде просто ділити ресурси, доступні в межах ресурсу Pod, оскільки він не має явних запитів і обмежень.
apiVersion: v1
kind: Pod
metadata:
name: pod-resources-demo
namespace: pod-resources-example
spec:
resources:
limits:
cpu: "1"
memory: "200Mi"
requests:
cpu: "1"
memory: "100Mi"
containers:
- name: pod-resources-demo-ctr-1
image: nginx
resources:
limits:
cpu: "0.5"
memory: "100Mi"
requests:
cpu: "0.5"
memory: "50Mi"
- name: pod-resources-demo-ctr-2
image: fedora
command:
- sleep
- inf
Як Podʼи з запитаними ресурсами плануються
Коли ви створюєте Pod, планувальник Kubernetes вибирає вузол, на якому Pod буде запущено. Кожен вузол має максимальну місткість для кожного з типів ресурсів: кількість процесорних ядер (CPU) та обсяг памʼяті, які він може надати для Podʼів. Планувальник забезпечує, що для кожного типу ресурсів сума запитів ресурсів запланованих контейнерів буде менше, ніж місткість вузла. Зверніть увагу, що навіть якщо фактичне використання ресурсів CPU або памʼяті на вузлі дуже низьке, планувальник все одно відмовляється розміщувати Pod на вузлі, якщо перевірка місткості не пройшла успішно. Це захищає від нестачі ресурсів на вузлі, коли пізніше збільшується використання ресурсів, наприклад, під час денного піка запитів.
Як Kubernetes застосовує запити на ресурси та обмеження
Коли kubelet запускає контейнер як частину Podʼа, він передає запити та обмеження для памʼяті та CPU цього контейнера до середовища виконання контейнера.
У Linux середовище виконання контейнера зазвичай налаштовує контрольні групи (cgroups) ядра, які застосовують і виконують обмеження, що ви визначили.
- Обмеження CPU встановлює жорсткий ліміт на те, скільки часу процесора контейнер може використовувати. Протягом кожного інтервалу планування (часового відрізка) ядро Linux перевіряє, чи перевищується це обмеження; якщо так, ядро чекає, перш ніж дозволити цій групі продовжити виконання.
- Запит CPU зазвичай визначає вагу. Якщо кілька різних контейнерів (cgroups) хочуть працювати на конкуруючій системі, робочі навантаження з більшими запитами CPU отримують більше часу CPU, ніж робочі навантаження з малими запитами.
- Запит памʼяті в основному використовується під час планування Podʼа (Kubernetes). На вузлі, що використовує cgroups v2, середовище виконання контейнера може використовувати запит памʼяті як підказку для встановлення
memory.min
таmemory.low
. - Обмеження памʼяті встановлює обмеження памʼяті для цієї контрольної групи. Якщо контейнер намагається виділити більше памʼяті, ніж це обмеження, підсистема управління памʼяттю Linux активується і, зазвичай, втручається, зупиняючи один з процесів у контейнері, який намагався виділити памʼять. Якщо цей процес є PID 1 контейнера, і контейнер позначений як можливий до перезапуску, Kubernetes перезапускає контейнер.
- Обмеження памʼяті для Podʼа або контейнера також може застосовуватися до сторінок в памʼяті, резервованих томами, як от
emptyDir
. Kubelet відстежуєtmpfs
томиemptyDir
як використання памʼяті контейнера, а не як локальне ефемерне сховище. При використанніemptyDir
в памʼяті, обовʼязково ознайомтеся з примітками нижче.
Якщо контейнер перевищує свій запит на памʼять і вузол, на якому він працює, стикається з браком памʼяті взагалі, ймовірно, що Pod, якому належить цей контейнер, буде виселено.
Контейнер може або не може дозволяти перевищувати своє обмеження CPU протягом тривалого часу. Однак середовища виконання контейнерів не припиняють роботу Podʼа або контейнерів через надмірне використання CPU.
Щоб визначити, чи не можна розмістити контейнер або, чи його роботи примусово припиняється через обмеження ресурсів, див. Налагодження.
Моніторинг використання обчислювальних ресурсів та ресурсів памʼяті
kubelet повідомляє про використання ресурсів Podʼа як частину статусу Podʼа.
Якщо в вашому кластері доступні інструменти для моніторингу, то використання ресурсів Podʼа можна отримати або безпосередньо з Metrics API, або з вашого інструменту моніторингу.
Міркування щодо томів emptyDir
, що зберігаються в памʼяті
Увага:
Якщо ви не вказуєтеsizeLimit
для emptyDir
тому, цей том може використовувати до граничного обсягу памʼяті цього Podʼа (Pod.spec.containers[].resources.limits.memory
). Якщо ви не встановлюєте граничний обсяг памʼяті, Pod не має верхньої межі на споживання памʼяті і може використовувати всю доступну памʼять на вузлі. Kubernetes планує Podʼи на основі запитів на ресурси (Pod.spec.containers[].resources.requests
) і не враховує використання памʼяті понад запит при вирішенні, чи може інший Pod розміститися на даному вузлі. Це може призвести до відмови в обслуговуванні та змусити ОС виконати обробку нестачі памʼяті (OOM). Можливо створити будь-яку кількість emptyDir
, які потенційно можуть використовувати всю доступну памʼять на вузлі, що робить OOM більш ймовірним.З точки зору управління памʼяттю, є деякі подібності між використанням памʼяті як робочої області процесу і використанням памʼяті для emptyDir
, що зберігається в памʼяті. Але при використанні памʼяті як том, як у випадку з emptyDir
, що зберігається в памʼяті, є додаткові моменти, на які слід звернути увагу:
- Файли, збережені в томі, що зберігається в памʼяті, майже повністю управляються застосунком користувча. На відміну від використання памʼяті як робочої області процесу, ви не можете покладатися на такі речі, як збір сміття на рівні мови програмування.
- Мета запису файлів в том полягає в збереженні даних або їх передачі між застосунками. Ні Kubernetes, ні ОС не можуть автоматично видаляти файли з тому, тому памʼять, яку займають ці файли, не може бути відновлена, коли система або Pod відчувають нестачу памʼяті.
- Томи
emptyDir
, що зберігаються в памʼяті, корисні через свою продуктивність, але памʼять зазвичай набагато менша за розміром і набагато дорожча за інші носії, такі як диски або SSD. Використання великої кількості памʼяті для томівemptyDir
може вплинути на нормальну роботу вашого Podʼа або всього вузла, тому їх слід використовувати обережно.
Якщо ви адмініструєте кластер або простір імен, ви також можете встановити ResourceQuota, що обмежує використання памʼяті; також може бути корисно визначити LimitRange для додаткового забезпечення обмежень. Якщо ви вказуєте spec.containers[].resources.limits.memory
для кожного Podʼа, то максимальний розмір тому emptyDir
буде дорівнювати граничному обсягу памʼяті Podʼа.
Як альтернатива, адміністратор кластера може забезпечити дотримання обмежень на розмір томів emptyDir
в нових Podʼах, використовуючи механізм політики, такий як ValidationAdmissionPolicy.
Локальне тимчасове сховище
Kubernetes v1.25 [stable]
На вузлах існує локальне тимчасове сховище, яке підтримується локально приєднаними пристроями для запису або іноді ОЗУ. "Тимчасове" означає, що не існує гарантії тривалості.
Podʼи використовують тимчасове локальне сховище для тимчасового простору, кешування та для логів. kubelet може надавати тимчасовий простір Podʼам, використовуючи локальне тимчасове сховище для підключення emptyDir
тому до контейнерів.
Крім того, kubelet використовує цей тип сховища для збереження логів контейнерів на рівні вузла, образів контейнерів та шарів з можливістю запису запущених контейнерів.
Увага:
Якщо вузол виходить з ладу, дані у його тимчасовому сховищі можуть бути втрачені. Ваші програми не можуть розраховувати на будь-які SLA щодо продуктивності (наприклад, IOPS диска) з локального тимчасового сховища.Примітка:
Щоб квота ресурсів працювала на тимчасовому сховищі, потрібно зробити дві речі:
- Адміністратор встановлює обмеження ресурсів для тимчасового сховища в просторі імен.
- Користувач повинен вказати обмеження для ресурсу тимчасового сховища в специфікації Podʼа.
Якщо користувач не вказує обмеження ресурсу тимчасового сховища в специфікації Podʼа, то обмеження ресурсу не накладається на тимчасове сховище.
Kubernetes дозволяє відстежувати, резервувати та обмежувати обсяг тимчасового локального сховища, яке може використовувати Pod.
Налаштування для локального тимчасового сховища
Kubernetes підтримує два способи налаштування локального тимчасового сховища на вузлі:
У цій конфігурації ви розміщуєте всі різновиди тимчасових локальних даних (таких як тимчасові томи emptyDir
, шари з можливістю запису, образи контейнерів, логи) в одній файловій системі. Найефективніший спосіб налаштування kubelet — призначити цю файлову систему для даних Kubernetes (kubelet).
Kubelet також записує логи контейнерів на рівні вузла та обробляє їх аналогічно до тимчасового локального сховища.
Kubelet записує логи в файли всередині свого налаштованого каталогу журналів (/var/log
типово); та має базовий каталог для інших локально збережених даних (/var/lib/kubelet
типово).
Зазвичай як /var/lib/kubelet
, так і /var/log
знаходяться на кореневій файловій системі системи, і kubelet розроблений з урахуванням цієї структури.
Ваш вузол може мати стільки інших файлових систем, не використовуваних для Kubernetes, скільки вам потрібно.
Ви маєте файлову систему на вузлі, яку використовуєте для тимчасових даних, які надходять від запущених Podʼів: логи та томи emptyDir
. Ви можете використовувати цю файлову систему для інших даних (наприклад: системні логи, не повʼязані з Kubernetes); це може навіть бути кореневою файловою системою.
Kubelet також записує логи контейнерів на рівні вузла у першу файлову систему та обробляє їх аналогічно до тимчасового локального сховища.
Ви також використовуєте окрему файлову систему, яка базується на іншому логічному пристрої зберігання. У цій конфігурації каталог, де ви вказуєте kubelet розміщувати шари образів контейнерів та шари з можливістю запису, знаходиться на цій другій файловій системі.
Перша файлова система не містить жодних шарів образів або шарів з можливістью запису.
Ваш вузол може мати стільки інших файлових систем, не використовуваних для Kubernetes, скільки вам потрібно.
Kubelet може вимірювати, скільки локального сховища він використовує. Він робить це, якщо ви налаштували вузол за однією з підтримуваних конфігурацій для локального тимчасового сховища.
Якщо у вас інша конфігурація, то kubelet не застосовує обмеження ресурсів для тимчасового локального сховища.
Примітка:
Kubelet відстежує тимчасові томиtmpfs
як використання памʼяті контейнера, а не як локальне тимчасове сховище.Примітка:
Kubelet відстежує тільки кореневу файлову систему для тимчасового сховища. Розкладки ОС, які монтували окремий диск у/var/lib/kubelet
або /var/lib/containers
, не будуть правильно відображати тимчасове сховище.Налаштування запитів та обмежень для локального тимчасового сховища
Ви можете вказати ephemeral-storage
для керування локальним тимчасовим сховищем. Кожен контейнер Podʼа може вказати одне або обидва з наступного:
spec.containers[].resources.limits.ephemeral-storage
spec.containers[].resources.requests.ephemeral-storage
Обмеження та запити для ephemeral-storage
вимірюються в кількості байтів. Ви можете виражати сховище як звичайне ціле число або як число з плаваючою точкою, використовуючи один з наступних суфіксів: E, P, T, G, M, k. Ви також можете використовувати еквіваленти степенів двійки: Ei, Pi, Ti, Gi, Mi, Ki. Наприклад, наступні кількості приблизно представляють одне й те ж значення:
128974848
129e6
129M
123Mi
Звертайте увагу на регістр суфіксів. Якщо ви запитуєте 400m
тимчасового сховища, це запит на 0,4 байти. Хтось, хто вводить це, мабуть, мав на меті запросити 400 мебібайтів (400Mi
) або 400 мегабайтів (400M
).
У наступному прикладі Pod має два контейнери. Кожен контейнер має запит на 2 гігабайти локального тимчасового сховища. Кожен контейнер має обмеження на 4 гігабайти локального тимчасового сховища. Отже, у Podʼа запит на 4 гігабайти локального тимчасового сховища, і обмеження на 8 ГіБ локального тимчасового сховища. З цього обмеження 500 Мі може бути витрачено на тимчасовий том emptyDir
.
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: app
image: images.my-company.example/app:v4
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "4Gi"
volumeMounts:
- name: ephemeral
mountPath: "/tmp"
- name: log-aggregator
image: images.my-company.example/log-aggregator:v6
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "4Gi"
volumeMounts:
- name: ephemeral
mountPath: "/tmp"
volumes:
- name: ephemeral
emptyDir:
sizeLimit: 500Mi
Як розміщуються Podʼи з запитами на локальне тимчасове сховище
При створенні Podʼа планувальник Kubernetes вибирає вузол, на якому буде виконуватися Под. Кожен вузол має максимальну кількість локального тимчасового сховища, яке він може надати для Podʼів. Для отримання додаткової інформації дивіться розділ Виділення ресурсів вузла.
Планувальник забезпечує те, щоб сума запитів ресурсів запланованих контейнерів була меншою за потужність вузла.
Керування використанням локального тимчасового сховища
Якщо kubelet керує локальним тимчасовим сховищем як ресурсом, тоді kubelet вимірює використання сховища у таких областях:
emptyDir
томи, за винятком tmpfsemptyDir
томів- каталоги, де зберігаються логи на рівні вузла
- шари контейнера з можливістю запису
Якщо Pod використовує більше тимчасового сховища, ніж дозволяється, kubelet встановлює сигнал виселення, який викликає виселення Podʼа.
Для ізоляції на рівні контейнера, якщо записуваний шар контейнера та використання логу перевищують обмеження щодо сховища, то kubelet позначає Pod для виселення.
Для ізоляції на рівні Podʼа kubelet визначає загальне обмеження сховища для Podʼа, підсумовуючи обмеження для контейнерів у цьому Podʼі. У цьому випадку, якщо сума використання локального тимчасового сховища з усіх контейнерів та emptyDir
томів Podʼа перевищує загальне обмеження сховища для Podʼа, то kubelet також позначає Pod для виселення.
Увага:
Якщо kubelet не вимірює локальне тимчасове сховище, тоді Pod, який перевищує своє обмеження локального сховища, не буде виселено за порушення обмежень ресурсів локального сховища.
Проте, якщо простір файлової системи для записуваних шарів контейнерів, журналів на рівні вузла або emptyDir
томів стає малим, вузол встановлює для себе позначку недостатності місця у локальному сховищі, і ця позначка викликає виселення будь-яких Podʼів, які не толерують цю позначку. Дивіться підтримані конфігурації для локального тимчасового сховища.
kubelet підтримує різні способи вимірювання використання сховища Podʼа:
kubelet виконує регулярні заплановані перевірки, які сканують кожний emptyDir
том, каталог логів контейнера та записуваний шар контейнера.
Під час сканування вимірюється обсяг використаного простору.
Примітка:
У цьому режимі kubelet не відстежує відкриті дескриптори файлів для видалених файлів.
Якщо ви (або контейнер) створюєте файл всередині emptyDir
тому, потім щось відкриває цей файл, і ви видаляєте файл, поки він ще відкритий, то inode для видаленого файлу залишається до тих пір, поки ви не закриєте цей файл, але kubelet не класифікує цей простір як використаний.
Kubernetes v1.31 [beta]
(стандартно увімкнено: false)Квоти проєктів — це функціональність на рівні операційної системи для управління використанням сховища у файлових системах. У Kubernetes ви можете ввімкнути квоти проєктів для моніторингу використання сховища. Переконайтеся, що файлова система, яка підтримує emptyDir
томи, на вузлі надає підтримку квот проєктів. Наприклад, XFS та ext4fs пропонують квоти проєктів.
Примітка:
Квоти проєктів дозволяють вам відслідковувати використання сховища, вони не встановлюють обмеження.Kubernetes використовує ідентифікатори проєктів, що починаються з 1048576
. Використані ідентифікатори зареєстровані в /etc/projects
та /etc/projid
. Якщо ідентифікатори проєктів у цьому діапазоні використовуються для інших цілей у системі, ці ідентифікатори проєктів повинні бути зареєстровані в /etc/projects
та /etc/projid
, щоб Kubernetes не використовував їх.
Квоти є швидкими та точними, ніж сканування каталогів. Коли каталог призначений для проєкту, всі файли, створені в каталозі, створюються в цьому проєкті, і ядро просто відстежує, скільки блоків використовується файлами в цьому проєкті. Якщо файл створений і видалений, але має відкритий файловий дескриптор, він продовжує споживати місце. Відстеження квот точно відображає цей простір, тоді як сканування каталогів не враховує місце, використане видаленими файлами.
Щоб використовувати квоти для відстеження використання ресурсів Podʼів, Pod повинен знаходитися в просторі імен користувача. У просторах імен користувачів ядро обмежує зміни ідентифікаторів проєктів у файловій системі, забезпечуючи надійність зберігання метрик, розрахованих за квотами.
Якщо ви хочете використовувати квоти проєктів, вам потрібно:
Увімкнути функціональну можливість
LocalStorageCapacityIsolationFSQuotaMonitoring=true
використовуючи полеfeatureGates
в конфігурації kubelet.Переконайтеся, що функціональну можливість
UserNamespacesSupport
увімкнено, і що ядро, реалізація CRI та середовище виконання OCI підтримують простори імен користувачів.Переконайтеся, що коренева файлова система (або додаткова файлова система запуску) має увімкнену підтримку квот проєктів. Всі файлові системи XFS підтримують квоти проєктів. Для файлових систем ext4fs вам потрібно увімкнути функцію відстеження квот проєктів допоки файлова система не змонтована.
# Для ext4, з /dev/block-device, не змонтовано sudo tune2fs -O project -Q prjquota /dev/block-device
Переконайтеся, що коренева файлова система (або додаткова файлова система запуску) змонтована з увімкненими квотами проєктів. Для XFS та ext4fs параметр монтування має назву
prjquota
.
Якщо ви не хочете використовувати квоти проєкту, вам слід зробити так:
- Вимкнути функціональну можливість
LocalStorageCapacityIsolationFSQuotaMonitoring
використовуючи полеfeatureGates
в kubelet configuration.
Розширені ресурси
Розширені ресурси — це повністю кваліфіковані імена ресурсів поза доменом kubernetes.io
. Вони дозволяють операторам кластера оголошувати, а користувачам використовувати ресурси, які не вбудовані в Kubernetes.
Щоб скористатися Розширеними ресурсами, потрібно виконати два кроки. По-перше, оператор кластера повинен оголошувати Розширений Ресурс. По-друге, користувачі повинні запитувати Розширений Ресурс в Podʼах.
Керування розширеними ресурсами
Ресурси на рівні вузла
Ресурси на рівні вузла повʼязані з вузлами.
Керовані ресурси втулків пристроїв
Дивіться Втулок пристроїв щодо того, як оголошувати ресурси, що керуються втулком пристроїв на кожному вузлі.
Інші ресурси
Щоб оголошувати новий розширений ресурс на рівні вузла, оператор кластера може надіслати HTTP-запит типу PATCH
до API-сервера, щоб вказати доступну кількість в полі status.capacity
для вузла у кластері. Після цієї операції поле status.capacity
вузла буде містити новий ресурс. Поле status.allocatable
оновлюється автоматично з новим ресурсом асинхронно за допомогою kubelet.
Оскільки планувальник використовує значення status.allocatable
вузла при оцінці придатності Podʼа, планувальник враховує нове значення лише після цього асинхронного оновлення. Між моментом зміни потужності вузла новим ресурсом і часом, коли перший Pod, який запитує ресурс, може бути запланований на цьому вузлі, може відбуватися коротка затримка.
Приклад:
Нижче наведено приклад використання curl
для формування HTTP-запиту, який оголошує пʼять ресурсів "example.com/foo" на вузлі k8s-node-1
, майстер якого k8s-master
.
curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "add", "path": "/status/capacity/example.com~1foo", "value": "5"}]' \
http://k8s-master:8080/api/v1/nodes/k8s-node-1/status
Примітка:
У запиті~1
— це кодування символу /
в шляху патча. Значення операційного шляху у JSON-Patch інтерпретується як JSON-вказівник. Для отримання докладнішої інформації дивіться RFC 6901, розділ 3.Ресурси на рівні кластера
Ресурси на рівні кластера не повʼязані з вузлами. Зазвичай ними керують розширювачі планувальника, які відповідають за споживання ресурсів і квоту ресурсів.
Ви можете вказати розширені ресурси, які обробляються розширювачами планувальника, в конфігурації планувальника.
Приклад:
Наступна конфігурація для політики планувальника вказує на те, що ресурс на рівні кластера "example.com/foo" обробляється розширювачем планувальника.
- Планувальник відправляє Pod до розширювача планувальника тільки у випадку, якщо Pod запитує "example.com/foo".
- Поле
ignoredByScheduler
вказує, що планувальник не перевіряє ресурс "example.com/foo" в своєму предикатіPodFitsResources
.
{
"kind": "Policy",
"apiVersion": "v1",
"extenders": [
{
"urlPrefix":"<extender-endpoint>",
"bindVerb": "bind",
"managedResources": [
{
"name": "example.com/foo",
"ignoredByScheduler": true
}
]
}
]
}
Використання розширених ресурсів
Користувачі можуть використовувати розширені ресурси у специфікаціях Podʼа, подібно до CPU та памʼяті. Планувальник відповідає за облік ресурсів, щоб одночасно не виділялося більше доступної кількості ресурсів для Podʼів.
Сервер API обмежує кількість розширених ресурсів цілими числами. Приклади дійсних значень: 3
, 3000m
та 3Ki
. Приклади недійсних значень: 0.5
та 1500m
(томущо 1500m
буде давати в результаті 1.5
).
Примітка:
Розширені ресурси замінюють Opaque Integer Resources. Користувачі можуть використовувати будь-який префікс доменного імені, крімkubernetes.io
, який зарезервований.Щоб використовувати розширений ресурс у Podʼі, включіть імʼя ресурсу як ключ у масив spec.containers[].resources.limits
у специфікації контейнера.
Примітка:
Розширені ресурси не можуть бути перевищені, тому запити та обмеження мають бути рівними, якщо обидва присутні у специфікації контейнера.Pod є запланованим лише у випадку, якщо всі запити ресурсів задовольняються, включаючи CPU, памʼять та будь-які розширені ресурси. Pod залишається у стані PENDING
, поки запит ресурсу не може бути задоволений.
Приклад:
Нижче наведено Pod, який запитує 2 CPU та 1 "example.com/foo" (розширений ресурс).
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: myimage
resources:
requests:
cpu: 2
example.com/foo: 1
limits:
example.com/foo: 1
Обмеження PID
Обмеження ідентифікаторів процесів (PID) дозволяють налаштувати kubelet для обмеження кількості PID, яку може використовувати певний Pod. Див. Обмеження PID для отримання інформації.
Усунення несправностей
Мої Podʼи знаходяться в стані очікування з повідомленням події FailedScheduling
Якщо планувальник не може знайти жодного вузла, де може розмістити Pod, Pod залишається
незапланованим, поки не буде знайдено місце. Кожного разу, коли планувальник не може знайти місце для Podʼа, створюється подія. Ви можете використовувати kubectl
для перегляду подій Podʼа; наприклад:
kubectl describe pod frontend | grep -A 9999999999 Events
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 23s default-scheduler 0/42 nodes available: insufficient cpu
У прикладі Pod під назвою "frontend" не вдалося запланувати через недостатній ресурс CPU на будь-якому вузлі. Схожі повідомлення про помилку також можуть вказувати на невдачу через недостатню памʼять (PodExceedsFreeMemory). Загалом, якщо Pod знаходиться в стані очікування з таким типом повідомлення, є кілька речей, які варто спробувати:
- Додайте більше вузлів у кластер.
- Завершіть непотрібні Podʼи, щоб звільнити місце для очікуваних Podʼів.
- Перевірте, що Pod не є більшим, ніж усі вузли. Наприклад, якщо всі вузли мають місткість
cpu: 1
, то Pod з запитомcpu: 1.1
ніколи не буде запланованим. - Перевірте наявність "taint" вузла. Якщо більшість ваших вузлів мають "taint", і новий Pod не толерує цей "taint", планувальник розглядає розміщення лише на залишкових вузлах, які не мають цього "taint".
Ви можете перевірити місткості вузлів та виділені обсяги ресурсів за допомогою команди kubectl describe nodes
. Наприклад:
kubectl describe nodes e2e-test-node-pool-4lw4
Name: e2e-test-node-pool-4lw4
[ ... lines removed for clarity ...]
Capacity:
cpu: 2
memory: 7679792Ki
pods: 110
Allocatable:
cpu: 1800m
memory: 7474992Ki
pods: 110
[ ... lines removed for clarity ...]
Non-terminated Pods: (5 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
kube-system fluentd-gcp-v1.38-28bv1 100m (5%) 0 (0%) 200Mi (2%) 200Mi (2%)
kube-system kube-dns-3297075139-61lj3 260m (13%) 0 (0%) 100Mi (1%) 170Mi (2%)
kube-system kube-proxy-e2e-test-... 100m (5%) 0 (0%) 0 (0%) 0 (0%)
kube-system monitoring-influxdb-grafana-v4-z1m12 200m (10%) 200m (10%) 600Mi (8%) 600Mi (8%)
kube-system node-problem-detector-v0.1-fj7m3 20m (1%) 200m (10%) 20Mi
(0%) 100Mi (1%)
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
CPU Requests CPU Limits Memory Requests Memory Limits
------------ ---------- --------------- -------------
680m (34%) 400m (20%) 920Mi (11%) 1070Mi (13%)
У виводі ви можете побачити, що якщо Pod запитує більше 1,120 CPU або більше 6,23 ГБ памʼяті, то цей Pod не поміститься на вузлі.
Дивлячись на розділ "Podʼи", ви можете побачити, які Podʼи займають місце на вузлі.
Обсяг ресурсів, доступних для Podʼів, менший за місткість вузла, оскільки системні служби використовують частину доступних ресурсів. У Kubernetes API, кожен вузол має поле .status.allocatable
(див. NodeStatus для деталей).
Поле .status.allocatable
описує обсяг ресурсів, доступних для Podʼів на цьому вузлі (наприклад: 15 віртуальних ЦП та 7538 МіБ памʼяті). Для отримання додаткової інформації про виділені ресурси вузла в Kubernetes дивіться Резервування обчислювальних ресурсів для системних служб.
Ви можете налаштувати квоти ресурсів для обмеження загального обсягу ресурсів, який може споживати простір імен. Kubernetes забезпечує дотримання квот для обʼєктів в конкретному просторі імен, коли існує ResourceQuota в цьому просторі імен. Наприклад, якщо ви призначаєте конкретні простори імен різним командам, ви можете додавати ResourceQuotas в ці простори імен. Встановлення квот ресурсів допомагає запобігти використанню однією командою так багато будь-якого ресурсу, що це впливає на інші команди.
Вам також варто розглянути, який доступ ви надаєте в цьому просторі імен: повний дозвіл на запис у простір імен дозволяє тому, хто має такий доступ, видаляти будь-який ресурс, включаючи налаштований ResourceQuota.
Робота мого контейнера завершується примусово
Робота вашого контейнера може бути завершена через нестачу ресурсів. Щоб перевірити, чи контейнер був завершений через досягнення обмеження ресурсів, викличте kubectl describe pod
для цікавого вас Podʼа:
kubectl describe pod simmemleak-hra99
Вивід буде схожий на:
Name: simmemleak-hra99
Namespace: default
Image(s): saadali/simmemleak
Node: kubernetes-node-tf0f/10.240.216.66
Labels: name=simmemleak
Status: Running
Reason:
Message:
IP: 10.244.2.75
Containers:
simmemleak:
Image: saadali/simmemleak:latest
Limits:
cpu: 100m
memory: 50Mi
State: Running
Started: Tue, 07 Jul 2019 12:54:41 -0700
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
Started: Fri, 07 Jul 2019 12:54:30 -0700
Finished: Fri, 07 Jul 2019 12:54:33 -0700
Ready: False
Restart Count: 5
Conditions:
Type Status
Ready False
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 42s default-scheduler Successfully assigned simmemleak-hra99 to kubernetes-node-tf0f
Normal Pulled 41s kubelet Container image "saadali/simmemleak:latest" already present on machine
Normal Created 41s kubelet Created container simmemleak
Normal Started 40s kubelet Started container simmemleak
Normal Killing 32s kubelet Killing container with id ead3fb35-5cf5-44ed-9ae1-488115be66c6: Need to kill Pod
У прикладі Restart Count: 5
вказує на те, що контейнер simmemleak
у Podʼі був завершений та перезапущений пʼять разів (до цього моменту). Причина OOMKilled
показує, що контейнер намагався використовувати більше памʼяті, ніж встановлений йому ліміт.
Наступним кроком може бути перевірка коду програми на витік памʼяті. Якщо ви встановите, що програма працює так, як очікувалося, розгляньте встановлення вищого ліміту памʼяті (і, можливо, запит) для цього контейнера.
Що далі
- Отримайте практичний досвід призначення ресурсів памʼяті контейнерам та Podʼам.
- Отримайте практичний досвід призначення ресурсів ЦП контейнерам та Podʼам.
- Прочитайте, як API-довідка визначає контейнер та його вимоги до ресурсів
- Прочитайте про квоти ресурсів проєкту в XFS
- Дізнайтеся більше про конфігурацію планувальника kube-scheduler (v1)
- Дізнайтеся більше про класи якості обслуговування для Podʼів
5 - Проби життєздатності, готовності та запуску
Kubernetes має різні типи проб:
Проба життєздатності
Проби життєздатності (Liveness) визначають, коли перезапустити контейнер. Наприклад, проби життєздатності можуть виявити тупик, коли додаток працює, але не може виконувати роботу.
Якщо контейнеру не вдається пройти пробу життєздатності, kubelet перезапускає контейнер.
Проби життєздатності не чекають, поки проби готовності будуть успішними. Якщо ви хочете почекати перед виконанням проби життєздатності, ви можете визначити initialDelaySeconds
або використовувати пробу запуску.
Проба готовності
Проби готовності (Readiness) визначають, коли контейнер готовий приймати трафік. Це корисно, коли потрібно зачекати, поки застосунок виконає тривалі початкові завдання, такі як встановлення мережевих зʼєднань, завантаження файлів та наповнення кешів.
Якщо проба готовності повертає неуспішний стан, Kubernetes видаляє Pod з усіх відповідних точок доступу сервісу.
Проби готовності виконуються в контейнері протягом всього його життєвого циклу.
Проба запуску
Проба запуску (Startup) перевіряє, чи застосунок у контейнері запущено. Це можна використовувати для виконання перевірок життєздатності на повільних контейнерах, уникнення їхнього примусового завершення kubelet до того, як вони будуть запущені.
Якщо така проба налаштована, вона вимикає перевірки життєздатності та готовності, поки вона не буде успішною.
Цей тип проби виконується лише при запуску, на відміну від проб життєздатності та готовності, які виконуються періодично.
- Докладніше про Налаштування проб життєздатності, готовності та запуску.
6 - Організація доступу до кластеру за допомогою файлів kubeconfig
Використовуйте файли kubeconfig для організації інформації про кластери, користувачів, простори імен та механізми автентифікації. kubectl
використовує файли kubeconfig, щоб знайти інформацію, необхідну для вибору кластера та звʼязку з сервером API кластера.
Примітка:
Файл, який використовується для налаштування доступу до кластерів, називається файлом kubeconfig. Це загальний спосіб посилання на файли конфігурації. Це не означає, що існує файл з іменемkubeconfig
.Попередження:
Використовуйте файли kubeconfig лише з надійних джерел. Використання спеціально створеного файлу kubeconfig може призвести до виконання зловмисного коду або розголошення файлів. Якщо вам все ж потрібно використовувати ненадійний файл kubeconfig, уважно перевірте його, так само як ви це зробили б з файлом скрипту оболонки.Типово kubectl
шукає файл з імʼям config
у каталозі $HOME/.kube
. Ви можете вказати інші файли kubeconfig, встановивши змінну середовища KUBECONFIG
або встановивши прапорець --kubeconfig
.
Для покрокових інструкцій щодо створення та вказівки файлів kubeconfig див. Налаштування доступу до кількох кластерів.
Підтримка кількох кластерів, користувачів та механізмів автентифікації
Припустимо, у вас є декілька кластерів, і ваші користувачі та компоненти автентифікуються різними способами. Наприклад:
- Робочий kubelet може автентифікуватися за допомогою сертифікатів.
- Користувач може автентифікуватися за допомогою токенів.
- Адміністратори можуть мати набори сертифікатів, які вони надають окремим користувачам.
За допомогою файлів kubeconfig ви можете організувати ваші кластери, користувачів та простори імен. Ви також можете визначити контексти, щоб швидко та легко перемикатися між кластерами та просторами імен.
Контекст
Елемент context в файлі kubeconfig використовується для групування параметрів доступу під зручною назвою. Кожен контекст має три параметри: кластер, простір імен та користувач. Типово, інструмент командного рядка kubectl
використовує параметри з поточного контексту для звʼязку з кластером.
Щоб обрати поточний контекст:
kubectl config use-context
Змінна середовища KUBECONFIG
Змінна середовища KUBECONFIG
містить список файлів kubeconfig. Для Linux та Mac список розділяється двокрапкою. Для Windows список розділяється крапкою з комою. Змінна середовища KUBECONFIG
не є обовʼязковою. Якщо змінна середовища KUBECONFIG
не існує, kubectl
використовує стандартний файл kubeconfig, $HOME/.kube/config
.
Якщо змінна середовища KUBECONFIG
існує, kubectl
використовує ефективну конфігурацію, яка є результатом обʼєднання файлів, перерахованих у змінній середовища KUBECONFIG
.
Обʼєднання файлів kubeconfig
Щоб переглянути вашу конфігурацію, введіть цю команду:
kubectl config view
Як описано раніше, вихідні дані можуть бути з одного файлу kubeconfig або бути результатом обʼєднання кількох файлів kubeconfig.
Ось правила, які використовує kubectl
під час обʼєднання файлів kubeconfig:
Якщо встановлено прапорець
--kubeconfig
, використовуйте лише вказаний файл. Обʼєднання не здійснюється. Дозволяється лише один екземпляр цього прапорця.У іншому випадку, якщо встановлена змінна середовища
KUBECONFIG
, використовуйте її як список файлів, які потрібно обʼєднати. Обʼєднайте файли, перераховані у змінній середовищаKUBECONFIG
, згідно з наступними правилами:- Ігноруйте порожні імена файлів.
- Виводьте помилки для файлів з вмістом, який не може бути десеріалізований.
- Перший файл, що встановлює певне значення або ключ зіставлення, має перевагу.
- Ніколи не змінюйте значення або ключ зіставлення. Наприклад: Зберігайте контекст першого файлу, який встановлює
current-context
. Наприклад: Якщо два файли вказують наred-user
, використовуйте лише значення зred-user
першого файлу. Навіть якщо другий файл має несумісні записи підred-user
, відкиньте їх.
Для прикладу встановлення змінної середовища
KUBECONFIG
дивіться Встановлення змінної середовища KUBECONFIG.В іншому випадку використовуйте стандартний файл kubeconfig,
$HOME/.kube/config
, без обʼєднання.Визначте контекст, який буде використовуватися на основі першого збігу в цьому ланцюжку:
- Використовуйте прапорець командного рядка
--context
, якщо він існує. - Використовуйте
current-context
з обʼєднаних файлів kubeconfig.
Порожній контекст допускається на цьому етапі.
- Використовуйте прапорець командного рядка
Визначте кластер та користувача. На цьому етапі може бути або не бути контексту. Визначте кластер та користувача на основі першого збігу в цьому ланцюжку, який запускається двічі: один раз для користувача та один раз для кластера:
- Використовуйте прапорці командного рядка, якщо вони існують:
--user
або--cluster
. - Якщо контекст не порожній, беріть користувача або кластер з контексту.
Користувач та кластер можуть бути порожніми на цьому етапі.
- Використовуйте прапорці командного рядка, якщо вони існують:
Визначте фактичну інформацію про кластер, яку слід використовувати. На цьому етапі може бути або не бути інформації про кластер. Побудуйте кожен елемент інформації про кластер на основі цього ланцюжка; перший збіг перемагає:
- Використовуйте прапорці командного рядка, якщо вони існують:
--server
,--certificate-authority
,--insecure-skip-tls-verify
. - Якщо існують будь-які атрибути інформації про кластер з обʼєднаних файлів kubeconfig, використовуйте їх.
- Якщо немає розташування сервера, відмовтеся.
- Використовуйте прапорці командного рядка, якщо вони існують:
Визначте фактичну інформацію про користувача, яку слід використовувати. Побудуйте інформацію про користувача, використовуючи ті ж правила, що і для інформації про кластер, за винятком того, що дозволяється лише одна техніка автентифікації для кожного користувача:
- Використовуйте прапорці командного рядка, якщо вони існують:
--client-certificate
,--client-key
,--username
,--password
,--token
. - Використовуйте поля
user
з обʼєднаних файлів kubeconfig. - Якщо є дві суперечливі техніки, відмовтеся.
- Використовуйте прапорці командного рядка, якщо вони існують:
Для будь-якої інформації, що все ще відсутня, використовуйте стандартні значення і, можливо, запитайте інформацію для автентифікації.
Посилання на файли
Посилання на файли та шляхи в файлі kubeconfig є відносними до місця розташування файлу kubeconfig. Посилання на файли в командному рядку є відносними до поточного робочого каталогу. У файлі $HOME/.kube/config
відносні шляхи зберігаються відносно, абсолютні шляхи зберігаються абсолютно.
Проксі
Ви можете налаштувати kubectl
використовувати проксі для кожного кластера за допомогою proxy-url
у вашому файлі kubeconfig, на зразок такого:
apiVersion: v1
kind: Config
clusters:
- cluster:
proxy-url: http://proxy.example.org:3128
server: https://k8s.example.org/k8s/clusters/c-xxyyzz
name: development
users:
- name: developer
contexts:
- context:
name: development
Що далі
7 - Управління ресурсами для вузлів Windows
Ця сторінка надає огляд різниці у способах управління ресурсами між Linux та Windows.
На Linux-вузлах використовуються cgroups як межа Pod для керування ресурсами. Контейнери створюються в межах цих груп для ізоляції мережі, процесів та файлової системи. API cgroup для Linux може використовуватися для збору статистики використання процесора, введення/виведення та памʼяті.
Натомість, у Windows використовує job object на кожен контейнер з фільтром системного простору імен, щоб обмежити всі процеси в контейнері та забезпечити логічну ізоляцію від хосту. (Обʼєкти завдань є механізмом ізоляції процесів Windows і відрізняються від того, що Kubernetes називає завданням).
Не існує можливості запуску контейнера Windows без фільтрації простору імен. Це означає, що системні привілеї не можуть бути встановлені в контексті хосту, і, отже, привілейовані контейнери не доступні в Windows. Контейнери не можуть припускати ідентичність хосту, оскільки менеджер облікових записів безпеки (Security Account Manager, SAM) є окремим.
Управління памʼяттю
Windows не має спеціального процесу припинення процесів з обмеженням памʼяті, як у Linux. Windows завжди трактує всі виділення памʼяті в режимі користувача як віртуальні, і сторінкові файли є обовʼязковими.
Вузли Windows не перевантажують памʼять для процесів. Основний ефект полягає в тому, що Windows не досягне умов нестачі памʼяті так само як Linux, і процеси будуть перенесені на диск замість виявлення випадків нестачі памʼяті (OOM). Якщо памʼять перевантажена, і всю фізичну памʼять вичерпано, то запис на диск може знизити продуктивність.
Управління CPU
Windows може обмежувати кількість часу CPU, виділену для різних процесів, але не може гарантувати мінімальну кількість часу CPU.
На Windows kubelet підтримує прапорець командного рядка для встановлення пріоритету планування процесу kubelet: --windows-priorityclass
. Цей прапорець дозволяє процесу kubelet отримувати більше часових сегментів процесора порівняно з іншими процесами, які виконуються на хості Windows. Додаткову інформацію про допустимі значення та їх значення можна знайти за посиланням Класи пріоритетів Windows. Щоб переконатися, що запущені Podʼи не голодують kubelet між циклами CPU, встановіть цей прапорець на значення ABOVE_NORMAL_PRIORITY_CLASS
або вище.
Резервування ресурсів
Для обліку памʼяті та процесора, що використовуються операційною системою, контейнерною системою та процесами хосту Kubernetes, можна (і потрібно) резервувати ресурси памʼяті та процесора за допомогою прапорців kubelet --kube-reserved
та/або --system-reserved
. У Windows ці значення використовуються лише для розрахунку доступних ресурсів вузла.
Увага:
При розгортанні навантажень встановлюйте ліміти ресурсів памʼяті та процесора на контейнери. Це також віднімає від NodeAllocatable
та допомагає глобальному планувальнику кластера визначити, які Podʼи розмістити на яких вузлах.
Планування Podʼів без лімітів може перевантажити вузли Windows, і в екстремальних випадках може призвести до того, що вузли стануть несправними.
У Windows доброю практикою є резервування принаймні 2ГБ памʼяті.
Щоб визначити, скільки CPU резервувати, ідентифікуйте максимальну щільність Podʼів для кожного вузла та відстежуйте використання процесора системними службами, що працюють там, а потім виберіть значення, яке відповідає потребам вашої робочого навантаження.