التحقق من صحة Kubernetes YAML مقابل أفضل الممارسات والسياسات

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

التحقق من صحة Kubernetes YAML مقابل أفضل الممارسات والسياسات

TL؛ DR: تقارن هذه المقالة بين ستة أدوات ثابتة للتحقق من صحة ملفات Kubernetes YAML وتقييمها مقابل أفضل الممارسات والمتطلبات.

عادةً ما يتم تحديد أحمال عمل Kubernetes في شكل مستندات YAML. إحدى مشكلات YAML هي صعوبة وضع الحدود أو العلاقات بين ملفات البيان.

ماذا لو أردنا التأكد من أن جميع الصور المنشورة في المجموعة تأتي من سجل موثوق به؟

كيف يمكن منع إرسال عمليات النشر إلى المجموعة التي لم يتم تعيين PodDisruptionBudgets عليها؟

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

يمكن تقسيم النظام البيئي للتحقق الثابت من Kubernetes YAML إلى الفئات التالية:

  • أدوات التحقق من واجهة برمجة التطبيقات (API).. تقوم الأدوات الموجودة في هذه الفئة بالتحقق من صحة بيان YAML مقابل متطلبات خادم Kubernetes API.
  • اختبار جاهز. تأتي الأدوات من هذه الفئة مع اختبارات جاهزة للأمان والامتثال لأفضل الممارسات وما إلى ذلك.
  • أدوات التحقق المخصصة. يسمح لك أعضاء هذه الفئة بإنشاء اختبارات مخصصة بلغات مختلفة، مثل Rego وJavascript.

في هذه المقالة، سنقوم بوصف ومقارنة ستة أدوات مختلفة:

  1. كوبيفال.
  2. درجة كوبي؛
  3. التكوين لينت؛
  4. النحاس.
  5. مسابقة؛
  6. بولاريس.

حسنا، دعونا نبدأ!

التحقق من عمليات النشر

قبل أن نبدأ بمقارنة الأدوات، دعونا ننشئ قاعدة لاختبارها.

يحتوي البيان أدناه على عدد من الأخطاء والتناقضات مع أفضل الممارسات: كم عدد الأخطاء والتناقضات التي يمكنك العثور عليها؟

apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-echo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: http-echo
  template:
    metadata:
      labels:
        app: http-echo
    spec:
      containers:
      - name: http-echo
        image: hashicorp/http-echo
        args: ["-text", "hello-world"]
        ports:
        - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: http-echo
spec:
  ports:
  - port: 5678
    protocol: TCP
    targetPort: 5678
  selector:
    app: http-echo

(base-valid.yaml)

سوف نستخدم YAML هذا لمقارنة الأدوات المختلفة.

البيان أعلاه base-valid.yaml ويمكن العثور على بيانات أخرى من هذه المقالة في مستودعات Git.

يصف البيان تطبيق ويب تتمثل مهمته الرئيسية في الاستجابة برسالة "Hello World" على المنفذ 5678. ويمكن نشره باستخدام الأمر التالي:

kubectl apply -f hello-world.yaml

وهكذا - للتحقق من العمل:

kubectl port-forward svc/http-echo 8080:5678

اذهب الآن إلى http://localhost:8080 والتأكد من تشغيل التطبيق. لكن هل يتبع أفضل الممارسات؟ دعونا تحقق.

1. كوبيفال

في القلب kubeval تكمن فكرة أن أي تفاعل مع Kubernetes يحدث من خلال REST API الخاص به. بمعنى آخر، يمكنك استخدام مخطط API للتحقق مما إذا كان YAML معين يتوافق معه. لنلقي نظرة على مثال.

تعليمات التحميل kubeval متاحة على موقع المشروع.

وفي وقت كتابة المقال الأصلي، كان الإصدار 0.15.0 متاحًا.

بمجرد التثبيت، دعنا نغذيه بالبيان أعلاه:

$ kubeval base-valid.yaml
PASS - base-valid.yaml contains a valid Deployment (http-echo)
PASS - base-valid.yaml contains a valid Service (http-echo)

في حالة النجاح، سيتم الخروج من kubeval برمز خروج 0. يمكنك التحقق من ذلك على النحو التالي:

$ echo $?
0

لنجرب الآن kubeval ببيان مختلف:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-echo
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: http-echo
    spec:
      containers:
      - name: http-echo
        image: hashicorp/http-echo
        args: ["-text", "hello-world"]
        ports:
        - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: http-echo
spec:
  ports:
  - port: 5678
    protocol: TCP
    targetPort: 5678
  selector:
    app: http-echo

(kubeval-invalid.yaml)

يمكنك اكتشاف المشكلة؟ نطلق:

$ kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml contains an invalid Deployment (http-echo) - selector: selector is required
PASS - kubeval-invalid.yaml contains a valid Service (http-echo)

# проверим код возврата
$ echo $?
1

لم يتم التحقق من صحة المورد.

