Kabuk operatörüyle tanışın: Kubernetes için operatörler oluşturmak artık daha kolay

Blogumuzda bundan bahseden makaleler zaten vardı. Kubernetes'teki operatör yetenekleri ve nasıl basit bir operatörü kendiniz yazın. Bu sefer operatörlerin oluşturulmasını son derece kolay bir seviyeye taşıyan Açık Kaynak çözümümüzü dikkatinize sunmak istiyoruz - göz atın kabuk operatörü!

Neden?

Bir kabuk operatörünün fikri oldukça basittir: Kubernetes nesnelerinden gelen olaylara abone olun ve bu olaylar alındığında, olay hakkında bilgi sağlayan harici bir program başlatın:

Kabuk operatörüyle tanışın: Kubernetes için operatörler oluşturmak artık daha kolay

Buna olan ihtiyaç, kümelerin çalışması sırasında gerçekten doğru şekilde otomatikleştirmek istediğimiz küçük görevler ortaya çıkmaya başladığında ortaya çıktı. Tüm bu küçük görevler basit bash komut dosyaları kullanılarak çözüldü, ancak bildiğiniz gibi operatörleri Golang'da yazmak daha iyidir. Açıkçası, bu tür küçük görevlerin her biri için bir operatörün tam ölçekli gelişimine yatırım yapmak etkisiz olacaktır.

15 dakika içinde operatör

Kubernetes kümesinde nelerin otomatikleştirilebileceğine ve kabuk operatörünün nasıl yardımcı olabileceğine dair bir örneğe bakalım. Bir örnek şu olabilir: liman işçisi kayıt defterine erişmek için bir sırrın kopyalanması.

Özel bir kayıt defterindeki görüntüleri kullanan bölmeler, bildirimlerinde, kayıt defterine erişmeye yönelik verileri içeren bir sırra bağlantı içermelidir. Bu gizli dizi, bölmeler oluşturulmadan önce her ad alanında oluşturulmalıdır. Bu manuel olarak yapılabilir, ancak dinamik ortamlar kurarsak, bir uygulamanın ad alanı çok fazla olacaktır. Ve eğer 2-3 başvuru da olmazsa... sırların sayısı çok fazla olur. Sırlarla ilgili bir şey daha: Zaman zaman kayıt defterine erişim anahtarını değiştirmek istiyorum. Sonunda, manuel işlemler çözüm olarak tamamen etkisiz — sırların oluşturulmasını ve güncellenmesini otomatikleştirmemiz gerekiyor.

Basit otomasyon

Her N saniyede bir çalışan ve ad alanlarını bir sırrın varlığı açısından kontrol eden ve eğer sır yoksa yaratılacak bir kabuk betiği yazalım. Bu çözümün avantajı, cron'daki bir kabuk betiğine benzemesidir - herkes için klasik ve anlaşılır bir yaklaşım. Dezavantajı, lansmanları arasındaki aralıkta yeni bir ad alanının oluşturulabilmesi ve bir süre boyunca sırsız kalması ve bu da bölmelerin başlatılmasında hatalara yol açmasıdır.

Kabuk operatörü ile otomasyon

Komut dosyamızın düzgün çalışması için, bir ad alanı eklendiğinde klasik cron başlatma işleminin bir başlatma ile değiştirilmesi gerekir: bu durumda, onu kullanmadan önce bir gizli kod oluşturabilirsiniz. Bunu kabuk operatörü kullanarak nasıl uygulayacağımızı görelim.

Öncelikle senaryoya bakalım. Kabuk operatörü terimlerindeki komut dosyalarına kancalar denir. Bir bayrakla çalıştırıldığında her kanca --config kabuk operatörüne bağlantıları hakkında bilgi verir; hangi etkinliklerin başlatılması gerektiği konusunda. Bizim durumumuzda kullanacağız onKubernetesEvent:

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

Burada etkinlik eklemekle ilgilendiğimiz açıklanmaktadır (add) türündeki nesneler namespace.

Şimdi olay gerçekleştiğinde yürütülecek kodu eklemeniz gerekiyor:

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

Harika! Sonuç küçük, güzel bir senaryoydu. Onu "canlandırmak" için iki adım kaldı: görüntüyü hazırlayın ve kümede başlatın.

Kancayla görüntü hazırlama

Senaryoya bakarsanız komutların kullanıldığını görebilirsiniz. kubectl и jq. Bu, görüntünün aşağıdaki şeylere sahip olması gerektiği anlamına gelir: kancamız, olayları izleyecek ve kancayı çalıştıracak bir kabuk operatörü ve kanca tarafından kullanılan komutlar (kubectl ve jq). Hub.docker.com'da zaten kabuk operatörü, kubectl ve jq'nin paketlendiği hazır bir görüntü var. Geriye kalan tek şey basit bir kanca eklemek 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

Bir kümede çalıştırma

Kancaya tekrar bakalım ve bu sefer kümede hangi eylemleri ve hangi nesnelerle gerçekleştirdiğini yazalım:

  1. ad alanı oluşturma etkinliklerine abone olur;
  2. başlatıldığı yerin dışındaki ad alanlarında bir sır oluşturur.

İmajımızın başlatılacağı bölmenin bu eylemleri gerçekleştirmek için izinlere sahip olması gerektiği ortaya çıktı. Bu, kendi ServiceAccount'unuzu oluşturarak yapılabilir. İzin ClusterRole ve ClusterRoleBinding şeklinde yapılmalıdır çünkü kümenin tamamındaki nesnelerle ilgileniyoruz.

