متأخرا أفضل من ألا تأتي أبدا. أو كيف ارتكبنا خطأً خطيرًا تقريبًا ، عدم وجود دعم من Dockerfiles العاديين لبناء صور التطبيق.
سنتحدث عن
werf ، وهي أداة مساعدة GitOps تتكامل مع أي نظام CI / CD وتوفر التحكم في دورة حياة التطبيق بالكامل ، مما يتيح لك:
- جمع ونشر الصور
- نشر التطبيقات في Kubernetes
- حذف الصور غير المستخدمة باستخدام سياسات خاصة.
تتمثل فلسفة المشروع في تجميع الأدوات منخفضة المستوى في نظام واحد موحد يمنح مهندسي DevOps التحكم في التطبيقات. حيثما كان ذلك ممكنا ، ينبغي أن تشارك المرافق القائمة (مثل هيلم و Docker). إذا لم يكن هناك حل لمشكلة ما ، فيمكننا إنشاء وصيانة كل ما هو ضروري لهذا الغرض.
الخلفية: جامع الصور الخاص بك
هذا ما حدث مع جامع الصور في werf: لم يكن لدينا Dockerfile المعتاد. إذا غطت بسرعة في تاريخ المشروع ، فإن هذه المشكلة تجلى في الإصدارات الأولى من werf (التي لا تزال
تعرف باسم dapp ).
إنشاء أداة لبناء التطبيقات في صور Docker ، أدركنا بسرعة أن Dockerfile لم يكن مناسبًا لبعض المهام المحددة للغاية:
- الحاجة إلى إنشاء تطبيقات ويب صغيرة نموذجية وفقًا للمخطط القياسي التالي:
- تثبيت تبعيات التطبيق على مستوى النظام
- تثبيت حزمة من مكتبات تبعية التطبيق ،
- جمع الأصول
- والأهم من ذلك ، قم بتحديث الكود الموجود في الصورة بسرعة وكفاءة.
- عند إجراء تغييرات على ملفات المشروع ، يجب على المنشئ إنشاء طبقة جديدة بسرعة عن طريق تطبيق تصحيح على الملفات المعدلة.
- إذا تغيرت بعض الملفات ، فمن الضروري إعادة بناء المرحلة التابعة المناسبة.
اليوم في جامعنا هناك العديد من الاحتمالات ، ولكن كانت الرغبات والرغبات الأولية هي تلك.
بشكل عام ، دون تفكير مرتين ، قمنا بتسليح أنفسنا بلغة البرمجة المستخدمة
(انظر أدناه) وتخطينا الطريق - قم بتنفيذ
DSL الخاص بنا ! المقابلة للمهام ، كان الغرض منه هو وصف عملية التجميع حسب المراحل وتحديد تبعيات هذه المراحل على الملفات. ويكمله
جامعه الخاص ، الذي حول DSL إلى الهدف النهائي - صورة مجمعة. في البداية ، كان DSL في روبي ، وعندما
تحولنا إلى Golang ، بدأ وصف التكوين الخاص
بمجمعنا في ملف YAML.
التكوين القديم ل dapp على روبي
التكوين الحالي ل werf على YAMLتغيرت آلية جامع أيضا مع مرور الوقت. في البداية ، أنشأنا للتو Dockerfile مؤقت مؤقت من التكوين لدينا على الطاير ، ثم بدأنا في تشغيل تعليمات التجميع في حاويات مؤقتة وجعل الالتزام.
ملحوظة : في الوقت الحالي ، تم تطوير أداة التجميع الخاصة بنا ، والتي تعمل مع التكوين الخاص بها (في YAML) والمسمى بـ Stapel-collector ، لتصبح أداة قوية إلى حد ما. وصفه المفصل يستحق مقالات منفصلة ، ويمكن الاطلاع على التفاصيل الرئيسية في الوثائق .مشكلة الوعي
لكننا أدركنا ، وليس فورًا ، أننا
ارتكبنا خطأً واحدًا: لم نقم بإضافة القدرة
على جمع الصور من خلال Dockerfile القياسي ودمجها في نفس البنية التحتية للإدارة المتكاملة للتطبيقات (على سبيل المثال ، جمع الصور ونشرها وتنظيفها). كيف يمكنك إنشاء أداة نشر في Kubernetes وعدم تنفيذ دعم Dockerfile ، أي طريقة قياسية لوصف الصور لمعظم المشاريع؟
بدلاً من الإجابة على هذا السؤال ، نحن نقدم حلاً. ماذا لو كان لديك بالفعل Dockerfile (أو مجموعة من Dockerfiles) وتريد استخدام werf؟
ملحوظة : بالمناسبة ، لماذا تريد حتى استخدام werf؟ الميزات الرئيسية هي كما يلي:- دورة إدارة التطبيق الكامل بما في ذلك تنظيف الصورة ؛
- القدرة على التحكم في تجميع العديد من الصور من تكوين واحد ؛
- تحسين هيلم متوافق عملية نشر الرسم البياني.
يمكن العثور على قائمة أكثر اكتمالا منها على صفحة المشروع .لذلك ، إذا اقترحنا سابقًا إعادة كتابة Dockerfile إلى التكوين الخاص بنا ، الآن سنكون سعداء أن نقول: "دع werf يبني Dockerfiles الخاص بك!"
كيف تستخدم؟
ظهر التنفيذ الكامل لهذه الميزة في الإصدار
werf v1.0.3-beta.1 . المبدأ العام بسيط: يحدد المستخدم المسار إلى Dockerfile الموجود في werf config ، ثم يقوم بتشغيل
werf build
... وهذا كل شيء - werf سيجمع الصورة. النظر في مثال مجردة.
Dockerfile
التالية في جذر المشروع:
FROM ubuntu:18.04 RUN echo Building ...
وأعلن
werf.yaml
الذي يستخدم
Dockerfile
هذا:
configVersion: 1 project: dockerfile-example --- image: ~ dockerfile: ./Dockerfile
هذا كل شئ! يبقى
لتشغيل werf build
:

