دمج ثلاثي الاتجاهات في werf: النشر إلى Kubernetes باستخدام Helm "على المنشطات"

لقد حدث ما كنا ننتظره (وليس نحن فقط) لفترة طويلة: werf، الأداة المساعدة مفتوحة المصدر الخاصة بنا لبناء التطبيقات وتسليمها إلى Kubernetes، تدعم الآن تطبيق التغييرات باستخدام تصحيحات الدمج الثلاثية! بالإضافة إلى ذلك، من الممكن اعتماد موارد K3 الموجودة في إصدارات Helm دون إعادة بناء هذه الموارد.

دمج ثلاثي الاتجاهات في werf: النشر إلى Kubernetes باستخدام Helm "على المنشطات"

إذا كانت قصيرة جدًا، فإننا نضعها WERF_THREE_WAY_MERGE=enabled - نحصل على النشر "كما في kubectl apply"، متوافق مع عمليات تثبيت Helm 2 الحالية وأكثر من ذلك بقليل.

ولكن لنبدأ بالنظرية: ما هي بالضبط تصحيحات الدمج الثلاثية، وكيف توصل الأشخاص إلى طريقة إنشائها، ولماذا هي مهمة في عمليات CI/CD مع البنية التحتية المستندة إلى Kubernetes؟ وبعد ذلك، دعونا نرى ما هو الدمج ثلاثي الاتجاهات في werf، وما هي الأوضاع المستخدمة افتراضيًا وكيفية إدارتها.

ما هو تصحيح الدمج ثلاثي الاتجاهات؟

لذا، فلنبدأ بمهمة نشر الموارد الموضحة في بيانات YAML في Kubernetes.

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

أوامر Kupectl الحتمية

الطريقة الأولى لإدارة الكائنات في Kubernetes هي استخدام أوامر kubectl الحتمية لإنشاء هذه الكائنات وتعديلها وحذفها. ببساطة:

  • الفريق kubectl run يمكنك تشغيل النشر أو الوظيفة:
    kubectl run --generator=deployment/apps.v1 DEPLOYMENT_NAME --image=IMAGE
  • الفريق kubectl scale - تغيير عدد النسخ المتماثلة:
    kubectl scale --replicas=3 deployment/mysql
  • إلخ

قد يبدو هذا النهج مناسبًا للوهلة الأولى. ولكن هناك مشاكل:

  1. من الصعب أتمتة.
  2. كيف تعكس التكوين في جيت؟ كيفية مراجعة التغييرات التي تحدث للمجموعة؟
  3. كيفية توفير قابلية اعادة الأنتاج تكوينات عند إعادة التشغيل؟
  4. ...

من الواضح أن هذا النهج لا يتناسب بشكل جيد مع تخزين التطبيقات والبنية التحتية كرمز (IaC؛ أو حتى جيت أوبس كخيار أكثر حداثة، واكتسب شعبية في النظام البيئي Kubernetes). لذلك، لم تحصل هذه الأوامر على مزيد من التطوير في kubectl.

إنشاء العمليات والحصول عليها واستبدالها وحذفها

مع الابتدائية خلق الأمر بسيط: أرسل البيان إلى العملية create kube api وتم إنشاء المورد. يمكن تخزين تمثيل YAML للبيان في Git وإنشائه باستخدام الأمر kubectl create -f manifest.yaml.

С إزالة بسيط أيضًا: استبدل نفس الشيء manifest.yaml من Git إلى الفريق kubectl delete -f manifest.yaml.

عملية replace يسمح لك باستبدال تكوين المورد بالكامل بتكوين جديد، دون إعادة إنشاء المورد. هذا يعني أنه قبل إجراء تغيير على أحد الموارد، من المنطقي الاستعلام عن الإصدار الحالي من خلال العملية getوتغييره وتحديثه مع العملية replace. تم بناء خادم kube قفل متفائل وإذا كان بعد الجراحة get لقد تغير الكائن، ثم العملية replace لن يمر.

لتخزين التكوين في Git وتحديثه باستخدام الاستبدال، عليك القيام بهذه العملية get، قم بدمج التكوين من Git مع ما تلقيناه وقم بالتنفيذ replace. بشكل افتراضي، kubectl يسمح لك فقط باستخدام الأمر kubectl replace -f manifest.yamlحيث manifest.yaml - بيان جاهز بالكامل (في حالتنا مدمج) ويجب تثبيته. اتضح أن المستخدم بحاجة إلى تنفيذ بيانات الدمج، وهذا ليس بالأمر الهين...

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

