Ang ideya ng isang shell-operator ay medyo simple: mag-subscribe sa mga kaganapan mula sa mga bagay ng Kubernetes, at kapag natanggap ang mga kaganapang ito, maglunsad ng isang panlabas na programa, na nagbibigay ng impormasyon tungkol sa kaganapan:
Ang pangangailangan para dito ay lumitaw nang, sa panahon ng pagpapatakbo ng mga kumpol, nagsimulang lumitaw ang maliliit na gawain na talagang gusto naming i-automate sa tamang paraan. Ang lahat ng maliliit na gawaing ito ay nalutas gamit ang mga simpleng bash script, bagaman, tulad ng alam mo, mas mahusay na magsulat ng mga operator sa Golang. Malinaw, ang pamumuhunan sa ganap na pagpapaunlad ng isang operator para sa bawat ganoong maliit na gawain ay hindi magiging epektibo.
Operator sa loob ng 15 minuto
Tingnan natin ang isang halimbawa ng kung ano ang maaaring i-automate sa isang Kubernetes cluster at kung paano makakatulong ang shell-operator. Ang isang halimbawa ay ang sumusunod: pagkopya ng isang lihim upang ma-access ang registry ng docker.
Ang mga pod na gumagamit ng mga larawan mula sa isang pribadong registry ay dapat maglaman sa kanilang manifest ng isang link sa isang lihim na may data para sa pag-access sa registry. Ang lihim na ito ay dapat gawin sa bawat namespace bago gumawa ng mga pod. Maaari itong gawin nang manu-mano, ngunit kung magse-set up tayo ng mga dynamic na kapaligiran, magiging marami ang namespace para sa isang application. At kung wala ring 2-3 application... ang bilang ng mga sikreto ay nagiging napakalaki. At isa pang bagay tungkol sa mga lihim: Gusto kong baguhin ang susi upang ma-access ang pagpapatala sa pana-panahon. Sa bandang huli, mga manu-manong operasyon bilang solusyon ganap na hindi epektibo — kailangan nating i-automate ang paglikha at pag-update ng mga lihim.
Simpleng automation
Sumulat tayo ng shell script na tumatakbo nang isang beses bawat N segundo at sinusuri ang mga namespace para sa pagkakaroon ng isang lihim, at kung walang sikreto, ito ay nilikha. Ang bentahe ng solusyon na ito ay mukhang isang shell script sa cron - isang klasiko at naiintindihan na diskarte sa lahat. Ang downside ay na sa pagitan sa pagitan ng mga paglulunsad nito ay maaaring malikha ang isang bagong namespace at sa loob ng ilang panahon ay mananatili itong walang lihim, na hahantong sa mga pagkakamali sa paglulunsad ng mga pod.
Automation gamit ang shell-operator
Para gumana nang tama ang aming script, kailangang mapalitan ng paglulunsad ang classic na cron launch kapag may naidagdag na namespace: sa kasong ito, maaari kang gumawa ng lihim bago ito gamitin. Tingnan natin kung paano ito ipatupad gamit ang shell-operator.
Una, tingnan natin ang script. Ang mga script sa mga termino ng shell-operator ay tinatawag na mga kawit. Bawat kawit kapag tumakbo na may bandila --config nagpapaalam sa shell-operator tungkol sa mga binding nito, i.e. sa kung anong mga kaganapan ang dapat itong ilunsad. Sa aming kaso gagamitin namin onKubernetesEvent:
#!/bin/bash
if [[ $1 == "--config" ]] ; then
cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "namespace",
"event":["add"]
}
]}
EOF
fi
Inilalarawan dito na kami ay interesado sa pagdaragdag ng mga kaganapan (add) mga bagay ng uri namespace.
Ngayon ay kailangan mong idagdag ang code na isasagawa kapag nangyari ang kaganapan:
#!/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
Malaki! Ang resulta ay isang maliit, magandang script. Upang "muling buhayin" ito, may dalawang hakbang na natitira: ihanda ang imahe at ilunsad ito sa cluster.
Paghahanda ng isang imahe na may kawit
Kung titingnan mo ang script, makikita mo na ang mga utos ay ginagamit kubectl и jq. Nangangahulugan ito na ang imahe ay dapat magkaroon ng mga sumusunod na bagay: ang aming hook, isang shell-operator na makikinig sa mga kaganapan at magpapatakbo ng hook, at ang mga utos na ginagamit ng hook (kubectl at jq). Ang Hub.docker.com ay mayroon nang yari na imahe kung saan naka-package ang shell-operator, kubectl at jq. Ang natitira na lang ay magdagdag ng isang simpleng kawit Dockerfile:
Tingnan natin muli ang hook at sa pagkakataong ito ay isulat kung anong mga aksyon at kung anong mga bagay ang ginagawa nito sa cluster:
nag-subscribe sa mga kaganapan sa paglikha ng namespace;
lumilikha ng isang lihim sa mga namespace maliban sa kung saan ito inilunsad.
Lumalabas na ang pod kung saan ilulunsad ang aming larawan ay dapat may mga pahintulot na gawin ang mga pagkilos na ito. Magagawa ito sa pamamagitan ng paglikha ng iyong sariling ServiceAccount. Ang pahintulot ay dapat gawin sa anyo ng ClusterRole at ClusterRoleBinding, dahil interesado kami sa mga bagay mula sa buong kumpol.
Ang huling paglalarawan sa YAML ay magiging ganito:
Iyon lang: magsisimula ang shell-operator, mag-subscribe sa mga kaganapan sa paglikha ng namespace at patakbuhin ang hook kapag kinakailangan.
Kaya, ang ang isang simpleng script ng shell ay naging isang tunay na operator para sa Kubernetes at gumagana bilang bahagi ng isang kumpol. At lahat ng ito nang walang kumplikadong proseso ng pagbuo ng mga operator sa Golang:
May isa pang paglalarawan sa bagay na ito...
Ilalahad namin ang kahulugan nito nang mas detalyado sa isa sa mga sumusunod na publikasyon.
pagsasala
Mahusay ang pagsubaybay sa mga bagay, ngunit madalas na kailangang tumugon pagbabago ng ilang mga katangian ng bagay, halimbawa, upang baguhin ang bilang ng mga replika sa Deployment o upang baguhin ang mga label ng bagay.
Kapag dumating ang isang kaganapan, natatanggap ng shell-operator ang JSON manifest ng object. Maaari naming piliin ang mga katangian na interesado sa amin sa JSON na ito at patakbuhin ang hook lamang kapag nagbago sila. Mayroong isang larangan para dito jqFilter, kung saan kailangan mong tukuyin ang jq expression na ilalapat sa JSON manifest.
Halimbawa, upang tumugon sa mga pagbabago sa mga label para sa mga Deployment object, kailangan mong i-filter ang field labels palabas ng field metadata. Ang config ay magiging ganito:
Ginagawa ng expression na jqFilter na ito ang mahabang JSON manifest ng Deployment sa maikling JSON na may mga label:
Ang shell-operator ay tatakbo lamang sa hook kapag ang maikling JSON na ito ay nagbago, at ang mga pagbabago sa iba pang mga katangian ay hindi papansinin.
Konteksto ng paglulunsad ng Hook
Binibigyang-daan ka ng hook config na tumukoy ng ilang opsyon para sa mga kaganapan - halimbawa, 2 opsyon para sa mga kaganapan mula sa Kubernetes at 2 iskedyul:
Isang maliit na digression: oo, sinusuportahan ng shell-operator nagpapatakbo ng mga script ng istilong crontab. Higit pang mga detalye ay matatagpuan sa dokumentasyon.
Upang makilala kung bakit inilunsad ang hook, ang shell-operator ay gumagawa ng isang pansamantalang file at ipinapasa ang path dito sa isang variable sa hook BINDING_CONTEXT_TYPE. Ang file ay naglalaman ng isang paglalarawan ng JSON ng dahilan ng pagpapatakbo ng hook. Halimbawa, bawat 10 minuto tatakbo ang hook na may sumusunod na nilalaman:
Ang mga nilalaman ng mga patlang ay maaaring maunawaan mula sa kanilang mga pangalan, at higit pang mga detalye ay maaaring basahin sa dokumentasyon. Isang halimbawa ng pagkuha ng pangalan ng mapagkukunan mula sa isang field resourceName ang paggamit ng jq ay naipakita na sa isang hook na ginagaya ang mga lihim:
jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH
Maaari kang makakuha ng iba pang mga field sa katulad na paraan.
Ano ang susunod?
Sa imbakan ng proyekto, sa / mga halimbawa ng mga direktoryo, may mga halimbawa ng mga kawit na handang tumakbo sa isang kumpol. Kapag nagsusulat ng iyong sariling mga kawit, maaari mong gamitin ang mga ito bilang batayan.
Mayroong suporta para sa pagkolekta ng mga sukatan gamit ang Prometheus - ang mga available na sukatan ay inilalarawan sa seksyon METRICS.
Tulad ng maaari mong hulaan, ang shell-operator ay nakasulat sa Go at ipinamahagi sa ilalim ng lisensya ng Open Source (Apache 2.0). Kami ay magpapasalamat para sa anumang tulong sa pag-unlad proyekto sa GitHub: at mga bituin, at mga isyu, at mga kahilingan sa paghila.
Pag-alis ng belo ng lihim, ipapaalam din namin sa iyo na ang shell-operator ay maliit bahagi ng aming system na maaaring panatilihing napapanahon ang mga add-on sa cluster ng Kubernetes at magsagawa ng iba't ibang awtomatikong pagkilos. Magbasa nang higit pa tungkol sa sistemang ito sinabi literal sa Lunes sa HighLoad++ 2019 sa St. Petersburg - malapit na naming i-publish ang video at transcript ng ulat na ito.
May plano kaming buksan ang natitirang bahagi ng system na ito: ang addon-operator at ang aming koleksyon ng mga hook at module. By the way, addon-operator na pala available sa github, ngunit ang dokumentasyon para dito ay nasa daan pa rin. Ang paglabas ng koleksyon ng mga module ay pinlano para sa tag-init.