ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΠ΅ΠΌ shell-operator: ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ для Kubernetes стало Π΅Ρ‰Ρ‘ ΠΏΡ€ΠΎΡ‰Π΅

Π’ нашСм Π±Π»ΠΎΠ³Π΅ ΡƒΠΆΠ΅ Π±Ρ‹Π»ΠΈ ΡΡ‚Π°Ρ‚ΡŒΠΈ, Ρ€Π°ΡΡΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΡ€ΠΎ возмоТности ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠ² Π² Kubernetes ΠΈ ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ простой ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ самому. На этот Ρ€Π°Π· Ρ…ΠΎΡ‚ΠΈΠΌ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π²Π°ΡˆΠ΅ΠΌΡƒ вниманию нашС Open Source-Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ созданиС ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠ² Π½Π° супСрлёгкий ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ, β€” ΠΏΠΎΠ·Π½Π°ΠΊΠΎΠΌΡŒΡ‚Π΅ΡΡŒ с shell-operator!

Π—Π°Ρ‡Π΅ΠΌ?

ИдСя shell-operator довольно проста: ΠΏΠΎΠ΄ΠΏΠΈΡΠ°Ρ‚ΡŒΡΡ Π½Π° события ΠΎΡ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Kubernetes, Π° ΠΏΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ этих событий Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ внСшнюю ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, прСдоставив Π΅ΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ событии:

ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΠ΅ΠΌ shell-operator: ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ для Kubernetes стало Π΅Ρ‰Ρ‘ ΠΏΡ€ΠΎΡ‰Π΅

ΠŸΠΎΡ‚Ρ€Π΅Π±Π½ΠΎΡΡ‚ΡŒ Π² Π½Ρ‘ΠΌ Π²ΠΎΠ·Π½ΠΈΠΊΠ»Π° Ρƒ нас, ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΈ эксплуатации кластСров стали ΠΏΠΎΡΠ²Π»ΡΡ‚ΡŒΡΡ ΠΌΠ΅Π»ΠΊΠΈΠ΅ Π·Π°Π΄Π°Ρ‡ΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΡ‡Π΅Π½ΡŒ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΌ ΠΏΡƒΡ‚Ρ‘ΠΌ. ВсС эти ΠΌΠ΅Π»ΠΊΠΈΠ΅ Π·Π°Π΄Π°Ρ‡ΠΈ Ρ€Π΅ΡˆΠ°Π»ΠΈΡΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ простых bash-скриптов, хотя, ΠΊΠ°ΠΊ извСстно, ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ Π»ΡƒΡ‡ΡˆΠ΅ ΠΏΠΈΡΠ°Ρ‚ΡŒ Π½Π° Golang. ΠžΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ Π²ΠΊΠ»Π°Π΄Ρ‹Π²Π°Ρ‚ΡŒΡΡ Π² ΠΏΠΎΠ»Π½ΠΎΠΌΠ°ΡΡˆΡ‚Π°Π±Π½ΡƒΡŽ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° ΠΏΠΎΠ΄ ΠΊΠ°ΠΆΠ΄ΡƒΡŽ Ρ‚Π°ΠΊΡƒΡŽ ΠΌΠ΅Π»ΠΊΡƒΡŽ Π·Π°Π΄Π°Ρ‡Ρƒ Π±Ρ‹Π»ΠΎ Π±Ρ‹ нСэффСктивно.

ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ Π·Π° 15 ΠΌΠΈΠ½ΡƒΡ‚

Рассмотрим Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½ΠΎ Π² Kubernetes-кластСрС ΠΈ Ρ‡Π΅ΠΌ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ shell-operator. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΆΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ: Ρ‚ΠΈΡ€Π°ΠΆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сСкрСта для доступа ΠΊ docker registry.