YAML'deki son açıklama şuna benzer:

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

Birleştirilmiş görüntüyü basit bir Dağıtım olarak başlatabilirsiniz:

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

Kolaylık sağlamak için, kabuk operatörünün başlatılacağı ve oluşturulan bildirimlerin uygulanacağı ayrı bir ad alanı oluşturulur:

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

Hepsi bu kadar: Kabuk operatörü başlayacak, ad alanı oluşturma olaylarına abone olacak ve gerektiğinde kancayı çalıştıracak.

Kabuk operatörüyle tanışın: Kubernetes için operatörler oluşturmak artık daha kolay

Bu durumda, basit bir kabuk betiği Kubernetes için gerçek bir operatöre dönüştü ve bir kümenin parçası olarak çalışır. Ve tüm bunlar, Golang'da operatör geliştirmenin karmaşık süreci olmadan:

Kabuk operatörüyle tanışın: Kubernetes için operatörler oluşturmak artık daha kolay

Bu konuyla ilgili bir örnek daha var...Kabuk operatörüyle tanışın: Kubernetes için operatörler oluşturmak artık daha kolay

Anlamını aşağıdaki yayınlardan birinde daha ayrıntılı olarak açıklayacağız.

süzme

Nesneleri takip etmek iyidir ancak çoğu zaman tepki verme ihtiyacı vardır. bazı nesne özelliklerini değiştirmeörneğin Dağıtımdaki kopyaların sayısını değiştirmek veya nesne etiketlerini değiştirmek için.

Bir olay geldiğinde, kabuk operatörü nesnenin JSON bildirimini alır. Bu JSON'da ilgimizi çeken özellikleri seçip kancayı çalıştırabiliriz. sadece değiştiklerinde. Bunun için bir alan var jqFilterJSON bildirimine uygulanacak jq ifadesini belirtmeniz gereken yer.

Örneğin, Dağıtım nesnelerinin etiketlerindeki değişikliklere yanıt vermek için alanı filtrelemeniz gerekir labels saha dışında metadata. Yapılandırma şu şekilde olacaktır:

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

Bu jqFilter ifadesi, Dağıtımın uzun JSON bildirimini aşağıdaki etiketlerle kısa JSON'a dönüştürür:

Kabuk operatörüyle tanışın: Kubernetes için operatörler oluşturmak artık daha kolay

Kabuk operatörü kancayı yalnızca bu kısa JSON değiştiğinde çalıştıracak ve diğer özelliklerde yapılan değişiklikler göz ardı edilecektir.

Kanca başlatma bağlamı

Hook yapılandırması, etkinlikler için çeşitli seçenekler belirlemenize olanak tanır; örneğin, Kubernetes'teki etkinlikler için 2 seçenek ve 2 program:

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

Küçük bir açıklama: evet, kabuk operatörü destekliyor crontab tarzı komut dosyalarını çalıştırma. Daha fazla ayrıntıyı şu adreste bulabilirsiniz: belgeleme.

Kancanın neden başlatıldığını ayırt etmek için kabuk operatörü geçici bir dosya oluşturur ve bu dosyanın yolunu bir değişkenle kancaya iletir. BINDING_CONTEXT_TYPE. Dosya, kancanın çalıştırılma nedeninin JSON açıklamasını içerir. Örneğin, kanca her 10 dakikada bir aşağıdaki içerikle çalışacaktır:

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

... ve Pazartesi günü şununla başlayacak:

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

için onKubernetesEvent Daha fazla JSON tetikleyicisi olacak çünkü nesnenin bir açıklamasını içerir:

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

Alanların içerikleri isimlerinden anlaşılabileceği gibi daha detaylı bilgi de şuradan okunabilir. belgeleme. Bir alandan kaynak adı alma örneği resourceName jq kullanımı zaten sırları kopyalayan bir kancada gösterilmiştir:

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

Diğer alanları da benzer şekilde alabilirsiniz.

Sırada ne var?

Proje deposunda, /örnek dizinlerBir kümede çalışmaya hazır kanca örnekleri vardır. Kendi kancalarınızı yazarken bunları temel olarak kullanabilirsiniz.

Prometheus'u kullanarak metrikleri toplama desteği mevcuttur; mevcut metrikler bu bölümde açıklanmıştır. METRİKLER.

Tahmin edebileceğiniz gibi kabuk operatörü Go'da yazılmıştır ve Açık Kaynak lisansı (Apache 2.0) altında dağıtılmaktadır. Her türlü kalkınma yardımına minnettar olacağız GitHub'daki proje: ve yıldızlar, sorunlar ve çekme istekleri.

Gizlilik perdesini aralayarak, size paravan operatörünün de olduğunu bildireceğiz. küçük Kubernetes kümesinde kurulu olan eklentileri güncel tutabilen ve çeşitli otomatik eylemleri gerçekleştirebilen sistemimizin bir parçasıdır. Bu sistem hakkında daha fazlasını okuyun söyledi kelimenin tam anlamıyla Pazartesi günü St. Petersburg'daki HighLoad++ 2019'da - bu raporun videosunu ve metnini yakında yayınlayacağız.

Bu sistemin geri kalanını açma planımız var: eklenti operatörü ve kanca ve modül koleksiyonumuz. Bu arada eklenti operatörü zaten github'da mevcutancak bununla ilgili belgeler hâlâ yolda. Modül koleksiyonunun yaz aylarında piyasaya sürülmesi planlanıyor.

Bizi izlemeye devam edin!

PS

Blogumuzda da okuyun:

Kaynak: habr.com

Yorum ekle