Memperkenalkan shell-operator: membuat operator untuk Kubernet lebih mudah

Sudah ada artikel di blog kami tentang kemampuan operator di Kubernetes dan cara menulis operator sederhana sendiri . Kali ini kami ingin menyampaikan kepada Anda solusi Open Source kami, yang membawa kreasi operator ke tingkat yang sangat mudah - berkenalan dengan operator shell !

Mengapa


Gagasan operator shell cukup sederhana: berlangganan acara dari objek Kubernetes, dan ketika menerima acara ini, mulai program eksternal, berikan informasi tentang acara tersebut:



Perlunya muncul bersama kami ketika, selama operasi cluster, tugas-tugas kecil mulai tampak bahwa kami benar-benar ingin mengotomatisasi dengan cara yang benar. Semua tugas kecil ini diselesaikan dengan bantuan skrip bash sederhana, meskipun, seperti yang Anda tahu, operator lebih baik ditulis dalam Golang. Jelas, berinvestasi dalam pengembangan operator skala penuh untuk setiap tugas kecil seperti itu tidak efisien.

Operator dalam 15 menit


Mari kita lihat contoh apa yang dapat diotomatiskan dalam kluster Kubernetes dan bagaimana operator shell akan membantu. Contohnya adalah sebagai berikut: menduplikasi rahasia untuk mengakses register buruh pelabuhan.

Pod yang menggunakan gambar dari registri pribadi harus berisi dalam manifesnya tautan ke rahasia dengan data untuk mengakses registri. Rahasia ini harus dibuat di setiap namespace sebelum membuat pod. Sangat mungkin untuk melakukan ini secara manual, tetapi jika kita mengatur lingkungan yang dinamis, maka namespace untuk satu aplikasi akan menjadi banyak. Dan jika aplikasi juga bukan 2-3 ... jumlah rahasia menjadi sangat besar. Dan satu hal lagi tentang rahasia: Saya ingin mengubah kunci untuk mengakses registri dari waktu ke waktu. Akibatnya, operasi manual sebagai solusi sama sekali tidak efektif - Anda perlu mengotomatiskan pembuatan dan pemutakhiran rahasia.

Otomatisasi mudah


Kami akan menulis skrip shell yang berjalan sekali setiap N detik dan memeriksa rahasia namespace, dan jika tidak ada rahasia, maka itu dibuat. Keuntungan dari solusi ini adalah ia terlihat seperti skrip shell di cron - pendekatan klasik dan mudah dipahami. Downside adalah bahwa dalam interval antara peluncurannya namespace baru dapat dibuat dan untuk beberapa waktu akan tetap tanpa rahasia, yang akan menyebabkan kesalahan dalam meluncurkan pod.

Otomasi dengan shell-operator


Agar skrip kami berfungsi dengan benar, peluncuran cron klasik perlu diganti dengan peluncuran ketika acara namespace ditambahkan: dalam hal ini, Anda dapat mengatur untuk membuat rahasia sebelum menggunakannya. Mari kita lihat bagaimana mengimplementasikan ini menggunakan shell-operator.

Pertama, mari kita parsing skrip. Skrip dalam hal shell-operator disebut kait. Setiap kait saat startup dengan flag --config memberi tahu operator shell tentang binding-nya, mis. oleh acara apa yang perlu diluncurkan. Dalam kasus kami, kami akan menggunakan onKubernetesEvent :

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

Dijelaskan di sini bahwa kami tertarik pada acara untuk menambahkan ( add ) objek dari namespace .

Sekarang Anda perlu menambahkan kode yang akan dieksekusi ketika acara terjadi:

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

Hebat! Hasilnya adalah sebuah skrip kecil yang indah. Untuk "menghidupkan kembali" itu, dua langkah tetap: untuk menyiapkan gambar dan menjalankannya di cluster.

Mempersiapkan gambar dengan kail


Jika Anda melihat skrip, Anda dapat melihat bahwa perintah kubectl dan jq . Ini berarti bahwa gambar harus memiliki hal-hal berikut: kait kami, operator shell yang akan memantau acara dan menjalankan kait, serta perintah yang digunakan oleh kait (kubectl dan jq). Hub.docker.com sudah memiliki gambar siap pakai di mana shell-operator, kubectl dan jq dikemas. Tetap menambahkan pengait dengan Dockerfile sederhana:

 $ 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 

Peluncuran cluster


Sekali lagi, mari kita lihat hook dan kali ini tuliskan tindakan apa dan dengan objek apa yang dilakukan di cluster:

  1. Berlangganan acara namespace
  2. menciptakan rahasia di ruang nama selain tempat menjalankannya.

Ternyata pod di mana gambar kita akan diluncurkan harus memiliki izin untuk tindakan ini. Ini dapat dilakukan dengan membuat ServiceAccount Anda sendiri. Izin harus dibuat dalam bentuk ClusterRole dan ClusterRoleBinding, karena kami tertarik pada objek dari seluruh cluster.

Deskripsi akhir dalam YAML adalah sesuatu seperti ini:

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