Pod’Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ ΠΎΠ±Ρ€Π°Π·Ρ‹ ΠΈΠ· private registry, Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ Π² своём манифСстС ссылку Π½Π° сСкрСт с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ для доступа ΠΊ registry. Π­Ρ‚ΠΎΡ‚ сСкрСт Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ создан Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ namespace ΠΏΠ΅Ρ€Π΅Π΄ созданиСм pod’ΠΎΠ². Π­Ρ‚ΠΎ Π²ΠΏΠΎΠ»Π½Π΅ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ ΠΈ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ, Π½ΠΎ Ссли ΠΌΡ‹ настроим динамичСскиС окруТСния, Ρ‚ΠΎ namespace для ΠΎΠ΄Π½ΠΎΠ³ΠΎ прилоТСния станСт ΠΌΠ½ΠΎΠ³ΠΎ. А Ссли ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ 2-3… количСство сСкрСтов становится ΠΎΡ‡Π΅Π½ΡŒ большим. И Π΅Ρ‰Ρ‘ ΠΎΠ΄ΠΈΠ½ ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΏΡ€ΠΎ сСкрСты: ΠΊΠ»ΡŽΡ‡ для доступа ΠΊ registry Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π±Ρ‹ ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ врСмя ΠΎΡ‚ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ. Π’ ΠΈΡ‚ΠΎΠ³Π΅, Ρ€ΡƒΡ‡Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π² качСствС Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎ нСэффСктивны β€” Π½ΡƒΠΆΠ½ΠΎ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ созданиС ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ сСкрСтов.

ΠŸΡ€ΠΎΡΡ‚Π°Ρ автоматизация

НапишСм shell-скрипт, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ запускаСтся Ρ€Π°Π· Π² N сСкунд ΠΈ провСряСт namespace’Ρ‹ Π½Π° Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ сСкрСта, Π° Ссли сСкрСта Π½Π΅Ρ‚, Ρ‚ΠΎ ΠΎΠ½ создаётся. Плюс этого Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ, Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΎ выглядит ΠΊΠ°ΠΊ shell-скрипт Π² cron’Π΅ β€” классичСский ΠΈ всСм понятный ΠΏΠΎΠ΄Ρ…ΠΎΠ΄. ΠœΠΈΠ½ΡƒΡ ΠΆΠ΅ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π² ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΊΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ Π΅Π³ΠΎ запусками ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ создан Π½ΠΎΠ²Ρ‹ΠΉ namespace ΠΈ ΠΊΠ°ΠΊΠΎΠ΅-Ρ‚ΠΎ врСмя ΠΎΠ½ останСтся Π±Π΅Π· сСкрСта, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Ρ‚ ΠΊ ошибкам запуска pod’ΠΎΠ².

Автоматизация с shell-operator

Для ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹ нашСго скрипта классичСский запуск ΠΏΠΎ cron’Ρƒ Π½ΡƒΠΆΠ½ΠΎ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π½Π° запуск ΠΏΡ€ΠΈ событии добавлСния namespace: Π² Ρ‚Π°ΠΊΠΎΠΌ случаС ΠΌΠΎΠΆΠ½ΠΎ ΡƒΡΠΏΠ΅Ρ‚ΡŒ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ сСкрСт Π΄ΠΎ Π΅Π³ΠΎ использования. ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΠΌ, ΠΊΠ°ΠΊ это Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ shell-operator.

Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, Ρ€Π°Π·Π±Π΅Ρ€Ρ‘ΠΌ скрипт. Π‘ΠΊΡ€ΠΈΠΏΡ‚Ρ‹ Π² Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Ρ… shell-operator Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ Ρ…ΡƒΠΊΠ°ΠΌΠΈ. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ…ΡƒΠΊ ΠΏΡ€ΠΈ запускС с Ρ„Π»Π°Π³ΠΎΠΌ --config сообщаСт shell-operator’Ρƒ ΠΎ своих binding’Π°Ρ…, Ρ‚.Π΅. ΠΏΠΎ ΠΊΠ°ΠΊΠΈΠΌ событиям Π΅Π³ΠΎ Π½ΡƒΠΆΠ½ΠΎ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ. Π’ нашСм случаС Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ onKubernetesEvent:

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

Π—Π΄Π΅ΡΡŒ описано, Ρ‡Ρ‚ΠΎ нас ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΡŽΡ‚ события добавлСния (add) ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Ρ‚ΠΈΠΏΠ° namespace.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π½ΡƒΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΏΡ€ΠΈ наступлСнии события:

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

ΠžΡ‚Π»ΠΈΡ‡Π½ΠΎ! ΠŸΠΎΠ»ΡƒΡ‡ΠΈΠ»ΡΡ нСбольшой, красивый скрипт. Π§Ρ‚ΠΎΠ±Ρ‹ Β«ΠΎΠΆΠΈΠ²ΠΈΡ‚ΡŒΒ» Π΅Π³ΠΎ, остаётся Π΄Π²Π° шага: ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΈΡ‚ΡŒ ΠΎΠ±Ρ€Π°Π· ΠΈ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Π² кластСрС.

ΠŸΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ° ΠΎΠ±Ρ€Π°Π·Π° с Ρ…ΡƒΠΊΠΎΠΌ