عمليات النشر باستخدام إصدار API apps/v1، يجب أن يتضمن محددًا يتطابق مع تسمية الكبسولة. لا يتضمن البيان أعلاه محددًا، لذلك أبلغ kubeval عن خطأ وتم الخروج برمز غير صفري.

وأتساءل ماذا يحدث إذا ركضت kubectl apply -f مع هذا البيان؟

حسنًا، دعنا نحاول:

$ kubectl apply -f kubeval-invalid.yaml
error: error validating "kubeval-invalid.yaml": error validating data: ValidationError(Deployment.spec):
missing required field "selector" in io.k8s.api.apps.v1.DeploymentSpec; if you choose to ignore these errors,
turn validation off with --validate=false

بالضبط الخطأ الذي حذر منه كوبيفال. يمكنك إصلاحه عن طريق إضافة محدد:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-echo
spec:
  replicas: 2
  selector:          # !!!
    matchLabels:     # !!!
      app: http-echo # !!!
  template:
    metadata:
      labels:
        app: http-echo
    spec:
      containers:
      - name: http-echo
        image: hashicorp/http-echo
        args: ["-text", "hello-world"]
        ports:
        - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: http-echo
spec:
  ports:
  - port: 5678
    protocol: TCP
    targetPort: 5678
  selector:
    app: http-echo

(base-valid.yaml)

تتمثل ميزة أدوات مثل kubeval في أنه يمكن اكتشاف هذه الأخطاء مبكرًا في دورة النشر.

بالإضافة إلى ذلك، لا تتطلب عمليات التحقق هذه الوصول إلى المجموعة: يمكن إجراؤها دون اتصال بالإنترنت.

افتراضيًا، يتحقق kubeval من الموارد مقابل أحدث مخطط Kubernetes API. ومع ذلك، في معظم الحالات، قد تحتاج إلى التحقق من صحة إصدار معين من Kubernetes. يمكنك القيام بذلك باستخدام العلم --kubernetes-version:

$ kubeval --kubernetes-version 1.16.1 base-valid.yaml

لاحظ أن الإصدار يجب أن يكون بالتنسيق Major.Minor.Patch.

للحصول على قائمة بالإصدارات التي يتم دعم التحقق منها، راجع مخطط JSON على جيثب، والذي يستخدمه kubeval للتحقق من الصحة. إذا كنت تريد تشغيل kubeval دون الاتصال بالإنترنت، فقم بتنزيل المخططات وحدد موقعها المحلي باستخدام العلامة --schema-location.

بالإضافة إلى ملفات YAML الفردية، يمكن لـ kubeval أيضًا العمل مع الدلائل وstdin.

بالإضافة إلى ذلك، يتم دمج Kubeval بسهولة في خط أنابيب CI. أولئك الذين يرغبون في إجراء الاختبارات قبل دفع البيانات إلى المجموعة سيكونون سعداء بمعرفة أن kubeval يدعم ثلاثة تنسيقات إخراج:

  1. نص عادي؛
  2. جسون؛
  3. اختبار أي شيء بروتوكول (TAP).

ويمكن استخدام أي من التنسيقات لتحليل المخرجات بشكل أكبر لتكوين ملخص للنتائج من النوع المطلوب.

أحد الجوانب السلبية لـ kubeval هو أنه لا يتحقق حاليًا من تعريفات الموارد المخصصة (CRDs). ومع ذلك، يمكن تكوين kubeval تجاهلهم.

Kubeval هي أداة رائعة للتحقق من صحة الموارد وتقييمها؛ ومع ذلك، يجب التأكيد على أن اجتياز الاختبار لا يضمن توافق المورد مع أفضل الممارسات.

على سبيل المثال، باستخدام العلامة latest في حاوية لا يلبي أفضل الممارسات. ومع ذلك، لا يعتبر kubeval هذا خطأ ولا يبلغ عنه. وهذا يعني أن التحقق من صحة YAML سيكتمل دون سابق إنذار.

ولكن ماذا لو كنت بحاجة إلى تقييم YAML واكتشاف الانتهاكات مثل العلامة latest؟ كيفية التحقق من صحة ملف YAML مقابل أفضل الممارسات؟

2. نقاط كوبي

نقاط كوبي يوزع بيانات YAML ويقيمها مقابل الاختبارات المضمنة. ويتم اختيار هذه الاختبارات بناءً على توصيات الأمان وأفضل الممارسات، مثل:

  • تشغيل حاوية ليس كجذر.
  • توافر الشيكات الصحية جراب.
  • وضع الطلبات والحدود للموارد.

وينتج عن الاختبار ثلاث نتائج: OK, تحذير и حرج.

يمكن تجربة Kube-score عبر الإنترنت أو تثبيته محليًا.

في وقت كتابة المقال الأصلي، كان الإصدار الأحدث من kube-score هو 1.7.0.

دعونا نختبره على بياننا base-valid.yaml:

$ kube-score score base-valid.yaml

