Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Bu yil asosiy Evropa Kubernetes konferentsiyasi - KubeCon + CloudNativeCon Europe 2020 virtual bo'ldi. Biroq, formatning bunday o'zgarishi uzoq vaqtdan beri rejalashtirilgan "Boringmi? Bash! Shell-operator bilan tanishing” Ochiq kodli loyihamizga bag‘ishlangan qobiq operatori.

Nutqdan ilhomlangan ushbu maqola Kubernetes uchun operatorlarni yaratish jarayonini soddalashtirishga yondashuvni taqdim etadi va shell-operator yordamida minimal kuch bilan qanday qilib o'zingizni yaratishingiz mumkinligini ko'rsatadi.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Tanitish hisobot videosi (Ingliz tilida ~ 23 daqiqa, maqoladan ko'ra sezilarli darajada ma'lumotli) va undan matn ko'rinishidagi asosiy parcha. Bor!

Flant-da biz doimo hamma narsani optimallashtiramiz va avtomatlashtiramiz. Bugun biz yana bir qiziqarli kontseptsiya haqida gaplashamiz. Tanishish: bulutli mahalliy qobiq skripti!

Biroq, keling, bularning barchasi sodir bo'ladigan kontekstdan boshlaylik: Kubernetes.

Kubernetes API va kontrollerlar

Kubernetes-dagi API har bir turdagi ob'ekt uchun kataloglari bo'lgan fayl serveri sifatida taqdim etilishi mumkin. Ushbu serverdagi ob'ektlar (resurslar) YAML fayllari bilan ifodalanadi. Bundan tashqari, serverda uchta narsani qilish imkonini beruvchi asosiy API mavjud:

  • qabul qilish resurs turi va nomi bo'yicha;
  • o'zgartirish resurs (bu holda server faqat "to'g'ri" ob'ektlarni saqlaydi - barcha noto'g'ri tuzilgan yoki boshqa kataloglar uchun mo'ljallangan ob'ektlar o'chiriladi);
  • kuzatib boring resurs uchun (bu holda foydalanuvchi darhol uning joriy/yangilangan versiyasini oladi).

Shunday qilib, Kubernetes uchta asosiy usulga ega (YAML manifestlari uchun) o'ziga xos fayl serveri vazifasini bajaradi (ha, aslida boshqalar ham bor, lekin biz ularni hozircha o'tkazib yuboramiz).

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Muammo shundaki, server faqat ma'lumotlarni saqlashi mumkin. Ishlash uchun sizga kerak nazorat qiluvchi - Kubernetes dunyosidagi ikkinchi eng muhim va asosiy tushuncha.

Nazoratchilarning ikkita asosiy turi mavjud. Birinchisi Kubernetes-dan ma'lumot oladi, uni ichki mantiq bo'yicha qayta ishlaydi va uni K8s-ga qaytaradi. Ikkinchisi Kubernetesdan ma'lumot oladi, lekin birinchi turdan farqli o'laroq, ba'zi tashqi resurslarning holatini o'zgartiradi.

Keling, Kubernetes-da joylashtirishni yaratish jarayonini batafsil ko'rib chiqaylik:

  • Joylashtirish nazoratchisi (shu jumladan kube-controller-manager) Deployment haqida ma'lumot oladi va ReplicaSet ni yaratadi.
  • ReplicaSet ushbu ma'lumotlar asosida ikkita replika (ikki pod) yaratadi, ammo bu podalar hali rejalashtirilmagan.
  • Rejalashtiruvchi podkastlarni rejalashtiradi va ularning YAMLlariga tugun ma'lumotlarini qo'shadi.
  • Kubelets tashqi resursga o'zgartirishlar kiritadi (aytaylik, Docker).

Keyin bu ketma-ketlik teskari tartibda takrorlanadi: kubelet konteynerlarni tekshiradi, podning holatini hisoblab chiqadi va uni qaytarib yuboradi. ReplicaSet tekshirgichi holatni oladi va replika to'plamining holatini yangilaydi. Xuddi shu narsa Deployment Controller bilan sodir bo'ladi va foydalanuvchi nihoyat yangilangan (joriy) holatni oladi.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Shell-operator

Ma'lum bo'lishicha, Kubernetes turli kontrollerlarning birgalikdagi ishiga asoslangan (Kubernetes operatorlari ham kontrollerlar). Savol tug'iladi, minimal harakat bilan o'z operatoringizni qanday yaratish mumkin? Va bu erda biz ishlab chiqqanimiz yordamga keladi qobiq operatori. Bu tizim ma'murlariga tanish usullardan foydalangan holda o'z bayonotlarini yaratishga imkon beradi.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Oddiy misol: sirlarni nusxalash