المجموع: هل يمكننا بناء طرح مستمر فقط باستخدام الإنشاء والاستبدال والحذف، مع التأكد من تخزين تكوين البنية التحتية في Git جنبًا إلى جنب مع الكود وCI/CD المناسب؟

من حيث المبدأ، نستطيع... من أجل هذا سوف تحتاج إلى تنفيذ عملية الدمج البيانات ونوع من الارتباط الذي:

  • يتحقق من وجود كائن في الكتلة،
  • ينفذ إنشاء الموارد الأولية،
  • تحديثه أو حذفه.

عند التحديث يرجى ملاحظة ذلك ربما تغير المورد منذ آخر get والتعامل تلقائيًا مع حالة القفل المتفائل - قم بمحاولات التحديث المتكررة.

ومع ذلك، لماذا نعيد اختراع العجلة عندما يقدم kube-apiserver طريقة أخرى لتحديث الموارد: العملية patchمما يريح المستخدم من بعض المشاكل الموصوفة؟

بقعة

الآن نصل إلى البقع.

التصحيحات هي الطريقة الأساسية لتطبيق التغييرات على الكائنات الموجودة في Kubernetes. عملية patch يعمل مثل هذا:

  • يحتاج مستخدم kube-apiserver إلى إرسال تصحيح في نموذج JSON وتحديد الكائن،
  • وسوف يتعامل خادم apiserver نفسه مع الحالة الحالية للكائن ويعيده إلى النموذج المطلوب.

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

على النحو التالي:

  • باستخدام عملية create نقوم بإنشاء كائن وفقًا للبيان من Git،
  • من خلال delete - احذف إذا لم تعد هناك حاجة للكائن،
  • من خلال patch — نقوم بتغيير الكائن، وإحضاره إلى النموذج الموضح في Git.

ومع ذلك، للقيام بذلك، تحتاج إلى إنشاء التصحيح الصحيح!

كيف تعمل التصحيحات في Helm 2: دمج ثنائي الاتجاه

عندما تقوم بتثبيت إصدار لأول مرة، يقوم Helm بتنفيذ العملية create لموارد الرسم البياني.

عند تحديث إصدار Helm لكل مورد:

  • يأخذ في الاعتبار التصحيح بين إصدار المورد من المخطط السابق وإصدار المخطط الحالي،
  • يطبق هذا التصحيح.

سوف نسمي هذا التصحيح تصحيح دمج ثنائي الاتجاه، لأن هناك بيانين متضمنين في إنشائه:

  • بيان الموارد من الإصدار السابق،
  • بيان المورد من المورد الحالي.

عند إزالة العملية delete يتم استدعاء in kube apiserver للموارد التي تم الإعلان عنها في الإصدار السابق، ولكن لم يتم الإعلان عنها في الإصدار الحالي.

يواجه أسلوب تصحيح الدمج ثنائي الاتجاه مشكلة: فهو يؤدي إلى غير متزامن مع الحالة الحقيقية للمورد في المجموعة والبيان في Git.

توضيح المشكلة مع مثال

  • في Git، يخزن المخطط البيان الذي يحتوي على الحقل image النشر مهم ubuntu:18.04.
  • المستخدم عبر kubectl edit تم تغيير قيمة هذا الحقل إلى ubuntu:19.04.
  • عند إعادة نشر مخطط هيلم لا يولد التصحيح، لأن المجال image في الإصدار السابق من الإصدار وفي الرسم البياني الحالي هي نفسها.
  • بعد إعادة الانتشار image بقايا ubuntu:19.04، على الرغم من أن الرسم البياني يقول ubuntu:18.04.

لقد حصلنا على عدم التزامن وفقدنا التصريح.

ما هو المورد المتزامن؟

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

اتضح عامة جدا قاعدة الموارد المتزامنة: عند طرح أحد الموارد، يمكنك تغيير أو حذف فقط تلك الحقول المحددة صراحةً في البيان من Git (أو تم تحديدها في إصدار سابق وتم حذفها الآن).

