Shell-Bedreiwer aféieren: Bedreiwer fir Kubernetes erstellen ass just méi einfach ginn

Et goufe schonn Artikelen op eisem Blog geschwat Bedreiwer Kënnen an Kubernetes a wéi schreiwen eng einfach Bedreiwer selwer. Dës Kéier wëlle mir Är Opmierksamkeet eis Open Source Léisung presentéieren, déi d'Schafung vun Betreiber op e super einfachen Niveau hëlt - kuckt weg Shell-Operateur!

Firwat?

D'Iddi vun engem Shell-Operateur ass ganz einfach: abonnéiert op Eventer vu Kubernetes Objeten, a wann dës Eventer empfaange ginn, lancéiert en externe Programm, liwwert et Informatioun iwwer d'Evenement:

Shell-Bedreiwer aféieren: Bedreiwer fir Kubernetes erstellen ass just méi einfach ginn

De Besoin dofir ass entstanen, wéi während der Operatioun vu Cluster kleng Aufgaben ugefaang hunn, déi mir wierklech op déi richteg Manéier automatiséieren wollten. All dës kleng Aufgaben goufen mat einfachen Bash Scripten geléist, obwuel, wéi Dir wësst, et besser ass, Betreiber op Golang ze schreiwen. Selbstverständlech, Investitioun an voll-Skala Entwécklung vun engem Bedreiwer fir all esou kleng Aufgab wier ineffektiv.

Bedreiwer an 15 Minutten

Loosst eis e Beispill kucken wat an engem Kubernetes Cluster automatiséiert ka ginn a wéi de Shell-Bedreiwer hëllefe kann. E Beispill wier déi folgend: replizéiert e Geheimnis fir Zougang zum Docker Registry ze kréien.

Pods déi Biller aus engem privaten Registry benotzen, mussen an hirem Manifest e Link op e Geheimnis mat Daten fir Zougang zum Registry enthalen. Dëst Geheimnis muss an all Nummraum erstallt ginn ier Dir Pods erstellt. Dëst kann manuell gemaach ginn, awer wa mir dynamesch Ëmfeld astellen, da gëtt den Nummraum fir eng Applikatioun vill. A wann et och net 2-3 Uwendungen sinn ... gëtt d'Zuel vun de Geheimnisser ganz grouss. An nach eng Saach iwwer Geheimnisser: Ech géif gären de Schlëssel änneren fir Zougang zu de Registry vun Zäit zu Zäit. schlussendlech, manuell Operatiounen als Léisung komplett ineffektiv - mir mussen d'Schafung an d'Aktualiséierung vu Geheimnisser automatiséieren.

Einfach Automatisatioun

Loosst eis e Shell-Skript schreiwen, deen eemol all N Sekonnen leeft a kontrolléiert Nummraim fir d'Präsenz vun engem Geheimnis, a wann et kee Geheimnis ass, da gëtt et erstallt. De Virdeel vun dëser Léisung ass datt et ausgesäit wéi e Shell-Skript am Cron - eng klassesch a verständlech Approche fir jiddereen. De Nodeel ass datt am Intervall tëscht senge Starten en neien Nummraum erstallt ka ginn a fir eng Zäit bleift et ouni Geheimnis, wat zu Feeler beim Start vun Pods féiert.

Automatisatioun mat Shell-Bedreiwer

Fir datt eise Skript richteg funktionnéiert, muss de klassesche Cron-Start duerch e Start ersat ginn wann e Nummraum dobäigesat gëtt: an dësem Fall kënnt Dir e Geheimnis erstellen ier Dir se benotzt. Loosst eis kucken wéi Dir dëst mam Shell-Operator implementéiert.

Als éischt kucke mer de Skript. Skripte a Shell-Operateur Begrëffer ginn Haken genannt. All Haken wann se mat engem Fändel lafen --config informéiert de Shell-Operateur iwwer seng Bindungen, d.h. op wat Evenementer et soll lancéiert ginn. An eisem Fall wäerte mir benotzen onKubernetesEvent:

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

Et gëtt hei beschriwwen datt mir interesséiert sinn Eventer ze addéieren (add) Objete vun Typ namespace.

Elo musst Dir de Code addéieren deen ausgefouert gëtt wann den Event geschitt:

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

Super! D'Resultat war e klengt, schéint Skript. Fir et ze "erliewen" ginn et zwee Schrëtt lénks: d'Bild virbereeden an et am Cluster starten.

Virbereedung vun engem Bild mat engem Haken

Wann Dir de Skript kuckt, kënnt Dir gesinn datt d'Befehle benotzt ginn kubectl и jq. Dëst bedeit datt d'Bild déi folgend Saache muss hunn: eisen Hook, e Shell-Bedreiwer deen d'Evenementer iwwerwaacht an den Hook ausféiert, an d'Befehle benotzt vum Hook (kubectl an jq). Hub.docker.com huet schonn e fäerdeg Bild an deem Shell-Operateur, kubectl an jq verpackt sinn. Alles wat bleift ass en einfachen Haken ze addéieren 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

Lafen an engem Cluster

Loosst eis den Haken nach eng Kéier kucken an dës Kéier opschreiwen wéi eng Handlungen a mat wéi enge Objeten en am Cluster ausféiert:

  1. abonnéiert op Nummraum Kreatioun Evenementer;
  2. erstellt e Geheimnis an anere Nummraim wéi dee wou et lancéiert gëtt.

Et stellt sech eraus datt de Pod, an deem eist Bild lancéiert gëtt, Permissiounen muss hunn fir dës Aktiounen ze maachen. Dëst kann gemaach ginn andeems Dir Ären eegene ServiceAccount erstellt. D'Erlaabnis muss a Form vu ClusterRole a ClusterRoleBinding gemaach ginn, well mir interesséieren eis fir Objeten aus dem ganze Stärekoup.