Если ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π½Π° скрипт, Ρ‚ΠΎ Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ kubectl ΠΈ jq. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π² ΠΎΠ±Ρ€Π°Π·Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ Π²Π΅Ρ‰ΠΈ: наш Ρ…ΡƒΠΊ, shell-operator, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠ»Π΅Π΄ΠΈΡ‚ΡŒ Π·Π° событиями ΠΈ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ Ρ…ΡƒΠΊ, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Ρ…ΡƒΠΊΠΎΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ (kubectl ΠΈ jq). На hub.docker.com ΡƒΠΆΠ΅ Π΅ΡΡ‚ΡŒ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π·, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΡƒΠΏΠ°ΠΊΠΎΠ²Π°Π½Ρ‹ shell-operator, kubectl ΠΈ jq. ΠžΡΡ‚Π°Ρ‘Ρ‚ΡΡ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ…ΡƒΠΊ простым 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

Запуск Π² кластСрС

Π•Ρ‰Ρ‘ Ρ€Π°Π· посмотрим Π½Π° Ρ…ΡƒΠΊ ΠΈ Π½Π° этот Ρ€Π°Π· Π²Ρ‹ΠΏΠΈΡˆΠ΅ΠΌ, ΠΊΠ°ΠΊΠΈΠ΅ дСйствия ΠΈ с ΠΊΠ°ΠΊΠΈΠΌΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ ΠΎΠ½ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚ Π² кластСрС:

  1. подписываСтся Π½Π° события создания namespace’ΠΎΠ²;
  2. создаёт сСкрСт Π² namespace’Π°Ρ…, ΠΎΡ‚Π»ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, Π³Π΄Π΅ Π·Π°ΠΏΡƒΡ‰Π΅Π½.

ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎ pod, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡ‰Π΅Π½ наш ΠΎΠ±Ρ€Π°Π·, Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΠΌΠ΅Ρ‚ΡŒ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π½Π° эти дСйствия. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ создания своСго ServiceAccount. Π Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π½ΡƒΠΆΠ½ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ Π² Π²ΠΈΠ΄Π΅ ClusterRole ΠΈ ClusterRoleBinding, Ρ‚.ΠΊ. Π½Π°ΠΌ интСрСсны ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ со всСго кластСра.

Π˜Ρ‚ΠΎΠ³ΠΎΠ²ΠΎΠ΅ описаниС Π² YAML получится ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Ρ‚Π°ΠΊΠΈΠΌ:

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

Π—Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ собранный ΠΎΠ±Ρ€Π°Π· ΠΌΠΎΠΆΠ½ΠΎ Π² Π²ΠΈΠ΄Π΅ простого Deployment:

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

Для удобства создаётся ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ namespace, Π³Π΄Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ shell-operator ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ созданныС манифСсты:

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

На этом всё: shell-operator запустится, ΠΏΠΎΠ΄ΠΏΠΈΡˆΠ΅Ρ‚ΡΡ Π½Π° события создания namespace’ΠΎΠ² ΠΈ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ Ρ…ΡƒΠΊ, ΠΊΠΎΠ³Π΄Π° Π½ΡƒΠΆΠ½ΠΎ.

ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΠ΅ΠΌ shell-operator: ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ для Kubernetes стало Π΅Ρ‰Ρ‘ ΠΏΡ€ΠΎΡ‰Π΅

Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, простой shell-скрипт прСвратился Π² настоящий operator для Kubernetes ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΊΠ°ΠΊ составная Ρ‡Π°ΡΡ‚ΡŒ кластСра. И всё это β€” Π±Π΅Π· слоТного процСсса Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠ² Π½Π° Golang:

ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΠ΅ΠΌ shell-operator: ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ для Kubernetes стало Π΅Ρ‰Ρ‘ ΠΏΡ€ΠΎΡ‰Π΅

Π•ΡΡ‚ΡŒ ΠΈ другая ΠΈΠ»Π»ΡŽΡΡ‚Ρ€Π°Ρ†ΠΈΡ Π½Π° этот ΡΡ‡Ρ‘Ρ‚β€¦ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΠ΅ΠΌ shell-operator: ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ для Kubernetes стало Π΅Ρ‰Ρ‘ ΠΏΡ€ΠΎΡ‰Π΅

Π•Ρ‘ смысл ΠΌΡ‹ раскроСм ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ Π² ΠΎΠ΄Π½ΠΎΠΉ ΠΈΠ· ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΉ.

Π€ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΡ

