Воведување на школка-оператор: создавањето оператори за Kubernetes штотуку стана полесно

Веќе има написи на нашиот блог за кои се зборува можности на операторот во Кубернетес и како напишете едноставен оператор сами. Овој пат би сакале да ви го претставиме нашето внимание со отворен код, кое го носи создавањето на оператори на супер лесно ниво - проверете школка-оператор!

Зошто?

Идејата за школка-оператор е прилично едноставна: претплатете се на настани од објекти на Kubernetes и кога ќе ги примите овие настани, стартувајте надворешна програма, обезбедувајќи му информации за настанот:

Воведување на школка-оператор: создавањето оператори за Kubernetes штотуку стана полесно

Потребата за тоа се појави кога за време на работата на кластерите почнаа да се појавуваат мали задачи кои навистина сакавме да ги автоматизираме на вистински начин. Сите овие мали задачи беа решени со користење на едноставни баш скрипти, иако, како што знаете, подобро е да пишувате оператори во Golang. Очигледно, инвестирањето во целосен развој на оператор за секоја таква мала задача би било неефикасно.

Оператор за 15 минути

Ајде да погледнеме пример за тоа што може да се автоматизира во кластерот Kubernetes и како операторот на школка може да помогне. Пример би бил следниов: реплицирање тајна за пристап до регистарот на докер.

Подовите што користат слики од приватен регистар мора да содржат во својот манифест врска до тајна со податоци за пристап до регистарот. Оваа тајна мора да се креира во секој именски простор пред да се креираат подлоги. Ова може да се направи рачно, но ако поставиме динамични средини, тогаш именскиот простор за една апликација ќе стане многу. И ако исто така нема 2-3 апликации... бројот на тајни станува многу голем. И уште нешто за тајните: би сакал одвреме-навреме да го менувам клучот за пристап до регистарот. На крајот, рачни операции како решение целосно неефикасни — треба да го автоматизираме создавањето и ажурирањето на тајните.

Едноставна автоматизација

Ајде да напишеме скрипта за школка која работи еднаш на секои N секунди и ги проверува именските простори за присуство на тајна, а ако нема тајна, тогаш таа се креира. Предноста на ова решение е што изгледа како скрипта на школка во cron - класичен и разбирлив пристап за секого. Негативната страна е што во интервалот помеѓу неговите лансирања може да се создаде нов именски простор и некое време ќе остане без тајна, што ќе доведе до грешки при стартување на подлоги.

Автоматизација со школка-оператор

За нашата скрипта да работи правилно, класичното стартување на cron треба да се замени со стартување кога ќе се додаде именски простор: во овој случај, можете да креирате тајна пред да ја користите. Ајде да видиме како да го имплементираме ова користејќи школка-оператор.

Прво, да го погледнеме сценариото. Скриптите во услови на школка-оператор се нарекуваат куки. Секоја кука кога работи со знаменце --config го известува операторот на школка за неговите врзувања, т.е. за тоа кои настани треба да биде лансирана. Во нашиот случај ќе користиме onKubernetesEvent:

#!/bin/bash
if [[ $1 == "--config" ]] ; then
cat <<EOF
{
"onKubernetesEvent": [
  { "kind": "namespace",
    "event":["add"]
  }
]}
EOF
fi

Овде е опишано дека сме заинтересирани за додавање настани (add) објекти од типот namespace.

Сега треба да го додадете кодот што ќе се изврши кога ќе се случи настанот:

#!/bin/bash
if [[ $1 == "--config" ]] ; then
  # конфигурация
cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "namespace",
  "event":["add"]
}
]}
EOF
else
  # реакция:
  # узнать, какой namespace появился
  createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
  # создать в нём нужный секрет
  kubectl create -n ${createdNamespace} -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  ...
data:
  ...
EOF
fi

Одлично! Резултатот беше мало, убаво сценарио. За да го „оживеете“, остануваат уште два чекори: подгответе ја сликата и стартувајте ја во кластерот.

Подготовка на слика со кука

Ако ја погледнете скриптата, можете да видите дека се користат командите kubectl и jq. Ова значи дека сликата мора да ги има следниве работи: нашата кука, школка-оператор што ќе ги следи настаните и ќе ја извршува куката и командите што ги користи куката (kubectl и jq). Hub.docker.com веќе има готова слика во која се спакувани shell-operator, kubectl и jq. Останува само да се додаде едноставна кука Dockerfile:

$ cat Dockerfile
FROM flant/shell-operator:v1.0.0-beta.1-alpine3.9
ADD namespace-hook.sh /hooks

$ docker build -t registry.example.com/my-operator:v1 . 
$ docker push registry.example.com/my-operator:v1

Трчање во кластер

Ајде повторно да ја погледнеме куката и овојпат да запишеме какви дејства и со какви предмети врши во кластерот:

  1. се претплати на настани за создавање именски простор;
  2. создава тајна во именски простори различни од оној каде што е лансиран.

Излегува дека подлогата во која ќе биде лансирана нашата слика мора да има дозволи да ги прави овие дејства. Ова може да се направи со креирање на сопствена сметка за услуги. Дозволата мора да се направи во форма на ClusterRole и ClusterRoleBinding, бидејќи ние сме заинтересирани за објекти од целиот кластер.

Конечниот опис во YAML ќе изгледа вака:

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: monitor-namespaces-acc

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: monitor-namespaces
rules:
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get", "watch", "list"]
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list", "create", "patch"]

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: monitor-namespaces
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: monitor-namespaces
subjects:
  - kind: ServiceAccount
    name: monitor-namespaces-acc
    namespace: example-monitor-namespaces