Déi lescht Beschreiwung am YAML wäert sou ausgesinn:

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

Dir kënnt dat gesammelt Bild als einfachen Deployment starten:

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

Fir d'Bequemlechkeet gëtt e separaten Nummraum erstallt wou de Shell-Bedreiwer lancéiert gëtt an déi erstallt Manifester applizéiert ginn:

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

Dat ass alles: de Shell-Bedreiwer fänkt un, abonnéiert op Nummraumkreatiounsevenementer a leeft den Hook wann néideg.

Shell-Bedreiwer aféieren: Bedreiwer fir Kubernetes erstellen ass just méi einfach ginn

Sou, en einfache Shell-Skript gouf zu engem richtege Bedreiwer fir Kubernetes a schafft als Deel vun engem Cluster. An dat alles ouni de komplexe Prozess fir Betreiber zu Golang z'entwéckelen:

Shell-Bedreiwer aféieren: Bedreiwer fir Kubernetes erstellen ass just méi einfach ginn

Et gëtt eng aner Illustratioun zu dëser Matière ...Shell-Bedreiwer aféieren: Bedreiwer fir Kubernetes erstellen ass just méi einfach ginn

Mir wäerte seng Bedeitung méi detailléiert an enger vun de folgende Publikatiounen opzeweisen.

Filter

D'Objete verfollegen ass gutt, awer et gëtt dacks e Besoin fir op ze reagéieren änneren e puer Objet Eegeschafte, zum Beispill, d'Zuel vun de Repliken am Deployment z'änneren oder d'Objetetikett z'änneren.

Wann en Event ukomm ass, kritt de Shell-Bedreiwer den JSON Manifest vum Objet. Mir kënnen d'Eegeschafte wielt déi eis an dësem JSON interesséieren an den Hook lafen nëmmen wann se änneren. Et gëtt e Feld fir dëst jqFilter, wou Dir musst de jq Ausdrock uginn, deen op de JSON Manifest applizéiert gëtt.

Zum Beispill, fir op Ännerungen an Etiketten fir Deployment-Objeten ze reagéieren, musst Dir d'Feld filteren labels aus dem Terrain metadata. D'Konfiguratioun wäert esou sinn:

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

Dëse jqFilter Ausdrock verwandelt dem Deployment säi laange JSON Manifest a kuerzen JSON mat Etiketten:

Shell-Bedreiwer aféieren: Bedreiwer fir Kubernetes erstellen ass just méi einfach ginn

Shell-Operateur wäert nëmmen den Hook lafen wann dëse kuerze JSON ännert, an Ännerungen an aner Eegeschafte ginn ignoréiert.

Hook starten Kontext

D'Hook Config erlaabt Iech verschidden Optiounen fir Eventer ze spezifizéieren - zum Beispill 2 Optiounen fir Eventer vu Kubernetes an 2 Zäitplang:

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

Eng kleng Digression: jo, Shell-Bedreiwer ënnerstëtzt Lafen crontab Stil Scripten. Méi Detailer fannt Dir an Dokumentatioun.

Fir z'ënnerscheeden firwat den Haken lancéiert gouf, erstellt de Shell-Bedreiwer eng temporär Datei a passéiert de Wee dohinner an enger Variabel un den Haken BINDING_CONTEXT_TYPE. De Fichier enthält eng JSON Beschreiwung vum Grond fir den Hook ze lafen. Zum Beispill, all 10 Minutten leeft den Haken mat de folgenden Inhalter:

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

... an e Méindeg fänkt et domat un:

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

fir onKubernetesEvent Et wäert méi JSON Ausléiser ginn, well et enthält eng Beschreiwung vum Objet:

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

Den Inhalt vun de Felder kann aus hiren Nimm verstane ginn, a méi Detailer kënne gelies ginn Dokumentatioun. E Beispill fir e Ressourcenumm aus engem Feld ze kréien resourceName mat jq gouf schonn an engem Haken gewisen deen Geheimnisser replizéiert:

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

Dir kënnt aner Felder op eng ähnlech Manéier kréien.

Wat d'nächst?

Am Projet Repository, an /Beispiller Verzeichnungen, Et gi Beispiller vun Haken déi prett sinn op engem Cluster ze lafen. Wann Dir Är eegen Haken schreift, kënnt Dir se als Basis benotzen.

Et gëtt Ënnerstëtzung fir Metriken mat Prometheus ze sammelen - déi verfügbar Metriken ginn an der Sektioun beschriwwen METRIK.

Wéi Dir kéint roden, ass de Shell-Bedreiwer a Go geschriwwen a verdeelt ënner enger Open Source Lizenz (Apache 2.0). Mir wäerten dankbar sinn fir all Entwécklungshëllef Projet op GitHub: a Stären, an Themen, an zitt Ufroen.

Ophiewen de Schleier vum Geheimnis, mir wäerten Iech och informéieren datt Shell-Bedreiwer ass kleng Deel vun eisem System, deen Add-ons am Kubernetes-Cluster um neiste Stand halen kann a verschidde automatesch Aktiounen ausféieren. Liest méi iwwer dëse System erzielt wuertwiertlech e Méindeg um HighLoad++ 2019 zu St.

Mir hunn e Plang fir de Rescht vun dësem System opzemaachen: den Addon-Bedreiwer an eis Sammlung vun Haken a Moduler. Iwwregens ass den Addon-Bedreiwer schonn verfügbar op github, awer d'Dokumentatioun dofir ass nach ënnerwee. D'Verëffentlechung vun der Sammlung vu Moduler ass fir de Summer geplangt.

Bleift drun!

PS

Liest och op eisem Blog:

Source: will.com

Setzt e Commentaire