Π‘Π»Π΅ΠΆΠ΅Π½ΠΈΠ΅ Π·Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ β€” это Ρ…ΠΎΡ€ΠΎΡˆΠΎ, Π½ΠΎ Π·Π°Ρ‡Π°ΡΡ‚ΡƒΡŽ Π±Ρ‹Π²Π°Π΅Ρ‚ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ Ρ€Π΅Π°Π³ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½Π° ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΊΠ°ΠΊΠΈΡ…-Ρ‚ΠΎ свойств ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π½Π° ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ количСства Ρ€Π΅ΠΏΠ»ΠΈΠΊ Π² Deployment’С ΠΈΠ»ΠΈ Π½Π° ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π»Π΅ΠΉΠ±Π»ΠΎΠ² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.

Когда ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ событиС, shell-operator ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ JSON-манифСст ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. МоТно Π²Ρ‹Π΄Π΅Π»ΠΈΡ‚ΡŒ Π² этом JSON ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΡŽΡ‰ΠΈΠ΅ нас свойства ΠΈ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ Ρ…ΡƒΠΊ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ ΠΈΡ… измСнСниях. Для этого прСдусмотрСно ΠΏΠΎΠ»Π΅ jqFilter, Π³Π΄Π΅ Π½ΡƒΠΆΠ½ΠΎ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ jq, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΎ ΠΊ JSON-манифСсту.

НапримСр, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅Π°Π³ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½Π° ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π»Π΅ΠΉΠ±Π»ΠΎΠ² Ρƒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Deployment, Π½ΡƒΠΆΠ½ΠΎ ΠΎΡ‚Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΠ»Π΅ labels ΠΈΠ· поля metadata. ΠšΠΎΠ½Ρ„ΠΈΠ³ Π±ΡƒΠ΄Π΅Ρ‚ Ρ‚Π°ΠΊΠΎΠΉ:

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

Π­Ρ‚ΠΎ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π² jqFilter ΠΏΡ€Π΅Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π΄Π»ΠΈΠ½Π½Ρ‹ΠΉ JSON-манифСста Deployment’Π° Π² ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΉ JSON с Π»Π΅ΠΉΠ±Π»Π°ΠΌΠΈ:

ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΠ΅ΠΌ shell-operator: ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ для Kubernetes стало Π΅Ρ‰Ρ‘ ΠΏΡ€ΠΎΡ‰Π΅

shell-operator Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ Ρ…ΡƒΠΊ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚Π΅Ρ… случаях, ΠΊΠΎΠ³Π΄Π° измСнится этот ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΉ JSON, Π° измСнСния Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… свойствах Π±ΡƒΠ΄ΡƒΡ‚ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ.

ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ запуска Ρ…ΡƒΠΊΠ°

ΠšΠΎΠ½Ρ„ΠΈΠ³ Ρ…ΡƒΠΊΠ° позволяСт ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ нСсколько Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ² событий β€” Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, 2 Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π° для событий ΠΎΡ‚ Kubernetes ΠΈ 2 расписания:

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

НСбольшоС отступлСниС: Π΄Π°, shell-operator ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ запуск скриптов Π² стилС crontab. Π‘ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ.

Π§Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°Π·Π»ΠΈΡ‡Π°Ρ‚ΡŒ, Π² связи с Ρ‡Π΅ΠΌ Π±Ρ‹Π» Π·Π°ΠΏΡƒΡ‰Π΅Π½ Ρ…ΡƒΠΊ, shell-operator создаёт Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‘Ρ‚ Ρ…ΡƒΠΊΡƒ ΠΏΡƒΡ‚ΡŒ ΠΊ Π½Π΅ΠΌΡƒ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ BINDING_CONTEXT_TYPE. Π’ Ρ„Π°ΠΉΠ»Π΅ Π»Π΅ΠΆΠΈΡ‚ JSON-описаниС ΠΏΡ€ΠΈΡ‡ΠΈΠ½Ρ‹ запуска Ρ…ΡƒΠΊΠ°. НапримСр, ΠΊΠ°ΠΆΠ΄Ρ‹Π΅ 10 ΠΌΠΈΠ½ΡƒΡ‚ Ρ…ΡƒΠΊ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ с Ρ‚Π°ΠΊΠΈΠΌ содСрТимым:

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

… Π° Π² понСдСльник запустится с Ρ‚Π°ΠΊΠΈΠΌ:

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

