الكتابة بعد أداة أخرى Kubernetes templating


إذا كنت تعمل مع بيئة Kubernetes ، فربما يمكنك الاستفادة من العديد من أدوات templating الموجودة ، بعضها جزء من مديري الحزم مثل Helm أو Ksonnet ، أو مجرد لغات templating (قالب Jinja2 ، Go ، إلخ). كل منهم له عيوبه الخاصة بالإضافة إلى المزايا وسنقوم بتصفحها ونكتب الأداة الخاصة بنا التي ستحاول الجمع بين أفضل الميزات.


فلماذا لا هيلم؟


هناك عدد من المقالات التي تنتقد هيلم (على سبيل المثال واحد منهم فقط: فكر مرتين قبل استخدام هيلم ). تكمن المشكلة الرئيسية في Helm في أنه يعمل مع تمثيلات السلسلة وأن بيانات Kubernetes هي كائنات (json) . يبدأ الجحيم الحقيقي لمطور مخطط Helm عندما يحتاج (ق) إلى حساب المسافات البادئة لبيان yaml ، في بعض الأحيان يبدو مثل هذا (إنه مثال حقيقي من المخطط الخاص بي):


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


لكن هيلم اليوم هو في الواقع المعيار لحزم تطبيقات Kubernetes. الميزة الرئيسية لـ Helm هي مجتمع كبير وعدد كبير من المستودعات العامة مع المخططات. ومؤخرًا ، أعلن مطورو Helm عن مركز Helm . لذا ، يشبه Helm اليوم Docker - إنه ليس الوحيد ، ولكنه يتمتع بدعم ومجتمع.


هناك تغييرات واعدة تأتي مع إصدار Helm 3 لكن لا أحد يعرف متى يمكن أن يكون.


في الختام ، مزايا هيلم:


  • مجتمع كبير وعدد من الرسوم البيانية العامة
  • (نسبيا) بناء جملة صديقة الإنسان. على الأقل هو yaml + go template ؛)

العيوب:


  • العمل مع السلاسل وليس الأشياء
  • عدد محدود من المشغلين والوظائف التي يمكنك استخدامها

حسنا ، إذن ربما Ksonnet؟


إذا كنت تقارن بين Helm و Ksonnet ، فإن الأخير له ميزة كبيرة ، وهو أنه يعمل مع الكائنات. Ksonnet هي أداة تعتمد على لغة JSON templating Jsonnet. ميزة أخرى رائعة حول Ksonnet هي أن لديها مكتبات Jsonnet متوافقة مع Kubernetes-API والتي يمكنك استيرادها إلى قالبك والعمل مع كائنات Kubernetes كما هو الحال في أي لغة 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); 

تبدو رائعة ، أليس كذلك؟
يكون الأمر أقل بقليل عندما لا تعمل مع كائنات API ولكن مع كائنات json التي تم استيرادها من ملف yaml / json :


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

ولكن لا يزال هذا شيئًا وهو أفضل من العمل مع الأوتار في Helm. عيب Ksonnet هو أنه يحتوي على مجتمع أصغر وحزم أقل من Helm (على الرغم من أنه يمكنك استيراد مخططات Helm في مشروع Ksonnet الخاص بك ، لكنك ستعمل معهم ككائنات json ، وليس ككائنات مكتبة jsonnet). ونتيجة لمجتمع أصغر ومساهمة هناك نقص في بعض الميزات عند محاولة كتابة الرسم البياني الخاص بك. أحدهم خبرته بنفسي: أنت تعلم أنه في Helm يمكنك إنشاء ConfigMap من دليل يحتوي على عدد من ملفات التكوين بهذه الطريقة:


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

يمكنك أن تتخيل إحباطي عندما اكتشفت أنه لا يوجد مثل هذه الميزة في Ksonnet. هناك حلول على الرغم من. ولكن النقطة المهمة هي أنه مجرد مثال على الموقف عندما تكتب مخططك بسعادة ثم فجأة يؤدي نقص بعض الميزات إلى توقفك في منتصف الطريق.
في المجموع ، مزايا Ksonnet:


  • العمل مع الأشياء
  • مكتبات Jsonnet المتوافقة مع Kubernetes-API
  • هيلم دعم استيراد الرسم البياني