Keling, oddiy misolni ko'rib chiqaylik.

Aytaylik, bizda Kubernetes klasteri bor. Unda nom maydoni mavjud default qandaydir sir bilan mysecret. Bundan tashqari, klasterda boshqa nom maydonlari mavjud. Ulardan ba'zilari o'ziga xos yorliq bilan biriktirilgan. Bizning maqsadimiz Secretni yorliqli nomlar bo'shliqlariga nusxalashdir.

Vazifani murakkablashtiradi, chunki klasterda yangi nomlar bo'shliqlari paydo bo'lishi mumkin va ularning ba'zilarida bu belgi bo'lishi mumkin. Boshqa tomondan, yorliq o'chirilganda, Secret ham o'chirilishi kerak. Bunga qo'shimcha ravishda, Sirning o'zi ham o'zgarishi mumkin: bu holda, yangi Secret barcha nomlar bo'shliqlariga teglar bilan ko'chirilishi kerak. Agar biron bir nom maydonida Secret tasodifan o'chirilsa, bizning operatorimiz uni darhol tiklashi kerak.

Vazifa tuzilgandan so'ng, uni qobiq operatori yordamida amalga oshirishni boshlash vaqti keldi. Lekin birinchi navbatda qobiq operatorining o'zi haqida bir necha so'z aytishga arziydi.

Shell-operator qanday ishlaydi

Kubernetes-dagi boshqa ish yuklari singari, shell-operator ham o'z podida ishlaydi. Katalogdagi ushbu podda /hooks bajariladigan fayllar saqlanadi. Bular Bash, Python, Ruby va boshqalardagi skriptlar bo'lishi mumkin. Biz bunday bajariladigan fayllarni ilgaklar deb ataymiz (ilgaklar).

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Shell-operator Kubernetes voqealariga obuna bo'ladi va bizga kerak bo'lgan voqealarga javoban ushbu ilgaklarni ishga tushiradi.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Shell-operator qaysi kancani va qachon ishga tushirishni qanday biladi? Gap shundaki, har bir kanca ikki bosqichga ega. Ishga tushirish vaqtida qobiq operatori barcha ilgaklarni argument bilan boshqaradi --config Bu konfiguratsiya bosqichi. Va undan keyin ilgaklar odatdagi tarzda ishga tushiriladi - ular bog'langan voqealarga javoban. Ikkinchi holda, ilgak bog'lovchi kontekstni oladi (majburiy kontekst) - JSON formatidagi ma'lumotlar, biz quyida batafsilroq gaplashamiz.

Bashda operator yaratish

Endi biz amalga oshirishga tayyormiz. Buning uchun biz ikkita funktsiyani yozishimiz kerak (aytmoqchi, tavsiya qilamiz kutubxona shell_lib, bu Bash-da yozish ilgaklarini sezilarli darajada osonlashtiradi):

  • birinchisi konfiguratsiya bosqichi uchun kerak - u majburiy kontekstni ko'rsatadi;
  • ikkinchisi kancaning asosiy mantig'ini o'z ichiga oladi.

#!/bin/bash

source /shell_lib.sh

function __config__() {
  cat << EOF
    configVersion: v1
    # BINDING CONFIGURATION
EOF
}

function __main__() {
  # THE LOGIC
}

hook::run "$@"

Keyingi qadam, bizga qanday ob'ektlar kerakligini hal qilishdir. Bizning holatlarimizda biz quyidagilarni kuzatishimiz kerak:

  • o'zgarishlar uchun manba siri;
  • klasterdagi barcha nomlar bo'shliqlari, shuning uchun qaysi biriga yorliq yopishtirilganligini bilib olasiz;
  • maqsadli sirlar, ularning barchasi manba siri bilan hamohang bo'lishini ta'minlash.

Yashirin manbaga obuna bo'ling

Buning uchun ulanish konfiguratsiyasi juda oddiy. Biz bu nom bilan Secretga qiziqayotganimizni bildiramiz mysecret nom maydonida default:

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