apps/v1/Deployment http-echo
[CRITICAL] Container Image Tag
  · http-echo -> Image with latest tag
      Using a fixed tag is recommended to avoid accidental upgrades
[CRITICAL] Pod NetworkPolicy
  · The pod does not have a matching network policy
      Create a NetworkPolicy that targets this pod
[CRITICAL] Pod Probes
  · Container is missing a readinessProbe
      A readinessProbe should be used to indicate when the service is ready to receive traffic.
      Without it, the Pod is risking to receive traffic before it has booted. It is also used during
      rollouts, and can prevent downtime if a new version of the application is failing.
      More information: https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[CRITICAL] Container Security Context
  · http-echo -> Container has no configured security context
      Set securityContext to run the container in a more secure context.
[CRITICAL] Container Resources
  · http-echo -> CPU limit is not set
      Resource limits are recommended to avoid resource DDOS. Set resources.limits.cpu
  · http-echo -> Memory limit is not set
      Resource limits are recommended to avoid resource DDOS. Set resources.limits.memory
  · http-echo -> CPU request is not set
      Resource requests are recommended to make sure that the application can start and run without
      crashing. Set resources.requests.cpu
  · http-echo -> Memory request is not set
      Resource requests are recommended to make sure that the application can start and run without crashing.
      Set resources.requests.memory
[CRITICAL] Deployment has PodDisruptionBudget
  · No matching PodDisruptionBudget was found
      It is recommended to define a PodDisruptionBudget to avoid unexpected downtime during Kubernetes
      maintenance operations, such as when draining a node.
[WARNING] Deployment has host PodAntiAffinity
  · Deployment does not have a host podAntiAffinity set
      It is recommended to set a podAntiAffinity that stops multiple pods from a deployment from
      being scheduled on the same node. This increases availability in case the node becomes unavailable.

يجتاز YAML اختبارات kubeval، بينما يشير kube-score إلى أوجه القصور التالية:

  • لم يتم تكوين اختبارات الجاهزية.
  • لا توجد طلبات وحدود لموارد وحدة المعالجة المركزية والذاكرة.
  • لم يتم تعيين ميزانيات تعطيل الكبسولة.
  • لا توجد قواعد للوجود المنفصل (مضاد للتقارب) لتعظيم التوفر.
  • تعمل الحاوية كجذر.

كل هذه ملاحظات معقولة حول أوجه القصور التي يجب معالجتها حتى يصبح النشر أكثر كفاءة وموثوقية.

فريق kube-score إخراج المعلومات بشكل يمكن للإنسان قراءته، بما في ذلك كافة المخالفات من نوعها تحذير и حرجمما يساعد كثيرا أثناء التطوير.

يمكن لأولئك الذين يرغبون في استخدام هذه الأداة كجزء من خط أنابيب CI تمكين المزيد من الإخراج المضغوط باستخدام العلامة --output-format ci (في هذه الحالة، يتم أيضًا عرض الاختبارات مع النتيجة OK):

$ kube-score score base-valid.yaml --output-format ci

[OK] http-echo apps/v1/Deployment
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU limit is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Memory limit is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU request is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Memory request is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Image with latest tag
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: The pod does not have a matching network policy
[CRITICAL] http-echo apps/v1/Deployment: Container is missing a readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Container has no configured security context
[CRITICAL] http-echo apps/v1/Deployment: No matching PodDisruptionBudget was found
[WARNING] http-echo apps/v1/Deployment: Deployment does not have a host podAntiAffinity set
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service

على غرار kubeval، تُرجع kube-score رمز خروج غير صفري عند فشل الاختبار. حرج. يمكنك أيضًا تمكين معالجة مماثلة لـ تحذير.

بالإضافة إلى ذلك، من الممكن التحقق من الموارد مقابل إصدارات API المختلفة (على غرار kubeval). ومع ذلك، فإن هذه المعلومات "مشفرة" في نتيجة kube نفسها: لا يمكنك تحديد إصدار مختلف من Kubernetes. يمكن أن يصبح هذا القيد مشكلة كبيرة إذا كنت تنوي ترقية مجموعتك أو إذا كان لديك مجموعات متعددة بإصدارات مختلفة من K8s.

يرجى ملاحظة أن لديك بالفعل مشكلة مع اقتراح لتنفيذ هذه الفرصة.

يمكن العثور على مزيد من المعلومات حول kube-score على الموقع الرسمي.

تعد اختبارات Kube-score أداة رائعة لتنفيذ أفضل الممارسات، ولكن ماذا لو كنت بحاجة إلى إجراء تغييرات على الاختبار أو إضافة قواعد مخصصة؟ للأسف، هذا لا يمكن القيام به.

Kube-score غير قابل للتوسيع: لا يمكنك إضافة سياسات إليه أو تعديلها.

إذا كنت تريد كتابة اختبارات مخصصة للتحقق من سياسات الشركة، فيمكنك استخدام إحدى الأدوات الأربع التالية: config-lint، أو copper، أو conftest، أو Polaris.

