Pristatome apvalkalo operatorių: kurti operatorius Kubernetes tapo dar lengviau

Mūsų tinklaraštyje jau buvo straipsnių apie tai operatoriaus galimybės Kubernetes ir kaip pats parašyk paprastą operatorių. Šį kartą norime jūsų dėmesiui pristatyti mūsų atvirojo kodo sprendimą, kuris operatorių kūrimą perkelia į itin lengvą lygį – pažiūrėkite apvalkalo operatorius!

Kodėl?

Korpuso operatoriaus idėja yra gana paprasta: užsiprenumeruokite įvykius iš Kubernetes objektų ir, gavus šiuos įvykius, paleiskite išorinę programą, suteikdami jai informaciją apie įvykį:

Pristatome apvalkalo operatorių: kurti operatorius Kubernetes tapo dar lengviau

To poreikis atsirado tada, kai klasterių veikimo metu pradėjo atsirasti smulkių užduočių, kurias labai norėjome automatizuoti tinkamu būdu. Visos šios nedidelės užduotys buvo išspręstos naudojant paprastus bash scenarijus, nors, kaip žinote, operatorius geriau rašyti Golang. Akivaizdu, kad investuoti į visapusišką operatoriaus plėtrą kiekvienai tokiai mažai užduočiai būtų neefektyvu.

Operatorius per 15 minučių

Pažvelkime į pavyzdį, ką galima automatizuoti Kubernetes klasteryje ir kaip gali padėti apvalkalo operatorius. Pavyzdys būtų toks: paslapties atkartojimas norint pasiekti docker registrą.

Poduose, kuriuose naudojami vaizdai iš privataus registro, apraše turi būti nuoroda į paslaptį su duomenimis, reikalingais prieigai prie registro. Ši paslaptis turi būti sukurta kiekvienoje vardų erdvėje prieš kuriant ankštis. Tai galima padaryti rankiniu būdu, tačiau jei nustatysime dinamines aplinkas, vienos programos vardų erdvė taps daug. O jei taip pat nėra 2-3 paraiškų... paslapčių skaičius tampa labai didelis. Ir dar vienas dalykas apie paslaptis: norėčiau retkarčiais pakeisti raktą, kad galėčiau pasiekti registrą. Galų gale, rankines operacijas kaip sprendimas visiškai neveiksmingas — turime automatizuoti paslapčių kūrimą ir atnaujinimą.

Paprasta automatika

Parašykime apvalkalo scenarijų, kuris paleidžiamas kartą per N sekundes ir tikrina, ar vardų erdvėse nėra paslapties, o jei paslapties nėra, tada jis sukuriamas. Šio sprendimo privalumas yra tas, kad jis atrodo kaip apvalkalo scenarijus cron – klasikinis ir visiems suprantamas požiūris. Neigiama yra tai, kad per intervalą tarp jo paleidimų galima sukurti naują vardų erdvę ir kurį laiką ji išliks be paslapties, o tai sukels klaidų paleidžiant podelius.

Automatika su apvalkalo operatoriumi

Kad mūsų scenarijus veiktų tinkamai, klasikinį cron paleidimą reikia pakeisti paleidimu, kai pridedama vardų sritis: tokiu atveju prieš naudodami galite sukurti paslaptį. Pažiūrėkime, kaip tai įgyvendinti naudojant apvalkalo operatorių.

Pirmiausia pažiūrėkime į scenarijų. Skriptai apvalkalo operatoriaus terminais vadinami kabliukais. Kiekvienas kabliukas bėgant su vėliava --config praneša apvalkalo operatoriui apie savo apkaustus, t.y. apie kokius renginius jis turėtų būti pradėtas. Mūsų atveju mes naudosime onKubernetesEvent:

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

Čia aprašyta, kad mes norime pridėti įvykių (add) tipo objektai namespace.

Dabar reikia pridėti kodą, kuris bus vykdomas įvykus įvykiui:

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

Puiku! Rezultatas buvo mažas, gražus scenarijus. Norėdami jį „atgaivinti“, liko du žingsniai: paruoškite vaizdą ir paleiskite jį klasteryje.

Vaizdo paruošimas kabliuku

Jei pažvelgsite į scenarijų, pamatysite, kad komandos yra naudojamos kubectl и jq. Tai reiškia, kad paveikslėlyje turi būti šie dalykai: mūsų kabliukas, apvalkalo operatorius, kuris stebės įvykius ir paleis kabliuką, ir kabliuko naudojamos komandos (kubectl ir jq). Hub.docker.com jau turi paruoštą vaizdą, kuriame supakuoti apvalkalo operatorius, kubectl ir jq. Belieka pridėti paprastą kabliuką 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

Bėgimas klasteryje

Dar kartą pažiūrėkime į kabliuką ir šį kartą užsirašykime kokius veiksmus ir su kokiais objektais jis atlieka klasteryje:

  1. prenumeruoja vardų erdvės kūrimo renginius;
  2. sukuria paslaptį kitose vardų erdvėse nei ta, kurioje ji paleidžiama.

Pasirodo, kad grupė, kurioje bus paleistas mūsų vaizdas, turi turėti leidimus atlikti šiuos veiksmus. Tai galima padaryti susikūrus savo ServiceAccount. Leidimas turi būti suteiktas ClusterRole ir ClusterRoleBinding forma, nes mus domina objektai iš viso klasterio.