function __config__() {
  cat << EOF
    configVersion: v1
    kubernetes:
    - name: src_secret
      apiVersion: v1
      kind: Secret
      nameSelector:
        matchNames:
        - mysecret
      namespace:
        nameSelector:
          matchNames: ["default"]
      group: main
EOF

Natijada, manba siri o'zgarganda ilgak ishga tushadi (src_secret) va quyidagi majburiy kontekstni oling:

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Ko'rib turganingizdek, unda nom va butun ob'ekt mavjud.

Nom maydonlarini kuzatish

Endi siz nom maydonlariga obuna bo'lishingiz kerak. Buning uchun biz quyidagi bog'lash konfiguratsiyasini belgilaymiz:

- name: namespaces
  group: main
  apiVersion: v1
  kind: Namespace
  jqFilter: |
    {
      namespace: .metadata.name,
      hasLabel: (
       .metadata.labels // {} |  
         contains({"secret": "yes"})
      )
    }
  group: main
  keepFullObjectsInMemory: false

Ko'rib turganingizdek, konfiguratsiyada nom bilan yangi maydon paydo bo'ldi jqFilter. Nomidan ko'rinib turibdiki, jqFilter barcha keraksiz ma'lumotlarni filtrlaydi va bizni qiziqtirgan maydonlar bilan yangi JSON ob'ektini yaratadi. Shunga o'xshash konfiguratsiyaga ega kanca quyidagi bog'lovchi kontekstni oladi:

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

U massivni o'z ichiga oladi filterResults klasterdagi har bir nom maydoni uchun. Mantiqiy o'zgaruvchi hasLabel yorliq berilgan nomlar maydoniga biriktirilganligini bildiradi. Selektor keepFullObjectsInMemory: false to'liq ob'ektlarni xotirada saqlashga hojat yo'qligini ko'rsatadi.

Maqsad sirlarini kuzatish

Biz izohi ko'rsatilgan barcha sirlarga obuna bo'lamiz managed-secret: "yes" (bu bizning maqsadimiz dst_secrets):

- name: dst_secrets
  apiVersion: v1
  kind: Secret
  labelSelector:
    matchLabels:
      managed-secret: "yes"
  jqFilter: |
    {
      "namespace":
        .metadata.namespace,
      "resourceVersion":
        .metadata.annotations.resourceVersion
    }
  group: main
  keepFullObjectsInMemory: false

Bunday holda jqFilter nom maydoni va parametrdan tashqari barcha ma'lumotlarni filtrlaydi resourceVersion. Oxirgi parametr sirni yaratishda annotatsiyaga o'tkazildi: bu sirlarning versiyalarini solishtirish va ularni yangilab turish imkonini beradi.

Shu tarzda sozlangan kanca, bajarilganda, yuqorida tavsiflangan uchta bog'lovchi kontekstni oladi. Ularni bir xil surat sifatida ko'rish mumkin (surat) klaster.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Ushbu ma'lumotlarning barchasiga asoslanib, asosiy algoritm ishlab chiqilishi mumkin. U barcha nom maydonlarida takrorlanadi va:

  • agar hasLabel masalalar true joriy nom maydoni uchun:
    • global sirni mahalliy bilan solishtiradi:
      • agar ular bir xil bo'lsa, u hech narsa qilmaydi;
      • agar ular farq qilsa - bajaradi kubectl replace yoki create;
  • agar hasLabel masalalar false joriy nom maydoni uchun:
    • Secret berilgan nomlar maydonida yo'qligiga ishonch hosil qiladi:
      • agar mahalliy sir mavjud bo'lsa, uni o'chirib tashlang kubectl delete;
      • mahalliy sir aniqlanmasa, u hech narsa qilmaydi.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Bash-da algoritmni amalga oshirish saytimizda yuklab olishingiz mumkin misollar bilan omborlar.

Shunday qilib, biz 35 qatorli YAML konfiguratsiyasi va bir xil miqdordagi Bash kodidan foydalangan holda oddiy Kubernetes kontrollerini yaratishga muvaffaq bo'ldik! Shell-operatorning vazifasi ularni bir-biriga bog'lashdir.

Biroq, sirlarni nusxalash yordamchi dasturni qo'llashning yagona sohasi emas. Uning nimalarga qodirligini ko'rsatish uchun yana bir nechta misollar.

1-misol: ConfigMap-ga o'zgartirishlar kiritish

Keling, uchta bo'lakdan iborat bo'lgan Deploymentni ko'rib chiqaylik. Podlar ba'zi konfiguratsiyalarni saqlash uchun ConfigMap-dan foydalanadi. Podlar ishga tushirilganda, ConfigMap ma'lum bir holatda edi (uni v.1 deb ataymiz). Shunga ko'ra, barcha podlar ConfigMapning ushbu maxsus versiyasidan foydalanadi.

Keling, ConfigMap o'zgargan deb faraz qilaylik (v.2). Biroq, podlar ConfigMap ning oldingi versiyasidan (v.1) foydalanadi:

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Qanday qilib ularni yangi ConfigMap (v.2) ga o'tishga majburlashim mumkin? Javob oddiy: shablondan foydalaning. Keling, bo'limga nazorat summasi izohini qo'shamiz template Joylashtirish konfiguratsiyasi:

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Natijada, ushbu nazorat summasi barcha podslarda qayd qilinadi va u Deployment bilan bir xil bo'ladi. Endi siz faqat ConfigMap o'zgarganda izohni yangilashingiz kerak. Va bu holda qobiq-operator yordam beradi. Sizga kerak bo'lgan yagona narsa dastur ConfigMap-ga obuna bo'ladigan va nazorat summasini yangilaydigan kanca.

Agar foydalanuvchi ConfigMap-ga o'zgartirishlar kiritsa, shell-operator ularni sezadi va nazorat summasini qayta hisoblab chiqadi. Shundan so'ng Kubernetesning sehri o'ynaydi: orkestr podani o'ldiradi, yangisini yaratadi va uning paydo bo'lishini kutadi. Ready, va keyingisiga o'tadi. Natijada, Deployment sinxronlashtiriladi va ConfigMapning yangi versiyasiga o'tadi.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

2-misol: Maxsus resurs ta'riflari bilan ishlash

Ma'lumki, Kubernetes sizga moslashtirilgan turdagi ob'ektlarni yaratishga imkon beradi. Misol uchun, siz turdagi yaratishingiz mumkin MysqlDatabase. Aytaylik, bu turdagi ikkita metadata parametrlari mavjud: name и namespace.

apiVersion: example.com/v1alpha1
kind: MysqlDatabase
metadata:
  name: foo
  namespace: bar

Bizda MySQL ma'lumotlar bazalarini yaratishimiz mumkin bo'lgan turli nomlar bo'shliqlari bo'lgan Kubernetes klasteri mavjud. Bunday holda, qobiq-operator resurslarni kuzatish uchun ishlatilishi mumkin MysqlDatabase, ularni MySQL serveriga ulash va klasterning kerakli va kuzatilgan holatlarini sinxronlashtirish.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

3-misol: Klaster tarmoq monitoringi

Ma'lumki, ping-dan foydalanish tarmoqni kuzatishning eng oddiy usuli hisoblanadi. Ushbu misolda biz shell-operator yordamida bunday monitoringni qanday amalga oshirishni ko'rsatamiz.

Avvalo, siz tugunlarga obuna bo'lishingiz kerak. Shell operatori har bir tugunning nomi va IP-manzilini talab qiladi. Ularning yordami bilan u bu tugunlarni ping qiladi.

configVersion: v1
kubernetes:
- name: nodes
  apiVersion: v1
  kind: Node
  jqFilter: |
    {
      name: .metadata.name,
      ip: (
       .status.addresses[] |  
        select(.type == "InternalIP") |
        .address
      )
    }
  group: main
  keepFullObjectsInMemory: false
  executeHookOnEvent: []
schedule:
- name: every_minute
  group: main
  crontab: "* * * * *"

Parametr executeHookOnEvent: [] kancaning har qanday hodisaga (ya'ni, tugunlarni o'zgartirish, qo'shish, o'chirishga javoban) ishlashiga to'sqinlik qiladi. Biroq, u yuguradi (va tugunlar ro'yxatini yangilang) Rejalashtirilgan - har daqiqada, sohada belgilanganidek schedule.