3.التكوين لينت

Config-lint هي أداة للتحقق من صحة ملفات تكوين YAML وJSON وTerraform وCSV وبيانات Kubernetes.

يمكنك تثبيته باستخدام تعليمات على موقع المشروع.

الإصدار الحالي حتى وقت كتابة المقال الأصلي هو 1.5.0.

لا يتضمن Config-lint اختبارات مضمنة للتحقق من صحة بيانات Kubernetes.

لإجراء أي اختبارات، يجب عليك إنشاء القواعد المناسبة. وهي مكتوبة في ملفات YAML تسمى "مجموعات القواعد" (مجموعات القواعد)، ولها البنية التالية:

version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
  - "*.yaml"
rules:
   # список правил

(rule.yaml)

دعونا ندرسها عن كثب:

  • حقل type يحدد نوع التكوين الذي سيستخدمه config-lint. لK8s يظهر هذا دائما Kubernetes.
  • في files بالإضافة إلى الملفات نفسها، يمكنك تحديد الدليل.
  • حقل rules والمقصود لوضع اختبارات المستخدم.

لنفترض أنك تريد التأكد من أن الصور الموجودة في عملية النشر يتم تنزيلها دائمًا من مستودع موثوق به مثل my-company.com/myapp:1.0. ستبدو قاعدة config-lint التي تقوم بهذا الفحص كما يلي:

- id: MY_DEPLOYMENT_IMAGE_TAG
  severity: FAILURE
  message: Deployment must use a valid image tag
  resource: Deployment
  assertions:
    - every:
        key: spec.template.spec.containers
        expressions:
          - key: image
            op: starts-with
            value: "my-company.com/"

(rule-trusted-repo.yaml)

يجب تحديد السمات التالية لكل قاعدة:

  • id - المعرف الفريد للقاعدة؛
  • severity - ربما بالفشل, تحذير и غير_متوافق;
  • message - في حالة انتهاك القاعدة، يتم عرض محتويات هذا السطر؛
  • resource — نوع المورد الذي تنطبق عليه هذه القاعدة؛
  • assertions - قائمة الشروط التي سيتم تقييمها فيما يتعلق بهذا المورد.

في القاعدة أعلاه assertion دعا every يتحقق من أن كافة الحاويات في Deployment'e (key: spec.templates.spec.containers) استخدم صورًا موثوقة (أي تلك التي تبدأ بـ my-company.com/).

تبدو مجموعة القواعد الكاملة كما يلي:

version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
  - "*.yaml"
rules:

 - id: DEPLOYMENT_IMAGE_REPOSITORY # !!!
    severity: FAILURE
    message: Deployment must use a valid image repository
    resource: Deployment
    assertions:
      - every:
          key: spec.template.spec.containers
          expressions:
            - key: image
              op: starts-with
              value: "my-company.com/"

(ruleset.yaml)

لتجربة الاختبار، دعونا نحفظه باسم check_image_repo.yaml. دعونا نتحقق من الملف base-valid.yaml:

$ config-lint -rules check_image_repo.yaml base-valid.yaml

[
  {
  "AssertionMessage": "Every expression fails: And expression fails: image does not start with my-company.com/",
  "Category": "",
  "CreatedAt": "2020-06-04T01:29:25Z",
  "Filename": "test-data/base-valid.yaml",
  "LineNumber": 0,
  "ResourceID": "http-echo",
  "ResourceType": "Deployment",
  "RuleID": "DEPLOYMENT_IMAGE_REPOSITORY",
  "RuleMessage": "Deployment must use a valid image repository",
  "Status": "FAILURE"
  }
]

فشل الشيك. الآن دعونا نتحقق من البيان التالي باستخدام مستودع الصور الصحيح:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-echo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: http-echo
  template:
    metadata:
      labels:
        app: http-echo
    spec:
      containers:
      - name: http-echo
         image: my-company.com/http-echo:1.0 # !!!
         args: ["-text", "hello-world"]
         ports:
         - containerPort: 5678

(image-valid-mycompany.yaml)

نجري نفس الاختبار مع البيان أعلاه. لم يتم العثور على اى مشكلات:

$ config-lint -rules check_image_repo.yaml image-valid-mycompany.yaml
[]

Config-lint هو إطار عمل تطلعي يسمح لك بإنشاء اختبارات مخصصة للتحقق من صحة بيانات Kubernetes YAML باستخدام YAML DSL.

ولكن ماذا لو كانت هناك حاجة إلى منطق واختبارات أكثر تعقيدًا؟ أليست قدرات YAML صغيرة جدًا بالنسبة لذلك؟ ماذا لو كان بإمكانك إنشاء اختبارات بلغة برمجة كاملة؟

4. نحاس

النحاس V2 هو إطار عمل للتحقق من صحة البيانات باستخدام الاختبارات المخصصة (على غرار config-lint).