تصحيح دمج ثنائي الاتجاه

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

  • تتم إضافة الحقول الجديدة المضافة إلى الإصدار المستهدف باستخدام التصحيح؛
  • تتم إعادة تعيين الحقول الموجودة مسبقًا في الإصدار المطبق الأخير وغير الموجودة في الإصدار المستهدف باستخدام التصحيح؛
  • يتم تحديث الحقول الموجودة في الإصدار الحالي من الكائن والتي تختلف عن الإصدار الهدف من البيان باستخدام التصحيح.

وعلى هذا المبدأ يتم إنشاء التصحيحات kubectl apply:

  • يتم تخزين آخر إصدار مطبق من البيان في التعليق التوضيحي للكائن نفسه،
  • الهدف - مأخوذ من ملف YAML المحدد،
  • الحالي من مجموعة قيد التشغيل.

الآن بعد أن انتهينا من النظرية، حان الوقت لإخبارك بما فعلناه في werf.

تطبيق التغييرات على werf

في السابق، كان werf، مثل Helm 2، يستخدم تصحيحات دمج ثنائية الاتجاه.

إصلاح التصحيح

من أجل التبديل إلى نوع جديد من التصحيحات - دمج ثلاثي الاتجاهات - الخطوة الأولى قدمنا ​​ما يسمى بقع الإصلاح.

عند النشر، يتم استخدام تصحيح دمج ثنائي الاتجاه، ولكن werf ينشئ بالإضافة إلى ذلك تصحيحًا من شأنه مزامنة الحالة الحقيقية للمورد مع ما هو مكتوب في Git (يتم إنشاء هذا التصحيح باستخدام نفس قاعدة الموارد المتزامنة الموضحة أعلاه). .

في حالة حدوث إلغاء التزامن، في نهاية النشر، يتلقى المستخدم تحذيرًا مع رسالة مقابلة وتصحيح يجب تطبيقه لجلب المورد إلى نموذج متزامن. يتم تسجيل هذا التصحيح أيضًا في تعليق توضيحي خاص werf.io/repair-patch. ومن المفترض أن أيدي المستخدم نفسه سوف يطبق هذا التصحيح: لن يطبقه werf على الإطلاق.

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

تصحيح الدمج ثلاثي الاتجاه للإصدارات الجديدة فقط

بدءًا من 1 ديسمبر 2019، ستبدأ الإصدارات التجريبية والألفا من werf افتراضيا استخدم تصحيحات الدمج ثلاثية الاتجاهات لتطبيق التغييرات فقط على إصدارات Helm الجديدة التي تم طرحها من خلال werf. ستستمر الإصدارات الحالية في استخدام أسلوب الدمج الثنائي + إصلاح التصحيحات.

يمكن تمكين وضع التشغيل هذا بشكل صريح عن طريق الإعداد WERF_THREE_WAY_MERGE_MODE=onlyNewReleases حاليا.

لاحظ: ظهرت الميزة في werf على عدة إصدارات: في قناة ألفا أصبحت جاهزة مع الإصدار الإصدار 1.0.5-alpha.19وفي القناة التجريبية - مع الإصدار 1.0.4-بيتا 20.

تصحيح دمج ثلاثي الاتجاهات لجميع الإصدارات

بدءًا من 15 ديسمبر 2019، ستبدأ الإصدارات التجريبية والألفا من werf في استخدام تصحيحات الدمج الثلاثية بشكل افتراضي لتطبيق التغييرات على جميع الإصدارات.

يمكن تمكين وضع التشغيل هذا بشكل صريح عن طريق الإعداد WERF_THREE_WAY_MERGE_MODE=enabled حاليا.

ما يجب القيام به مع القياس التلقائي للموارد؟

هناك نوعان من القياس التلقائي في Kubernetes: HPA (أفقي) وVPA (عمودي).

أفقي يحدد تلقائيا عدد النسخ المتماثلة، عمودي - عدد الموارد. يتم تحديد كل من عدد النسخ المتماثلة ومتطلبات الموارد في بيان المورد (راجع بيان المورد). spec.replicas أو spec.containers[].resources.limits.cpu, spec.containers[].resources.limits.memory и آخرون).

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

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

  • werf.io/set-replicas-only-on-creation=true
  • werf.io/set-resources-only-on-creation=true

