Це багатосторінковий друкований вигляд цього розділу. Натисність щоб друкувати.
Розширення Kubernetes
- 1: Використання власних ресурсів
- 1.1: Розширення API Kubernetes за допомогою CustomResourceDefinitions
- 1.2: Версії у CustomResourceDefinitions
- 2: Налаштування шару агрегації
- 3: Налаштування API сервера розширення
- 4: Налаштування кількох планувальників
- 5: Використання HTTP-проксі для доступу до Kubernetes API
- 6: Використання SOCKS5-проксі для доступу до Kubernetes API
- 7: Налаштування служби Konnectivity
1 - Використання власних ресурсів
1.1 - Розширення API Kubernetes за допомогою CustomResourceDefinitions
Ця сторінка показує, як встановити власний ресурс у API Kubernetes, створивши CustomResourceDefinition.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути не старішою ніж 1.16. Для перевірки версії введітьkubectl version
.
Якщо ви використовуєте старішу версію Kubernetes, яка все ще підтримується, використовуйте документацію для цієї версії, щоб отримати поради, які є відповідними для вашого кластера.Створення CustomResourceDefinition
При створенні нового CustomResourceDefinition (CRD) сервер API Kubernetes створює новий RESTful ресурсний шлях для кожної версії, яку ви вказуєте. Власний ресурс, створений з обʼєкта CRD, може бути або просторово обмеженим за іменем, або обмеженим на рівні кластера, як вказано в полі spec.scope
CRD. Як і з наявними вбудованими обʼєктами, видалення простору імен видаляє всі власні обʼєкти в цьому просторі імен. CustomResourceDefinition самі за собою не мають простору імен і доступні для всіх просторів імен.
Наприклад, якщо ви збережете наступне визначення CustomResourceDefinition у resourcedefinition.yaml
:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# назва повинна відповідати полям специфікації нижче, і мати формат: <plural>.<group>
name: crontabs.stable.example.com
spec:
# назва групи, яка буде використана для REST API: /apis/<group>/<version>
group: stable.example.com
# список версій, підтримуваних цим визначенням власних ресурсів
versions:
- name: v1
# Кожну версію можна ввімкнути/вимкнути за допомогою прапорця Served.
served: true
# Одна і лише одна версія повинна бути позначена як версія зберігання.
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
# або просторово обмежений за іменем, або на рівні кластера
scope: Namespaced
names:
# назва множини, яка буде використана в URL: /apis/<group>/<version>/<plural>
plural: crontabs
# назва однини, яка буде використана як псевдонім у CLI та для показу
singular: crontab
# вид - зазвичай це тип у форматі CamelCased однини. Ваші маніфести ресурсів використовують це.
kind: CronTab
# короткі назви дозволяють мати збіг для скорочених рядків з вашим ресурсом у CLI
shortNames:
- ct
та створите його:
kubectl apply -f resourcedefinition.yaml
Тоді буде створено новий просторово обмежений RESTful API шлях за адресою:
/apis/stable.example.com/v1/namespaces/*/crontabs/...
Цю URL-адресу шляху можна буде використовувати для створення та управління власними обʼєктами. kind
цих обʼєктів буде CronTab
зі специфікації обʼєкта CustomResourceDefinition, який ви створили вище.
Може знадобитися кілька секунд, щоб створити точку доступу. Ви можете спостерігати, що умова Established
вашого CustomResourceDefinition стає true або спостерігати інформацію про відкриття сервера API для вашого ресурсу, щоб він зʼявився.
Створення власних обʼєктів
Після створення обʼєкта CustomResourceDefinition ви можете створювати власні обʼєкти. Власні обʼєкти можуть містити власні поля. Ці поля можуть містити довільний JSON. У наступному прикладі поля cronSpec
та image
встановлені у власний обʼєкт типу CronTab
. Тип CronTab
походить зі специфікації обʼєкта CustomResourceDefinition, який ви створили вище.
Якщо ви збережете наступний YAML у my-crontab.yaml
:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
і створите його:
kubectl apply -f my-crontab.yaml
Потім ви можете управляти вашими обʼєктами CronTab за допомогою kubectl. Наприклад:
kubectl get crontab
Повинен вивести список, подібний до такого:
NAME AGE
my-new-cron-object 6s
Назви ресурсів нечутливі до регістру при використанні kubectl, і ви можете використовувати як однину, так і множину, визначені в CRD, а також будь-які короткі назви.
Ви також можете переглянути дані YAML:
kubectl get ct -o yaml
Ви повинні побачити, що він містить власні поля cronSpec
та image
з YAML, який ви використовували для його створення:
apiVersion: v1
items:
- apiVersion: stable.example.com/v1
kind: CronTab
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"stable.example.com/v1","kind":"CronTab","metadata":{"annotations":{},"name":"my-new-cron-object","namespace":"default"},"spec":{"cronSpec":"* * * * */5","image":"my-awesome-cron-image"}}
creationTimestamp: "2021-06-20T07:35:27Z"
generation: 1
name: my-new-cron-object
namespace: default
resourceVersion: "1326"
uid: 9aab1d66-628e-41bb-a422-57b8b3b1f5a9
spec:
cronSpec: '* * * * */5'
image: my-awesome-cron-image
kind: List
metadata:
resourceVersion: ""
selfLink: ""
Видалення CustomResourceDefinition
Коли ви видаляєте CustomResourceDefinition, сервер деінсталює RESTful API шлях та видаляє всі власні обʼєкти, збережені в ньому.
kubectl delete -f resourcedefinition.yaml
kubectl get crontabs
Error from server (NotFound): Unable to list {"stable.example.com" "v1" "crontabs"}: the server could not
find the requested resource (get crontabs.stable.example.com)
Якщо ви пізніше створите те саме CustomResourceDefinition, воно буде порожнім з початку.
Визначення структурної схеми
CustomResources зберігають структуровані дані у власних полях (разом з вбудованими полями apiVersion
, kind
та metadata
, які сервер API перевіряє неявно). З валідацією OpenAPI v3.0 можна вказати схему, яка перевіряється під час створення та оновлення. Подивіться нижче для деталей та обмежень такої схеми.
З apiextensions.k8s.io/v1
визначення структурної схеми є обовʼязковим для визначення власних ресурсів. У бета-версії CustomResourceDefinition структурна схема була необовʼязковою.
Структурна схема — це схема валідації OpenAPI v3.0, яка:
- вказує непорожній тип (за допомогою
type
в OpenAPI) для кореня, для кожного вказаного поля вузла обʼєкта (за допомогоюproperties
абоadditionalProperties
в OpenAPI) та для кожного елемента вузла масиву (за допомогоюitems
в OpenAPI), за винятком:- вузла з
x-kubernetes-int-or-string: true
- вузла з
x-kubernetes-preserve-unknown-fields: true
- вузла з
- для кожного поля в обʼєкті та кожного елемента в масиві, які вказані всередині будь-якого з
allOf
,anyOf
,oneOf
абоnot
, схема також вказує поле/елемент поза цими логічними виразами (порівняйте приклад 1 та 2). - не встановлює
description
,type
,default
,additionalProperties
,nullable
всерединіallOf
,anyOf
,oneOf
абоnot
, за винятком двох шаблонів дляx-kubernetes-int-or-string: true
(див. нижче). - якщо вказано
metadata
, то дозволяються обмеження тільки наmetadata.name
таmetadata.generateName
.
Неструктурний приклад 1:
allOf:
- properties:
foo:
...
суперечить правилу 2. Наступне було б правильним:
properties:
foo:
...
allOf:
- properties:
foo:
...
Неструктурний приклад 2:
allOf:
- items:
properties:
foo:
...
суперечить правилу 2. Наступне було б правильним:
items:
properties:
foo:
...
allOf:
- items:
properties:
foo:
...
Неструктурний приклад 3:
properties:
foo:
pattern: "abc"
metadata:
type: object
properties:
name:
type: string
pattern: "^a"
finalizers:
type: array
items:
type: string
pattern: "my-finalizer"
anyOf:
- properties:
bar:
type: integer
minimum: 42
required: ["bar"]
description: "foo bar object"
не є структурною схемою через наступні порушення:
- тип у корені відсутній (правило 1).
- тип
foo
відсутній (правило 1). bar
всерединіanyOf
не вказаний зовні (правило 2).- тип
bar
вanyOf
(правило 3). - опис встановлено в
anyOf
(правило 3). metadata.finalizers
можуть бути не обмежені (правило 4).
Натомість наступна відповідна схема є структурною:
type: object
description: "foo bar object"
properties:
foo:
type: string
pattern: "abc"
bar:
type: integer
metadata:
type: object
properties:
name:
type: string
pattern: "^a"
anyOf:
- properties:
bar:
minimum: 42
required: ["bar"]
Порушення правил структурної схеми повідомляються в умові NonStructural
у CustomResourceDefinition.
Обрізка полів
CustomResourceDefinitions зберігають перевірені дані ресурсів у сховищі постійного зберігання кластера, etcd.Так само як і з вбудованими ресурсами Kubernetes, такими як ConfigMap, якщо ви вказуєте поле, яке сервер API не впізнає, невідоме поле обрізається (видаляється) перед зберіганням.
CRD, перетворені з apiextensions.k8s.io/v1beta1
на apiextensions.k8s.io/v1
, можуть бути позбавлені структурних схем, і spec.preserveUnknownFields
може бути встановлено в true
.
Для застарілих обʼєктів власного визначення ресурсів, створених як apiextensions.k8s.io/v1beta1
з spec.preserveUnknownFields
встановленим в true
, також вірно наступне:
- Обрізка не ввімкнена.
- Ви можете зберігати довільні дані.
Для сумісності з apiextensions.k8s.io/v1
оновіть визначення своїх власних
ресурсів:
- Використовуйте структурну схему OpenAPI.
- Встановіть
spec.preserveUnknownFields
вfalse
.
Якщо ви збережете наступний YAML у my-crontab.yaml
:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
someRandomField: 42
і створите його:
kubectl create --validate=false -f my-crontab.yaml -o yaml
Ваш вивід буде подібним до:
apiVersion: stable.example.com/v1
kind: CronTab
metadata:
creationTimestamp: 2017-05-31T12:56:35Z
generation: 1
name: my-new-cron-object
namespace: default
resourceVersion: "285"
uid: 9423255b-4600-11e7-af6a-28d2447dc82b
spec:
cronSpec: '* * * * */5'
image: my-awesome-cron-image
Зверніть увагу, що поле someRandomField
було обрізано.
У цьому прикладі вимкнено перевірку на клієнтському боці, щоб показати поведінку сервера API, додавши параметр командного рядка --validate=false
. Оскільки схеми валідації OpenAPI також публікуються для клієнтів, kubectl
також перевіряє невідомі поля та відхиляє ці обʼєкти задовго до їх надсилання на сервер API.
Контроль обрізки полів
Типово усі невизначені поля власного ресурсу, у всіх версіях, обрізаються. Однак можна відмовитися від цього для певних піддерев полів, додавши x-kubernetes-preserve-unknown-fields: true
у структурну схему валідації OpenAPI v3.
Наприклад:
type: object
properties:
json:
x-kubernetes-preserve-unknown-fields: true
Поле json
може зберігати будь-яке значення JSON, без обрізки.
Ви також можете частково вказати допустимий JSON; наприклад:
type: object
properties:
json:
x-kubernetes-preserve-unknown-fields: true
type: object
description: this is arbitrary JSON
З цим дозволяються тільки значення типу object
.
Обрізка знову ввімкнена для кожного вказаного властивості (або additionalProperties
):
type: object
properties:
json:
x-kubernetes-preserve-unknown-fields: true
type: object
properties:
spec:
type: object
properties:
foo:
type: string
bar:
type: string
З цим значення:
json:
spec:
foo: abc
bar: def
something: x
status:
something: x
обрізається до:
json:
spec:
foo: abc
bar: def
status:
something: x
Це означає, що поле something
у вказаному обʼєкті spec
обрізається, але все поза цим обʼєктом — ні.
IntOrString
Вузли в схемі з x-kubernetes-int-or-string: true
виключаються з правила 1, таким чином наступна схема є структурною:
type: object
properties:
foo:
x-kubernetes-int-or-string: true
Також ці вузли частково виключаються з правила 3 у тому сенсі, що дозволяються наступні два шаблони (саме ці, без варіацій в порядку або додаткових полів):
x-kubernetes-int-or-string: true
anyOf:
- type: integer
- type: string
...
та
x-kubernetes-int-or-string: true
allOf:
- anyOf:
- type: integer
- type: string
- ... # нуль або більше
...
З однією з цих специфікацій, як ціле число, так і рядок будуть валідними.
У розділі Публікація схеми валідації, x-kubernetes-int-or-string: true
розгортається до одного з двох показаних вище шаблонів.
RawExtension
RawExtensions (як у runtime.RawExtension
) містять повні обʼєкти Kubernetes, тобто з полями apiVersion
і kind
.
Можна задати ці вбудовані обʼєкти (як повністю без обмежень, так і частково задані), встановивши x-kubernetes-embedded-resource: true
. Наприклад:
type: object
properties:
foo:
x-kubernetes-embedded-resource: true
x-kubernetes-preserve-unknown-fields: true
Тут поле foo
містить повний обʼєкт, наприклад:
foo:
apiVersion: v1
kind: Pod
spec:
...
Оскільки поруч вказано x-kubernetes-preserve-unknown-fields: true
, нічого не обрізається. Використання x-kubernetes-preserve-unknown-fields: true
є опціональним.
З x-kubernetes-embedded-resource: true
поля apiVersion
, kind
і metadata
неявно задаються та перевіряються на валідність.
Обслуговування декількох версій CRD
Дивіться версіювання визначення власних ресурсів для отримання додаткової інформації про обслуговування декількох версій вашого CustomResourceDefinition і міграцію ваших обʼєктів з однієї версії на іншу.
Розширені теми
Завершувачі
Завершувачі дозволяють контролерам реалізовувати асинхронні гаки перед видаленням. Власні обʼєкти підтримують завершувачі, аналогічні вбудованим обʼєктам.
Ви можете додати завершувач до власного обʼєкта ось так:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
finalizers:
- stable.example.com/finalizer
Ідентифікатори власних завершувачів складаються з імені домену, косої риски та назви завершувача. Будь-який контролер може додати завершувач до списку завершувачів будь-якого обʼєкта.
Перший запит на видалення обʼєкта з завершувачами встановлює значення для поля metadata.deletionTimestamp
, але не видаляє його. Після встановлення цього значення можна лише видаляти записи у списку finalizers
. Поки залишаються будь-які завершувачі, неможливо примусово видалити обʼєкт.
Коли поле metadata.deletionTimestamp
встановлене, контролери, які стежать за обʼєктом, виконують будь-які завершувачі, які вони обробляють, і видаляють завершувач зі списку після завершення. Відповідальність за видалення свого завершувача зі списку лежить на кожному контролері.
Значення поля metadata.deletionGracePeriodSeconds
контролює інтервал між оновленнями опитування.
Після того, як список завершувачів стане порожнім, тобто всі завершувачі будуть виконані, ресурс буде видалено Kubernetes.
Валідація
Власні ресурси перевіряються за допомогою схем OpenAPI v3.0, за допомогою x-kubernetes-validations, коли функція Правил валідації ввімкнена, і ви можете додати додаткову валідацію за допомогою вебхуків допуску.
Крім того, до схеми застосовуються такі обмеження:
Ці поля не можна встановлювати:
definitions
,dependencies
,deprecated
,discriminator
,id
,patternProperties
,readOnly
,writeOnly
,xml
,$ref
.
Поле
uniqueItems
не можна встановлювати вtrue
.Поле
additionalProperties
не можна встановлювати вfalse
.Поле
additionalProperties
є взаємозаперечним ізproperties
.
Розширення x-kubernetes-validations
можна використовувати для перевірки власних ресурсів за допомогою виразів загальної мови виразів (CEL), коли функція правил валідації увімкнена, а схема CustomResourceDefinition є структурною схемою.
Зверніться до розділу структурних схем для інших обмежень та функцій CustomResourceDefinition.
Схема визначається у CustomResourceDefinition. У наведеному нижче прикладі CustomResourceDefinition застосовує такі перевірки до власного обʼєкта:
spec.cronSpec
повинен бути рядком і відповідати формі, описаній регулярним виразом.spec.replicas
повинен бути цілим числом і мати мінімальне значення 1 та максимальне значення 10.
Збережіть CustomResourceDefinition у файл resourcedefinition.yaml
:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
# openAPIV3Schema - це схема для перевірки власних обʼєктів.
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\д+)?(\s+(\d+|\*)(/\д+)?){4}$'
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
і створіть його:
kubectl apply -f resourcedefinition.yaml
Запит на створення власного обʼєкта типу CronTab буде відхилено, якщо поля містять недійсні значення. У наведеному нижче прикладі власний обʼєкт містить поля з недійсними значеннями:
spec.cronSpec
не відповідає регулярному виразу.spec.replicas
більше 10.
Якщо ви збережете наступний YAML у файл my-crontab.yaml
:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * *"
image: my-awesome-cron-image
replicas: 15
і спробуєте створити його:
kubectl apply -f my-crontab.yaml
то отримаєте помилку:
The CronTab "my-new-cron-object" is invalid: []: Invalid value: map[string]interface {}{"apiVersion":"stable.example.com/v1", "kind":"CronTab", "metadata":map[string]interface {}{"name":"my-new-cron-object", "namespace":"default", "deletionTimestamp":interface {}(nil), "deletionGracePeriodSeconds":(*int64)(nil), "creationTimestamp":"2017-09-05T05:20:07Z", "uid":"e14d79e7-91f9-11e7-a598-f0761cb232d1", "clusterName":""}, "spec":map[string]interface {}{"cronSpec":"* * * *", "image":"my-awesome-cron-image", "replicas":15}}:
validation failure list:
spec.cronSpec in body should match '^(\d+|\*)(/\д+)?(\с+(\д+|\*)(/\д+)?){4}$'
spec.replicas in body should be less than or equal to 10
Якщо поля містять дійсні значення, запит на створення обʼєкта буде прийнято.
Збережіть наступний YAML у файл my-crontab.yaml
:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
replicas: 5
І створіть його:
kubectl apply -f my-crontab.yaml
crontab "my-new-cron-object" created
Проковзування валідації
Kubernetes v1.30 [beta]
(стандартно увімкнено: true)Якщо ви використовуєте версію Kubernetes старше v1.30, вам потрібно явно ввімкнути функціональну можливість CRDValidationRatcheting
, щоб використовувати цю поведінку, яка потім застосовується до всіх CustomResourceDefinitions у вашому кластері.
За умови увімкнення функціональної можливості, Kubernetes реалізує проковзування валідації для CustomResourceDefinitions. API сервер готовий прийняти оновлення ресурсів, які є недійсними після оновлення, за умови, що кожна частина ресурсу, яка не пройшла валідацію, не була змінена операцією оновлення. Іншими словами, будь-яка недійсна частина ресурсу, яка залишається недійсною, вже повинна була бути неправильною. Ви не можете використовувати цей механізм для оновлення дійсного ресурсу, щоб він став недійсним.
Ця функція дозволяє авторам CRD впевнено додавати нові перевірки до схеми OpenAPIV3 за певних умов. Користувачі можуть безпечно оновлюватися до нової схеми без зміни версії обʼєкта або порушення робочих процесів.
Хоча більшість перевірок, розміщених у схемі OpenAPIV3 CRD, підтримують обмеження, є кілька винятків. Наступні перевірки схеми OpenAPIV3 не підтримуються обмеженнями у реалізації в Kubernetes 1.31 і якщо порушені, продовжуватимуть видавати помилку як зазвичай:
Квантори
allOf
oneOf
anyOf
not
- будь-які перевірки в нащадках одного з цих полів
x-kubernetes-validations
Для Kubernetes 1.28, правила валідації CRD ігноруються обмеженнями. Починаючи з Alpha 2 у Kubernetes 1.29,x-kubernetes-validations
обмежуються лише, якщо вони не посилаються наoldSelf
.Перехідні правила ніколи не обмежуються: лише помилки, які виникають через правила, які не використовують
oldSelf
, автоматично обмежуються, якщо їх значення не змінені.Щоб написати власну логіку обмеження для виразів CEL, перегляньте optionalOldSelf.
x-kubernetes-list-type
Помилки, що виникають через зміну типу списку у підсхемі, не будуть обмежені. Наприклад, додаванняset
до списку з дублікатів завжди призведе до помилки.x-kubernetes-map-keys
Помилки, що виникають через зміну ключів карти у схемі списку, не будуть обмежені.required
Помилки, що виникають через зміну списку обовʼязкових полів, не будуть обмежені.properties
Додавання/видалення/модифікація імен властивостей не обмежуються, але зміни до перевірок у схемах та підсхемах властивостей можуть бути обмежені, якщо імʼя властивості залишається незмінним.additionalProperties
Видалення раніше вказаної валідаціїadditionalProperties
не буде обмежено.metadata
Помилки, що виникають через вбудовану валідацію обʼєктаmetadata
у Kubernetes, не будуть обмежені (наприклад, імʼя обʼєкта або символи у значенні мітки). Якщо ви вказуєте свої власні додаткові правила для метаданих власного ресурсу, ця додаткова валідація буде обмежена.
Правила валідації
Kubernetes v1.29 [stable]
Правила валідації використовують Common Expression Language (CEL) для валідації значень власних ресурсів. Правила валідації включаються в схеми CustomResourceDefinition за допомогою розширення x-kubernetes-validations
.
Правило обмежується місцем знаходження розширення x-kubernetes-validations
у схемі. Змінна self
у виразі CEL привʼязана до значення, що перевіряється.
Всі правила валідації обмежені поточним обʼєктом: ніякі міжобʼєктні або stateful правила валідації не підтримуються.
Наприклад:
...
openAPIV3Schema:
type: object
properties:
spec:
type: object
x-kubernetes-validations:
- rule: "self.minReplicas <= self.replicas"
message: "replicas should be greater than or equal to minReplicas."
- rule: "self.replicas <= self.maxReplicas"
message: "replicas should be smaller than or equal to maxReplicas."
properties:
...
minReplicas:
type: integer
replicas:
type: integer
maxReplicas:
type: integer
required:
- minReplicas
- replicas
- maxReplicas
відхилить запит на створення цього власного ресурсу:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
minReplicas: 0
replicas: 20
maxReplicas: 10
з відповіддю:
The CronTab "my-new-cron-object" is invalid:
* spec: Invalid value: map[string]interface {}{"maxReplicas":10, "minReplicas":0, "replicas":20}: replicas should be smaller than or equal to maxReplicas.
x-kubernetes-validations
може містити декілька правил. rule
під x-kubernetes-validations
представляє вираз, який буде оцінюватися CEL. message
представляє повідомлення, що показується при невдачі валідації. Якщо повідомлення не встановлено, відповідь буде такою:
The CronTab "my-new-cron-object" is invalid:
* spec: Invalid value: map[string]interface {}{"maxReplicas":10, "minReplicas":0, "replicas":20}: failed rule: self.replicas <= self.maxReplicas
Примітка:
Ви можете швидко перевірити вирази CEL на CEL Playground.Правила валідації компілюються при створенні/оновленні CRD. Запит на створення/оновлення CRD буде відхилено, якщо компіляція правил валідації зазнає невдачі. Процес компіляції включає перевірку типів.
Помилки компіляції:
no_matching_overload
: ця функція не має перевантаження для типів аргументів.Наприклад, правило
self == true
для поля типу integer призведе до помилки:Invalid value: apiextensions.ValidationRule{Rule:"self == true", Message:""}: compilation failed: ERROR: \<input>:1:6: found no matching overload for '_==_' applied to '(int, bool)'
no_such_field
: не містить бажаного поля.Наприклад, правило
self.nonExistingField > 0
для неіснуючого поля поверне наступну помилку:Invalid value: apiextensions.ValidationRule{Rule:"self.nonExistingField > 0", Message:""}: compilation failed: ERROR: \<input>:1:5: undefined field 'nonExistingField'
invalid argument
: недійсний аргумент для макросів.Наприклад, правило
has(self)
поверне помилку:Invalid value: apiextensions.ValidationRule{Rule:"has(self)", Message:""}: compilation failed: ERROR: <input>:1:4: invalid argument to has() macro
Приклади правил валідації:
Правило | Призначення |
---|---|
self.minReplicas <= self.replicas && self.replicas <= self.maxReplicas | Перевірка, що три поля, які визначають репліки, впорядковані належним чином |
'Available' in self.stateCounts | Перевірка наявності запису з ключем 'Available' у map |
(size(self.list1) == 0) != (size(self.list2) == 0) | Перевірка, що один з двох списків не порожній, але не обидва |
!('MY_KEY' in self.map1) || self['MY_KEY'].matches('^[a-zA-Z]*$') | Перевірка значення map для конкретного ключа, якщо він у мапі |
self.envars.filter(e, e.name == 'MY_ENV').all(e, e.value.matches('^[a-zA-Z]*$') | Перевірка поля 'value' у списку map, де ключове поле 'name' дорівнює 'MY_ENV' |
has(self.expired) && self.created + self.ttl < self.expired | Перевірка, що дата 'expired' після дати 'create' плюс тривалість 'ttl' |
self.health.startsWith('ok') | Перевірка, що рядкове поле 'health' починається з префіксу 'ok' |
self.widgets.exists(w, w.key == 'x' && w.foo < 10) | Перевірка, що властивість 'foo' елемента списку map з ключем 'x' менше 10 |
type(self) == string ? self == '100%' : self == 1000 | Перевірка поля int-or-string для обох випадків int і string |
self.metadata.name.startsWith(self.prefix) | Перевірка, що імʼя обʼєкта має префікс іншого поля значення |
self.set1.all(e, !(e in self.set2)) | Перевірка, що два списки множин не перетинаються |
size(self.names) == size(self.details) && self.names.all(n, n in self.details) | Перевірка, що мапа 'details' має ключі з елементів списку множин 'names' |
size(self.clusters.filter(c, c.name == self.primary)) == 1 | Перевірка, що властивість 'primary' має лише одну появу у списку мап 'clusters' |
Посилання: Supported evaluation on CEL
Якщо правило обмежене коренем ресурсу, воно може вибирати поля з будь-яких полів, оголошених у схемі OpenAPIv3 CRD, а також
apiVersion
,kind
,metadata.name
таmetadata.generateName
. Це включає вибір полів як уspec
, так і вstatus
в одному виразі:... openAPIV3Schema: type: object x-kubernetes-validations: - rule: "self.status.availableReplicas >= self.spec.minReplicas" properties: spec: type: object properties: minReplicas: type: integer ... status: type: object properties: availableReplicas: type: integer
Якщо Rule обмежене обʼєктом з властивостями, доступні властивості обʼєкта можна вибирати за допомогою
self.field
, а наявність поля можна перевірити за допомогоюhas(self.field)
. Поля зі значенням null трактуються як відсутні поля у виразах CEL.... openAPIV3Schema: type: object properties: spec: type: object x-kubernetes-validations: - rule: "has(self.foo)" properties: ... foo: type: integer
Якщо Rule обмежене обʼєктом з додатковими властивостями (тобто map), значення map доступні через
self[mapKey]
, наявність map можна перевірити за допомогоюmapKey in self
, а всі записи з map доступні за допомогою макросів і функцій CEL, таких якself.all(...)
.... openAPIV3Schema: type: object properties: spec: type: object x-kubernetes-validations: - rule: "self['xyz'].foo > 0" additionalProperties: ... type: object properties: foo: type: integer
Якщо правило обмежене масивом, елементи масиву доступні через
self[i]
та також за допомогою макросів і функцій.... openAPIV3Schema: type: object properties: ... foo: type: array x-kubernetes-validations: - rule: "size(self) == 1" items: type: string
Якщо правило обмежене скаляром,
self
привʼязується до значення скаляра.... openAPIV3Schema: type: object properties: spec: type: object properties: ... foo: type: integer x-kubernetes-validations: - rule: "self > 0"
Приклади:
тип поля, для якого обмежено правило | Приклад правила |
---|---|
кореневий обʼєкт | self.status.actual <= self.spec.maxDesired |
map обʼєктів | self.components['Widget'].priority < 10 |
список цілих чисел | self.values.all(value, value >= 0 && value < 100) |
рядок | self.startsWith('kube') |
apiVersion
, kind
, metadata.name
та metadata.generateName
завжди доступні з кореня обʼєкта та з будь-яких обʼєктів з анотацією x-kubernetes-embedded-resource
. Інші властивості метаданих недоступні.
Невідомі дані, збережені у власниї ресурсах за допомогою x-kubernetes-preserve-unknown-fields
, не доступні у виразах CEL. Це включає:
Невідомі значення полів, які зберігаються у схемах обʼєктів з
x-kubernetes-preserve-unknown-fields
.Властивості обʼєктів, де схема властивостей має "unknown type". "Unknown type" визначається рекурсивно як:
- Схема без типу і з встановленим
x-kubernetes-preserve-unknown-fields
- Масив, де схема елементів має "unknown type"
- Обʼєкт, де схема additionalProperties має "unknown type"
- Схема без типу і з встановленим
Доступні лише назви властивостей форми [a-zA-Z_.-/][a-zA-Z0-9_.-/]*
. Доступні назви властивостей екрануються за наступними правилами при доступі у виразі:
послідовність екранування | еквівалент назви властивості |
---|---|
__underscores__ | __ |
__dot__ | . |
__dash__ | - |
__slash__ | / |
__{keyword}__ | CEL RESERVED keyword |
Примітка: зарезервоване ключове слово CEL повинно точно збігатися з назвою властивості, щоб бути екранованим (наприклад, int у слові sprint не буде екрановано).
Приклади екранування:
назва властивості | правило з екранованою назвою властивості |
---|---|
namespace | self.__namespace__ > 0 |
x-prop | self.x__dash__prop > 0 |
redact__d | self.redact__underscores__d > 0 |
string | self.startsWith('kube') |
Рівність масивів з x-kubernetes-list-type
типу set
або map
ігнорує порядок елементів, тобто [1, 2] == [2, 1]
. Конкатенація масивів з x-kubernetes-list-type використовує семантику
типу списку:
set
:X + Y
виконує обʼєднання, де зберігаються позиції елементів уX
, а непересічні елементи уY
додаються, зберігаючи їх частковий порядок.map
:X + Y
виконує злиття, де зберігаються позиції всіх ключів уX
, але значення перезаписуються значеннями уY
, коли ключіX
таY
перетинаються. Елементи уY
з непересічними ключами додаються, зберігаючи їх частковий порядок.
Ось відповідність типів між OpenAPIv3 та CEL:
Тип OpenAPIv3 | Тип CEL |
---|---|
'object' з Properties | object / "message type" |
'object' з AdditionalProperties | map |
'object' з x-kubernetes-embedded-type | object / "message type", 'apiVersion', 'kind', 'metadata.name' та 'metadata.generateName' неявно включені у схему |
'object' з x-kubernetes-preserve-unknown-fields | object / "message type", невідомі поля НЕ доступні у виразі CEL |
x-kubernetes-int-or-string | динамічний обʼєкт, який може бути або int, або string, type(value) можна використовувати для перевірки типу |
'array | list |
'array' з x-kubernetes-list-type=map | list з порівнянням на основі map та гарантіями унікальності ключів |
'array' з x-kubernetes-list-type=set | list з порівнянням на основі множини та гарантіями унікальності елементів |
'boolean' | boolean |
'number' (всі формати) | double |
'integer' (всі формати) | int (64) |
'null' | null_type |
'string' | string |
'string' з format=byte (base64 encoded) | bytes |
'string' з format=date | timestamp (google.protobuf.Timestamp) |
'string' з format=datetime | timestamp (google.protobuf.Timestamp) |
'string' з format=duration | duration (google.protobuf.Duration) |
посилання: CEL types, OpenAPI types, Структурні схемм Kubernetes.
Поле messageExpression
Поле messageExpression
, аналогічно до поля message
, визначає рядок, яким буде повідомлено про негативний результат правила валідації. Однак messageExpression
дозволяє використовувати вираз CEL для побудови повідомлення, що дозволяє вставляти більш описову інформацію в повідомлення про невдачу валідації. messageExpression
має оцінюватися як рядок і може використовувати ті ж змінні, що і поле rule
. Наприклад:
x-kubernetes-validations:
- rule: "self.x <= self.maxLimit"
messageExpression: '"x перевищує максимальний ліміт " + string(self.maxLimit)'
Майте на увазі, що конкатенація рядків CEL (оператор +
) автоматично не призводить до перетворення в рядок. Якщо у вас є скаляр, який не є рядком, використовуйте функцію string(<значення>)
для перетворення скаляра в рядок, як показано в прикладі вище.
messageExpression
повинен оцінюватися як рядок, і це перевіряється при створенні CRD. Зауважте, що можна встановити як message
, так і messageExpression
для одного правила, і якщо обидва присутні, буде використовуватися messageExpression
. Однак, якщо messageExpression
оцінюється як помилка, буде використовуватися рядок, визначений у message
, і помилка messageExpression
буде зафіксована. Це повернення до попереднього стану також відбудеться, якщо вираз CEL, визначений у messageExpression
, генерує порожній рядок або рядок, що містить розриви рядків.
Якщо одна з вищезазначених умов виконується і message
не було встановлено, то буде використовуватися стандартне повідомлення про негативний результат валідації.
messageExpression
є виразом CEL, тому обмеження, зазначені в розділі Використання ресурсів функціями валідації, застосовуються. Якщо оцінка зупиняється через обмеження ресурсів під час виконання messageExpression
, жодні подальші правила валідації не будуть виконуватися.
Встановлення messageExpression
є необовʼязковим.
Поле message
Якщо ви хочете встановити статичне повідомлення, ви можете передати message
замість messageExpression
. Значення message
використовується як непрозорий рядок помилки, якщо перевірка не пройшла успішно.
Встановлення message
є необовʼязковим.
Поле reason
Ви можете додати машинно-читаєму причину негативного результату перевірки в межах validation
, щоб повертати її, коли запит не відповідає цьому правилу перевірки.
Наприклад:
x-kubernetes-validations:
- rule: "self.x <= self.maxLimit"
reason: "FieldValueInvalid"
Код стану HTTP, повернутий абоненту, буде відповідати причині першої невдачі перевірки. Наразі підтримуються такі причини: "FieldValueInvalid", "FieldValueForbidden", "FieldValueRequired", "FieldValueDuplicate". Якщо причини не встановлені або невідомі, типово використовується "FieldValueInvalid".
Встановлення reason
є необовʼязковим.
Поле fieldPath
Ви можете вказати шлях поля, який повертається, коли перевірка завершується негативним результатом.
Наприклад:
x-kubernetes-validations:
- rule: "self.foo.test.x <= self.maxLimit"
fieldPath: ".foo.test.x"
У вищенаведеному прикладі перевіряється значення поля x
, яке повинно бути менше значення maxLimit
. Якщо не вказано fieldPath
, коли результат перевірки негативний , fieldPath
буде типово відповідати місцю розташування self
. З вказаним fieldPath
повернена помилка буде мати fieldPath
, який належним чином посилатиметься на місце поля x
.
Значення fieldPath
повинно бути відносним шляхом JSON, що обмежений місцем цього розширення x-kubernetes-validations у схемі. Крім того, воно повинно посилатися на існуюче поле в межах схеми. Наприклад, коли перевірка перевіряє, чи є певний атрибут foo
у map testMap
, ви можете встановити fieldPath
на ".testMap.foo"
або .testMap['foo']'
. Якщо для перевірки потрібно перевірити унікальні атрибути у двох списках, fieldPath
можна встановити для будь-якого зі списків. Наприклад, його можна встановити на .testList1
або .testList2
. Наразі підтримується дочірня операція для посилання на існуюче поле. Для отримання додаткової інформації див. Підтримка JSONPath у Kubernetes. Поле fieldPath
не підтримує індексування масивів числовими значеннями.
Встановлення fieldPath
є необовʼязковим.
Поле optionalOldSelf
Kubernetes v1.30 [beta]
(стандартно увімкнено: true)Якщо у вашому кластері не включено проковзування перевірки CRD, API визначення власного ресурсу не містить цього поля, і спроба встановити його може призвести до помилки.
Поле optionalOldSelf
є булевим полем, яке змінює поведінку Правил переходу, описаних нижче. Зазвичай правило переходу не оцінюється, якщо oldSelf
не може бути визначено: під час створення обʼєкта або коли нове значення вводиться під час оновлення.
Якщо optionalOldSelf
встановлено в true, тоді правила переходу завжди будуть оцінюватися, і тип oldSelf
буде змінено на тип CEL Optional
.
optionalOldSelf
корисно в тих випадках, коли автори схеми хочуть мати більше інструментів керування ніж надається за стандартно на основі рівності, щоб ввести нові, зазвичай строгіші обмеження на нові значення, зазвичай більш жорсткі для нових значень, але все ще дозволяючи те, що старі значення можуть бути пропущені з використанням старих правил.
Example Usage:
CEL | Опис |
---|---|
self.foo == "foo" || (oldSelf.hasValue() && oldSelf.value().foo != "foo") | Проковзування правила. Якщо значення має значення «foo», воно повинно залишатися foo. Але якщо воно існувало до того, як було введено обмеження «foo», воно може використовувати будь-яке значення |
[oldSelf.orValue(""), self].all(x, ["OldCase1", "OldCase2"].exists(case, x == case)) || ["NewCase1", "NewCase2"].exists(case, self == case) || ["NewCase"].has(self) | "Перевірка для вилучених випадків перерахування, якщо oldSelf використовував їх" |
oldSelf.optMap(o, o.size()).orValue(0) < 4 || self.size() >= 4 | Перевірка нещодавно збільшеного мінімального розміру map або списку з проковзуванням |
Функції перевірки
Доступні функції включають:
- Стандартні функції CEL, визначені у списку стандартних визначень
- Стандартні макроси CEL
- Розширена бібліотека функцій рядків CEL (extended string function library)
- Розширена бібліотека функцій CEL для Kubernetes (CEL extension library)
Правила переходу
Правило, яке містить вираз з посиланням на ідентифікатор oldSelf
, неявно вважається правилом переходу. Правила переходу дозволяють авторам схеми запобігати певним переходам між двома в іншому випадку допустимими станами. Наприклад:
type: string
enum: ["low", "medium", "high"]
x-kubernetes-validations:
- rule: "!(self == 'high' && oldSelf == 'low') && !(self == 'low' && oldSelf == 'high')"
message: не можна переходити безпосередньо між 'low' та 'high'
На відміну від інших правил, правила переходу застосовуються тільки до операцій, що відповідають наступним критеріям:
Операція оновлює існуючий обʼєкт. Правила переходу ніколи не застосовуються до операцій створення.
Існують як старе, так і нове значення. Залишається можливим перевірити, чи було додано або вилучено значення, розмістивши правило переходу на батьківському вузлі. Правила переходу ніколи не застосовуються до створення власних ресурсів. Якщо вони розміщені в необовʼязковому полі, правило переходу не буде застосовуватися до операцій оновлення, які встановлюють або прибирають поле.
Шлях до вузла схеми, який перевіряється правилом переходу, повинен розподілятися на вузол, який може порівнюватися між старим обʼєктом і новим обʼєктом. Наприклад, елементи списку та їх нащадки (
spec.foo[10].bar
) не обовʼязково будуть кореліювати між існуючим обʼєктом та пізнішим оновленням того ж обʼєкта.
Помилки будуть генеруватися при записі CRD, якщо вузол схеми містить правило переходу, яке ніколи не може бути застосоване, наприклад "oldSelf не може бути використано на некорельованій частині схеми у межах path".
Правила переходу дозволені тільки для корелятивних частин схеми. Частина схеми є корелятивною, якщо всі батьківські схеми масиву мають тип x-kubernetes-list-type=map
; будь-які батьківські схеми масиву типу set
чи atomic
роблять неможливим однозначне корелювання між self
та oldSelf
.
Нижче наведено кілька прикладів правил переходу:
Використання | Правило |
---|---|
Незмінність | self.foo == oldSelf.foo |
Запобігання модифікації/видаленню після присвоєння | oldSelf != 'bar' || self == 'bar' або !has(oldSelf.field) || has(self.field) |
Тільки додавання до множини | self.all(element, element in oldSelf) |
Якщо попереднє значення було X, нове значення може бути лише A або B, не Y або Z | oldSelf != 'X' || self in ['A', 'B'] |
Монотонні (незменшувані) лічільники | self >= oldSelf |
Використання ресурсів функціями перевірки
Коли ви створюєте або оновлюєте CustomResourceDefinition, що використовує правила перевірки, API сервер перевіряє можливий вплив виконання цих правил перевірки. Якщо правило оцінюється як надмірно витратне у виконанні, API сервер відхиляє операцію створення або оновлення та повертає повідомлення про помилку. Подібна система використовується під час виконання, яка спостерігає за діями інтерпретатора. Якщо інтерпретатор виконує занадто багато інструкцій, виконання правила буде припинено, і виникне помилка. Кожен CustomResourceDefinition також має певний ліміт ресурсів для завершення виконання всіх своїх правил перевірки. Якщо сумарна оцінка всіх правил перевищує цей ліміт під час створення, то також виникне помилка перевірки.
Ймовірність виникнення проблем з ресурсним бюджетом перевірки низька, якщо ви лише зазначаєте правила, які завжди займають однакову кількість часу незалежно від розміру вхідних даних. Наприклад, правило, яке стверджує, що self.foo == 1
, само по собі не має ризику відхилення через ресурсний бюджет перевірки. Але якщо foo
є рядком і ви визначаєте правило перевірки self.foo.contains("someString")
, то це правило займає довше часу на виконання в залежності від довжини foo
. Інший приклад: якщо foo
є масивом, і ви вказали правило перевірки self.foo.all(x, x > 5)
. Система оцінки завжди припускає найгірший сценарій, якщо не вказано ліміт на довжину foo
, і це буде стосуватися будь-якого обʼєкта, який можна ітерувати (списки, мапи тощо).
Через це, вважається найкращою практикою встановлювати ліміт через maxItems
, maxProperties
і maxLength
для будь-якого обʼєкта, який обробляється в правилі перевірки, щоб уникнути помилок перевірки під час оцінки витрат. Наприклад, якщо є наступна схема з одним правилом:
openAPIV3Schema:
type: object
properties:
foo:
type: array
items:
type: string
x-kubernetes-validations:
- rule: "self.all(x, x.contains('a string'))"
то API сервер відхилить це правило через бюджет перевірки з помилкою:
spec.validation.openAPIV3Schema.properties[spec].properties[foo].x-kubernetes-validations[0].rule: Forbidden:
CEL rule exceeded budget by more than 100x (try simplifying the rule, or adding maxItems, maxProperties, and
maxLength where arrays, maps, and strings are used)
Відхилення відбувається тому, що self.all
передбачає виклик contains()
для кожного рядка у foo
, що в свою чергу перевіряє, чи містить даний рядок 'a string'
. Без обмежень, це дуже витратне правило.
Якщо ви не вказуєте жодного ліміту перевірки, оцінена вартість цього правила перевищить ліміт вартості для одного правила. Але якщо додати обмеження в потрібні місця, правило буде дозволено:
openAPIV3Schema:
type: object
properties:
foo:
type: array
maxItems: 25
items:
type: string
maxLength: 10
x-kubernetes-validations:
- rule: "self.all(x, x.contains('a string'))"
Система оцінки витрат враховує кількість разів, коли правило буде виконане, крім оціненої вартості самого правила. Наприклад, наступне правило матиме таку ж оцінену вартість, як і попередній приклад (незважаючи на те, що правило тепер визначено для окремих елементів масиву):
openAPIV3Schema:
type: object
properties:
foo:
type: array
maxItems: 25
items:
type: string
x-kubernetes-validations:
- rule: "self.contains('a string'))"
maxLength: 10
Якщо у списку всередині іншого списку є правило перевірки, яке використовує self.all
, це значно дорожче, ніж правило для не вкладеного списку. Правило, яке було б дозволено для не вкладеного списку, може потребувати нижчих обмежень для обох вкладених списків, щоб бути дозволеним. Наприклад, навіть без встановлення обмежень, наступне правило дозволено:
openAPIV3Schema:
type: object
properties:
foo:
type: array
items:
type: integer
x-kubernetes-validations:
- rule: "self.all(x, x == 5)"
Але те саме правило для наступної схеми (з доданим вкладеним масивом) викликає помилку перевірки:
openAPIV3Schema:
type: object
properties:
foo:
type: array
items:
type: array
items:
type: integer
x-kubernetes-validations:
- rule: "self.all(x, x == 5)"
Це тому, що кожен елемент foo
сам є масивом, і кожен підмасив викликає self.all
. Уникайте вкладених списків і map, якщо це можливо, де використовуються правила перевірки.
Встановлення станадартних значень
Примітка:
Щоб використовувати встановлення стандартних значень, ваш CustomResourceDefinition повинен використовувати версію APIapiextensions.k8s.io/v1
.Встановлення стандартних значень дозволяє вказати такі значення у схемі перевірки OpenAPI v3:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
# openAPIV3Schema це схема для перевірки власних обʼєктів.
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\д+)?){4}$'
default: "5 0 * * *"
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
default: 1
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
Таким чином, і cronSpec
, і replicas
будуть мати стандартні значення:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
image: my-awesome-cron-image
приводить до
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "5 0 * * *"
image: my-awesome-cron-image
replicas: 1
Встановлення стандартних значень відбувається на обʼєкті
- в запиті до API сервера з використанням стандартних значень версії запиту,
- під час читання з etcd з використанням стандартних значень версії зберігання,
- після втулків для мутаційного допуску з невипадковими змінами з використанням стандартних значень версії веб-хука допуску.
Стандартне значення, застосовані під час читання даних з etcd, автоматично не записуються назад у etcd. Потрібен запит на оновлення через API для збереження цих стандартних значень у etcd.
Стандартні значення мають бути обрізані (за винятком стандартних значень полів metadata
) та відповідати схемі перевірки.
Стандартні значення полів metadata
вузлів x-kubernetes-embedded-resources: true
(або частин типових значень з metadata
) не будуть обрізані під час створення CustomResourceDefinition, але будуть обрізані під час оброки запитів.
Стандартні значення та nullable
Значення null
для полів, які або не вказують прапорець nullable
, або задають його значення як false
, будуть видалені до того, як буде застосовано стандартне значення. Якщо стандартне значення присутнє, воно буде застосоване. Коли nullable
дорівнює true
, значення null
будуть збережені і не будуть змінені на стандартні значення.
Наприклад, розглянемо наступну схему OpenAPI:
type: object
properties:
spec:
type: object
properties:
foo:
type: string
nullable: false
default: "default"
bar:
type: string
nullable: true
baz:
type: string
створення обʼєкта зі значеннями null
для foo
, bar
і baz
:
spec:
foo: null
bar: null
baz: null
призведе до
spec:
foo: "default"
bar: null
де foo
буде обрізане та встановлене стандартне значення, оскільки поле є ненульовим, bar
залишиться зі значенням null
через nullable: true
, а baz
буде видалено, оскільки поле є ненульовим і не має стандартного значення.
Публікація схеми валідації в OpenAPI
Схеми валідації OpenAPI v3 CustomResourceDefinition, які є структурованими та дозволяють обрізку, публікуються як OpenAPI v3 та OpenAPI v2 з сервера API Kubernetes. Рекомендується використовувати документ OpenAPI v3, оскільки він є представленням схеми валідації OpenAPI v3 для CustomResourceDefinition без втрат, тоді як OpenAPI v2 представляє перетворення з втратами.
Kubectl використовує опубліковану схему для виконання клієнтської валідації (kubectl create
та kubectl apply
), пояснення схеми (kubectl explain
) для власних ресурсів. Опублікована схема також може бути використана для інших цілей, таких як генерація клієнтів або документації.
Сумісність з OpenAPI V2
Для сумісності з OpenAPI V2, схема валідації OpenAPI v3 виконує перетворення з втратамиу схему OpenAPI v2. Схема зʼявляється в полях definitions
та paths
у специфікації OpenAPI v2.
Під час перетворення застосовуються наступні зміни для збереження зворотної сумісності з kubectl версії 1.13. Ці зміни запобігають занадто строгій роботі kubectl та відхиленню дійсних схем OpenAPI, які він не розуміє. Перетворення не змінює схему валідації, визначену в CRD, і тому не впливає на валідацію на сервері API.
Наступні поля видаляються, оскільки вони не підтримуються OpenAPI v2:
- Поля
allOf
,anyOf
,oneOf
таnot
видаляються
- Поля
Якщо встановлено
nullable: true
, ми видаляємоtype
,nullable
,items
таproperties
, оскільки OpenAPI v2 не може відобразити nullable. Це необхідно для того, щоб kubectl не відхиляв правильні обʼєкти.
Додаткові колонки виводу
Інструмент kubectl покладається на форматування виводу на стороні сервера. Сервер API вашого кластера вирішує, які колонки показуються командою kubectl get
. Ви можете налаштувати ці колонки для CustomResourceDefinition. Наступний приклад додає колонки Spec
, Replicas
та Age
.
Збережіть CustomResourceDefinition у файл resourcedefinition.yaml
:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
additionalPrinterColumns:
- name: Spec
type: string
description: The cron spec defining the interval a CronJob is run
jsonPath: .spec.cronSpec
- name: Replicas
type: integer
description: The number of jobs launched by the CronJob
jsonPath: .spec.replicas
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
Створіть CustomResourceDefinition:
kubectl apply -f resourcedefinition.yaml
Створіть екземпляр, використовуючи my-crontab.yaml
з попереднього розділу.
Викличте вивід на стороні сервера:
kubectl get crontab my-new-cron-object
Зверніть увагу на колонки NAME
, SPEC
, REPLICAS
та AGE
у виводі:
NAME SPEC REPLICAS AGE
my-new-cron-object * * * * * 1 7s
Примітка:
КолонкаNAME
є неявною і не потребує визначення в CustomResourceDefinition.Пріоритет
Кожна колонка включає поле priority
. Наразі пріоритет розрізняє стовпці, що показуються у стандартному вигляді або в розгорнутому (за допомогою прапорця -o wide
).
- Колонки з пріоритетом
0
показані у стандартному вигляді. - Колонки з пріоритетом більшим за
0
показані тільки у широкому (wide) вигляді.
Тип
Поле type
колонки може бути одним з наступних (порівняйте OpenAPI v3 data types):
integer
— цілі числа без плаваючої точкиnumber
— числа з плаваючою точкоюstring
— строкиboolean
—true
абоfalse
date
— виводиться диференційовано як час, що минув від цієї мітки.
Якщо значення всередині CustomResource не відповідає типу, зазначеному для колонки, значення буде пропущено. Використовуйте валідацію CustomResource, щоб переконатися, що типи значень правильні.
Формат
Поле format
колонки може бути одним з наступних:
int32
int64
float
double
byte
date
date-time
password
Поле format
колонки контролює стиль, який використовується при виводі значення за допомогою kubectl
.
Селектори полів
Селектори полів дозволяють клієнтам вибирати власні ресурси на основі значення одного або декількох полів ресурсу.
Усі власні ресурси підтримують вибір полів metadata.name
та metadata.namespace
.
Поля, оголошені в CustomResourceDefinition, також можуть бути використані з селектором полів, коли вони включені в поле spec.versions[*].selectableFields
CustomResourceDefinition.
Поля селекторів власних ресурсів
Kubernetes v1.31 [beta]
(стандартно увімкнено: true)Для Kubernetes 1.31 можливість визначати селектори полів для власних ресурсів доступна стандартно (стандартно увімкнена з Kubernetes v1.31); ви можете вимкнути цю функцію для вашого кластера, відключивши функціональну можливість CustomResourceFieldSelectors
. Поле spec.versions[*].selectableFields
у CustomResourceDefinition може бути використане для оголошення, які інші поля у власному ресурсі можуть бути використані у селекторах полів з функціональною можливісюь CustomResourceFieldSelectors
(Ця функція є стандартно увімкненою з Kubernetes v1.31). Ось приклад, який додає поля .spec.color
та .spec.size
як доступні для вибору.
Збережіть CustomResourceDefinition у файл shirt-resource-definition.yaml
:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: shirts.stable.example.com
spec:
group: stable.example.com
scope: Namespaced
names:
plural: shirts
singular: shirt
kind: Shirt
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
color:
type: string
size:
type: string
selectableFields:
- jsonPath: .spec.color
- jsonPath: .spec.size
additionalPrinterColumns:
- jsonPath: .spec.color
name: Color
type: string
- jsonPath: .spec.size
name: Size
type: string
Створіть CustomResourceDefinition:
kubectl apply -f shirt-resource-definition.yaml
Визначте деякі сорочки (Shirts), редагуючи файл shirt-resources.yaml
; наприклад:
---
apiVersion: stable.example.com/v1
kind: Shirt
metadata:
name: example1
spec:
color: blue
size: S
---
apiVersion: stable.example.com/v1
kind: Shirt
metadata:
name: example2
spec:
color: blue
size: M
---
apiVersion: stable.example.com/v1
kind: Shirt
metadata:
name: example3
spec:
color: green
size: M
Створіть власні ресурси:
kubectl apply -f shirt-resources.yaml
Отримайте всі ресурси:
kubectl get shirts.stable.example.com
Вивід буде:
NAME COLOR SIZE
example1 blue S
example2 blue M
example3 green M
Отримайте сорочки синього кольору (отримайте сорочки у яких color
має значення blue
):
kubectl get shirts.stable.example.com --field-selector spec.color=blue
Повинен зʼявитися такий вивід:
NAME COLOR SIZE
example1 blue S
example2 blue M
Отримайте лише ресурси з кольором green
та розміром M
:
kubectl get shirts.stable.example.com --field-selector spec.color=green,spec.size=M
Повинен зʼявитися такий вивід:
NAME COLOR SIZE
example2 blue M
Субресурси
Власні ресурси підтримують субресурси /status
та /scale
.
Субресурси status та scale можна опціонально увімкнути, визначивши їх у CustomResourceDefinition.
Субресурс Status
Коли субресурс статусу увімкнено, субресурс /status
для власного ресурсу буде доступним.
Стани
status
таspec
представлені відповідно за допомогою JSONPath.status
та.spec
всередині власного ресурсу.Запити
PUT
до субресурсу/status
приймають обʼєкт власного ресурсу і ігнорують зміни до будь-чого, крім стануstatus
.Запити
PUT
до субресурсу/status
лише перевіряють станstatus
власного ресурсу.Запити
PUT
/POST
/PATCH
до власного ресурсу ігнорують зміни до стануstatus
.Значення
.metadata.generation
збільшується для всіх змін, за винятком змін у.metadata
або.status
.У корені схеми валідації OpenAPI CRD дозволяються тільки такі конструкції:
description
example
exclusiveMaximum
exclusiveMinimum
externalDocs
format
items
maximum
maxItems
maxLength
minimum
minItems
minLength
multipleOf
pattern
properties
required
title
type
uniqueItems
Субресурс Scale
Коли субресурс масштабу увімкнено, субресурс /scale
для власного ресурсу буде доступним.
Обʼєкт autoscaling/v1.Scale
надсилається як навантаження для /scale
.
Для увімкнення субресурсу масштабу наступні поля визначаються в CustomResourceDefinition.
specReplicasPath
визначає JSONPath всередині власного ресурсу, що відповідаєscale.spec.replicas
.- Це обовʼязкове значення.
- Дозволяються тільки JSONPath під
.spec
і з позначенням через крапку. - Якщо у власному ресурсі немає значення під
specReplicasPath
, субресурс/scale
поверне помилку при GET запиті.
statusReplicasPath
визначає JSONPath всередині власного ресурсу, що відповідаєscale.status.replicas
.- Це обовʼязкове значення.
- Дозволяються тільки JSONPath під
.status
і з позначенням через крапку. - Якщо у власному ресурсі немає значення під
statusReplicasPath
, значення репліки статусу у субресурсі/scale
за замовчуванням дорівнюватиме 0.
labelSelectorPath
визначає JSONPath всередині власного ресурсу, що відповідаєScale.Status.Selector
.- Це необовʼязкове значення.
- Воно повинно бути встановлено для роботи з HPA та VPA.
- Дозволяються тільки JSONPath під
.status
або.spec
і з позначенням через крапку. - Якщо у власному ресурсі немає значення під
labelSelectorPath
, значення селектора статусу у субресурсі/scale
за замовчуванням буде порожнім рядком. - Поле, на яке вказує цей JSONPath, повинно бути рядковим полем (не комплексним селектором), що містить серіалізований селектор міток у вигляді рядка.
У наступному прикладі увімкнено обидва субресурси: статусу та масштабу.
Збережіть CustomResourceDefinition у файл resourcedefinition.yaml
:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
status:
type: object
properties:
replicas:
type: integer
labelSelector:
type: string
# subresources описує субресурси для власних ресурсів.
subresources:
# status увімкнення субресурсу статусу.
status: {}
# scale увімкнення субресурсу масштабу.
scale:
# specReplicasPath визначає JSONPath всередині власного ресурсу, що відповідає Scale.Spec.Replicas.
specReplicasPath: .spec.replicas
# statusReplicasPath визначає JSONPath всередині власного ресурсу, що відповідає Scale.Status.Replicas.
statusReplicasPath: .status.replicas
# labelSelectorPath визначає JSONPath всередині власного ресурсу, що відповідає Scale.Status.Selector.
labelSelectorPath: .status.labelSelector
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
І створіть його:
kubectl apply -f resourcedefinition.yaml
Після створення обʼєкта CustomResourceDefinition, ви можете створювати власні обʼєкти.
Якщо ви збережете наступний YAML у файл my-crontab.yaml
:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
replicas: 3
і створите його:
kubectl apply -f my-crontab.yaml
Тоді будуть створені нові RESTful API точки доступу на рівні простору імен:
/apis/stable.example.com/v1/namespaces/*/crontabs/status
та
/apis/stable.example.com/v1/namespaces/*/crontabs/scale
Власний ресурс можна масштабувати за допомогою команди kubectl scale
. Наприклад, наступна команда встановлює .spec.replicas
власного ресурсу, створеного вище, до 5:
kubectl scale --replicas=5 crontabs/my-new-cron-object
crontabs "my-new-cron-object" scaled
kubectl get crontabs my-new-cron-object -o jsonpath='{.spec.replicas}'
5
Ви можете використовувати PodDisruptionBudget, щоб захистити власні ресурси, які мають увімкнений субресурс масштабу.
Категорії
Категорії — це список групованих ресурсів, до яких належить власний ресурс (наприклад, all
). Ви можете використовувати kubectl get <category-name>
, щоб вивести список ресурсів, що належать до категорії.
Наступний приклад додає all
у список категорій у CustomResourceDefinition та ілюструє, як вивести власний ресурс за допомогою kubectl get all
.
Збережіть наступний CustomResourceDefinition у файл resourcedefinition.yaml
:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
# categories - це список групованих ресурсів, до яких належить власний ресурс.
categories:
- all
і створіть його:
kubectl apply -f resourcedefinition.yaml
Після створення обʼєкта CustomResourceDefinition, ви можете створювати власні обʼєкти.
Збережіть наступний YAML у файл
my-crontab.yaml
:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
і створіть його:
kubectl apply -f my-crontab.yaml
Ви можете вказати категорію при використанні kubectl get
:
kubectl get all
і це включатиме власні ресурси типу CronTab
:
NAME AGE
crontabs/my-new-cron-object 3s
Що далі
Прочитайте про власні ресурси.
Дивіться CustomResourceDefinition.
Обслуговуйте кілька версій CustomResourceDefinition.
1.2 - Версії у CustomResourceDefinitions
Ця сторінка пояснює, як додати інформацію про версії до CustomResourceDefinitions, щоб вказати рівень стабільності ваших CustomResourceDefinitions або перейти на нову версію з конвертацією між представленнями API. Також описується, як оновити обʼєкт з однієї версії до іншої.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Ви вже повинні розуміти що таке власні ресурси.
Версія вашого Kubernetes сервера має бути не старішою ніж v1.16. Для перевірки версії введітьkubectl version
.Огляд
API CustomResourceDefinition надає робочий процес для впровадження та оновлення нових версій CustomResourceDefinition.
Коли створюється CustomResourceDefinition, перша версія встановлюється в списку spec.versions
CustomResourceDefinition на відповідний рівень стабільності та номер версії. Наприклад, v1beta1
буде вказувати, що перша версія ще не стабільна. Всі обʼєкти власних ресурсів спочатку будуть зберігатися в цій версії.
Після створення CustomResourceDefinition, клієнти можуть почати використовувати API v1beta1
.
Пізніше може знадобитися додати нову версію, наприклад v1
.
Додавання нової версії:
- Виберіть стратегію конвертації. Оскільки обʼєкти власних ресурсів повинні мати можливість обслуговуватися в обох версіях, це означає, що вони іноді будуть обслуговуватися у версії, відмінній від тієї, в якій зберігаються. Для цього іноді потрібно конвертувати обʼєкти власних ресурсів між версією, в якій вони зберігаються, та версією, в якій вони обслуговуються. Якщо конвертація передбачає зміни схеми та вимагає власної логіки, слід використовувати конвертаційний webhook. Якщо змін схеми немає, можна використовувати стратегію конвертації
None
, і при обслуговуванні різних версій буде змінено лише полеapiVersion
. - Якщо використовуються конвертаційні webhook'и, створіть і розгорніть конвертаційний webhook. Див. Конвертація через webhook для отримання більш детальної інформації.
- Оновіть CustomResourceDefinition, включивши нову версію в список
spec.versions
зserved:true
. Також встановіть полеspec.conversion
на вибрану стратегію конвертації. Якщо використовується конвертаційний webhook, налаштуйте полеspec.conversion.webhookClientConfig
для виклику webhook.
Після додавання нової версії клієнти можуть поступово перейти на нову версію. Цілком безпечно для деяких клієнтів використовувати стару версію, тоді як інші використовують нову версію.
Міграція збережених обʼєктів до нової версії:
Клієнти можуть безпечно використовувати як стару, так і нову версію до, під час і після оновлення обʼєктів до нової збереженої версії.
Видалення старої версії:
- Переконайтеся, що всі клієнти повністю перейшли на нову версію. Логи kube-apiserver можна переглянути для виявлення клієнтів, які все ще використовують стару версію.
- Встановіть
served
наfalse
для старої версії в спискуspec.versions
. Якщо якісь клієнти все ще несподівано використовують стару версію, вони можуть почати повідомляти про помилки при спробі доступу до обʼєктів власних ресурсів у старій версії. У такому випадку поверніться до використанняserved:true
на старій версії, мігруйте залишкових клієнтів на нову версію та повторіть цей крок. - Переконайтеся, що крок оновлення поточних обʼєктів до нової збереженої версії завершено.
- Перевірте, що
storage
встановлено наtrue
для нової версії в спискуspec.versions
в CustomResourceDefinition. - Перевірте, що стара версія більше не згадується в
status.storedVersions
CustomResourceDefinition.
- Перевірте, що
- Видаліть стару версію зі списку
spec.versions
CustomResourceDefinition. - Припиніть підтримку конвертації для старої версії в конвертаційних webhook'ах.
Зазначення кількох версій
Поле versions
в CustomResourceDefinition API може бути використане для підтримки кількох версій розроблених вами власних ресурсів. Версії можуть мати різні схеми, а конвертаційні webhook'и можуть конвертувати власні ресурси між версіями. Конвертації через webhook повинні дотримуватися конвенцій Kubernetes API в тих випадках, де це застосовується. Зокрема, дивіться документацію по змінах API для набору корисних порад та рекомендацій.
Примітка:
Уapiextensions.k8s.io/v1beta1
було поле version
замість versions
. Поле version
є застарілим і необовʼязковим, але якщо воно не пусте, воно повинно відповідати першому елементу у полі versions
.У цьому прикладі показано CustomResourceDefinition з двома версіями. У першому прикладі припускається, що всі версії мають однакову схему без конвертації між ними. У YAML-файлах наведено коментарі, які надають додатковий контекст.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# назва повинна відповідати полям spec нижче, і бути у формі: <plural>.<group>
name: crontabs.example.com
spec:
# імʼя групи, яке буде використовуватися для REST API: /apis/<group>/<version>
group: example.com
# список версій, підтримуваних цим CustomResourceDefinition
versions:
- name: v1beta1
# Кожна версія може бути увімкнена/вимкнена прапорцем Served.
served: true
# Лише одна версія повинна бути позначена як версія зберігання.
storage: true
# Схема обовʼязкова
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
# Секція конвертації була введена в Kubernetes 1.13+ зі стандартним значенням
# конвертації None (стратегії встановленя субполів None).
conversion:
# Конвертація None передбачає ту ж саму схему для всіх версій, і лише встановлює apiVersion
# поле власних ресрів у відповідне значення
strategy: None
# або Namespaced або Cluster
scope: Namespaced
names:
# plural, назва ресрусу в що використовується в URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular, назва ресурсу в що буде використовуватись як аліас в CLI та у виводі
singular: crontab
# kind, зазвичай тип в однині в CamelCase. Ваші маніфести будуть використовувати це.
kind: CronTab
# shortNames, дозволяють коротше звертатися до ресурсу в CLI
shortNames:
- ct
# Застаріло у версії v1.16 на користь apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
# імʼя має збігатися з полями spec нижче і бути у формі: <plural>.<group>
name: crontabs.example.com
spec:
# імʼя групи для використання в REST API: /apis/<group>/<version>
group: example.com
# список версій, які підтримуються цим CustomResourceDefinition
versions:
- name: v1beta1
# Кожна версія може бути увімкненна/вимкнена за допомогою прапорця Served.
served: true
# Лише одна версія повинна бути позначена як версія зберігання.
storage: true
- name: v1
served: true
storage: false
validation:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
# Розділ конвертації введений у Kubernetes 1.13+ зі стандартним значенням конвертації
# None (підполе strategy встановлено на None).
conversion:
# None конфертація передбачає однакову схему для всіх версій і лише встановлює поле apiVersion
# власних ресурсів у правильне значення
strategy: None
# або Namespaced, або Cluster
scope: Namespaced
names:
# plural, назва ресрусу в що використовується в URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular, назва ресурсу в що буде використовуватись як аліас в CLI та у виводі
singular: crontab
# kind, зазвичай тип в однині в PascalCased. Ваші маніфести будуть використовувати це.
kind: CronTab
# shortNames, дозволяють коротше звертатися до ресурсу в CLI
shortNames:
- ct
Ви можете зберегти CustomResourceDefinition у YAML-файлі, а потім використати kubectl apply
, щоб створити його.
kubectl apply -f my-versioned-crontab.yaml
Після створення API-сервер починає обслуговувати кожну включену версію за HTTP REST-точкою доступу. У наведеному вище прикладі, версії API доступні за адресами /apis/example.com/v1beta1
та /apis/example.com/v1
.
Пріоритет версії
Незалежно від порядку, в якому версії визначені в CustomResourceDefinition, версія з найвищим пріоритетом використовується kubectl як стандартна версія для доступу до обʼєктів. Пріоритет визначається шляхом аналізу поля name для визначення номера версії, стабільності (GA, Beta або Alpha) та послідовності в межах цього рівня стабільності.
Алгоритм, який використовується для сортування версій, розроблений для сортування версій таким же чином, як проєкт Kubernetes сортує версії Kubernetes. Версії починаються з v
, за яким слідує число, опціональне позначення beta
або alpha
, та опціональна додаткова числова інформація про версію. В загальному вигляді рядок версії може виглядати як v2
або v2beta1
. Версії сортуються за таким алгоритмом:
- Записи, що відповідають шаблонам версій Kubernetes, сортуються перед тими, що не відповідають шаблонам.
- Для записів, що відповідають шаблонам версій Kubernetes, числові частини рядка версії сортуються від більшого до меншого.
- Якщо після першої числової частини йдуть рядки
beta
абоalpha
, вони сортуються в такому порядку після еквівалентного рядка без суфіксаbeta
абоalpha
(який вважається GA версією). - Якщо після
beta
абоalpha
йде ще одне число, ці числа також сортуються від більшого до меншого. - Рядки, що не відповідають зазначеному формату, сортуються за алфавітом, і числові частини не мають спеціального порядку. Зауважте, що в наведеному нижче прикладі
foo1
сортується вище заfoo10
. Це відрізняється від сортування числових частин записів, що відповідають шаблонам версій Kubernetes.
Це може бути зрозуміло, якщо подивитися на наступний відсортований список версій:
- v10
- v2
- v1
- v11beta2
- v10beta3
- v3beta1
- v12alpha1
- v11alpha2
- foo1
- foo10
Для прикладу у розділі Зазначення кількох версій, порядок сортування версій — v1
, за яким слідує v1beta1
. Це змушує команду kubectl використовувати v1
як стандартну версію, якщо у наданому обʼєкті не вказано версію.
Застарівання версій
Kubernetes v1.19 [stable]
Починаючи з версії v1.19, CustomResourceDefinition може вказувати, що певна версія ресурсу, який він визначає, є застарілою. Коли API-запити до застарілої версії цього ресурсу здійснюються, у відповідь API повертається попереджувальне повідомлення в заголовку. Попереджувальне повідомлення для кожної застарілої версії ресурсу можна налаштувати за бажанням.
Налаштоване попереджувальне повідомлення повинно вказувати застарілу API-групу, версію та тип (kind), і, якщо це можливо, вказувати, яку API-групу, версію та тип слід використовувати замість цього.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
name: crontabs.example.com
spec:
group: example.com
names:
plural: crontabs
singular: crontab
kind: CronTab
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: false
# Це вказує, що версія v1alpha1 власного ресурсу є застарілою.
# API-запити до цієї версії отримують попереджувальний заголовок у відповіді сервера.
deprecated: true
# Це перевизначає стандартне попереджувальне повідомлення, яке повертається клієнтам API, що здійснюють запити до v1alpha1.
deprecationWarning: "example.com/v1alpha1 CronTab застарілий; див. http://example.com/v1alpha1-v1 для інструкцій щодо переходу на example.com/v1 CronTab"
schema: ...
- name: v1beta1
served: true
# Це вказує, що версія v1beta1 власного ресурсу є застарілою.
# API-запити до цієї версії отримують попереджувальний заголовок у відповіді сервера.
# Стандартне попереджувальне повідомлення повертається для цієї версії.
deprecated: true
schema: ...
- name: v1
served: true
storage: true
schema: ...
# Застаріло у v1.16 на користь apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: crontabs.example.com
spec:
group: example.com
names:
plural: crontabs
singular: crontab
kind: CronTab
scope: Namespaced
validation: ...
versions:
- name: v1alpha1
served: true
storage: false
# Це вказує, що версія v1alpha1 власного ресурсу є застарілою.
# API-запити до цієї версії отримують попереджувальний заголовок у відповіді сервера.
deprecated: true
# Це перевизначає стандартне попереджувальне повідомлення, яке повертається клієнтам API, що здійснюють запити до v1alpha1.
deprecationWarning: "example.com/v1alpha1 CronTab застарілий; див. http://example.com/v1alpha1-v1 для інструкцій щодо переходу на example.com/v1 CronTab"
- name: v1beta1
served: true
# Це вказує, що версія v1beta1 власного ресурсу є застарілою.
# API-запити до цієї версії отримують попереджувальний заголовок у відповіді сервера.
# Стандартне попереджувальне повідомлення повертається для цієї версії.
deprecated: true
- name: v1
served: true
storage: true
Видалення версії
Стара версія API не може бути видалена з маніфесту CustomResourceDefinition, доки наявні збережені дані не будуть мігровані до новішої версії API для всіх кластерів, які обслуговували стару версію власного ресурсу, та поки стара версія не буде видалена зі списку status.storedVersions
у CustomResourceDefinition.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
name: crontabs.example.com
spec:
group: example.com
names:
plural: crontabs
singular: crontab
kind: CronTab
scope: Namespaced
versions:
- name: v1beta1
# Це вказує, що версія v1beta1 власного ресурсу більше не обслуговується.
# API-запити до цієї версії отримують помилку "не знайдено" у відповіді сервера.
served: false
schema: ...
- name: v1
served: true
# Нова версія, що обслуговується повинна бути встановлена як версія зберігання
storage: true
schema: ...
Конвертація за допомогою вебхука
Kubernetes v1.16 [stable]
Примітка:
Конвертація за допомогою вебхука доступна як бета-версія з версії 1.15, і як альфа-версія з Kubernetes 1.13. ФункціяCustomResourceWebhookConversion
повинна бути увімкнена, що автоматично відбувається для багатьох кластерів з бета-функціями. Будь ласка, зверніться до документації функціональні можливості для отримання додаткової інформації.Наведений вище приклад має None-конвертацію між версіями, яка лише встановлює поле apiVersion
під час конвертації та не змінює решту обʼєкта. API-сервер також підтримує конвертації за допомогою вебхука, які викликають зовнішній сервіс у випадку, коли потрібна конвертація. Наприклад, коли:
- власний ресурс запитується у версії, яка відрізняється від збереженої версії.
- створюється спостереження (Watch) в одній версії, але змінений обʼєкт зберігається в іншій версії.
- запит на PUT для власного ресурсу здійснюється в іншій версії, ніж версія зберігання.
Щоб охопити всі ці випадки та оптимізувати конвертацію за допомогою API-сервера, запити на конвертацію можуть містити кілька обʼєктів з метою мінімізації зовнішніх викликів. Вебхук повинен виконувати ці конвертації незалежно.
Написання сервера для конвертації за допомогою вебхука
Будь ласка, зверніться до реалізації сервера вебхука для конвертації власних ресурсів, який проходить перевірку в e2e тесті Kubernetes. Вебхук обробляє запити ConversionReview
, що надсилаються API-серверами, і надсилає назад результати конвертації, загорнуті в ConversionResponse
. Зверніть увагу, що запит містить список власних ресурсів, які потрібно конвертувати незалежно, не змінюючи порядок обʼєктів. Приклад сервера організований таким чином, щоб його можна було повторно використовувати для інших конвертацій. Більшість загального коду знаходиться у файлі фреймворку, залишаючи лише одну функцію для реалізації різних конвертацій.
Примітка:
Приклад сервера вебхука для конвертації залишає полеClientAuth
порожнім, що стандартно встановлюється в NoClientCert
. Це означає, що сервер вебхука не автентифікує особу клієнтів, ймовірно API-серверів. Якщо вам потрібен взаємний TLS або інші способи автентифікації клієнтів, дивіться, як автентифікувати API-сервери.Допустимі зміни
Вебхук для конвертації не повинен змінювати нічого в полі metadata
обʼєкта, окрім labels
та annotations
. Спроби змінити name
, UID
та namespace
відхиляються і призводять до помилки запиту, що спричинив конвертацію. Усі інші зміни ігноруються.
Розгортання сервера вебхука для конвертації
Документація для розгортання вебхука для конвертації аналогічна документації для прикладу сервісу вебхука для допуску. Наступні секції передбачають, що сервер вебхука для конвертації розгорнутий як сервіс з іменем example-conversion-webhook-server
у просторі імен default
та обслуговує трафік за шляхом /crdconvert
.
Примітка:
Коли сервер вебхука розгорнуто в кластер Kubernetes як сервіс, він має бути доступний через сервіс на порту 443 (сам сервер може використовувати довільний порт, але обʼєкт сервісу повинен зіставити його з портом 443). Комунікація між API-сервером і сервісом вебхука може не вдатися, якщо використовується інший порт для сервісу.Налаштування CustomResourceDefinition для використання вебхуків конвертації
Приклад None
конвертації можна розширити для використання вебхука конвертації, змінивши розділ conversion
в розділі spec
:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# імʼя повинно відповідати полям spec нижче, і мати форму: <plural>.<group>
name: crontabs.example.com
spec:
# назва групи, яку використовувати для REST API: /apis/<group>/<version>
group: example.com
# список версій, які підтримуються цим CustomResourceDefinition
versions:
- name: v1beta1
# Кожну версію можна увімкнути/вимкнути за допомогою прапорця Served.
served: true
# Одна і тільки одна версія повинна бути позначена як версія для зберігання.
storage: true
# Кожна версія може визначити свою власну схему, коли немає визначеної схеми верхнього рівня.
schema:
openAPIV3Schema:
type: object
properties:
hostPort:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
conversion:
# стратегія Webhook інструктує сервер API викликати зовнішній вебхук для будь-якої конвертації між власними ресурсами.
strategy: Webhook
# вебхук необхідний, коли стратегія - `Webhook`, і він налаштовує точку доступу вебхука для виклику сервером API.
webhook:
# conversionReviewVersions вказує, які версії ConversionReview розуміються/надається перевага вебхуком.
# Перша версія у списку, яку розуміє сервер API, надсилається до вебхуку.
# Вебхук повинен відповісти обʼєктом ConversionReview в тій самій версії, що й отримана.
conversionReviewVersions: ["v1","v1beta1"]
clientConfig:
service:
namespace: default
name: example-conversion-webhook-server
path: /crdconvert
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
# або Namespaced, або Cluster
scope: Namespaced
names:
# plural, назва ресурсу в що використовується в URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular, назва ресурсу в що буде використовуватись як аліас в CLI та у виводі
singular: crontab
# kind, зазвичай тип в однині в CamelCased. Ваші маніфести будуть використовувати це.
kind: CronTab
# shortNames, дозволяють коротше звертатися до ресурсу в CLI
shortNames:
- ct
# Застаріло у v1.16 на користь apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
# імʼя повинно відповідати полям spec нижче, і мати форму: <plural>.<group>
name: crontabs.example.com
spec:
# назва групи, яку використовувати для REST API: /apis/<group>/<version>
group: example.com
# обрізає поля обʼєктів, які не вказані у схемах OpenAPI нижче.
preserveUnknownFields: false
# список версій, які підтримуються цим CustomResourceDefinition
versions:
- name: v1beta1
# Кожну версію можна включити/вимкнути за допомогою прапорця Served.
served: true
# Одна і тільки одна версія повинна бути позначена як версія зберігання.
storage: true
# Кожна версія може визначити свою власну схему, коли немає визначеної схеми верхнього рівня.
schema:
openAPIV3Schema:
type: object
properties:
hostPort:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
conversion:
# стратегія Webhook інструктує сервер API викликати зовнішній вебхук для будь-якої конвертації між власними ресурсами.
strategy: Webhook
# webhookClientConfig необхідний, коли стратегія - `Webhook`, і він налаштовує точку доступу вебхука для виклику сервером API.
webhookClientConfig:
service:
namespace: default
name: example-conversion-webhook-server
path: /crdconvert
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
# або Namespaced, або Cluster
scope: Namespaced
names:
# plural, назва ресурсу в що використовується в URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular, назва ресурсу в що буде використовуватись як аліас в CLI та у виводі
singular: crontab
# kind, зазвичай тип в однині в CamelCased. Ваші маніфести будуть використовувати це.
kind: CronTab
# shortNames, дозволяють коротше звертатися до ресурсу в CLI
shortNames:
- ct
Ви можете зберегти опис CustomResourceDefinition у файлі YAML, а потім використовувати
kubectl apply
, щоб застосувати його.
kubectl apply -f мій-версійний-crontab-з-конвертацією.yaml
Переконайтеся, що сервіс конвертації працює, перш ніж застосовувати нові зміни.
Звʼязок з вебхуком
Після того, як сервер API визначив, що запит потрібно надіслати до вебхуку конвертації, йому потрібно знати, як звʼязатися з вебхуком. Це вказується в розділі webhookClientConfig
конфігурації вебхука.
Вебхуки конвертації можуть бути викликані або через URL, або через посилання на сервіс, і можуть додатково містити власний пакет CA для перевірки TLS-зʼєднання.
URL
url
вказує знаходження вебхука, у стандартній формі URL (scheme://host:port/path
).
host
не повинен посилатися на сервіс, що працює в кластері; використовуйте посилання на сервіс, вказавши замість цього поле service
. Хост може бути вирішений через зовнішній DNS в деяких apiserver-ах (тобто kube-apiserver
не може виконувати внутрішній DNS, оскільки це було б порушенням рівня). host
також може бути IP-адресою.
Зверніть увагу, що використання localhost
або 127.0.0.1
як host
є ризикованим, якщо ви не приділяєте велику увагу тому, щоб запустити цей вебхук на всіх хостах, на яких працює apiserver, який може потребувати звернень до цього вебхука. Такі установки, швидше за все, не будуть переносними або не можуть бути легко запущені в новому кластері.
Схема повинна бути "https"; URL повинен починатися з "https://".
Спроба використання автентифікації користувача або базової автентифікації (наприклад, "user:password@") заборонена. Фрагменти ("#...") та параметри запиту ("?...") також не дозволені.
Ось приклад вебхука конвертації, налаштованого на виклик URL (і очікується, що сертифікат TLS буде перевірений за допомогою коренів довіри системи, тому не вказується caBundle
):
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhook:
clientConfig:
url: "https://my-webhook.example.com:9443/my-webhook-path"
...
# Застаріло у v1.16 на користь apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhookClientConfig:
url: "https://my-webhook.example.com:9443/my-webhook-path"
...
Посилання на сервіс
Розділ service
всередині webhookClientConfig
є посиланням на сервіс для вебхука конвертації. Якщо вебхук працює всередині кластера, то ви повинні використовувати service
замість url
. Простір імен та імʼя сервісу є обовʼязковими. Порт є необовʼязковим і типово дорівнює 443. Шлях є необовʼязковим і типово дорівнює "/".
Ось приклад вебхука, який налаштований на виклик сервісу на порту "1234" з шляхом "/my-path", і для перевірки TLS-зʼєднання на ServerName my-service-name.my-service-namespace.svc
з використанням власного пакету CA.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: my-service-namespace
name: my-service-name
path: /my-path
port: 1234
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
...
# Застаріло у v1.16 на користь apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhookClientConfig:
service:
namespace: my-service-namespace
name: my-service-name
path: /my-path
port: 1234
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
...
Запити та відповіді вебхуків
Запит
Вебхуки надсилають POST-запит з Content-Type: application/json
, з обʼєктом API ConversionReview
з API-групи apiextensions.k8s.io
, який серіалізується в JSON як тіло запиту.
Вебхуки можуть вказати, які версії обʼєктів ConversionReview
вони приймають, за допомогою поля conversionReviewVersions
у своїй CustomResourceDefinition:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhook:
conversionReviewVersions: ["v1", "v1beta1"]
...
Поле conversionReviewVersions
є обовʼязковим при створенні custom resource definitions apiextensions.k8s.io/v1
. Вебхуки повинні підтримувати принаймні одну версію ConversionReview
, яку розуміє поточний та попередній API сервер.
# Застаріло у v1.16 на користь apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
conversionReviewVersions: ["v1", "v1beta1"]
...
Якщо conversionReviewVersions
не вказано, стандартно при створенні custom resource definitions apiextensions.k8s.io/v1beta1
використовується v1beta1
.
API сервери надсилають першу версію ConversionReview
у списку conversionReviewVersions
, яку вони підтримують. Якщо жодна з версій у списку не підтримується API сервером, створення custom resource definition не буде дозволено. Якщо API сервер зустрічає конфігурацію вебхука конвертації, яка була створена раніше і не підтримує жодної з версій ConversionReview
, які сервер може надіслати, спроби виклику вебхука завершаться невдачею.
Цей приклад показує дані, що містяться в обʼєкті ConversionReview
для запиту на конверсію обʼєктів CronTab
до example.com/v1
:
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "ConversionReview",
"request": {
# Випадковий uid, який унікально ідентифікує цей виклик конвертації
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
# API група та версія, до якої повинні бути конвертовані обʼєкти
"desiredAPIVersion": "example.com/v1",
# Список обʼєктів для конвертації.
# Може містити один або більше обʼєктів, у одній або більше версіях.
"objects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"hostPort": "localhost:1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"hostPort": "example.com:2345"
}
]
}
}
{
# Застаріло у v1.16 на користь apiextensions.k8s.io/v1
"apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "ConversionReview",
"request": {
# Випадковий uid, який унікально ідентифікує цей виклик конвертації
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
# API група та версія, до якої повинні бути конвертовані обʼєкти
"desiredAPIVersion": "example.com/v1",
# Список обʼєктів для конвертації.
# Може містити один або більше обʼєктів, у одній або більше версіях.
"objects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"hostPort": "localhost:1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"hostPort": "example.com:2345"
}
]
}
}
Відповідь
Вебхуки відповідають зі статусом HTTP 200, Content-Type: application/json
та тілом, що містить обʼєкт ConversionReview
(у тій самій версії, у якій вони були надіслані), з заповненим розділом response
, серіалізованим у JSON.
Якщо конвертація успішна, вебхук має повернути розділ response
, що містить наступні поля:
uid
, скопійований зrequest.uid
, надісланого до вебхукаresult
, встановлений на{"status":"Success"}
convertedObjects
, що містить всі обʼєкти зrequest.objects
, конвертовані доrequest.desiredAPIVersion
Приклад мінімально успішної відповіді від вебхука:
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "ConversionReview",
"response": {
# має збігатись з <request.uid>
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
"result": {
"status": "Success"
},
# Обʼєкти мають відповідати порядку request.objects та мати apiVersion, встановлений у <request.desiredAPIVersion>.
# поля kind, metadata.uid, metadata.name та metadata.namespace не повинні змінюватися вебхуком.
# поля metadata.labels та metadata.annotations можуть бути змінені вебхуком.
# всі інші зміни полів metadata, зроблені вебхуком, ігноруються.
"convertedObjects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-б5da-fd6083580d66"
},
"host": "localhost",
"port": "1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-б553-d859cedde8a0"
},
"host": "example.com",
"port": "2345"
}
]
}
}
{
# Застаріло у версії v1.16 на користь apiextensions.k8s.io/v1
"apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "ConversionReview",
"response": {
# має відповідати <request.uid>
"uid": "705ab4f5-6393-11e8-б7cc-42010a800002",
"result": {
"status": "Failed"
},
# Обʼєкти мають відповідати порядку request.objects та мати apiVersion, встановлений у <request.desiredAPIVersion>.
# поля kind, metadata.uid, metadata.name та metadata.namespace не повинні змінюватися вебхуком.
# поля metadata.labels та metadata.annotations можуть бути змінені вебхуком.
# всі інші зміни полів metadata, зроблені вебхуком, ігноруються.
"convertedObjects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-б5da-fd6083580d66"
},
"host": "localhost",
"port": "1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-б575-460d-б553-d859cedde8a0"
},
"host": "example.com",
"port": "2345"
}
]
}
}
Якщо конвертація не вдалася, вебхук має повернути розділ response
, що містить наступні поля:
uid
, скопійований зrequest.uid
, надісланого до вебхукуresult
, встановлений на{"status":"Failed"}
Попередження:
Невдала конвертація може порушити доступ для читання та запису до власних ресурсів, включаючи можливість оновлення або видалення ресурсів. Збоїв у конвертації слід уникати за будь-якої можливості, і не слід використовувати їх для забезпечення дотримання обмежень на валідацію (використовуйте схеми валідації або admission webhook).Приклад відповіді від вебхуку, що вказує на невдачу запиту конвертації, з додатковим повідомленням:
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "ConversionReview",
"response": {
"uid": "<значення з request.uid>",
"result": {
"status": "Failed",
"message": "hostPort не вдалося розділити на окремі host та port"
}
}
}
{
# Застаріло у версії v1.16 на користь apiextensions.k8s.io/v1
"apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "ConversionReview",
"response": {
"uid": "<значення з request.uid>",
"result": {
"status": "Failed",
"message": "hostPort не вдалося розділити на окремі host та port"
}
}
}
Запис, читання та оновлення обʼєктів CustomResourceDefinition з версіями
Коли обʼєкт записується, він зберігається у версії, визначеній як версія зберігання на момент запису. Якщо версія зберігання змінюється, наявні обʼєкти ніколи не конвертуються автоматично. Проте новостворені або оновлені обʼєкти записуються у новій версії зберігання. Можливо, що обʼєкт було записано у версії, яка більше не обслуговується.
Коли ви зчитуєте обʼєкт, ви вказуєте версію як частину шляху. Ви можете запитати обʼєкт у будь-якій версії, яка наразі обслуговується. Якщо ви вказуєте версію, яка відрізняється від версії, у якій зберігається обʼєкт, Kubernetes повертає вам обʼєкт у запитуваній версії, але збережений обʼєкт не змінюється на диску.
Що відбувається з обʼєктом, який повертається під час обслуговування запиту на читання, залежить від того, що вказано у spec.conversion
CRD:
- Якщо вказано стандартне значення стратегії
None
, єдині зміни обʼєкта — це зміна рядкаapiVersion
і, можливо, обрізання невідомих полів (залежно від конфігурації). Зазначимо, що це навряд чи призведе до хороших результатів, якщо схеми відрізняються між версіями зберігання та запитуваною версією. Зокрема, не слід використовувати цю стратегію, якщо ті самі дані представлені у різних полях між версіями. - Якщо вказано конвретацію за допомогою вебхуку, тоді цей механізм контролює конверсію.
Якщо ви оновлюєте існуючий обʼєкт, він перезаписується у версії, яка наразі є версією зберігання. Це єдиний спосіб, за допомогою якого обʼєкти можуть змінюватися з однієї версії на іншу.
Щоб проілюструвати це, розглянемо наступну гіпотетичну послідовність подій:
- Версія зберігання —
v1beta1
. Ви створюєте обʼєкт. Він зберігається у версіїv1beta1
. - Ви додаєте версію
v1
до вашого CustomResourceDefinition і призначаєте її версією зберігання. Схеми дляv1
таv1beta1
є ідентичними, що зазвичай має місце під час підвищення API до стабільного стану в екосистемі Kubernetes. - Ви читаєте свій обʼєкт у версії
v1beta1
, потім читаєте обʼєкт знову у версіїv1
. Обидва отримані обʼєкти є ідентичними, за винятком поля apiVersion. - Ви створюєте новий обʼєкт. Він зберігається у версії
v1
. Тепер у вас є два обʼєкти: один у версіїv1beta1
, інший у версіїv1
. - Ви оновлюєте перший обʼєкт. Тепер він зберігається у версії
v1
, оскільки це поточна версія зберігання.
Попередні версії зберігання
API сервер записує кожну версію, яка коли-небудь була позначена як версія зберігання у полі статусу storedVersions
. Обʼєкти можуть бути збережені у будь-якій версії, яка коли-небудь була визначена як версія зберігання. Ніякі обʼєкти не можуть існувати у зберіганні у версії, яка ніколи не була версією зберігання.
Оновлення існуючих обʼєктів до нової версії зберігання
При застаріванні версій та припиненні підтримки виберіть процедуру оновлення зберігання.
Варіант 1: Використання Storage Version Migrator
- Запустіть Storage Version Migrator.
- Видаліть стару версію з поля
status.storedVersions
CustomResourceDefinition.
Варіант 2: Ручне оновлення наявних обʼєктів до нової версії зберігання
Наведено приклад процедури оновлення з v1beta1
до v1
.
- Встановіть
v1
як версію зберігання у файлі CustomResourceDefinition та застосуйте це за допомогою kubectl. ТеперstoredVersions
міститьv1beta1, v1
. - Напишіть процедуру оновлення для отримання всіх наявних обʼєктів і запишіть їх з тим самим вмістом. Це змушує бекенд записувати обʼєкти у поточній версії зберігання, якою є
v1
. - Видаліть
v1beta1
з поляstatus.storedVersions
CustomResourceDefinition.
Примітка:
Прапорець --subresource
використовується з командами kubectl get, patch, edit та replace для отримання та оновлення субресурсів, таких як status
і scale
, для всіх ресурсів API, які їх підтримують. Цей прапорець доступний, починаючи з версії kubectl v1.24. Раніше читання субресурсів (наприклад, status
) через kubectl передбачало використання kubectl --raw
, а оновлення субресурсів за допомогою kubectl взагалі було неможливим. Починаючи з v1.24, інструмент kubectl
можна використовувати для редагування або накладання патчів на субресурс status
обʼєкта CRD. Див. Як патчити Deployment за допомогою прапорця subresource.
Ця сторінка є частиною документації Kubernetes v1.31. Якщо ви використовуєте іншу версію Kubernetes, зверніться до документації для відповідної версії.
Ось приклад того, як накладати патч на субресурс status
обʼєкта CRD за допомогою kubectl
:
kubectl patch customresourcedefinitions <CRD_Name> --subresource='status' --type='merge' -p '{"status":{"storedVersions":["v1"]}}'
2 - Налаштування шару агрегації
Налаштування шару агрегації дозволяє розширити apiserver Kubernetes додатковими API, які не є частиною основних API Kubernetes.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Примітка:
Існує кілька вимог щодо налаштування для роботи шару агрегації у вашому середовищі, щоб підтримувати взаємну автентифікацію TLS між проксі-сервером та apiserverʼом розширення. Kubernetes та kube-apiserver мають декілька ЦС (центрів сертифікації), тому переконайтеся, що проксі підписаний ЦС шару агрегації, а не іншим ЦС, таким як загальний ЦС Kubernetes.Увага:
Повторне використання одного ЦС для різних типів клієнтів може негативно вплинути на здатність кластера функціонувати. Для отримання додаткової інформації див. Повторне використання ЦС та конфлікти.Потоки автентифікації
На відміну від Custom Resource Definitions (CRDs), API агрегації включає ще один сервер, ваш apiserver розширення, крім стандартного apiserver Kubernetes. Kubernetes apiserver повинен взаємодіяти з вашим apiserver розширення, а ваш apiserver розширення повинен взаємодіяти з Kubernetes apiserver. Щоб ця взаємодія була захищеною, Kubernetes apiserver використовує x509 сертифікати для автентифікації себе перед apiserver розширення.
У цьому розділі описано, як працюють потоки автентифікації та авторизації та як їх налаштувати.
Основний потік виглядає наступним чином:
- Kubernetes apiserver: автентифікація користувача, що запитує, та авторизація його прав на запитаний API шлях.
- Kubernetes apiserver: проксіювання запиту до apiserverʼа розширення.
- apiserver розширення: автентифікація запиту від Kubernetes apiserver.
- apiserver розширення: авторизація запиту від початкового користувача.
- apiserver розширення: виконання.
У решті цього розділу описуються ці кроки детально.
Потік можна побачити на наступній діаграмі.
Джерело для вищезазначених потоків можна знайти у вихідному коді цього документа.
Автентифікація та авторизація Kubernetes Apiserver
Запит до API шляху, який обслуговується apiserver розширення, починається так само, як і всі API запити: з комунікації з Kubernetes apiserver. Цей шлях вже був зареєстрований з Kubernetes apiserver apiserver розширення.
Користувач взаємодіє з Kubernetes apiserver, запитуючи доступ до шляху. Kubernetes apiserver використовує стандартну автентифікацію та авторизацію, налаштовану в Kubernetes apiserver, для автентифікації користувача та авторизації доступу до конкретного шляху.
Для загального огляду автентифікації в кластері Kubernetes див. "Автентифікація в кластері". Для загального огляду авторизації доступу до ресурсів кластера Kubernetes див. "Огляд авторизації".
Все до цього моменту було стандартними запитами API Kubernetes, автентифікацією та авторизацією.
Kubernetes apiserver тепер готовий відправити запит до apiserverʼа розширення.
Проксіювання запиту Kubernetes Apiserver
Kubernetes apiserver тепер відправить або проксує запит до apiserverʼа розширення, який зареєстрований для обробки цього запиту. Для цього потрібно знати кілька речей:
- Як Kubernetes apiserver повинен автентифікуватися у apiserver розширення, інформуючи його, що запит, який надходить мережею, надходить від дійсного Kubernetes apiserver?
- Як Kubernetes apiserver повинен інформувати apiserver розширення про імʼя користувача та групу, з якими оригінальний запит був автентифікований?
Щоб забезпечити ці два аспекти, ви повинні налаштувати Kubernetes apiserver, використовуючи кілька прапорців.
Автентифікація клієнта Kubernetes Apiserver
Kubernetes apiserver підключається до apiserverʼа розширення через TLS, автентифікується за допомогою клієнтського сертифіката. Ви повинні надати наступне для Kubernetes apiserver при запуску, використовуючи вказані параметри:
- файл приватного ключа через
--proxy-client-key-file
- підписаний файл клієнтського сертифіката через
--proxy-client-cert-file
- сертифікат CA, який підписав файл клієнтського сертифіката через
--requestheader-client-ca-file
- дійсні значення загального імені (CN) в підписаному клієнтському сертифікаті через
--requestheader-allowed-names
Kubernetes apiserver використовуватиме файли, вказані --proxy-client-*-file
, щоб автентифікуватися у apiserver розширення. Щоб запит був вважався дійсним відповідно до стандартів apiserverʼа розширення, мають виконуватися наступні умови:
- Підключення має бути виконане за допомогою клієнтського сертифіката, який підписаний CA, сертифікат якого знаходиться в
--requestheader-client-ca-file
. - Підключення має бути виконане за допомогою клієнтського сертифіката, CN якого знаходиться в одному з тих, що перелічені в
--requestheader-allowed-names
.
Примітка:
Ви можете встановити цей параметр як порожній рядок:--requestheader-allowed-names=""
. Це позначатиме для apiserverʼа розширення, що будь-яке CN прийнятне.Після запуску з цими параметрами Kubernetes apiserver:
- Використовуватиме їх для автентифікації у apiserver розширення.
- Створить ConfigMap у просторі імен
kube-system
з назвоюextension-apiserver-authentication
, в який він помістить сертифікат CA та дозволені CN. Ці дані можна отримати apiserverʼа розширенняs для перевірки запитів.
Зверніть увагу, що той самий клієнтський сертифікат використовується Kubernetes apiserver для автентифікації для усіх apiserverʼів розширень. Він не створює окремий клієнтський сертифікат для кожного apiserverʼа розширення, а лише один, щоб автентифікуватися як Kubernetes apiserver. Цей самий сертифікат використовується для всіх запитів apiserverʼа розширення.
Імʼя користувача та група оригінального запиту
Коли Kubernetes apiserver проксіює запит до apiserverʼа розширення, він повідомляє apiserver розширення імʼя користувача та групу, з якими успішно був автентифікований початковий запит. Він надає це у http заголовках свого проксі-запиту. Ви повинні повідомити Kubernetes apiserver назви заголовків, які слід використовувати.
- заголовок, в якому зберігати імʼя користувача через
--requestheader-username-headers
- заголовок, в якому зберігати групу через
--requestheader-group-headers
- префікс для всіх додаткових заголовків через
--requestheader-extra-headers-prefix
Ці назви заголовків також поміщаються в ConfigMap extension-apiserver-authentication
, так що їх можна отримати та використати apiserverʼа розширенняs.
Apiserver розширення автентифікує запит
apiserver розширення, отримавши проксі-запит від Kubernetes apiserver, повинен перевірити, що запит дійсно надійшов від дійсного автентифікуючого проксі, роль якого виконує Kubernetes apiserver. apiserver розширення перевіряє його за допомогою:
- Отримання наступного з ConfigMap в
kube-system
, як описано вище:- Сертифікат CA клієнта
- Список дозволених імен (CN)
- Назви заголовків для імені користувача, групи та додаткової інформації
- Перевірте, що TLS-зʼєднання було автентифіковано за допомогою сертифіката клієнта, який:
- Був підписаний CA, чий сертифікат відповідає отриманому сертифікату CA.
- Має CN у списку дозволених CN, якщо список не порожній, в іншому випадку дозволяються всі CN.
- Витягу імені користувача та групи з відповідних заголовків.
Якщо вище зазначене пройшло, тоді запит є дійсним проксійним запитом від законного проксі автентифікації, у цьому випадку — apiserver Kubernetes.
Зверніть увагу, що відповідальність за надання вищезазначеного лежить на реалізації apiserverʼа розширення. Більшість роблять це стандартно, використовуючи пакет k8s.io/apiserver/
. Інші можуть надати опції для зміни цього за допомогою параметрів командного рядка.
Для того, щоб мати дозвіл на отримання конфігураційного файлу, apiserver розширення потребує відповідної ролі. Існує стандартна роль з назвою extension-apiserver-authentication-reader
в просторі імен kube-system
, яка може бути призначена.
Apiserver розширення авторизує запит
Тепер apiserver розширення може перевірити, що користувач/група, отримані з заголовків, мають дозвіл на виконання даного запиту. Він робить це, надсилаючи стандартний запит SubjectAccessReview до apiserver Kubernetes.
Для того, щоб apiserver розширення мав право на надсилання запиту SubjectAccessReview
до apiserver Kubernetes, йому потрібні відповідні дозволи. Kubernetes включає стандартну ClusterRole
з назвою system:auth-delegator
, яка має необхідні дозволи. Її можна надати обліковому запису служби apiserverʼа розширенняа.
Виконання Apiserver розширення
Якщо перевірка SubjectAccessReview
пройде успішно, apiserver розширення виконує запит.
Увімкнення прапорців Apiserver Kubernetes
Увімкніть агрегаційний шар за допомогою наступних прапорців kube-apiserver
. Вони можуть вже бути налаштовані вашим постачальником.
--requestheader-client-ca-file=<шлях до сертифікату CA агрегатора>
--requestheader-allowed-names=front-proxy-client
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--proxy-client-cert-file=<шлях до сертифікату проксі-клієнта агрегатора>
--proxy-client-key-file=<шлях до ключа проксі-клієнта агрегатора>
Повторне використання та конфлікти сертифікатів CA
У Kubernetes apiserver є два параметри CA клієнта:
--client-ca-file
--requestheader-client-ca-file
Кожен з цих параметрів працює незалежно і може конфліктувати один з одним, якщо їх не використовувати належним чином.
--client-ca-file
: Коли запит надходить на Kubernetes apiserver, якщо цей параметр увімкнено, Kubernetes apiserver перевіряє сертифікат запиту. Якщо він підписаний одним з сертифікатів CA в файлі, на який вказує--client-ca-file
, то запит вважається законним, а користувач — значенням загального іменіCN=
, а група — організацієюO=
. Див. документацію з автентифікації TLS.--requestheader-client-ca-file
: Коли запит надходить на Kubernetes apiserver, якщо цей параметр увімкнено, Kubernetes apiserver перевіряє сертифікат запиту. Якщо він підписаний одним із сертифікатів CA у файлі, на який вказує--requestheader-client-ca-file
, то запит вважається потенційно законним. Потім Kubernetes apiserver перевіряє, чи є загальне імʼяCN=
одним з імен у списку, наданому параметром--requestheader-allowed-names
. Якщо імʼя дозволене, запит схвалюється; якщо ні, запит відхиляється.
Якщо обидва параметри --client-ca-file
та --requestheader-client-ca-file
надані, то спочатку запит перевіряє CA --requestheader-client-ca-file
, а потім --client-ca-file
. Зазвичай для кожного з цих параметрів використовуються різні сертифікати CA, або кореневі CA, або проміжні CA; звичайні клієнтські запити відповідають --client-ca-file
, тоді як агрегаційні запити відповідають --requestheader-client-ca-file
. Однак, якщо обидва використовують той самий CA, то звичайні клієнтські запити, які зазвичай пройшли б через --client-ca-file
, не пройдуть, оскільки CA буде відповідати CA в --requestheader-client-ca-file
, але загальне імʼя CN=
не буде відповідати одному з припустимих загальних імен в --requestheader-allowed-names
. Це може призвести до того, що kublete та інші компоненти панелі управління, так само як і інші клієнти, не зможуть автентифікуватись на Kubernetes apiserver.
З цієї причини використовуйте різні сертифікати CA для опції --client-ca-file
, щоб авторизувати компоненти панелі управління та кінцевих користувачів, і опції --requestheader-client-ca-file
, щоб авторизувати запити apiserverʼа агрегації.
Попередження:
Не використовуйте знову CA, який використовується в іншому контексті, якщо ви не розумієте ризики та механізми захисту використання CA.Якщо ви не запускаєте kube-proxy на хості, на якому працює API-сервер, вам потрібно впевнитися, що система ввімкнена з наступним прапорцем kube-apiserver
:
--enable-aggregator-routing=true
Реєстрація обʼєктів APIService
Ви можете динамічно налаштувати, які клієнтські запити будуть проксійовані до apiserverʼа розширення. Нижче наведено приклад реєстрації:
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: <імʼя обʼєкта реєстрації>
spec:
group: <назва групи API, яку обслуговує цей apiserver розширення>
version: <версія API, яку обслуговує цей apiserver розширення>
groupPriorityMinimum: <пріоритет цього APIService для цієї групи, див. документацію API>
versionPriority: <пріоритет упорядкування цієї версії у межах групи, див. документацію API>
service:
namespace: <простір імен сервісу apiserverʼа розширення>
name: <імʼя сервісу apiserverʼа розширення>
caBundle: <pem-кодований ca-сертифікат, який підписує сертифікат сервера, який використовується вебзапитом>
Імʼя обʼєкта APIService повинно бути дійсним імʼям сегмента шляху.
Звертання до apiserverʼа розширення
Після того, як Kubernetes apiserver вирішив, що запит потрібно надіслати до apiserverʼа розширення, він повинен знати, як з ним звʼязатися.
Блок service
— це посилання на сервіс для apiserverʼа розширення. Простір імен та імʼя сервісу обовʼязкові. Порт є необовʼязковим і типово дорівнює 443.
Ось приклад apiserverʼа розширення, який налаштований для виклику на порті "1234" та перевірки зʼєднання TLS проти ServerName my-service-name.my-service-namespace.svc
, використовуючи власний пакет CA.
apiVersion: apiregistration.k8s.io/v1
kind: APIService
...
spec:
...
service:
namespace: my-service-namespace
name: my-service-name
port: 1234
caBundle: "Ci0tLS0tQk...<base64-кодований PEM пакет>...tLS0K"
...
Що далі
- Налаштуйте apiserver розширення для роботи з шаром агрегації.
- Для загального огляду див. Розширення Kubernetes API за допомогою шару агрегації.
- Дізнайтеся, як Розширити API Kubernetes, використовуючи визначення власних ресурсів.
3 - Налаштування API сервера розширення
Налаштування API сервера розширення для роботи з шаром агрегації дозволяє розширювати apiserver Kubernetes додатковими API, які не є частиною основних API Kubernetes.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.- Необхідно налаштувати шар агрегації та увімкнути прапорці apiserver.
Налаштування API сервера розширення для роботи з шаром агрегації
Наступні кроки описують налаштування apiserverʼа розширення на високому рівні. Ці кроки застосовуються незалежно від того, чи використовуєте ви YAML конфігурації, чи API. Робиться спроба конкретно визначити будь-які відмінності між цими двома підходами. Для конкретного прикладу їх реалізації за допомогою YAML конфігурацій, ви можете ознайомитися з sample-apiserver у репозиторії Kubernetes.
Альтернативно, ви можете використовувати наявне стороннє рішення, таке як apiserver-builder, яке має згенерувати кістяк та автоматизувати всі наступні кроки для вас.
- Переконайтеся, що APIService API увімкнено (перевірте
--runtime-config
). Воно має бути типово увімкнене, якщо воно не було свідомо вимкнено у вашому кластері. - Можливо, вам потрібно створити правило RBAC, яке дозволяє додавати обʼєкти APIService, або попросити адміністратора вашого кластера створити його. (Оскільки розширення API впливають на весь кластер, не рекомендується проводити тестування/розробку/налагодження розширення API у робочому кластері.)
- Створіть простір імен Kubernetes, у якому ви хочете запустити свій api-сервер розширення.
- Отримайте сертифікат CA, який буде використовуватися для підпису сертифіката сервера, що використовує api-сервер розширення для HTTPS.
- Створіть серверний сертифікат/ключ для api-сервера, який буде використовуватися для HTTPS. Цей сертифікат повинен бути підписаний вище згаданим CA. Він також повинен мати CN у вигляді імені Kube DNS. Це імʼя формується на основі сервісу Kubernetes і має вигляд
<service name>.<service name namespace>.svc
. - Створіть Secret Kubernetes з серверним сертифікатом/ключем у вашому просторі імен.
- Створіть Deployment Kubernetes для api-сервера розширення і переконайтеся, що ви завантажуєте Secret як том. Він повинен містити посилання на робочий образ вашого api-сервера розширення. Deployment також повинен бути у вашому просторі імен.
- Переконайтеся, що ваш api-сервер розширення завантажує ці сертифікати з того тому і що вони використовуються в процесі рукостискання (handshake) HTTPS.
- Створіть службовий обліковий запис (service account) Kubernetes у вашому просторі імен.
- Створіть кластерну роль Kubernetes для операцій, які ви хочете дозволити над вашими ресурсами.
- Створіть привʼязку кластерної ролі до службового облікового запису (service account) у вашому просторі імен до створеної кластерної ролі.
- Створіть привʼязку кластерної ролі до службового облікового запису (service account) у вашому просторі імен до кластерної ролі
system:auth-delegator
для делегування рішень щодо автентифікації на основному API серверу Kubernetes. - Створіть привʼязку службового облікового запису (service account) у вашому просторі імен до ролі
extension-apiserver-authentication-reader
. Це дозволяє вашому api-серверу розширення отримувати доступ до ConfigMapextension-apiserver-authentication
. - Створіть apiservice Kubernetes. CA сертифікат повинен бути закодований в base64, не містити позбавлений нових рядків і використаний як spec.caBundle в apiservice. Він не повинен бути привʼязаний до простору імен. Якщо ви використовуєте kube-aggregator API, передайте лише PEM-кодований CA bundle, оскільки кодування в base64 виконується за вас.
- Використовуйте kubectl для отримання вашого ресурсу. Під час запуску kubectl повинен повернути "No resources found.". Це повідомлення вказує на те, що все спрацювало, але наразі у вас немає створених обʼєктів цього типу ресурсу.
Що далі
- Пройдіть кроки, щоб налаштувати шар агрегації API та увімкнути прапорці apiserver.
- Для загального огляду дивіться Розширення API Kubernetes за допомогою шару агрегації.
- Дізнайтеся, як Розширити API Kubernetes за допомогою Custom Resource Definitions.
4 - Налаштування кількох планувальників
Kubernetes постачається зі стандартним планувальником. Якщо стандартний планувальник не підходить для ваших потреб, ви можете реалізувати власний. До того, ви можете одночасно запускати кілька планувальників поряд зі стандартним планувальником і вказувати Kubernetes, який планувальник використовувати для кожного з ваших Podʼів. Тепер навчимося запускати кілька планувальників в Kubernetes на прикладі.
Детальний опис того, як реалізувати планувальник, виходить за рамки цього документа. Будь ласка, зверніться до реалізації kube-scheduler в pkg/scheduler в теці вихідних кодів Kubernetes для канонічного прикладу.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Упакування планувальника
Упакуйте ваш планувальник у контейнерний образ. Для цілей цього прикладу ви можете використовувати стандартний планувальник (kube-scheduler) як ваш другий планувальник. Клонуйте вихідний код Kubernetes з GitHub і зберіть планувальник з сирців.
git clone https://github.com/kubernetes/kubernetes.git
cd kubernetes
make
Створіть контейнерний образ, що містить виконавчий файл kube-scheduler. Ось Dockerfile
для створення образу:
FROM busybox
ADD ./_output/local/bin/linux/amd64/kube-scheduler /usr/local/bin/kube-scheduler
Збережіть файл як Dockerfile
, зберіть образ і завантажте його до реєстру. У цьому прикладі образ завантажується до Google Container Registry (GCR). Для отримання додаткової інформації, будь ласка, прочитайте документацію GCR. Як альтернативу ви також можете використовувати docker hub. Для отримання додаткової інформації зверніться до документації docker hub.
docker build -t gcr.io/my-gcp-project/my-kube-scheduler:1.0 . # Назва образу та репозиторію
gcloud docker -- push gcr.io/my-gcp-project/my-kube-scheduler:1.0 # тут є лише прикладом
Визначення розгортання Kubernetes для планувальника
Тепер, коли ви маєте ваш планувальник у контейнерному образі, створіть конфігурацію Podʼа для нього і запустіть його у вашому кластері Kubernetes. Але замість того, щоб створювати Pod безпосередньо в кластері, ви можете використовувати Deployment для цього прикладу. Deployment керує Replica Set, який, своєю чергою, керує Podʼами, забезпечуючи стійкість планувальника до збоїв. Ось конфігурація розгортання. Збережіть її як my-scheduler.yaml
:
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-scheduler
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-scheduler-as-kube-scheduler
subjects:
- kind: ServiceAccount
name: my-scheduler
namespace: kube-system
roleRef:
kind: ClusterRole
name: system:kube-scheduler
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-scheduler-as-volume-scheduler
subjects:
- kind: ServiceAccount
name: my-scheduler
namespace: kube-system
roleRef:
kind: ClusterRole
name: system:volume-scheduler
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-scheduler-extension-apiserver-authentication-reader
namespace: kube-system
roleRef:
kind: Role
name: extension-apiserver-authentication-reader
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: my-scheduler
namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
name: my-scheduler-config
namespace: kube-system
data:
my-scheduler-config.yaml: |
apiVersion: kubescheduler.config.k8s.io/v1beta2
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: my-scheduler
leaderElection:
leaderElect: false
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
component: scheduler
tier: control-plane
name: my-scheduler
namespace: kube-system
spec:
selector:
matchLabels:
component: scheduler
tier: control-plane
replicas: 1
template:
metadata:
labels:
component: scheduler
tier: control-plane
version: second
spec:
serviceAccountName: my-scheduler
containers:
- command:
- /usr/local/bin/kube-scheduler
- --config=/etc/kubernetes/my-scheduler/my-scheduler-config.yaml
image: gcr.io/my-gcp-project/my-kube-scheduler:1.0
livenessProbe:
httpGet:
path: /healthz
port: 10259
scheme: HTTPS
initialDelaySeconds: 15
name: kube-second-scheduler
readinessProbe:
httpGet:
path: /healthz
port: 10259
scheme: HTTPS
resources:
requests:
cpu: '0.1'
securityContext:
privileged: false
volumeMounts:
- name: config-volume
mountPath: /etc/kubernetes/my-scheduler
hostNetwork: false
hostPID: false
volumes:
- name: config-volume
configMap:
name: my-scheduler-config
У наведеному вище маніфесті ви використовуєте KubeSchedulerConfiguration для налаштування поведінки вашої реалізації планувальника. Ця конфігурація була передана kube-scheduler під час ініціалізації за допомогою параметра --config
. Конфігураційний файл зберігається у ConfigMap my-scheduler-config
. Pod Deployment my-scheduler
монтує ConfigMap my-scheduler-config
як том.
У вищезгаданій конфігурації планувальника ваша реалізація планувальника представлена за допомогою KubeSchedulerProfile.
Примітка:
Щоб визначити, чи відповідає планувальник за планування конкретного Podʼа, полеspec.schedulerName
в PodTemplate або Pod маніфесті повинно збігатися з полем schedulerName
профілю KubeSchedulerProfile
. Усі планувальники, що працюють у кластері, повинні мати унікальні імена.Також зверніть увагу, що ви створюєте окремий службовий обліковий запис my-scheduler
і привʼязуєте до нього кластерну роль system:kube-scheduler
, щоб він міг отримати ті ж привілеї, що й kube-scheduler
.
Будь ласка, зверніться до документації kube-scheduler для детального опису інших параметрів командного рядка та довідкової інформації щодо конфігурації планувальника для детального опису інших налаштовуваних конфігурацій kube-scheduler
.
Запуск другого планувальника в кластері
Щоб запустити ваш планувальник у кластері Kubernetes, створіть Deployment вказаний у конфігурації вище у кластері Kubernetes:
kubectl create -f my-scheduler.yaml
Переконайтеся, що Pod планувальника працює:
kubectl get pods --namespace=kube-system
NAME READY STATUS RESTARTS AGE
....
my-scheduler-lnf4s-4744f 1/1 Running 0 2m
...
У цьому списку ви повинні побачити Pod "Running" my-scheduler, на додачу до стандартного планувальника kube-scheduler.
Увімкнення обрання лідера
Щоб запустити кілька планувальників з увімкненим обранням лідера, ви повинні зробити наступне:
Оновіть наступні поля для KubeSchedulerConfiguration у ConfigMap my-scheduler-config
у вашому YAML файлі:
leaderElection.leaderElect
доtrue
leaderElection.resourceNamespace
до<lock-object-namespace>
leaderElection.resourceName
до<lock-object-name>
Примітка:
Панель управління створює обʼєкти блокування для вас, але простір імен вже повинен існувати. Ви можете використовувати простір іменkube-system
.Якщо у вашому кластері увімкнено RBAC, ви повинні оновити кластерну роль system:kube-scheduler
. Додайте імʼя вашого планувальника до імен ресурсів у правилі, яке застосовується до ресурсів endpoints
та leases
, як у наступному прикладі:
kubectl edit clusterrole system:kube-scheduler
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-scheduler
rules:
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- apiGroups:
- coordination.k8s.io
resourceNames:
- kube-scheduler
- my-scheduler
resources:
- leases
verbs:
- get
- update
- apiGroups:
- ""
resourceNames:
- kube-scheduler
- my-scheduler
resources:
- endpoints
verbs:
- delete
- get
- patch
- update
Вказання планувальників для Podʼів
Тепер, коли ваш другий планувальник працює, створіть кілька Podʼів і вкажіть, щоб вони планувалися або стандартним планувальником, або тим, який ви розгорнули. Щоб запланувати Pod за допомогою конкретного планувальника, вкажіть імʼя планувальника у специфікації Podʼа. Розгляньмо три приклади.
Специфікація Podʼа без вказаного імені планувальника
apiVersion: v1 kind: Pod metadata: name: no-annotation labels: name: multischeduler-example spec: containers: - name: pod-with-no-annotation-container image: registry.k8s.io/pause:2.0
Коли імʼя планувальника не вказано, Pod автоматично планується за допомогою стандартного планувальника.
Збережіть цей файл як
pod1.yaml
і надішліть його до кластера Kubernetes.kubectl create -f pod1.yaml
Специфікація Podʼа з
default-scheduler
apiVersion: v1 kind: Pod metadata: name: annotation-default-scheduler labels: name: multischeduler-example spec: schedulerName: default-scheduler containers: - name: pod-with-default-annotation-container image: registry.k8s.io/pause:2.0
Планувальник вказується шляхом надання його імені як значення для
spec.schedulerName
. У цьому випадку ми надаємо імʼя стандартного планувальника, яке єdefault-scheduler
.Збережіть цей файл як
pod2.yaml
і надішліть його до кластера Kubernetes.kubectl create -f pod2.yaml
Специфікація Podʼа з
my-scheduler
apiVersion: v1 kind: Pod metadata: name: annotation-second-scheduler labels: name: multischeduler-example spec: schedulerName: my-scheduler containers: - name: pod-with-second-annotation-container image: registry.k8s.io/pause:2.0
У цьому випадку ми вказуємо, що цей Pod має бути запланований за допомогою планувальника, який ми розгорнули —
my-scheduler
. Зверніть увагу, що значенняspec.schedulerName
повинно відповідати імені, яке було надано планувальнику в поліschedulerName
профілюKubeSchedulerProfile
.Збережіть цей файл як
pod3.yaml
і надішліть його до кластера Kubernetes.kubectl create -f pod3.yaml
Переконайтеся, що всі три Podʼи працюють.
kubectl get pods
Перевірка, що Podʼи були заплановані за допомогою бажаних планувальників
Для спрощення роботи з цими прикладами ми не перевірили, що Podʼи дійсно були заплановані за допомогою бажаних планувальників. Ми можемо перевірити це, змінивши порядок подання конфігурацій Podʼів і розгортання вище. Якщо ми передамо всі конфігурації Podʼів до кластера Kubernetes перед передачею конфігурації розгортання планувальника, ми побачимо, що Pod annotation-second-scheduler
залишається в стані "Pending" назавжди, тоді як інші два Podʼи заплановані. Після надсилання конфігурації розгортання планувальника і запуску нашого нового планувальника, Pod annotation-second-scheduler
також запланується.
Як альтернативу, ви можете переглянути записи "Scheduled" у лозі подій, щоб перевірити, що Podʼи були заплановані бажаними планувальниками.
kubectl get events
Ви також можете використовувати власну конфігурацію планувальника або власний контейнерний образ для основного планувальника кластера, змінивши його статичний маніфест Podʼа на відповідних вузлах панелі управління.
5 - Використання HTTP-проксі для доступу до Kubernetes API
Ця сторінка показує, як використовувати HTTP-проксі для доступу до Kubernetes API.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Якщо у вас ще немає застосунку, що працює у вашому кластері, запустіть застосунок Hello world, скориставшись:
kubectl create deployment hello-app --image=gcr.io/google-samples/hello-app:2.0 --port=8080
Використання kubectl для запуску проксі-сервера
Ця команда запускає проксі до сервера Kubernetes API:
kubectl proxy --port=8080
Дослідження Kubernetes API
Коли проксі-сервер працює, ви можете досліджувати API за допомогою curl
, wget
або оглядача.
Отримання версій API:
curl http://localhost:8080/api/
Вихідні дані повинні виглядати приблизно так:
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "10.0.2.15:8443"
}
]
}
Отримання списку Podʼів:
curl http://localhost:8080/api/v1/namespaces/default/pods
Вихідні дані повинні виглядати приблизно так:
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "33074"
},
"items": [
{
"metadata": {
"name": "kubernetes-bootcamp-2321272333-ix8pt",
"generateName": "kubernetes-bootcamp-2321272333-",
"namespace": "default",
"uid": "ba21457c-6b1d-11e6-85f7-1ef9f1dab92b",
"resourceVersion": "33003",
"creationTimestamp": "2016-08-25T23:43:30Z",
"labels": {
"pod-template-hash": "2321272333",
"run": "kubernetes-bootcamp"
},
...
Що далі
Дізнайтеся більше про kubectl proxy.
6 - Використання SOCKS5-проксі для доступу до Kubernetes API
Kubernetes v1.24 [stable]
Ця сторінка показує, як використовувати SOCKS5-проксі для доступу до API віддаленого кластера Kubernetes. Це корисно, коли кластер, до якого ви хочете отримати доступ, не відкриває свій API безпосередньо в інтернет.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути не старішою ніж v1.24. Для перевірки версії введітьkubectl version
.Вам потрібне програмне забезпечення для SSH-клієнта (інструмент ssh
) і сервіс SSH, що працює на віддаленому сервері. Ви повинні мати можливість увійти до сервісу SSH на віддаленому сервері.
Контекст завдання
Примітка:
У цьому прикладі трафік тунелюється за допомогою SSH, де SSH-клієнт і сервер виступають як SOCKS-проксі. Ви можете також використовувати будь-які інші види SOCKS5 проксі.На схемі 1 представлено, що ви збираєтесь досягти в цьому завданні.
- У вас є компʼютер-клієнт, який називається локальним у подальших кроках, з якого ви будете створювати запити для спілкування з Kubernetes API.
- Сервер Kubernetes/API розміщений на віддаленому сервері.
- Ви будете використовувати програмне забезпечення SSH-клієнта і сервера для створення безпечного SOCKS5-тунелю між локальним і віддаленим сервером. HTTPS-трафік між клієнтом і Kubernetes API буде проходити через SOCKS5-тунель, який сам тунелюється через SSH.
Схема 1. Компоненти уроку про SOCKS5
Використання ssh для створення SOCKS5-проксі
Наступна команда запускає SOCKS5-проксі між вашим клієнтським компʼютером і віддаленим SOCKS-сервером:
# SSH-тунель продовжує працювати у фоновому режимі після виконання цієї команди
ssh -D 1080 -q -N username@kubernetes-remote-server.example
SOCKS5-проксі дозволяє вам підключатися до сервера API вашого кластера на основі наступної конфігурації:
-D 1080
: відкриває SOCKS-проксі на локальному порту :1080.-q
: тихий режим. Приглушує більшість попереджень і діагностичних повідомлень.-N
: не виконувати віддалені команди. Корисно для простого пересилання портів.username@kubernetes-remote-server.example
: віддалений SSH-сервер, за яким працює кластер Kubernetes (наприклад, bastion host).
Конфігурація клієнта
Щоб отримати доступ до сервера Kubernetes API через проксі, вам потрібно вказати kubectl
надсилати запити через створений раніше SOCKS
проксі. Зробіть це або налаштуванням відповідної змінної середовища, або через атрибут proxy-url
у файлі kubeconfig. Використання змінної середовища:
export HTTPS_PROXY=socks5://localhost:1080
Щоб завжди використовувати це налаштування в конкретному контексті kubectl
, вкажіть атрибут proxy-url
у відповідному записі cluster
у файлі ~/.kube/config
. Наприклад:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LRMEMMW2 # скорочено для читабельності
server: https://<API_SERVER_IP_ADDRESS>:6443 # сервер "Kubernetes API", тобто IP-адреса kubernetes-remote-server.example
proxy-url: socks5://localhost:1080 # "SSH SOCKS5 проксі" на діаграмі вище
name: default
contexts:
- context:
cluster: default
user: default
name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
user:
client-certificate-data: LS0tLS1CR== # скорочено для читабельності
client-key-data: LS0tLS1CRUdJT= # скорочено для читабельності
Після створення тунелю через команду ssh, зазначену вище, і визначення змінної середовища або атрибуту proxy-url
, ви можете взаємодіяти з вашим кластером через цей проксі. Наприклад:
kubectl get pods
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-85cb69466-klwq8 1/1 Running 0 5m46s
Примітка:
До версії
kubectl
1.24 більшість командkubectl
працювали з використанням socks-проксі, за виняткомkubectl exec
.kubectl
підтримує як змінні середовищаHTTPS_PROXY
, так іhttps_proxy
. Вони використовуються іншими програмами, які підтримують SOCKS, такими якcurl
. Тому в деяких випадках краще визначити змінну середовища в командному рядку:HTTPS_PROXY=socks5://localhost:1080 kubectl get pods
При використанні
proxy-url
проксі використовується лише для відповідного контекстуkubectl
, тоді як змінна середовища вплине на всі контексти.Імʼя хосту сервера k8s API можна додатково захистити від витоку DNS, використовуючи протокольну назву
socks5h
замість більш відомого протоколуsocks5
, показаного вище. У цьому випадкуkubectl
попросить проксі-сервер (наприклад, ssh bastion) виконати розвʼязання доменного імені сервера k8s API замість його розвʼязання у системі, яка запускаєkubectl
. Зауважте також, що зsocks5h
URL сервера k8s API, як-отhttps://localhost:6443/api
, не стосується вашого локального клієнтського компʼютера. Натомість він стосуєтьсяlocalhost
, відомого на проксі-сервері (наприклад, ssh bastion).
Очищення
Зупиніть процес пересилання портів ssh, натиснувши CTRL+C
у терміналі, де він працює.
Введіть unset https_proxy
у терміналі, щоб припинити пересилання HTTP-трафіку через проксі.
Додаткові матеріали
7 - Налаштування служби Konnectivity
Служба Konnectivity надає проксі на рівні TCP для комунікації між панеллю управління та кластером.
Перш ніж ви розпочнете
Вам потрібно мати кластер Kubernetes, а також інструмент командного рядка kubectl повинен бути налаштований на звʼязок з вашим кластером. Рекомендується виконувати цей посібник на кластері з щонайменше двома вузлами, які не є хостами панелі управління. Якщо у вас ще немає кластера, ви можете створити його за допомогою minikube.
Налаштування служби Konnectivity
Для виконання наступних кроків потрібна конфігурація egress, наприклад:
apiVersion: apiserver.k8s.io/v1beta1
kind: EgressSelectorConfiguration
egressSelections:
# Оскільки ми хочемо контролювати вихідний трафік з кластеру, ми використовуємо
# "cluster" як назву. Інші підтримувані значення: "etcd" та "controlplane".
- name: cluster
connection:
# Це керує протоколом між API-сервером та сервером Konnectivity.
# Підтримувані значення: "GRPC" та "HTTPConnect". Між двома режимами
# немає відмінностей для кінцевого користувача. Вам потрібно встановити
# сервер Konnectivity в тому ж режимі.
proxyProtocol: GRPC
transport:
# Це керує транспортом, який використовує API-сервер для спілкування з
# сервером Konnectivity. Якщо сервер Konnectivity розташований на тому ж
# компʼютері, рекомендується використовувати UDS. Вам потрібно налаштувати
# сервер Konnectivity на прослуховування того самого UDS-сокету.
# Інший підтримуваний транспорт - "tcp". Вам потрібно налаштувати TLS-конфігурацію
# для захисту TCP-транспорту.
uds:
udsName: /etc/kubernetes/konnectivity-server/konnectivity-server.socket
Вам потрібно налаштувати API-сервер для використання служби Konnectivity та направлення мережевого трафіку на вузли кластера:
Переконайтеся, що функція Проєкція токенів службових облікових записів увімкенна у вашому кластері. Вона є типово увімкненою з версії Kubernetes v1.20.
Створіть файл конфігурації egress, наприклад
admin/konnectivity/egress-selector-configuration.yaml
.Встановіть прапорець
--egress-selector-config-file
API-сервера на шлях до файлу конфігурації виходу API-сервера.Якщо ви використовуєте з'ʼєднання UDS, додайте конфігурацію томів до kube-apiserver:
spec: containers: volumeMounts: - name: konnectivity-uds mountPath: /etc/kubernetes/konnectivity-server readOnly: false volumes: - name: konnectivity-uds hostPath: path: /etc/kubernetes/konnectivity-server type: DirectoryOrCreate
Згенеруйте або отримайте сертифікат та kubeconfig для konnectivity-server. Наприклад, ви можете використовувати інструмент командного рядка OpenSSL для створення сертифіката X.509, використовуючи сертифікат CA кластера /etc/kubernetes/pki/ca.crt
з хосту панелі управління.
openssl req -subj "/CN=system:konnectivity-server" -new -newkey rsa:2048 -nodes -out konnectivity.csr -keyout konnectivity.key
openssl x509 -req -in konnectivity.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out konnectivity.crt -days 375 -sha256
SERVER=$(kubectl config view -o jsonpath='{.clusters..server}')
kubectl --kubeconfig /etc/kubernetes/konnectivity-server.conf config set-credentials system:konnectivity-server --client-certificate konnectivity.crt --client-key konnectivity.key --embed-certs=true
kubectl --kubeconfig /etc/kubernetes/konnectivity-server.conf config set-cluster kubernetes --server "$SERVER" --certificate-authority /etc/kubernetes/pki/ca.crt --embed-certs=true
kubectl --kubeconfig /etc/kubernetes/konnectivity-server.conf config set-context system:konnectivity-server@kubernetes --cluster kubernetes --user system:konnectivity-server
kubectl --kubeconfig /etc/kubernetes/konnectivity-server.conf config use-context system:konnectivity-server@kubernetes
rm -f konnectivity.crt konnectivity.key konnectivity.csr
Потім вам потрібно розгорнути сервер Konnectivity та агентів. kubernetes-sigs/apiserver-network-proxy є посиланням на референсну реалізацію.
Розгорніть сервер Konnectivity на ваших вузлах панелі управління. Наданий маніфест konnectivity-server.yaml
передбачає, що компоненти Kubernetes розгорнуті як статичний Pod у вашому кластері. Якщо ні, ви можете розгорнути сервер Konnectivity як DaemonSet.
apiVersion: v1
kind: Pod
metadata:
name: konnectivity-server
namespace: kube-system
spec:
priorityClassName: system-cluster-critical
hostNetwork: true
containers:
- name: konnectivity-server-container
image: registry.k8s.io/kas-network-proxy/proxy-server:v0.0.37
command: ["/proxy-server"]
args: [
"--logtostderr=true",
# Це повинно збігатися зі значенням, встановленим у egressSelectorConfiguration.
"--uds-name=/etc/kubernetes/konnectivity-server/konnectivity-server.socket",
"--delete-existing-uds-file",
# Наступні два рядки передбачають, що сервер Konnectivity
# розгорнуто на тому ж компʼютері, що й apiserver, і сертифікати та
# ключ API-сервера знаходяться за вказаною шляхом.
"--cluster-cert=/etc/kubernetes/pki/apiserver.crt",
"--cluster-key=/etc/kubernetes/pki/apiserver.key",
# Це повинно збігатися зі значенням, встановленим у egressSelectorConfiguration.
"--mode=grpc",
"--server-port=0",
"--agent-port=8132",
"--admin-port=8133",
"--health-port=8134",
"--agent-namespace=kube-system",
"--agent-service-account=konnectivity-agent",
"--kubeconfig=/etc/kubernetes/konnectivity-server.conf",
"--authentication-audience=system:konnectivity-server"
]
livenessProbe:
httpGet:
scheme: HTTP
host: 127.0.0.1
port: 8134
path: /healthz
initialDelaySeconds: 30
timeoutSeconds: 60
ports:
- name: agentport
containerPort: 8132
hostPort: 8132
- name: adminport
containerPort: 8133
hostPort: 8133
- name: healthport
containerPort: 8134
hostPort: 8134
volumeMounts:
- name: k8s-certs
mountPath: /etc/kubernetes/pki
readOnly: true
- name: kubeconfig
mountPath: /etc/kubernetes/konnectivity-server.conf
readOnly: true
- name: konnectivity-uds
mountPath: /etc/kubernetes/konnectivity-server
readOnly: false
volumes:
- name: k8s-certs
hostPath:
path: /etc/kubernetes/pki
- name: kubeconfig
hostPath:
path: /etc/kubernetes/konnectivity-server.conf
type: FileOrCreate
- name: konnectivity-uds
hostPath:
path: /etc/kubernetes/konnectivity-server
type: DirectoryOrCreate
Потім розгорніть агентів Konnectivity у вашому кластері:
apiVersion: apps/v1
# Instead of this, you can deploy agents as Deployments. It is not necessary to have an agent on each node.
kind: DaemonSet
metadata:
labels:
addonmanager.kubernetes.io/mode: Reconcile
k8s-app: konnectivity-agent
namespace: kube-system
name: konnectivity-agent
spec:
selector:
matchLabels:
k8s-app: konnectivity-agent
template:
metadata:
labels:
k8s-app: konnectivity-agent
spec:
priorityClassName: system-cluster-critical
tolerations:
- key: "CriticalAddonsOnly"
operator: "Exists"
containers:
- image: us.gcr.io/k8s-artifacts-prod/kas-network-proxy/proxy-agent:v0.0.37
name: konnectivity-agent
command: ["/proxy-agent"]
args: [
"--logtostderr=true",
"--ca-cert=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
# Оскільки сервер konnectivity працює з hostNetwork=true,
# це є IP-адреса машини-майстра.
"--proxy-server-host=35.225.206.7",
"--proxy-server-port=8132",
"--admin-server-port=8133",
"--health-server-port=8134",
"--service-account-token-path=/var/run/secrets/tokens/konnectivity-agent-token"
]
volumeMounts:
- mountPath: /var/run/secrets/tokens
name: konnectivity-agent-token
livenessProbe:
httpGet:
port: 8134
path: /healthz
initialDelaySeconds: 15
timeoutSeconds: 15
serviceAccountName: konnectivity-agent
volumes:
- name: konnectivity-agent-token
projected:
sources:
- serviceAccountToken:
path: konnectivity-agent-token
audience: system:konnectivity-server
Нарешті, якщо RBAC включено у вашому кластері, створіть відповідні правила RBAC:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:konnectivity-server
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: system:konnectivity-server
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: konnectivity-agent
namespace: kube-system
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile