Menulis alat templating Kubernet lain


Jika Anda bekerja dengan lingkungan Kubernetes maka Anda mungkin menggunakan beberapa alat templating yang ada, beberapa dari mereka menjadi bagian dari manajer paket seperti Helm atau Ksonnet , atau hanya bahasa templating (Jinja2, Go template dll). Semua dari mereka memiliki kelemahannya sendiri serta kelebihannya dan kami akan membahasnya dan menulis alat kami sendiri yang akan mencoba menggabungkan fitur-fitur terbaik.


Jadi, mengapa tidak Helm?


Ada sejumlah artikel yang mengkritik Helm (mis. Salah satunya saja: Berpikir dua kali sebelum menggunakan Helm ). Masalah utama dengan Helm adalah bahwa ia bekerja dengan representasi string dan manifes Kubernetes adalah objek (json) . Neraka sebenarnya untuk pengembang Helm chart dimulai ketika dia perlu menghitung indentasi untuk manifes yaml , kadang-kadang terlihat seperti ini (ini adalah contoh nyata dari bagan saya):


 spec: jobTemplate: spec: template: spec: containers: - name: my-awesome-container resources: {{ toYaml .Values.resources | indent 14 }} 


Tapi Helm hari ini adalah de-facto standar untuk kemasan aplikasi Kubernetes. Keuntungan utama dari Helm adalah komunitas besar dan sejumlah besar repositori publik dengan grafik. Dan baru-baru ini pengembang Helm telah mengumumkan hub Helm . Jadi Helm hari ini seperti Docker - ini bukan satu-satunya tetapi memiliki komunitas dan dukungan.


Ada perubahan yang menjanjikan dengan rilis Helm 3 tetapi tidak ada yang tahu kapan itu bisa terjadi.


Untuk menyimpulkan, keunggulan Helm:


  • Komunitas besar dan sejumlah bagan publik
  • (Relatif) sintaks yang ramah manusia. Setidaknya itu yaml + go templat;)

Kekurangan:


  • Bekerja dengan string dan bukan objek
  • Jumlah operator dan fungsi terbatas yang dapat Anda gunakan

Oke, mungkin Ksonnet?


Jika Anda membandingkan Helm dengan Ksonnet, yang terakhir memiliki keunggulan besar, yaitu bekerja dengan objek. Ksonnet adalah alat berbasis bahasa JSON templating Jsonnet. Fitur keren lainnya tentang Ksonnet adalah memiliki pustaka Jsonnet yang kompatibel dengan Kubernetes-API yang dapat Anda impor ke template Anda dan bekerja dengan objek Kubernetes seperti dalam bahasa OOP:


 local k = import "k.libsonnet"; local deployment = k.apps.v1beta1.deployment; local appDeployment = deployment .new( params.name, params.replicas, container .new(params.name, params.image) .withPorts(containerPort.new(targetPort)), labels); 

Terlihat mengesankan, bukan?
Agak kurang rapi ketika Anda bekerja bukan dengan objek API tetapi dengan hanya objek json yang diimpor dari file yaml / json :


 { global: {}, components: { "deployment-nginx-deployment-dkecx"+: { spec+: { replicas: 10, template+: { spec+: { containers+: [ { name: "nginx", image: "nginx:latest", ports: [ { containerPort: 80, }, ], }, ], }, }, }, }, }, } 

Tapi tetap saja itu adalah sesuatu dan itu lebih baik daripada bekerja dengan string di Helm. Kerugian dari Ksonnet adalah ia memiliki komunitas yang lebih kecil dan paket yang lebih sedikit daripada Helm (meskipun Anda dapat mengimpor grafik Helm ke proyek Ksonnet Anda, tetapi Anda akan bekerja dengan mereka sebagai objek json, bukan sebagai objek jsonnet-library). Dan sebagai hasil dari komunitas yang lebih kecil dan kontribusi ada kekurangan beberapa fitur ketika Anda mencoba untuk menulis bagan Anda sendiri. Salah satunya saya alami sendiri: Anda tahu bahwa di Helm Anda dapat membangun ConfigMap dari direktori yang berisi sejumlah file konfigurasi dengan cara ini:


 apiVersion: v1 kind: ConfigMap metadata: name: conf data: {{- (.Files.Glob "foo/*").AsConfig | nindent 2 }} 