Можете да ја стартувате собраната слика како едноставно распоредување:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-operator
spec:
  template:
    spec:
      containers:
      - name: my-operator
        image: registry.example.com/my-operator:v1
      serviceAccountName: monitor-namespaces-acc

За погодност, се создава посебен именски простор каде што ќе се стартува операторот на школка и ќе се применат креираните манифестации:

$ kubectl create ns example-monitor-namespaces
$ kubectl -n example-monitor-namespaces apply -f rbac.yaml
$ kubectl -n example-monitor-namespaces apply -f deployment.yaml

Тоа е сè: операторот на школка ќе започне, ќе се претплати на настани за создавање именски простор и ќе ја стартува куката кога е потребно.

Воведување на школка-оператор: создавањето оператори за Kubernetes штотуку стана полесно

Така, едноставна скрипта за школка се претвори во вистински оператор за Kubernetes и работи како дел од кластер. И сето тоа без сложениот процес на развој на оператори во Голанг:

Воведување на школка-оператор: создавањето оператори за Kubernetes штотуку стана полесно

Има уште една илустрација за ова прашање...Воведување на школка-оператор: создавањето оператори за Kubernetes штотуку стана полесно

Неговото значење подетално ќе го откриеме во една од следните публикации.

филтрирање

Следењето на објекти е добро, но често има потреба да се реагира менување на некои својства на објектот, на пример, за да го промените бројот на реплики во Deployment или да ги промените етикетите на објектите.

Кога ќе пристигне настан, операторот на школка го прима JSON манифестот на објектот. Можеме да ги избереме својствата што не интересираат во овој JSON и да ја стартуваме куката само кога се менуваат. Има поле за ова jqFilter, каде што треба да го наведете изразот jq што ќе се примени на JSON манифестот.

На пример, за да одговорите на промените во етикетите за објектите за распоредување, треба да го филтрирате полето labels надвор од теренот metadata. Конфигурацијата ќе биде вака:

cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "deployment",
  "event":["update"],
  "jqFilter": ".metadata.labels"
}
]}
EOF

Овој израз jqFilter го претвора долгиот JSON манифест на Deployment во краток JSON со ознаки:

Воведување на школка-оператор: создавањето оператори за Kubernetes штотуку стана полесно

школка-оператор ќе ја активира куката само кога ќе се промени овој краток JSON, а промените на другите својства ќе бидат игнорирани.

Контекс на лансирање на кука

Конфигурацијата на куката ви овозможува да наведете неколку опции за настани - на пример, 2 опции за настани од Kubernetes и 2 распореди:

{"onKubernetesEvent":[
  {"name":"OnCreatePod",
  "kind": "pod",
  "event":["add"]
  },
  {"name":"OnModifiedNamespace",
  "kind": "namespace",
  "event":["update"],
  "jqFilter": ".metadata.labels"
  }
],
"schedule": [
{ "name":"every 10 min",
  "crontab":"* */10 * * * *"
}, {"name":"on Mondays at 12:10",
"crontab": "* 10 12 * * 1"
]}

Мала дигресија: да, поддржува школка-оператор водење на скрипти во стилот на кронтаб. Повеќе детали може да се најдат во документација.

За да се направи разлика зошто куката е лансирана, операторот на школка создава привремена датотека и ја пренесува патеката до неа во променлива до куката BINDING_CONTEXT_TYPE. Датотеката содржи JSON опис на причината за вклучување на куката. На пример, на секои 10 минути куката ќе работи со следнава содржина:

[{ "binding": "every 10 min"}]

... а во понеделник ќе започне со ова:

[{ "binding": "every 10 min"}, { "binding": "on Mondays at 12:10"}]

За onKubernetesEvent Ќе има повеќе JSON предизвикувачи, бидејќи содржи опис на објектот:

[
 {
 "binding": "onCreatePod",
 "resourceEvent": "add",
 "resourceKind": "pod",
 "resourceName": "foo",
 "resourceNamespace": "bar"
 }
]

Содржината на полињата може да се разбере од нивните имиња, а повеќе детали може да се прочитаат во документација. Пример за добивање име на ресурс од поле resourceName користењето на jq веќе е прикажано во кука која реплицира тајни:

jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH

Можете да добиете и други полиња на сличен начин.

Што е следно?

Во проектното складиште, во /примери директориуми, има примери на куки кои се подготвени да работат на кластер. Кога пишувате свои куки, можете да ги користите како основа.

Постои поддршка за собирање метрика со помош на Прометеј - достапните метрики се опишани во делот МЕТРИКИ.

Како што може да претпоставите, школка-операторот е напишан во Go и дистрибуиран под лиценца со отворен код (Apache 2.0). Ќе бидеме благодарни за секаква развојна помош проект на GitHub: и ѕвезди, и прашања, и повлекување барања.

Подигнувајќи го превезот на тајноста, ќе ве информираме и дека школка-оператор е мал дел од нашиот систем што може да ги ажурира инсталираните додатоци во кластерот Кубернетес и да врши различни автоматски дејства. Прочитајте повеќе за овој систем раскажано буквално во понеделник на HighLoad++ 2019 во Санкт Петербург - наскоро ќе ги објавиме видеото и транскриптот од овој извештај.

Имаме план да го отвориме остатокот од овој систем: додатниот оператор и нашата колекција куки и модули. Патем, додаток-оператор е веќе достапно на github, но документацијата за тоа е се уште на пат. Издавањето на колекцијата на модули е планирано за лето.

Останете со нас!

PS

Прочитајте и на нашиот блог:

Извор: www.habr.com

Додадете коментар