Galutinis YAML aprašymas atrodys maždaug taip:

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

Surinktą vaizdą galite paleisti kaip paprastą diegimą:

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

Patogumui sukuriama atskira vardų erdvė, kurioje bus paleistas apvalkalo operatorius ir pritaikyti sukurti manifestai:

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

Tai viskas: apvalkalo operatorius pradės, užsiprenumeruos vardų erdvės kūrimo įvykius ir prireikus paleis kabliuką.

Pristatome apvalkalo operatorių: kurti operatorius Kubernetes tapo dar lengviau

tokiu būdu, paprastas apvalkalo scenarijus virto tikru operatoriumi Kubernetes ir veikia kaip klasterio dalis. Ir visa tai be sudėtingo operatorių kūrimo proceso Golange:

Pristatome apvalkalo operatorių: kurti operatorius Kubernetes tapo dar lengviau

Yra dar viena iliustracija šiuo klausimu...Pristatome apvalkalo operatorių: kurti operatorius Kubernetes tapo dar lengviau

Išsamiau jo reikšmę atskleisime viename iš šių leidinių.

filtravimas

Stebėti objektus yra gerai, bet dažnai reikia reaguoti kai kurių objektų savybių keitimas, pavyzdžiui, norėdami pakeisti diegimo kopijų skaičių arba pakeisti objektų etiketes.

Kai ateina įvykis, apvalkalo operatorius gauna objekto JSON manifestą. Galime pasirinkti ypatybes, kurios mus domina šiame JSON, ir paleisti kabliuką tik kai jie pasikeičia. Tam yra laukas jqFilter, kur reikia nurodyti jq išraišką, kuri bus taikoma JSON manifestui.

Pavyzdžiui, norėdami reaguoti į diegimo objektų etikečių pakeitimus, turite filtruoti lauką labels iš lauko metadata. Konfigūracija bus tokia:

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

Ši jqFilter išraiška paverčia ilgą diegimo JSON aprašą trumpu JSON su etiketėmis:

Pristatome apvalkalo operatorių: kurti operatorius Kubernetes tapo dar lengviau

shell-operator veiks tik tada, kai pasikeis šis trumpas JSON, o kitų savybių pakeitimai bus ignoruojami.

Kablio paleidimo kontekstas

Kabliuko konfigūracija leidžia nurodyti kelias įvykių parinktis, pavyzdžiui, 2 įvykių parinktis iš Kubernetes ir 2 tvarkaraščius:

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

Mažas nukrypimas: taip, apvalkalo operatorių palaiko paleisti crontab stiliaus scenarijus. Daugiau informacijos galite rasti dokumentacija.

Kad atskirtų, kodėl kabliukas buvo paleistas, apvalkalo operatorius sukuria laikiną failą ir perduoda kelią į jį kintamuoju kabliui BINDING_CONTEXT_TYPE. Faile yra JSON aprašymas, kodėl paleisti kabliukas. Pavyzdžiui, kas 10 minučių kabliukas paleidžiamas tokiu turiniu:

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

... o pirmadienį prasidės taip:

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

onKubernetesEvent Bus daugiau JSON aktyviklių, nes jame yra objekto aprašymas:

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

Laukų turinį galima suprasti iš jų pavadinimų, o daugiau informacijos galima perskaityti dokumentacija. Ištekliaus pavadinimo gavimo iš lauko pavyzdys resourceName jq naudojimas jau buvo parodytas kabliuke, kuris atkartoja paslaptis:

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

Panašiu būdu galite gauti ir kitus laukus.

Kas toliau?

Projekto saugykloje, in /pavyzdžiai katalogai, yra kabliukų, kurie yra paruošti paleisti klasteryje, pavyzdžių. Rašydami savo kabliukus, galite juos naudoti kaip pagrindą.

Yra palaikymas metrikų rinkimui naudojant Prometheus – galimos metrikos aprašytos skyriuje METRIKA.

Kaip galite atspėti, apvalkalo operatorius yra parašytas Go ir platinamas pagal atvirojo kodo licenciją (Apache 2.0). Būsime dėkingi už bet kokią pagalbą vystymuisi projektas „GitHub“.: ir žvaigždutės, ir problemos, ir traukimo užklausos.

Pakėlę paslapties šydą taip pat informuosime, kad apvalkalo operatorius yra maža mūsų sistemos dalis, kuri gali nuolat atnaujinti Kubernetes klasteryje įdiegtus priedus ir atlikti įvairius automatinius veiksmus. Skaitykite daugiau apie šią sistemą pasakojo pažodžiui pirmadienį HighLoad++ 2019 Sankt Peterburge – netrukus paskelbsime šio pranešimo vaizdo įrašą ir nuorašą.

Turime planą atidaryti likusią šios sistemos dalį: priedų operatorių ir mūsų kabliukų bei modulių kolekciją. Beje, priedų operatorius jau yra pasiekiama github, tačiau jo dokumentai vis dar ruošiami. Modulių kolekcijos išleidimas planuojamas vasarą.

Būkite suderinti!

PS

Taip pat skaitykite mūsų tinklaraštyje:

Šaltinis: www.habr.com

Добавить комментарий