في حالة وجود مثل هذا التعليق التوضيحي، فلن يقوم werf بإعادة تعيين القيم المقابلة في كل عملية نشر، ولكنه سيقوم فقط بتعيينها عند إنشاء المورد في البداية.

لمزيد من التفاصيل، راجع وثائق المشروع ل HPA и VPA.

منع استخدام تصحيح الدمج ثلاثي الاتجاهات

يمكن للمستخدم حاليًا حظر استخدام التصحيحات الجديدة في werf باستخدام متغير البيئة WERF_THREE_WAY_MERGE_MODE=disabled. ومع ذلك، بدءا اعتبارًا من 1 مارس 2020، لن يتم تطبيق هذا الحظر. وسيكون من الممكن فقط استخدام تصحيحات الدمج الثلاثية.

اعتماد الموارد في werf

إن إتقان طريقة تطبيق التغييرات باستخدام تصحيحات الدمج الثلاثية سمح لنا بالتنفيذ الفوري لميزة مثل اعتماد الموارد الموجودة في المجموعة في إصدار Helm.

تواجه Helm 2 مشكلة: لا يمكنك إضافة مورد إلى بيانات المخطط الموجود بالفعل في المجموعة دون إعادة إنشاء هذا المورد من البداية (انظر. #6031, #3275). لقد علمنا werf قبول الموارد الموجودة للإصدار. للقيام بذلك، تحتاج إلى تثبيت تعليق توضيحي على الإصدار الحالي من المورد من المجموعة قيد التشغيل (على سبيل المثال، باستخدام kubectl edit):

"werf.io/allow-adoption-by-release": RELEASE_NAME

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

لاحظ: إعدادات WERF_THREE_WAY_MERGE_MODE لا يؤثر على اعتماد الموارد - في حالة الاعتماد، يتم دائمًا استخدام تصحيح الدمج ثلاثي الاتجاهات.

التفاصيل - في توثيق.

الاستنتاجات والخطط المستقبلية

آمل أنه بعد هذه المقالة أصبح من الواضح ما هي تصحيحات الدمج الثلاثي ولماذا أتت إليها. من وجهة نظر عملية لتطوير مشروع Werf، كان تنفيذها خطوة أخرى نحو تحسين النشر الشبيه بـ "Helm". يمكنك الآن نسيان مشاكل مزامنة التكوين التي غالبًا ما تنشأ عند استخدام Helm 3. وفي الوقت نفسه، تمت إضافة ميزة جديدة مفيدة لاعتماد موارد Kubernetes التي تم تنزيلها بالفعل إلى إصدار Helm.

لا تزال هناك بعض المشكلات والتحديات المتعلقة بعمليات النشر المشابهة لـ Helm، مثل استخدام قوالب Go، والتي سنستمر في معالجتها.

يمكن أيضًا العثور على معلومات حول طرق تحديث الموارد واعتمادها على الموقع صفحة التوثيق هذه.

خوذة 3

تستحق ملاحظة خاصة مطلق سراحه منذ بضعة أيام فقط، ظهر إصدار رئيسي جديد من Helm - v3 - والذي يستخدم أيضًا تصحيحات الدمج الثلاثي ويتخلص من Tiller. يتطلب الإصدار الجديد من Helm الهجرة عمليات التثبيت الحالية لتحويلها إلى تنسيق تخزين الإصدار الجديد.

Werf من جانبه تخلص حاليًا من استخدام Tiller وتحول إلى 3-way merge وأضاف أكثر بكثير، مع الحفاظ على توافقه مع عمليات تثبيت Helm 2 الحالية (لا يلزم تنفيذ أي برامج نصية للترحيل). لذلك، حتى يتحول werf إلى Helm 3، لا يفقد مستخدمو werf المزايا الرئيسية لـ Helm 3 على Helm 2 (يمتلكها werf أيضًا).

ومع ذلك، فإن تبديل werf إلى قاعدة بيانات Helm 3 أمر لا مفر منه وسيحدث في المستقبل القريب. من المفترض أن يكون هذا هو werf 1.1 أو werf 1.2 (في الوقت الحالي، الإصدار الرئيسي من werf هو 1.0؛ لمزيد من المعلومات حول جهاز إصدار werf، راجع هنا). خلال هذا الوقت، سيكون لدى Helm 3 الوقت الكافي لتحقيق الاستقرار.

PS

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

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

إضافة تعليق