ومع ذلك، فهو يختلف عن الأخير في أنه لا يستخدم YAML لوصف الاختبارات. بدلاً من ذلك، يمكن كتابة الاختبارات بلغة JavaScript. يوفر النحاس مكتبة تحتوي على العديد من الأدوات الأساسيةللمساعدة في قراءة المعلومات حول كائنات Kubernetes والإبلاغ عن الأخطاء.

يمكن العثور على تسلسل خطوات تثبيت النحاس في الوثائق الرسمية.

2.0.1 هو الإصدار الأحدث من هذه الأداة المساعدة في وقت كتابة المقالة الأصلية.

مثل config-lint، لا يحتوي Copper على اختبارات مدمجة. دعونا نكتب واحدة. دعه يتحقق من أن عمليات النشر تستخدم صور الحاوية حصريًا من المستودعات الموثوقة مثل my-company.com.

قم بإنشاء ملف check_image_repo.js بالمحتوى التالي:

$$.forEach(function($){
    if ($.kind === 'Deployment') {
        $.spec.template.spec.containers.forEach(function(container) {
            var image = new DockerImage(container.image);
            if (image.registry.lastIndexOf('my-company.com/') != 0) {
                errors.add_error('no_company_repo',"Image " + $.metadata.name + " is not from my-company.com repo", 1)
            }
        });
    }
});

الآن لاختبار بياننا base-valid.yaml، استخدم الأمر copper validate:

$ copper validate --in=base-valid.yaml --validator=check_image_tag.js

Check no_company_repo failed with severity 1 due to Image http-echo is not from my-company.com repo
Validation failed

من الواضح أنه يمكن إجراء اختبارات أكثر تعقيدًا باستخدام النحاس - على سبيل المثال، التحقق من أسماء النطاقات في بيانات الدخول أو رفض البودات التي تعمل في الوضع المميز.