Для onKubernetesEvent срабатываний JSON Π±ΡƒΠ΄Π΅Ρ‚ побольшС, Ρ‚.ΠΊ. ΠΎΠ½ΠΎ содСрТит описаниС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°:

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

Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠΈΠΌΠΎΠ΅ ΠΏΠΎΠ»Π΅ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ½ΡΡ‚ΡŒ ΠΈΠ· ΠΈΡ… ΠΈΠΌΡ‘Π½, Π° Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ β€” ΠΏΡ€ΠΎΡ‡Π΅ΡΡ‚ΡŒ Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ получСния ΠΈΠΌΠ΅Π½ΠΈ рСсурса ΠΈΠ· поля resourceName с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ jq ΡƒΠΆΠ΅ Π±Ρ‹Π» ΠΏΠΎΠΊΠ°Π·Π°Π½ Π² Ρ…ΡƒΠΊΠ΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ‚ΠΈΡ€Π°ΠΆΠΈΡ€ΡƒΠ΅Ρ‚ сСкрСты:

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

Аналогичным ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ ΠΈ ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ поля.

Π§Ρ‚ΠΎ дальшС?

Π’ Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°, Π² Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ /examples, Π΅ΡΡ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Ρ…ΡƒΠΊΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ для запуска Π² кластСрС. ΠŸΡ€ΠΈ написании своих Ρ…ΡƒΠΊΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ€Π°Ρ‚ΡŒ ΠΈΡ… Π·Π° основу.

Π•ΡΡ‚ΡŒ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° сбора ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Prometheus β€” ΠΎ доступных ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠ°Ρ… написано Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ METRICS.

Как Π»Π΅Π³ΠΊΠΎ Π΄ΠΎΠ³Π°Π΄Π°Ρ‚ΡŒΡΡ shell-operator написан Π½Π° Go ΠΈ распространяСтся ΠΏΠΎΠ΄ Open Source-Π»ΠΈΡ†Π΅Π½Π·ΠΈΠ΅ΠΉ (Apache 2.0). ΠœΡ‹ Π±ΡƒΠ΄Π΅ΠΌ Π±Π»Π°Π³ΠΎΠ΄Π°Ρ€Π½Ρ‹ любой ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΠΏΠΎ Ρ€Π°Π·Π²ΠΈΡ‚ΠΈΡŽ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° Π½Π° GitHub: ΠΈ Π·Π²Ρ‘Π·Π΄ΠΎΡ‡ΠΊΠ°ΠΌ, ΠΈ issues, ΠΈ pull requests.

ΠŸΡ€ΠΈΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Ρ завСсу Ρ‚Π°ΠΉΠ½Ρ‹, Ρ‚Π°ΠΊΠΆΠ΅ сообщим, Ρ‡Ρ‚ΠΎ shell-operator β€” это нСбольшая Ρ‡Π°ΡΡ‚ΡŒ нашСй систСмы, которая ΡƒΠΌΠ΅Π΅Ρ‚ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ Π² Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΌ состоянии дополнСния, установлСнныС Π² кластСрС Kubernetes, ΠΈ осущСствляСт Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ автоматичСскиС дСйствия. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎΠ± этой систСмС ΠΌΡ‹ рассказали Π±ΡƒΠΊΠ²Π°Π»ΡŒΠ½ΠΎ Π² понСдСльник Π½Π° HighLoad++ 2019 Π² Π‘Π°Π½ΠΊΡ‚-ΠŸΠ΅Ρ‚Π΅Ρ€Π±ΡƒΡ€Π³Π΅ β€” Π²ΠΈΠ΄Π΅ΠΎ ΠΈ Ρ€Π°ΡΡˆΠΈΡ„Ρ€ΠΎΠ²ΠΊΡƒ этого Π΄ΠΎΠΊΠ»Π°Π΄Π° вскорС ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅ΠΌ.

Π£ нас Π΅ΡΡ‚ΡŒ ΠΏΠ»Π°Π½ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΡŒ ΠΈ ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ части этой систСмы: addon-operator ΠΈ Π½Π°ΡˆΡƒ ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡŽ Ρ…ΡƒΠΊΠΎΠ² ΠΈ ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ. ΠšΡΡ‚Π°Ρ‚ΠΈ, addon-operator ΡƒΠΆΠ΅ доступСн Π½Π° GitHub, Π½ΠΎ докумСнтация ΠΊ Π½Π΅ΠΌΡƒ ΠΏΠΎΠΊΠ° Π² ΠΏΡƒΡ‚ΠΈ. Π Π΅Π»ΠΈΠ· ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ планируСтся Π»Π΅Ρ‚ΠΎΠΌ.

Stay tuned!

P.S.

Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π² нашСм Π±Π»ΠΎΠ³Π΅:

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com