Anda dapat membayangkan frustrasi saya ketika saya mengetahui bahwa tidak ada fitur seperti itu di Ksonnet. Namun ada beberapa solusi. Tapi intinya adalah itu hanya contoh dari situasi ketika Anda dengan senang hati menulis bagan Anda dan tiba-tiba kurangnya fitur menghentikan Anda di tengah jalan.
Secara total, keunggulan Ksonnet:


  • Bekerja dengan benda
  • Perpustakaan Jsonnet yang kompatibel dengan Kubernetes-API
  • Dukungan impor grafik helm

Kekurangan:


  • Komunitas yang lebih kecil dan jumlah paket asli Ksonnet yang lebih sedikit
  • Kurangnya beberapa fungsi yang dapat Anda gunakan di Helm
  • Sintaks baru => peningkatan waktu belajar => peningkatan faktor bus
  • Sintaks kadang-kadang bisa menjadi jelek dan kurang dapat dibaca manusia (terutama ketika membuat solusi untuk kekurangan fitur)

Mari kita pikirkan alat templating yang ideal


Berikut adalah beberapa kriteria untuk alat templating "ideal":


  • Ini harus bekerja dengan objek, bukan string
  • Seharusnya memiliki kemampuan untuk bekerja dengan objek yang kompatibel dengan Kubernetes-API
  • Seharusnya memiliki serangkaian fungsi yang layak untuk bekerja dengan string
  • Ini harus bekerja dengan baik dengan format json dan yaml
  • Itu harus ramah manusia
  • Itu harus sederhana
  • Seharusnya memiliki kemampuan untuk mengimpor grafik Helm yang ada (karena ini adalah kenyataan dan kami ingin memanfaatkan komunitas Helm)

Cukup untuk sekarang. Saya membaca daftar ini di kepala saya dan berpikir dalam hati: oke, mengapa tidak mencoba Python? Mari kita lihat apakah itu sesuai dengan kriteria kami:


  • Bekerja dengan benda, bukan string . Ya, kita bisa menggunakan tipe dict dan list untuk itu.
  • Memiliki kemampuan untuk bekerja dengan objek yang kompatibel dengan Kubernetes-API . Ya, from kubernetes import client
  • Memiliki serangkaian fungsi yang layak untuk bekerja dengan string . Banyak!
  • Bekerja dengan baik dengan format json dan yaml . Dengan sangat baik.
  • Ramah manusia Tidak ada apa-apa.
  • Sederhana Ya
  • Kemampuan untuk mengimpor grafik Helm yang ada . Itu, kita akan menambahkan diri kita sendiri.

Ok, terlihat menjanjikan. Saya memutuskan untuk menulis alat templating sederhana di atas perpustakaan klien Python Resmi untuk kubernetes dan sekarang izinkan saya menunjukkan kepada Anda apa yang keluar darinya.


Temui karavel


Tidak ada yang istimewa atau rumit tentang alat ini. Saya baru saja mengambil perpustakaan Kubernetes (yang memberi saya kemampuan untuk bekerja dengan objek Kubernetes) dan menulis beberapa fungsionalitas dasar untuk grafik Helm yang ada (sehingga orang dapat mengambilnya dan menambahkannya ke grafik mereka sendiri). Jadi, mari kita melakukan tur.
Pertama-tama, alat ini dapat diakses di repo Github dan Anda dapat menemukan direktori dengan contoh di sana.


Mulai cepat dengan gambar Docker


Jika Anda ingin mencobanya, cara paling sederhana adalah dengan menggunakan gambar buruh pelabuhan ini :


 $ docker run greegorey/karavel -h usage: karavelcli.py [-h] subcommand ... optional arguments: -h, --help show this help message and exit list of subcommands: subcommand template generates manifests from template ensure ensure helm dependencies 

Tentu saja, jika Anda ingin membuat templat bagan, Anda perlu memasang direktori bagan Anda:


 $ cd example $ docker run -v $PWD:/chart greegorey/karavel template . 

Jadi, mari kita lihat struktur grafik. Ini sangat mirip dengan salah satu Helm:


 $ cd example $ tree . . β”œβ”€β”€ dependencies β”œβ”€β”€ prod.yaml β”œβ”€β”€ requirements.yaml β”œβ”€β”€ templates β”‚  β”œβ”€β”€ custom-resource.py β”‚  β”œβ”€β”€ deployment.py β”‚  └── service-helm.py └── values.yaml 2 directories, 6 files 