وظائف المرافق المختلفة مدمجة في النحاس:

  • DockerImage يقرأ ملف الإدخال المحدد وينشئ كائنًا بالسمات التالية:
    • name - اسم الصورة،
    • tag - علامة الصورة،
    • registry - تسجيل الصور
    • registry_url - بروتوكول (https://) وتسجيل الصور،
    • fqin - الموقع الكامل للصورة.
  • وظيفة findByName يساعد في العثور على مورد حسب نوع معين (kind) والاسم (name) من ملف الإدخال.
  • وظيفة findByLabels يساعد في العثور على مورد حسب النوع المحدد (kind) والتسميات (labels).

يمكن العثور على جميع وظائف المرافق المتاحة هنا.

افتراضيًا، يقوم بتحميل ملف إدخال YAML بأكمله إلى متغير $$ ويجعلها متاحة للنصوص البرمجية (تقنية مألوفة لأولئك الذين لديهم خبرة في jQuery).

الميزة الرئيسية لـ Copper واضحة: لا تحتاج إلى تعلم لغة متخصصة ويمكنك استخدام ميزات JavaScript المتنوعة لإنشاء اختباراتك الخاصة، مثل استيفاء السلسلة والوظائف وما إلى ذلك.

وتجدر الإشارة أيضًا إلى أن الإصدار الحالي من Copper يعمل بإصدار ES5 من محرك JavaScript، وليس ES6.

التفاصيل متوفرة في الموقع الرسمي للمشروع.

ومع ذلك، إذا لم تكن من كبار المعجبين بجافا سكريبت وتفضل لغة مخصصة للاستعلام عن السياسات ووصفها، فيجب عليك النظر في ملف conftest.

5. المسابقة

Conftest هو إطار عمل للتحقق من بيانات التكوين. مناسب أيضًا لاختبار/التحقق من بيانات Kubernetes. يتم وصف الاختبارات باستخدام لغة استعلام متخصصة ريغو.

يمكنك تثبيت المسابقة مع تعليماتالمدرجة على موقع المشروع.

في وقت كتابة المقال الأصلي، كان أحدث إصدار متاح هو 0.18.2.

على غرار config-lint و copper، تأتي conftest بدون أي اختبارات مدمجة. دعونا نحاول ذلك ونكتب سياستنا الخاصة. كما في الأمثلة السابقة، سوف نتحقق مما إذا كانت صور الحاوية مأخوذة من مصدر موثوق.

إنشاء دليل conftest-checksوفيه ملف بالاسم check_image_registry.rego بالمحتوى التالي:

package main

deny[msg] {

  input.kind == "Deployment"
  image := input.spec.template.spec.containers[_].image
  not startswith(image, "my-company.com/")
  msg := sprintf("image '%v' doesn't come from my-company.com repository", [image])
}

الآن دعونا نختبر base-valid.yaml من خلال conftest:

$ conftest test --policy ./conftest-checks base-valid.yaml

FAIL - base-valid.yaml - image 'hashicorp/http-echo' doesn't come from my-company.com repository
1 tests, 1 passed, 0 warnings, 1 failure

فشل الاختبار كما هو متوقع لأن الصور واردة من مصدر غير موثوق به.

في ملف Rego، نحدد كتلة deny. وتعتبر حقيقتها بمثابة انتهاك. إذا كتل deny متعددة، وتتحقق منها المسابقة بشكل مستقل، ويتم التعامل مع حقيقة أي من الكتل على أنها انتهاك.

بالإضافة إلى الإخراج الافتراضي، يدعم conftest تنسيق JSON وTAP والجدول - وهي ميزة مفيدة جدًا إذا كنت بحاجة إلى تضمين التقارير في مسار CI موجود. يمكنك ضبط التنسيق المطلوب باستخدام العلم --output.

لتسهيل تصحيح أخطاء السياسة، تم وضع علامة على conftest --trace. يقوم بطباعة تتبع لكيفية قيام conftest بتوزيع ملفات السياسة المحددة.

يمكن نشر سياسات المسابقة ومشاركتها في سجلات OCI (مبادرة الحاوية المفتوحة) باعتبارها عناصر.

الأوامر push и pull تسمح لك بنشر قطعة أثرية أو استرداد قطعة أثرية موجودة من سجل بعيد. فلنحاول نشر السياسة التي أنشأناها في سجل Docker المحلي باستخدامها conftest push.

بدء تسجيل Docker المحلي:

$ docker run -it --rm -p 5000:5000 registry

في محطة أخرى، انتقل إلى الدليل الذي قمت بإنشائه سابقًا conftest-checks وقم بتشغيل الأمر التالي:

$ conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latest

إذا كان الأمر ناجحًا، فستظهر لك رسالة مثل هذه:

2020/06/10 14:25:43 pushed bundle with digest: sha256:e9765f201364c1a8a182ca637bc88201db3417bacc091e7ef8211f6c2fd2609c

الآن قم بإنشاء دليل مؤقت وقم بتشغيل الأمر فيه conftest pull. سيقوم بتنزيل الحزمة التي تم إنشاؤها بواسطة الأمر السابق فيها:

$ cd $(mktemp -d)
$ conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latest

سيظهر دليل فرعي في الدليل المؤقت policy، الذي يحتوي على ملف سياستنا:

$ tree
.
└── policy
  └── check_image_registry.rego

يمكن تشغيل الاختبارات مباشرة من المستودع:

$ conftest test --update 127.0.0.1:5000/amitsaha/opa-bundle-example:latest base-valid.yaml
..
FAIL - base-valid.yaml - image 'hashicorp/http-echo' doesn't come from my-company.com repository
2 tests, 1 passed, 0 warnings, 1 failure

لسوء الحظ، DockerHub غير مدعوم حتى الآن. لذا اعتبر نفسك محظوظًا إذا استخدمته سجل حاوية Azure (ACR) أو السجل الخاص بك.

تنسيق قطعة أثرية هو نفسه فتح حزم وكيل السياسة (OPA)، والذي يسمح لك باستخدام conftest لإجراء الاختبارات من حزم OPA الموجودة.

يمكنك معرفة المزيد حول مشاركة السياسة وميزات المسابقة الأخرى على الموقع الرسمي للمشروع.

6. بولاريس

الأداة الأخيرة التي سيتم مناقشتها في هذه المقالة هي بولاريس. (إعلانه العام الماضي نحن مترجمة بالفعل - تقريبا. ترجمة.)

يمكن تثبيت Polaris في مجموعة أو استخدامه في وضع سطر الأوامر. كما كنت قد خمنت، فهو يسمح لك بتحليل بيانات Kubernetes بشكل ثابت.

عند التشغيل في وضع سطر الأوامر، تتوفر اختبارات مدمجة تغطي مجالات مثل الأمان وأفضل الممارسات (على غرار kube-score). بالإضافة إلى ذلك، يمكنك إنشاء اختباراتك الخاصة (كما في config-lint، و copper، و conftest).

بمعنى آخر، يجمع Polaris بين مزايا كلتا فئتي الأدوات: مع الاختبارات المضمنة والمخصصة.

لتثبيت Polaris في وضع سطر الأوامر، استخدم التعليمات على موقع المشروع.

وفي وقت كتابة المقال الأصلي، كان الإصدار 1.0.3 متاحًا.

بعد اكتمال التثبيت، يمكنك تشغيل Polaris على البيان base-valid.yaml بالأمر التالي:

$ polaris audit --audit-path base-valid.yaml

سيتم إخراج سلسلة JSON توضح بالتفصيل الاختبارات التي تم إجراؤها ونتائجها. سيكون للإخراج الهيكل التالي:

{
  "PolarisOutputVersion": "1.0",
  "AuditTime": "0001-01-01T00:00:00Z",
  "SourceType": "Path",
  "SourceName": "test-data/base-valid.yaml",
  "DisplayName": "test-data/base-valid.yaml",
  "ClusterInfo": {
    "Version": "unknown",
    "Nodes": 0,
    "Pods": 2,
    "Namespaces": 0,
    "Controllers": 2
  },
  "Results": [
    /* длинный список */
  ]
}

السحب الكامل متاح هنا.

مثل kube-score، يحدد Polaris المشكلات التي لا يتبع فيها البيان أفضل الممارسات:

  • فحوصات صحة الكبسولة مفقودة.
  • لم يتم تحديد علامات لصور الحاوية.
  • تعمل الحاوية كجذر.
  • لم يتم تحديد Request'y و Limit'y للذاكرة ووحدة المعالجة المركزية.

يتم تعيين درجة من الأهمية لكل اختبار، اعتمادًا على نتائجه: تحذير أو خطر. لمعرفة المزيد حول الاختبارات المضمنة المتاحة، راجع توثيق.

إذا لم تكن هناك حاجة إلى تفاصيل، يمكنك تحديد العلم --format score. في هذه الحالة، سيقوم Polaris بإخراج رقم في النطاق من 1 إلى 100 − أحرز هدفاً (أي التقييم):

$ polaris audit --audit-path test-data/base-valid.yaml --format score
68

كلما اقتربت النتيجة من 100، زادت درجة الالتزام. إذا قمت بالتحقق من رمز الخروج للأمر polaris audit، فتبين أنه يساوي 0.

قوة polaris audit يمكنك الخروج برمز غير الصفر باستخدام علامتين:

  • علم --set-exit-code-below-score يأخذ كوسيطة قيمة عتبة في النطاق 1-100. في هذه الحالة، سينتهي الأمر برمز خروج 4 إذا كانت النتيجة أقل من العتبة. يعد هذا مفيدًا جدًا عندما يكون لديك قيمة حدية معينة (على سبيل المثال 75) وتريد أن يتم تنبيهك إذا انخفضت النتيجة إلى أقل من ذلك.
  • علم --set-exit-code-on-danger سيؤدي إلى خروج الأمر بالرمز 3 في حالة فشل أحد اختبارات الخطر.

لنحاول الآن إنشاء اختبار مخصص يتحقق مما إذا كانت الصورة مأخوذة من مستودع موثوق به. يتم تحديد اختبارات المستخدم بتنسيق YAML، ويتم وصف الاختبار نفسه باستخدام مخطط JSON.

يصف مقتطف YAML التالي اختبارًا جديدًا يسمى checkImageRepo:

checkImageRepo:
  successMessage: Image registry is valid
  failureMessage: Image registry is not valid
  category: Images
  target: Container
  schema:
    '$schema': http://json-schema.org/draft-07/schema
    type: object
    properties:
      image:
        type: string
        pattern: ^my-company.com/.+$

دعونا نلقي نظرة فاحصة على ذلك:

  • successMessage - سيتم عرض هذا السطر إذا اكتمل الاختبار بنجاح؛
  • failureMessage - ستظهر هذه الرسالة في حالة الفشل؛
  • category - يشير إلى إحدى الفئات: Images, Health Checks, Security, Networking и Resources;
  • target--- يحدد نوع الكائن (spec) يتم تطبيق الاختبار. القيم الممكنة: Container, Pod أو Controller;
  • يتم تحديد الاختبار نفسه في الكائن schema باستخدام مخطط JSON. في هذا الاختبار، الكلمة الأساسية pattern يستخدم لمقارنة مصدر الصورة مع المصدر المطلوب.

لإجراء الاختبار أعلاه، تحتاج إلى إنشاء تكوين Polaris التالي:

checks:
  checkImageRepo: danger
customChecks:
  checkImageRepo:
    successMessage: Image registry is valid
    failureMessage: Image registry is not valid
    category: Images
    target: Container
    schema:
      '$schema': http://json-schema.org/draft-07/schema
      type: object
      properties:
        image:
          type: string
          pattern: ^my-company.com/.+$

(polaris-conf.yaml)

دعونا نحلل الملف:

  • في checks يتم وصف الاختبارات ومستوى حرجتها. وبما أنه من المستحسن أن يتم تحذيرك عند التقاط صورة من مصدر غير موثوق به، فإننا نحدد المستوى هنا danger.
  • الاختبار نفسه checkImageRepo ثم تم تعيينه للكائن customChecks.

احفظ الملف كملف custom_check.yaml. الآن يمكنك الركض polaris audit مع بيان YAML الذي يتطلب التحقق من الصحة.

اختبار البيان لدينا base-valid.yaml:

$ polaris audit --config custom_check.yaml --audit-path base-valid.yaml

فريق polaris audit تم تشغيل الاختبار المخصص المذكور أعلاه فقط وفشل.

إذا قمت بإصلاح الصورة ل my-company.com/http-echo:1.0، سوف يكتمل Polaris بنجاح. البيان مع التغييرات موجود بالفعل مستودعاتحتى تتمكن من التحقق من الأمر السابق في البيان image-valid-mycompany.yaml.

الآن يطرح السؤال: كيفية تشغيل الاختبارات المضمنة مع الاختبارات المخصصة؟ بسهولة! تحتاج فقط إلى إضافة معرفات الاختبار المضمنة إلى ملف التكوين. ونتيجة لذلك سوف يأخذ الشكل التالي:

checks:
  cpuRequestsMissing: warning
  cpuLimitsMissing: warning
  # Other inbuilt checks..
  # ..
  # custom checks
  checkImageRepo: danger # !!!
customChecks:
  checkImageRepo:        # !!!
    successMessage: Image registry is valid
    failureMessage: Image registry is not valid
    category: Images
    target: Container
    schema:
      '$schema': http://json-schema.org/draft-07/schema
      type: object
      properties:
        image:
          type: string
          pattern: ^my-company.com/.+$

(config_with_custom_check.yaml)

يتوفر مثال لملف التكوين الكامل هنا.

تحقق من البيان base-valid.yamlباستخدام الاختبارات المضمنة والمخصصة، يمكنك استخدام الأمر:

$ polaris audit --config config_with_custom_check.yaml --audit-path base-valid.yaml

يكمل Polaris الاختبارات المضمنة باختبارات مخصصة، وبالتالي يجمع بين أفضل ما في العالمين.

ومن ناحية أخرى، فإن عدم القدرة على استخدام لغات أكثر قوة مثل Rego أو JavaScript يمكن أن يكون عاملاً مقيدًا يمنعك من إنشاء اختبارات أكثر تعقيدًا.

مزيد من المعلومات حول Polaris متاحة على موقع المشروع.

ملخص

على الرغم من وجود العديد من الأدوات للتحقق من صحة ملفات Kubernetes YAML وتقييمها، ومن المهم أن يكون لديك فهم واضح لكيفية تصميم الاختبارات وتنفيذها.

على سبيل المثال، إذا أخذت بيانات Kubernetes التي تمر عبر خط أنابيب، فقد يكون kubeval هو الخطوة الأولى في مثل هذا المسار. سيتأكد من أن تعريفات الكائنات تتطابق مع مخطط Kubernetes API.

وبمجرد الانتهاء من هذه المراجعة، يمكن المضي قدمًا في اختبارات أكثر تعقيدًا، مثل الامتثال لأفضل الممارسات القياسية والسياسات المحددة. هذا هو المكان الذي سيكون فيه kube-score وPolaris مفيدًا.

بالنسبة لأولئك الذين لديهم متطلبات معقدة ويحتاجون إلى ضبط اختباراتهم، سيكون النحاس وConfig-lint وConftest أمرًا رائعًا..

يستخدم كل من Conftest وconfig-lint YAML لتحديد الاختبارات المخصصة، بينما يتيح لك copper الوصول إلى لغة برمجة كاملة، مما يجعله خيارًا جذابًا للغاية.

ومن ناحية أخرى، هل يجب عليك استخدام إحدى هذه الأدوات، وبالتالي إنشاء جميع الاختبارات يدويًا، أم تفضل Polaris، وتضيف إليها ما هو مطلوب فقط؟ لا توجد إجابة واحدة على هذا السؤال.

ويحتوي الجدول أدناه على وصف مختصر لكل أداة:

أداة
مصير
القيود
اختبارات المستخدم

kubeval
التحقق من صحة بيانات YAML مقابل إصدار مخطط API محدد
لا يعرف كيفية العمل مع CRD
لا

نقاط kube
يتجلى تحليل YAML في مقابل أفضل الممارسات
لا يمكنك تحديد إصدار Kubernetes API الخاص بك للتحقق من صحة الموارد
لا

copper
إطار عمل عام لإنشاء اختبارات JavaScript مخصصة لبيانات YAML
لا توجد اختبارات مدمجة. توثيق ضئيل
نعم

التكوين لينت
إطار عام لإنشاء اختبارات بلغة خاصة بالمجال مضمنة في YAML. يدعم تنسيقات التكوين المختلفة (مثل Terraform)
لا توجد اختبارات جاهزة. قد لا تكون التأكيدات والوظائف المضمنة كافية
نعم

مسابقة
إطار عمل لإنشاء اختباراتك الخاصة في Rego (لغة استعلام متخصصة). يسمح بمشاركة السياسة عبر حزم OCI
لا توجد اختبارات مدمجة. عليك أن تتعلم ريجو. Docker Hub غير مدعوم عند نشر السياسات
نعم

بولاريس
يتجلى تحليل YAML في مقابل أفضل الممارسات القياسية. يسمح لك بإنشاء الاختبارات الخاصة بك باستخدام مخطط JSON
قد لا تكون إمكانات الاختبار المستندة إلى مخطط JSON كافية
نعم

نظرًا لأن هذه الأدوات لا تعتمد على الوصول إلى مجموعة Kubernetes، فهي سهلة التثبيت. إنها تسمح لك بتصفية الملفات المصدر وتقديم تعليقات سريعة لسحب مؤلفي الطلبات في المشاريع.

PS من المترجم

اقرأ أيضًا على مدونتنا:

المصدر: www.habr.com

إضافة تعليق