Shell-operator bilan tanishish: Kubernetes uchun operatorlarni yaratish endi osonlashdi

Bizning blogimizda allaqachon maqolalar haqida gapirilgan Kubernetesdagi operator imkoniyatlari va qanday oddiy operatorni o'zingiz yozing. Bu safar biz sizning e'tiboringizga operatorlarni yaratishni juda oson darajaga olib chiqadigan Open Source yechimimizni taqdim qilmoqchimiz - tekshiring qobiq operatori!

Nima uchun?

Shell-operator g'oyasi juda oddiy: Kubernetes ob'ektlaridan voqealarga obuna bo'ling va bu hodisalar qabul qilinganda, tashqi dasturni ishga tushiring va unga voqea haqida ma'lumot bering:

Shell-operator bilan tanishish: Kubernetes uchun operatorlarni yaratish endi osonlashdi

Bunga ehtiyoj, klasterlarning ishlashi paytida biz haqiqatan ham to'g'ri avtomatlashtirishni xohlagan kichik vazifalar paydo bo'la boshlaganda paydo bo'ldi. Bu kichik vazifalarning barchasi oddiy bash skriptlari yordamida hal qilindi, garchi siz bilganingizdek, Golangda operatorlarni yozish yaxshiroqdir. Shubhasiz, har bir bunday kichik vazifa uchun operatorni to'liq miqyosda rivojlantirishga sarmoya kiritish samarasiz bo'ladi.

Operator 15 daqiqada

Keling, Kubernetes klasterida nimani avtomatlashtirish mumkinligi va shell-operator qanday yordam berishi mumkinligi haqidagi misolni ko'rib chiqaylik. Bunga misol bo'lishi mumkin: docker registriga kirish uchun sirni takrorlash.

Shaxsiy registrdagi rasmlardan foydalanadigan podkastlar o'zlarining manifestlarida ro'yxatga olish kitobiga kirish uchun ma'lumotlarga ega bo'lgan sirga havolani o'z ichiga olishi kerak. Ushbu sir podkastlarni yaratishdan oldin har bir nom maydonida yaratilishi kerak. Buni qo'lda qilish mumkin, ammo agar biz dinamik muhitlarni o'rnatsak, unda bitta dastur uchun nom maydoni juda ko'p bo'ladi. Va agar 2-3 ta ilova bo'lmasa ... sirlar soni juda ko'p bo'ladi. Va sirlar haqida yana bir narsa: men vaqti-vaqti bilan ro'yxatga olish kitobiga kirish uchun kalitni o'zgartirmoqchiman. Natijada, qo'lda operatsiyalar yechim sifatida butunlay samarasiz — sirlarni yaratish va yangilashni avtomatlashtirishimiz kerak.

Oddiy avtomatlashtirish

Keling, har N soniyada bir marta ishlaydigan va nomlar bo'shliqlarini sir borligini tekshiradigan qobiq skriptini yozaylik va agar sir bo'lmasa, u yaratilgan. Ushbu yechimning afzalligi shundaki, u crondagi qobiq skriptiga o'xshaydi - bu hamma uchun klassik va tushunarli yondashuv. Salbiy tomoni shundaki, uni ishga tushirish oralig'ida yangi nomlar maydoni yaratilishi mumkin va u bir muncha vaqt sirsiz qoladi, bu esa podlarni ishga tushirishda xatolarga olib keladi.

Shell-operator bilan avtomatlashtirish

Bizning skriptimiz to'g'ri ishlashi uchun nomlar maydoni qo'shilganda klassik cron ishga tushirilishi ishga tushirilishi bilan almashtirilishi kerak: bu holda siz uni ishlatishdan oldin sir yaratishingiz mumkin. Keling, buni shell-operator yordamida qanday amalga oshirishni ko'rib chiqaylik.

Birinchidan, skriptni ko'rib chiqaylik. Shell-operator atamasidagi skriptlar kancalar deb ataladi. Bayroq bilan yugurishda har bir ilgak --config shell-operatorga uning bog'lanishlari haqida ma'lumot beradi, ya'ni. u qanday voqealar bo'yicha ishga tushirilishi kerak. Bizning holatlarimizda biz foydalanamiz onKubernetesEvent:

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