العيوب:


  • مجتمع أصغر وعدد أصغر من حزم Ksonnet الأصلية
  • نقص في بعض الوظائف التي يمكنك استخدامها في هيلم
  • بناء جملة جديد => زيادة وقت التعلم => عامل ناقل متزايد
  • يمكن أن يكون بناء الجملة في بعض الأحيان قبيحًا وأقل قابلية للقراءة للإنسان (خاصةً عند إنشاء حلول للمشاكل التي تفتقر إلى الميزات)

دعونا نفكر في أداة templating مثالية


فيما يلي بعض المعايير لأداة templating "المثالية":


  • يجب أن تعمل مع الكائنات ، وليس سلاسل
  • يجب أن يكون لديه القدرة على العمل مع الكائنات المتوافقة مع Kubernetes-API
  • يجب أن يحتوي على مجموعة لائقة من الوظائف للعمل مع السلاسل
  • يجب أن تعمل بشكل جيد مع تنسيقات json و yaml
  • يجب أن تكون صديقة للإنسان
  • يجب أن تكون بسيطة
  • يجب أن يكون لديه القدرة على استيراد مخططات Helm الحالية (لأن هذا هو الواقع ونريد الاستفادة من مجتمع Helm)

هذا يكفي الآن. مررت بهذه القائمة في رأسي وفكرت بنفسي: حسنًا ، لماذا لا أجرب بايثون؟ دعونا نرى ما إذا كان يناسب معاييرنا:


  • العمل مع الأشياء ، وليس الجمل . نعم ، يمكننا استخدام أنواع list dict لذلك.
  • لديك القدرة على العمل مع الكائنات المتوافقة مع Kubernetes-API . نعم ، from kubernetes import client
  • لديك مجموعة لائقة من الوظائف للعمل مع السلاسل . الكثير!
  • العمل بشكل جيد مع صيغ json و yaml . لطيف جدا.
  • صديقة الإنسان لا القرف.
  • بسيط نعم
  • القدرة على استيراد مخططات Helm الحالية . هذا ، سوف نضيف أنفسنا.

حسنا ، يبدو واعدا. قررت أن أكتب أداة templating بسيطة على قمة مكتبة عملاء Official Python من أجل kubernetes والآن دعني أريك ما خرج منها.


تلبية كارافيل


لا يوجد شيء خاص أو معقد حول هذه الأداة. أخذت للتو مكتبة Kubernetes (التي منحتني القدرة على العمل مع كائنات Kubernetes) وكتبت بعض الوظائف الأساسية لمخططات Helm الحالية (بحيث يمكن للمرء أن يجلبها ويضيفها إلى مخططهم الخاص). لذلك ، يتيح لك جولة.
بادئ ذي بدء ، يمكن الوصول إلى هذه الأداة في Github repo ويمكنك العثور على دليل مع أمثلة هناك.


بداية سريعة مع صورة عامل الميناء


إذا كنت ترغب في تجربتها ، فإن أبسط طريقة هي استخدام صورة عامل النقل هذه :


 $ 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 

بالطبع ، إذا كنت ترغب في قالب المخططات ، فأنت بحاجة إلى تحميل دليل المخطط الخاص بك:


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

لذلك ، دعونا نلقي نظرة على هيكل الرسم البياني. انها تشبه الى حد بعيد واحدة من هيلم:


 $ cd example $ tree . . ├── dependencies ├── prod.yaml ├── requirements.yaml ├── templates │  ├── custom-resource.py │  ├── deployment.py │  └── service-helm.py └── values.yaml 2 directories, 6 files 

مثل Helm ، يحتوي على requirements.yaml ملف yaml بنفس التنسيق:


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

هنا يمكنك فقط سرد تبعيات Helm التي تريد استيرادها إلى المخطط الخاص بك. التبعيات انتقل إلى دليل dependencies . لجلبهم أو تحديثهم ، استخدم أمر ensure :


 $ karavel ensure . 

بعد ذلك سيبدو دليل dependencies كما يلي:


 $ 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 

الآن بعد التأكد من تبعياتنا ، دعونا نلقي نظرة على القوالب. أولاً ، نقوم بإنشاء نشر nginx بسيط:


 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 