Endi savol tug'iladi, biz paketlarni yo'qotish kabi muammolarni qanday aniq bilamiz? Keling, kodni ko'rib chiqaylik:

function __main__() {
  for i in $(seq 0 "$(context::jq -r '(.snapshots.nodes | length) - 1')"); do
    node_name="$(context::jq -r '.snapshots.nodes['"$i"'].filterResult.name')"
    node_ip="$(context::jq -r '.snapshots.nodes['"$i"'].filterResult.ip')"
    packets_lost=0
    if ! ping -c 1 "$node_ip" -t 1 ; then
      packets_lost=1
    fi
    cat >> "$METRICS_PATH" <<END
      {
        "name": "node_packets_lost",
        "add": $packets_lost,
        "labels": {
          "node": "$node_name"
        }
      }
END
  done
}

Biz tugunlar ro'yxatini takrorlaymiz, ularning nomlari va IP manzillarini olamiz, ularga ping yuboramiz va natijalarni Prometeyga yuboramiz. Shell-operator ko'rsatkichlarni Prometeyga eksport qilishi mumkin, ularni muhit o'zgaruvchisida ko'rsatilgan yo'lga muvofiq joylashgan faylga saqlash $METRICS_PATH.

Mana bunday klasterda oddiy tarmoq monitoringi uchun operator qilishingiz mumkin.