Bu erda biz voqealarni qo'shishdan manfaatdor ekanligimiz tasvirlangan (add) turdagi ob'ektlar namespace.

Endi siz voqea sodir bo'lganda bajariladigan kodni qo'shishingiz kerak:

#!/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

Ajoyib! Natijada kichik, chiroyli skript paydo bo'ldi. Uni "jonlantirish" uchun ikkita qadam qoldi: tasvirni tayyorlash va uni klasterda ishga tushirish.

Tasvirni kanca bilan tayyorlash

Agar siz skriptga qarasangiz, buyruqlar ishlatilganligini ko'rishingiz mumkin kubectl и jq. Bu tasvir quyidagi narsalarga ega bo'lishi kerak degan ma'noni anglatadi: bizning kancamiz, hodisalarni kuzatuvchi va kancani ishga tushiradigan qobiq-operator va kanca tomonidan ishlatiladigan buyruqlar (kubectl va jq). Hub.docker.com allaqachon shell-operator, kubectl va jq paketlangan tayyor tasvirga ega. Qolgan narsa oddiy kanca qo'shishdir 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

Klasterda yugurish

Keling, yana kancaga qaraylik va bu safar u klasterda qanday harakatlar va qanday ob'ektlar bilan bajarishini yozing:

  1. nomlar maydonini yaratish voqealariga obuna bo'ladi;
  2. ishga tushirilganidan boshqa nom maydonlarida sir yaratadi.

Ma'lum bo'lishicha, bizning rasmimiz ishga tushiriladigan podda bu amallarni bajarish uchun ruxsat bo'lishi kerak. Buni shaxsiy ServiceAccount yaratish orqali amalga oshirish mumkin. Ruxsat ClusterRole va ClusterRoleBinding shaklida amalga oshirilishi kerak, chunki biz butun klasterdagi ob'ektlarga qiziqamiz.

YAML-dagi yakuniy tavsif quyidagicha ko'rinadi:

---
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

Siz yig'ilgan tasvirni oddiy Deployment sifatida ishga tushirishingiz mumkin:

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

Qulaylik uchun shell-operator ishga tushiriladigan va yaratilgan manifestlar qo'llaniladigan alohida nom maydoni yaratiladi:

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

Hammasi shu: qobiq operatori ishga tushadi, nomlar maydonini yaratish voqealariga obuna bo'ladi va kerak bo'lganda kancani ishga tushiradi.

Shell-operator bilan tanishish: Kubernetes uchun operatorlarni yaratish endi osonlashdi

Shunday qilib, oddiy qobiq skripti Kubernetes uchun haqiqiy operatorga aylandi va klasterning bir qismi sifatida ishlaydi. Va bularning barchasi Golangda operatorlarni ishlab chiqishning murakkab jarayonisiz:

Shell-operator bilan tanishish: Kubernetes uchun operatorlarni yaratish endi osonlashdi

Bu masala bo'yicha yana bir misol bor ...Shell-operator bilan tanishish: Kubernetes uchun operatorlarni yaratish endi osonlashdi

Uning ma'nosini keyingi nashrlardan birida batafsilroq ochib beramiz.

filtrlash

Ob'ektlarni kuzatish yaxshi, lekin ko'pincha ularga munosabat bildirish kerak ob'ektning ba'zi xususiyatlarini o'zgartirish, masalan, Deployment'dagi replikalar sonini o'zgartirish yoki ob'ekt teglarini o'zgartirish uchun.

Voqea kelganda, qobiq operatori ob'ektning JSON manifestini oladi. Biz ushbu JSON-da bizni qiziqtiradigan xususiyatlarni tanlashimiz va kancani ishga tushirishimiz mumkin faqatgina ular o'zgarganda. Buning uchun maydon mavjud jqFilter, bu erda JSON manifestiga qo'llaniladigan jq ifodasini belgilashingiz kerak.