لذا ، لكي يكون القالب صالحًا ، يجب أن يكون لديك وظيفة template() تُرجع إما كائن Kubernetes واحدًا أو list / tuple منها. يمكنك العثور على قائمة كائنات API لعميل Python هنا .
كما ترون ، الكود نظيف وبسيط وقابل للقراءة. يمكنك أن تتساءل من values.nginx.image.repository يأتي من values.nginx.image.repository ؟ تحصل على قيم من ملفات القيمة التي تمر بها عند رسم المخطط ، مثلما يحدث في Helm: karavel template -f one.yaml --values two.yaml . سوف نلقي نظرة عليها في وقت لاحق.


حسنًا ، ماذا عن مخططات هلم؟


الآن ، أنشأنا نشر الخاصة بنا. لكن ماذا لو أردنا استيراد مخطط هلم أو جزءًا من المخطط؟ دعنا نلقي نظرة على 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 

بسيط ، هاه؟ لاحظ هذا السطر: service = chart.get(name='svc', obj_class=client.V1Service) - أنشأنا كائنًا من فئة V1Service شكل ملف Helm yaml . إذا كنت لا تريد / تحتاج إلى القيام بذلك - فيمكنك دائمًا العمل مع dict عادل.


ماذا لو كنت أرغب في إنشاء مورد مخصص؟


حسنًا ، هناك مشكلة صغيرة في ذلك. لا يضيف Kubernetes API كائنات CRD إلى تعريف swagger json في /openapi/v2 ، والكائنات بيثون العميل /openapi/v2 على هذا التعريف. ولكن لا يزال بإمكانك العمل بسهولة مع الأشياء التي dict . مثل هذا:


 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 

لا تزال تبدو جميلة ، أليس كذلك؟


هل يمكنني الحصول على قيم لبيئات مختلفة ، مثل dev / prod؟


نعم تستطيع!
دعونا نلقي نظرة على values.yaml


 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 

لاحظ مفتاح helm داخل mysql dict: لقد استخدمناه عند تحديد قيم المخطط helm المخطط chart = HelmChart(name='mysql', version='0.13.1', values=values.mysql.helm) . تحتاج بعض مخططات Helm إلى releaseName لتسمية التطبيق namespace لسياسات RBAC. يتم تمرير هذه القيمتين إلى Helm كـ - --namespace NAME و الوسائط NAME في helm template .


الآن ، يمكنك تحديد ملف إضافي لبرود env ، وقوالب جميع الأمثلة لدينا:


 $ 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 

بعد ذلك يمكنك القيام kubeclt apply ونشر هذه الكائنات في الكتلة.


رائع! ماذا عن الترميز و base64؟


import base64


ماذا عن استخدام Vault للأسرار؟


import hvac


جلب عناوين المواقع؟


import importlib


وظائف التجزئة الآمنة؟


import Crypto


حصلت عليه. مع Python يمكنك القيام بالكثير من الأشياء مع إعلانات Kubernetes الخاصة بك.


هل هي متلازمة المعاهد الوطنية للصحة؟


لا :)
أنا كذلك بسعادة باستخدام هيلم في مشاريعي الحالية. هناك أشياء افتقدها رغم ذلك. لقد استخدمت Ksonnet في بعض مشاريعي أيضًا.
أود أن أفكر في هذه الأداة كدليل على المفهوم بأنه يمكن أن يكون لدينا أدوات تمجيد أفضل من هيلم وليس من الصعب جدًا تطويرها باستخدام بيثون. إذا كان هناك اهتمام / حاجة مجتمعية في مثل هذه الأداة ، يمكننا معا الاستمرار في تطويرها. أو يمكننا الانتظار لإصدار هيلم 3 ؛)


الخاتمة


لقد أوضحت لك أداة templating المستندة إلى Python لـ Kubernetes والتي تدعم ودعم الكائنات المتوافقة مع Kubernetes-API لاستيراد مخططات Helm. أي تعليقات ومناقشة من المجتمع هي موضع ترحيب ، ومرة ​​أخرى مرحبا بكم في الريبو .


شكرا لك على قراءة هذا وقد لطيفة اليوم!


المراجع


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


All Articles