بالإضافة إلى ذلك ، يمكنك إعلان
werf.yaml
التالي لبناء عدة صور من Dockerfiles مختلفة في وقت واحد:
configVersion: 1 project: dockerfile-example --- image: backend dockerfile: ./dockerfiles/Dockerfile-backend --- image: frontend dockerfile: ./dockerfiles/Dockerfile-frontend
أخيرًا ، يدعم أيضًا نقل معلمات
--build-arg
الإضافية - مثل -
--build-arg
و
--add-host
- من خلال التكوين werf. يتوفر وصف كامل لتكوين صورة Dockerfile
في صفحة الوثائق .
كيف يعمل؟
أثناء عملية الإنشاء ، تعمل ذاكرة التخزين المؤقت للطبقة المحلية القياسية في Docker. ومع ذلك ، الأهم من ذلك ، أن werf
يدمج أيضًا
تكوين Dockerfile في بنيته الأساسية . ماذا يعني هذا؟
- تتكون كل صورة تم جمعها من Dockerfile من مرحلة واحدة تسمى
dockerfile
(المزيد حول المراحل في werf ، يمكنك قراءتها هنا ). - للمرحلة ، يقوم
dockerfile
werf بحساب التوقيع ، والذي يعتمد على محتويات تكوين Dockerfile. عند تغيير تكوين Dockerfile ، يتغير توقيع مرحلة dockerfile ويبدأ werf في إعادة بناء هذه المرحلة بتكوين Dockerfile الجديد. إذا لم يتغير التوقيع ، فسيأخذ werf الصورة من ذاكرة التخزين المؤقت (تم توضيح مزيد من التفاصيل حول استخدام التواقيع في werf في هذا التقرير ) . - علاوة على ذلك ، يمكن نشر الصور التي تم جمعها
werf publish
الأمر werf publish
(أو werf build-and-publish
) واستخدامها للنشر في Kubernetes. سيتم تنظيف الصور المنشورة في Docker Registry باستخدام منظفات werf القياسية ، أي سيقوم تلقائيًا بتنظيف الصور القديمة (أقدم من N يومًا) والصور المرتبطة بفروع Git غير الموجودة وسياسات أخرى.
يمكنك معرفة المزيد حول النقاط الموضحة هنا من الوثائق:
ملاحظات والاحتياطات
1. عنوان URL الخارجي في ADD غير مدعوم
استخدام عنوان URL خارجي في توجيه
ADD
غير معتمد حاليًا. لن يبدأ Werf في إعادة الإنشاء عندما يتغير المورد إلى عنوان URL المحدد. قريبا من المخطط لإضافة هذه الميزة.
2. لا يمكنك إضافة. جيت إلى صورة
بشكل عام ، تعد إضافة دليل
.git
إلى صورة من الممارسات السيئة
الشرسة ، وإليكم السبب:
- إذا بقيت
.git
في الصورة النهائية ، فهذا ينتهك مبادئ التطبيق 12 عاملًا : نظرًا لأن الصورة النهائية يجب أن تكون مرتبطة بالتزام واحد ، فلا ينبغي أن يكون من الممكن إجراء عملية بحث git checkout
التزام تعسفي. .git
يزيد من حجم الصورة (قد يكون المستودع كبيرًا نظرًا لحقيقة أنه تمت إضافة ملفات كبيرة إليه مرة واحدة ثم حذفه). حجم شجرة العمل ، المرتبط فقط بالتزام محدد ، لن يعتمد على تاريخ العمليات في جيت. في الوقت نفسه ، لن تعمل إضافة .git
ثم إزالته من الصورة النهائية: ستظل الصورة تحتوي على طبقة إضافية - هكذا تعمل Docker.- يمكن أن يبدأ عامل إعادة الإعمار في إعادة البناء غير الضرورية ، حتى لو تم بناء نفس الالتزام ، ولكن من الأشجار المختلفة للعمل. على سبيل المثال ، ينشئ GitLab أدلة منفصلة مستنسخة في
/home/gitlab-runner/builds/HASH/[0-N]/yourproject
عند تمكين التجميع المتوازي. ستعود عملية إعادة الإنشاء الإضافية إلى حقيقة أن دليل .git
يختلف في الإصدارات المستنسخة المختلفة لنفس المستودع ، حتى إذا تم جمع نفس الالتزام.
النقطة الأخيرة لها نتيجة عند استخدام werf. يتطلب Werf وجود ذاكرة التخزين المؤقت التي تم تجميعها عند تشغيل أوامر معينة (على سبيل المثال ،
werf deploy
). أثناء تشغيل هذه الأوامر ، يحسب werf تواقيع المرحلة للصور المحددة في
werf.yaml
، ويجب أن تكون في ذاكرة التخزين المؤقتة للتجميع - وإلا فلن يتمكن الفريق من مواصلة العمل. إذا كان توقيع المرحلة يعتمد على محتويات .git ، فسنحصل على ذاكرة التخزين المؤقت غير المستقرة للتغييرات في الملفات غير ذات الصلة ، ولن يتمكن werf من مسامحة مثل هذا الإشراف (انظر
الوثائق لمزيد من التفاصيل).
بشكل عام ، تؤدي
إضافة بعض الملفات الضرورية فقط من خلال تعليمات
ADD
في أي حال إلى زيادة كفاءة وموثوقية
Dockerfile
المكتوبة ، كما تعمل على تحسين ثبات ذاكرة التخزين المؤقت التي تم تجميعها بواسطة
Dockerfile
هذا ضد التغييرات غير ذات الصلة في Git.
يؤدي
كانت طريقتنا الأولى في كتابة برنامج التحويل البرمجي الخاص بنا لتلبية احتياجات معينة صعبة وصادقة ومباشرة: بدلاً من استخدام عكازات أعلى Dockerfile القياسي ، كتبنا الحل الخاص بنا باستخدام بناء جملة مخصص. وقد أعطى هذا مزاياها: يتكيف Stapel-builder مع مهمته تمامًا.
ومع ذلك ، في عملية كتابة جامعنا ، تجاهلنا دعم Dockerfiles الحالي. الآن تم إصلاح هذا الخلل ، ونخطط في المستقبل لتطوير دعم Dockerfile جنبًا إلى جنب مع جامع Stapel المخصص للتجميع الموزع وللتجميع باستخدام Kubernetes (أي التجميع على المتسابقين داخل Kubernetes ، كما هو الحال في kaniko).
حتى إذا كان لديك فجأة بضعة Dockerfiles الكذب حولها ...
حاول werf !
PS قائمة الوثائق ذات الصلة
اقرأ أيضًا على مدونتنا: "
werf هو أداة CI / CD الخاصة بنا في Kubernetes (تقرير المراجعة والفيديو) ."