Seperti Helm, ia memiliki file requirements.yaml dengan tata letak yang sama:


 dependencies: - name: mysql version: 0.13.1 repository: https://kubernetes-charts.storage.googleapis.com/ 

Di sini Anda cukup mendaftar dependensi Helm yang ingin Anda impor ke bagan. Dependensi pergi ke direktori dependencies . Untuk mengambil atau memperbaruinya gunakan perintah sure:


 $ karavel ensure . 

Setelah itu direktori dependencies Anda akan terlihat seperti ini:


 $ tree dependencies dependencies └── mysql-0.13.1 └── mysql β”œβ”€β”€ Chart.yaml β”œβ”€β”€ README.md β”œβ”€β”€ templates β”‚  β”œβ”€β”€ NOTES.txt β”‚  β”œβ”€β”€ _helpers.tpl β”‚  β”œβ”€β”€ configurationFiles-configmap.yaml β”‚  β”œβ”€β”€ deployment.yaml β”‚  β”œβ”€β”€ initializationFiles-configmap.yaml β”‚  β”œβ”€β”€ pvc.yaml β”‚  β”œβ”€β”€ secrets.yaml β”‚  β”œβ”€β”€ svc.yaml β”‚  └── tests β”‚  β”œβ”€β”€ test-configmap.yaml β”‚  └── test.yaml └── values.yaml 4 directories, 13 files 

Sekarang setelah kita memastikan dependensi kita mari kita lihat templat. Pertama, kami membuat penyebaran nginx sederhana:


 from kubernetes import client from karavel.helpers import Values def template(): values = Values().values # Configure Pod template container container = client.V1Container( name='nginx', image='{}:{}'.format(values.nginx.image.repository, values.nginx.image.tag), ports=[client.V1ContainerPort(container_port=80)]) # Create and configurate a spec section template = client.V1PodTemplateSpec( metadata=client.V1ObjectMeta(labels={'app': 'nginx'}), spec=client.V1PodSpec(containers=[container])) # Create the specification of deployment spec = client.ExtensionsV1beta1DeploymentSpec( replicas=3, template=template) # Instantiate the deployment object deployment = client.ExtensionsV1beta1Deployment( api_version='extensions/v1beta1', kind='Deployment', metadata=client.V1ObjectMeta(name='nginx-deployment'), spec=spec) return deployment # [deployment], (deployment, deployment) are valid 

Jadi, agar templat menjadi valid, Anda harus memiliki fungsi template() yang mengembalikan objek Kubernetes tunggal atau list / tupelnya. Anda dapat menemukan daftar objek API untuk klien Python di sini .
Seperti yang Anda lihat, kodenya bersih, sederhana, mudah dibaca. Anda bisa bertanya-tanya dari mana berasal values.nginx.image.repository ? Ia mendapat nilai dari file nilai yang Anda lewati saat menyusun bagan, seperti di Helm: karavel template -f one.yaml --values two.yaml . Kita akan melihatnya nanti.


Oke, bagaimana dengan grafik Helm?


Sekarang, kami membuat Penempatan kami sendiri. Tetapi bagaimana jika kita ingin mengimpor Helm bag atau bagian dari bagan? Mari kita lihat templates/service-helm.py :


 from kubernetes import client from karavel.helm import HelmChart from karavel.helpers import Values def template(): values = Values().values # Initialize the chart (== helm template --values) chart = HelmChart(name='mysql', version='0.13.1', values=values.mysql.helm) # Get the desired object from chart service = chart.get(name='svc', obj_class=client.V1Service) # Create custom objects to add custom_ports = [ client.V1ServicePort( name='my-custom-port', protocol=values.mysql.protocol, port=values.mysql.port, target_port=39000, ) ] # Add custom objects to the service service.spec['ports'] = custom_ports # Change Helm-generated label service.metadata['labels']['release'] += '-suffix' # Delete Helm-generated label `heritage: Tiller` del service.metadata['labels']['heritage'] return service # [service], (service, service) are valid 