Anda dapat menjalankan gambar yang dirakit dalam bentuk Penerapan sederhana:

 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 


Untuk kenyamanan, namespace terpisah dibuat di mana shell-operator akan diluncurkan dan manifes yang dibuat diterapkan:

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


Itu saja: operator shell akan mulai, berlangganan acara pembuatan namespace dan mulai kail bila perlu.



Dengan demikian, skrip shell sederhana berubah menjadi operator nyata untuk Kubernetes dan berfungsi sebagai bagian integral dari kluster. Dan semua ini - tanpa proses rumit mengembangkan operator di Golang:



Ada ilustrasi lain tentang hal ini ...


Kami akan mengungkapkan maknanya secara lebih rinci di salah satu publikasi berikut. DIPERBARUI (1 Mei 2019): lihat “ Memperluas dan memperluas Kubernet (laporan ulasan dan video) ”.

Penyaringan


Melacak objek itu baik, tetapi sering kali perlu merespons perubahan dalam beberapa properti objek , misalnya, pada perubahan jumlah replika di Deployment, atau pada perubahan label objek.

Ketika suatu peristiwa tiba, operator shell menerima manifes JSON objek. Anda dapat memilih properti yang menarik bagi kami di JSON ini dan menjalankan hook hanya ketika mereka berubah. Untuk melakukan ini, bidang jqFilter , di mana Anda perlu menentukan ekspresi jq yang akan diterapkan pada manifes JSON.

Misalnya, untuk menanggapi perubahan label pada objek Penempatan, Anda perlu memfilter bidang labels dari bidang metadata . Konfigurasi akan seperti ini:

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

Ungkapan ini di jqFilter mengubah manifest JSON panjang Deployment menjadi JSON pendek dengan label:



Shell-operator hanya akan memicu pengait ketika JSON pendek ini berubah dan perubahan pada properti lainnya diabaikan.

Konteks peluncuran hook


Konfigurasi hook memungkinkan Anda menentukan beberapa opsi untuk acara - misalnya, 2 opsi untuk acara dari Kubernetes dan 2 jadwal:

 {"onKubernetesEvent":[ {"name":"OnCreatePod", "kind": "pod", "event":["add"] }, {"name":"OnModifiedNamespace", "kind": "namespace", "event":["update"], "jqFilter": ".metadata.labels" } ], "schedule": [ { "name":"every 10 min", "crontab":"0 */10 * * * *" }, {"name":"on Mondays at 12:10", "crontab": "0 10 12 * * 1" ]} 

Penyimpangan kecil: ya, operator shell mendukung menjalankan skrip gaya crontab . Anda dapat membaca lebih lanjut di dokumentasi .

Untuk membedakan mengapa hook diluncurkan, operator shell membuat file sementara dan meneruskan path ke BINDING_CONTEXT_TYPE di variabel BINDING_CONTEXT_TYPE . File tersebut berisi deskripsi JSON tentang alasan pengait dimulai. Misalnya, setiap 10 menit sebuah pengait akan dimulai dengan konten berikut:

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

... dan pada hari Senin akan dimulai dengan ini:

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

Untuk onKubernetesEvent akan ada lebih banyak JSON yang dipecat sejak itu itu berisi deskripsi objek:

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

Isi kolom dapat dipahami dari namanya, dan lebih terinci - baca di dokumentasi . Contoh untuk mendapatkan nama sumber daya dari bidang resourceName menggunakan jq telah ditunjukkan di sebuah pengait yang mereplikasi rahasia:

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

Demikian pula, Anda bisa mendapatkan bidang yang tersisa.

Apa selanjutnya


Di repositori proyek, di direktori / contoh , ada contoh kait yang siap dijalankan di kluster. Saat menulis kait Anda, Anda dapat menganggapnya sebagai dasar.

Ada dukungan untuk mengumpulkan metrik menggunakan Prometheus - metrik yang tersedia ditulis di bagian METRICS .

Seperti yang Anda duga, operator shell ditulis dalam Go dan didistribusikan di bawah lisensi Open Source (Apache 2.0). Kami akan berterima kasih atas bantuan apa pun dalam mengembangkan proyek di GitHub : tanda bintang, masalah, dan menarik permintaan.

Membuka tabir kerahasiaan, kami juga menginformasikan bahwa operator-shell adalah bagian kecil dari sistem kami, yang dapat terus memperbarui pengaya yang dipasang di kluster Kubernetes dan melakukan berbagai tindakan otomatis. Kami berbicara tentang sistem ini secara lebih rinci pada hari Senin di HighLoad ++ 2019 di St. Petersburg - video dan transkrip laporan ini akan segera diterbitkan.

Kami memiliki rencana untuk membuka sisa sistem ini: addon-operator dan koleksi kait dan modul kami. Omong-omong, addon-operator sudah tersedia di GitHub , tetapi dokumentasi untuknya masih dalam proses. Pelepasan koleksi modul direncanakan di musim panas.

Tetap disini!

PS


Baca juga di blog kami:

Source: https://habr.com/ru/post/id447442/


All Articles