Masalan, Deployment ob'ektlari uchun teglardagi o'zgarishlarga javob berish uchun siz maydonni filtrlashingiz kerak labels maydondan tashqarida metadata. Konfiguratsiya quyidagicha bo'ladi:

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

Ushbu jqFilter ifodasi Deploymentning uzun JSON manifestini teglar bilan qisqa JSONga aylantiradi:

Shell-operator bilan tanishish: Kubernetes uchun operatorlarni yaratish endi osonlashdi

shell-operator faqat ushbu qisqa JSON o'zgarganda kancani ishga tushiradi va boshqa xususiyatlarga o'zgartirishlar e'tiborga olinmaydi.

Hookni ishga tushirish konteksti

Kanca konfiguratsiyasi sizga voqealar uchun bir nechta variantni belgilash imkonini beradi - masalan, Kubernetes-dan tadbirlar uchun 2 ta variant va 2 ta jadval:

{"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"
]}

Kichkina chekinish: ha, shell-operator qo'llab-quvvatlaydi crontab uslubidagi skriptlarni ishga tushirish. Batafsil ma'lumotni sahifada topishingiz mumkin hujjatlar.

Ilgak nima uchun ishga tushirilganligini aniqlash uchun shell-operator vaqtinchalik fayl yaratadi va unga o'zgaruvchiga yo'lni kancaga uzatadi. BINDING_CONTEXT_TYPE. Faylda kancani ishga tushirish sababining JSON tavsifi mavjud. Masalan, har 10 daqiqada kanca quyidagi tarkib bilan ishlaydi:

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

... va dushanba kuni u quyidagicha boshlanadi:

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

uchun onKubernetesEvent Ko'proq JSON triggerlari bo'ladi, chunki u ob'ektning tavsifini o'z ichiga oladi:

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

Maydonlarning mazmunini ularning nomlaridan tushunish mumkin va batafsil ma'lumotni o'qish mumkin hujjatlar. Maydondan manba nomini olishga misol resourceName jq dan foydalanish sirlarni takrorlaydigan kancada allaqachon ko'rsatilgan:

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

Boshqa maydonlarni ham xuddi shunday tarzda olishingiz mumkin.

Keyin nima?

Loyiha omborida, in /kataloglarga misollar, klasterda ishlashga tayyor bo'lgan ilgaklar misollari mavjud. O'zingizning kancalaringizni yozishda siz ularni asos sifatida ishlatishingiz mumkin.

Prometey yordamida ko'rsatkichlarni yig'ish uchun yordam mavjud - mavjud ko'rsatkichlar bo'limda tasvirlangan METRIKA.

Siz taxmin qilganingizdek, shell-operator Go-da yozilgan va Open Source litsenziyasi (Apache 2.0) ostida tarqatilgan. Har qanday rivojlanish yordami uchun minnatdor bo'lamiz GitHub-dagi loyiha: va yulduzlar, va masalalar, va pull so'rovlar.

Maxfiylik pardasini ko'tarib, biz sizga shell-operator ekanligini ham ma'lum qilamiz kichik Kubernetes klasterida o'rnatilgan qo'shimchalarni yangilab turishi va turli xil avtomatik harakatlarni amalga oshirishi mumkin bo'lgan tizimimizning bir qismi. Ushbu tizim haqida ko'proq o'qing dedi tom ma'noda dushanba kuni Sankt-Peterburgdagi HighLoad++ 2019 da - biz tez orada ushbu hisobotning videosi va stenogrammasini e'lon qilamiz.

Bizda ushbu tizimning qolgan qismini ochish rejamiz bor: addon-operator va bizning ilgaklar va modullar to'plamimiz. Aytgancha, addon-operator allaqachon mavjud github da mavjud, lekin u uchun hujjatlar hali ham yo'lda. Modullar to'plamining chiqarilishi yozda rejalashtirilgan.

Yangiliklarni kuzatib boring, xabardor bo'lib boring; Biz bilan qoling!

PS

Shuningdek, bizning blogimizda o'qing:

Manba: www.habr.com

a Izoh qo'shish