Sederhana ya Perhatikan baris ini: service = chart.get(name='svc', obj_class=client.V1Service) - kami membuat objek kelas V1Service dari file Helm yaml . Jika Anda tidak ingin / perlu melakukan itu - Anda selalu dapat bekerja dengan dict .


Bagaimana jika saya ingin membuat sumber daya khusus?


Nah, ada masalah kecil dengan itu. API Kubernetes tidak menambahkan objek CRD ke definisi json /openapi/v2 di /openapi/v2 , dan objek Python-client dibuat berdasarkan definisi ini. Tetapi Anda masih dapat dengan mudah bekerja dengan objek-objek dict . Seperti ini:


 from kubernetes import client def template(): resource = { 'apiVersion': 'stable.example.com/v1', 'kind': 'Whale', 'metadata': client.V1ObjectMeta( name='my-object', ), 'spec': { 'image': 'my-whale-image:0.0.1', 'tail': 1, 'fins': 4, } } return resource # [resource], (resource, resource) are valid 

Masih terlihat bagus, bukan?


Bisakah saya memiliki nilai untuk lingkungan yang berbeda, misalnya dev / prod?


Ya kamu bisa!
Mari kita lihat values.yaml terlebih dahulu:


 nginx: image: repository: nginx tag: 1.15-alpine mysql: port: 3307 protocol: TCP helm: releaseName: my-release namespace: prod imageTag: '5.7.14' service: type: NodePort 

Catat kunci helm di dalam mysql dict: kami menggunakannya ketika menentukan nilai untuk bagan helm: chart = HelmChart(name='mysql', version='0.13.1', values=values.mysql.helm) . Beberapa grafik Helm memerlukan releaseName untuk penamaan aplikasi dan namespace untuk kebijakan RBAC. Kedua nilai ini diteruskan ke Helm sebagai argumen --namespace dan NAME dalam helm template .


Sekarang, Anda dapat menentukan file tambahan untuk prod env, dan templat semua contoh kami:


 $ karavel template -f values.yaml -f prod.yaml . --- # Source: templates/custom-resource.py apiVersion: stable.example.com/v1 kind: Whale metadata: name: my-object spec: fins: 4 image: my-whale-image:0.0.1 tail: 1 --- # Source: templates/deployment.py apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 template: metadata: labels: app: nginx spec: containers: - image: nginx:1.14-alpine name: nginx ports: - containerPort: 80 --- # Source: templates/service-helm.py apiVersion: v1 kind: Service metadata: annotations: null labels: app: prod-release-mysql chart: mysql-0.13.1 release: prod-release-suffix name: prod-release-mysql spec: ports: - name: my-custom-port port: 3308 protocol: TCP targetPort: 39000 selector: app: prod-release-mysql type: NodePort 

Setelah itu Anda bisa melakukan kubeclt apply dan menyebarkan objek-objek ini ke dalam cluster.


Keren! Bagaimana dengan encoding dan base64?


import base64


Bagaimana dengan menggunakan Vault untuk rahasia?


import hvac


Mengambil url?


import importlib


Fungsi hash aman?


import Crypto


Kamu mendapatkannya. Dengan Python Anda dapat melakukan banyak hal dengan manifes Kubernet Anda.


Apakah itu sindrom NIH?


Tidak :)
Saya dengan senang hati menggunakan Helm dalam proyek saya saat ini. Ada beberapa hal yang saya rindukan. Saya menggunakan Ksonnet di beberapa proyek saya juga.
Saya ingin menganggap alat ini sebagai bukti konsep bahwa kita dapat memiliki alat templating lebih baik daripada Helm dan tidak terlalu sulit untuk mengembangkannya menggunakan Python. Jika ada minat / kebutuhan masyarakat akan alat semacam itu, kita dapat bersama-sama terus mengembangkannya. Atau kita bisa menunggu rilis Helm 3;)


Kesimpulan


Saya telah menunjukkan kepada Anda alat templating berbasis Python untuk Kubernetes yang mendukung dan mendukung objek yang kompatibel dengan Kubernetes-API untuk mengimpor grafik Helm. Setiap komentar dan diskusi dari komunitas dipersilahkan, dan sekali lagi selamat datang di repo .


Terima kasih telah membaca ini dan semoga harimu menyenangkan!


Referensi


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


All Articles