Navbat mexanizmi

Ushbu maqola qobiq operatoriga o'rnatilgan yana bir muhim mexanizmni tasvirlamasdan to'liq bo'lmaydi. Tasavvur qiling-a, u klasterdagi hodisaga javoban qandaydir kancani bajaradi.

  • Agar bir vaqtning o'zida klasterda biror narsa sodir bo'lsa nima bo'ladi? yana bir narsa voqea?
  • Shell-operator kancaning boshqa nusxasini ishga tushiradimi?
  • Agar, aytaylik, klasterda birdaniga beshta voqea sodir bo'lsa-chi?
  • Shell-operator ularni parallel ravishda qayta ishlaydimi?
  • Xotira va protsessor kabi iste'mol qilinadigan resurslar haqida nima deyish mumkin?

Yaxshiyamki, shell-operator o'rnatilgan navbat mexanizmiga ega. Barcha hodisalar navbatga qo'yiladi va ketma-ket qayta ishlanadi.

Buni misollar bilan tushuntirib beraylik. Aytaylik, bizda ikkita ilgak bor. Birinchi voqea birinchi kancaga o'tadi. Uni qayta ishlash tugallangach, navbat oldinga siljiydi. Keyingi uchta voqea ikkinchi kancaga yo'naltiriladi - ular navbatdan olib tashlanadi va unga "to'plam" ga kiritiladi. Ya'ni hook bir qator hodisalarni oladi — yoki, aniqrogʻi, bogʻlovchi kontekstlar massivi.

Shuningdek, bular voqealarni bitta katta birlashtirish mumkin. Buning uchun parametr javobgardir group majburiy konfiguratsiyada.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Siz istalgan sondagi navbatlar/kancalar va ularning turli kombinatsiyalarini yaratishingiz mumkin. Misol uchun, bitta navbat ikkita kanca bilan ishlashi mumkin yoki aksincha.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Sizga kerak bo'lgan yagona narsa maydonni mos ravishda sozlashdir queue majburiy konfiguratsiyada. Agar navbat nomi ko'rsatilmagan bo'lsa, ilgak standart navbatda ishlaydi (default). Ushbu navbat mexanizmi ilgaklar bilan ishlashda barcha resurslarni boshqarish muammolarini to'liq hal qilish imkonini beradi.

xulosa

Biz qobiq-operator nima ekanligini tushuntirdik, undan qanday qilib tez va oson Kubernetes operatorlarini yaratish mumkinligini ko'rsatdik va undan foydalanishga bir nechta misollar keltirdik.

Shell-operator haqida batafsil ma'lumot, shuningdek uni ishlatish bo'yicha tezkor qo'llanma tegishli bo'limda mavjud. GitHub-dagi omborlar. Savollar bo'yicha biz bilan bog'lanishdan tortinmang: ularni maxsus bo'limda muhokama qilishingiz mumkin Telegram guruhi (rus tilida) yoki ichida bu forum (inzgliz tilida).

Va agar sizga yoqqan bo'lsa, biz har doim GitHub-da yangi nashrlarni/PR/yulduzlarni ko'rishdan xursandmiz, aytmoqchi, siz boshqalarni topishingiz mumkin. qiziqarli loyihalar. Ularning orasida alohida ta'kidlash kerak addon-operator, bu shell-operatorning katta ukasi. Ushbu yordamchi dastur qo'shimchalarni o'rnatish uchun Helm diagrammalaridan foydalanadi, yangilanishlarni etkazib berishi va turli diagramma parametrlarini/qiymatlarini kuzatishi, diagrammalarni o'rnatish jarayonini boshqarishi va klasterdagi hodisalarga javoban ularni o'zgartirishi mumkin.

Boringmi? Bash! Shell-operator bilan tanishing (KubeCon EU'2020 sharhi va video hisoboti)

Video va slaydlar

Spektakldan video (~23 daqiqa):


Hisobot taqdimoti:

PS

Shuningdek, bizning blogimizda o'qing:

Manba: www.habr.com

a Izoh qo'shish