تناقش المقالة مشكلة تنظيف الصور التي تتراكم في سجلات الحاويات (Docker Registry ونظائرها) في واقع خطوط أنابيب CI / CD الحديثة لتطبيقات السحابة الأصلية التي يتم تسليمها إلى Kubernetes. يتم تقديم المعايير الرئيسية لمدى ملاءمة الصور والصعوبات الناتجة في أتمتة التنظيف وتوفير المساحة وتلبية احتياجات الفرق. أخيرًا ، باستخدام مثال لمشروع محدد مفتوح المصدر ، سنخبرك كيف يمكن التغلب على هذه الصعوبات.
المقدمة
يمكن أن ينمو عدد الصور في سجل الحاوية بسرعة ، بحيث تشغل مساحة تخزين أكبر ، وبالتالي تزيد تكلفتها بشكل كبير. للتحكم في النمو المقبول للمساحة المشغولة في السجل أو الحد منه أو الحفاظ عليه ، من المقبول:
- استخدام عدد ثابت من العلامات للصور ؛
- تنظيف الصور بأي شكل من الأشكال.
القيد الأول صالح في بعض الأحيان للفرق الصغيرة. إذا كان لدى المطورين علامة دائمة كافية (
latest، main، test، borisإلخ) ، فلن يتضخم حجم السجل ويمكن أن يستغرق وقتًا طويلاً حتى لا تفكر في التنظيف. بعد كل شيء ، يتم تآكل جميع الصور غير ذات الصلة ، وببساطة لا يوجد عمل متبقي للتنظيف (كل شيء يتم بواسطة جامع القمامة العادي).
ومع ذلك ، فإن هذا النهج يحد بشدة من التنمية ونادرًا ما ينطبق على مشاريع CI / CD اليوم. أصبحت الأتمتة جزءًا لا يتجزأ من التطويريتيح لك اختبار وظائف جديدة ونشرها وتقديمها للمستخدمين بشكل أسرع. على سبيل المثال ، في جميع مشاريعنا ، يتم إنشاء خط أنابيب CI تلقائيًا عند كل التزام. يقوم ببناء صورة ، واختبارها ، وطرحها في دوائر Kubernetes المختلفة لتصحيح الأخطاء والفحوصات المتبقية ، وإذا سارت الأمور على ما يرام ، تصل التغييرات إلى المستخدم النهائي. وهذا ليس علم الصواريخ لفترة طويلة ، ولكن الحياة اليومية للكثيرين - على الأرجح بالنسبة لك ، لأنك تقرأ هذا المقال.
نظرًا لأنه تم إصلاح الأخطاء وتطوير وظائف جديدة بشكل متوازٍ ، ويمكن تنفيذ الإصدارات عدة مرات في اليوم ، فمن الواضح أن عملية التطوير مصحوبة بعدد كبير من الالتزامات ، مما يعني وجود عدد كبير من الصور في التسجيل... نتيجة لذلك ، تصبح مسألة تنظيم تنظيف فعال للسجل حادة ، أي إزالة الصور غير ذات الصلة.
ولكن كيف يمكنك تحديد ما إذا كانت الصورة ذات صلة؟
معايير ملاءمة الصورة
في الغالبية العظمى من الحالات ، ستكون المعايير الرئيسية على النحو التالي:
1. الأول (الأكثر وضوحًا والأكثر أهمية على الإطلاق) هو الصور المستخدمة حاليًا في Kubernetes . يمكن أن تؤدي إزالة هذه الصور إلى تكاليف تعطل خطيرة للإنتاج (على سبيل المثال ، قد تكون الصور مطلوبة أثناء النسخ المتماثل) أو تلغي جهود الفريق المنخرط في تصحيح الأخطاء على أي من الدوائر. (لهذا السبب ، قمنا حتى بإنشاء مُصدِّر بروميثيوس خاص يراقب عدم وجود مثل هذه الصور في أي مجموعة Kubernetes.)
2. الثانية (أقل وضوحًا ، ولكنها أيضًا مهمة جدًا وتتعلق مرة أخرى بالتشغيل) - الصور المطلوبة للتراجع في حالة الخطورة مشاكلفي الإصدار الحالي. على سبيل المثال ، في حالة Helm ، هذه هي الصور المستخدمة في الإصدارات المحفوظة من الإصدار. (بالمناسبة ، الحد الافتراضي في Helm هو 256 مراجعة ، ولكن لا يحتاج أي شخص فعليًا إلى حفظ مثل هذا العدد الكبير من الإصدارات؟ ..) بعد كل شيء ، لهذا ، على وجه الخصوص ، نقوم بتخزين الإصدارات حتى تتمكن من ذلك لاحقًا استخدام ، أي "التراجع" لهم إذا لزم الأمر.
3. ثالثاً - احتياجات المطورين : جميع الصور التي ترتبط بعملهم الحالي. على سبيل المثال ، إذا كنا نفكر في العلاقات العامة ، فمن المنطقي ترك الصورة المطابقة لآخر التزام ، ولنقل الالتزام السابق: بهذه الطريقة يمكن للمطور العودة بسرعة إلى أي مهمة والعمل مع أحدث التغييرات.
4. الرابع - الصور التيتتوافق مع إصدارات تطبيقنا ، أي هي المنتج النهائي: v1.0.0 ، 20.04.01 ، سييرا ، إلخ.
ملحوظة: تمت صياغة المعايير المحددة هنا بناءً على تجربة التفاعل مع العشرات من فرق التطوير من شركات مختلفة. ومع ذلك ، بالطبع ، اعتمادًا على تفاصيل عمليات التطوير والبنية التحتية المستخدمة (على سبيل المثال ، Kubernetes غير مستخدمة) ، قد تختلف هذه المعايير.
الأهلية والحلول الحالية
تقدم خدمات تسجيل الحاويات الشائعة ، كقاعدة عامة ، سياسات تنظيف الصور الخاصة بها: يمكنك من خلالها تحديد الشروط التي يتم بموجبها إزالة العلامة من السجل. ومع ذلك ، فإن هذه الشروط مقيدة بمعلمات مثل الأسماء ووقت الإنشاء وعدد العلامات *.
* يعتمد على تطبيقات تسجيل حاوية محددة. لقد أخذنا في الاعتبار إمكانيات الحلول التالية: Azure CR و Docker Hub و ECR و GCR و GitHub Packages و GitLab Container Registry و Harbour Registry و JFrog Artifactory و Quay.io - اعتبارًا من سبتمبر 2020.
هذه المجموعة من المعلمات كافية تمامًا لتلبية المعيار الرابع - أي لتحديد الصور التي تطابق الإصدارات. ومع ذلك ، بالنسبة لجميع المعايير الأخرى ، يتعين على المرء أن يختار نوعًا من الحلول الوسط (سياسة أكثر صرامة أو ، على العكس ، تجنيب) - اعتمادًا على التوقعات والقدرات المالية.
على سبيل المثال ، يمكن حل المعيار الثالث - المتعلق باحتياجات المطورين - من خلال تنظيم العمليات داخل فرق: تسمية محددة للصور ، والحفاظ على قوائم السماح الخاصة والاتفاقيات الداخلية. لكن في النهاية لا تزال بحاجة إلى أتمتة. وإذا كانت احتمالات الحلول الجاهزة غير كافية ، فعليك أن تفعل شيئًا خاصًا بك.
الموقف مشابه للمعيارين الأولين: لا يمكن تحقيقهما دون تلقي البيانات من النظام الخارجي - النظام الذي يتم فيه نشر التطبيقات (في حالتنا ، هو Kubernetes).
رسم توضيحي لسير العمل في Git
لنفترض أنك تعمل شيئًا كهذا في Git: تشير
الأيقونة برأس في الرسم التخطيطي إلى صور الحاوية التي تم نشرها حاليًا في Kubernetes لأي مستخدمين (مستخدمين ، أو مختبرين ، أو مديرين ، إلخ) أو يستخدمها المطورون لتصحيح الأخطاء وأهداف مماثلة.
ماذا يحدث إذا سمحت لك سياسات التنظيف بالاحتفاظ (وليس حذف) الصور فقط لأسماء العلامات المحددة ؟
من الواضح أن هذا السيناريو لن يرضي أحداً.
ما الذي سيتغير إذا سمحت لك السياسات بعدم حذف الصور لفترة زمنية معينة / عدد عمليات الالتزام الأخيرة ؟
أصبحت النتيجة أفضل بكثير ، لكنها لا تزال بعيدة عن المثالية. بعد كل شيء ، لا يزال لدينا مطورون يحتاجون إلى صور في السجل (أو حتى نشرها في K8s) لتصحيح الأخطاء ...
تلخيصًا للوضع الحالي في السوق: الوظائف المتوفرة في سجلات الحاوية لا توفر مرونة كافية عند التنظيف ، والسبب الرئيسي هو عدم وجود إمكانية تتفاعل مع العالم الخارجي . اتضح أن الفرق التي تحتاج إلى هذه المرونة مجبرة على تنفيذ إزالة الصور "خارج" نفسها باستخدام Docker Registry API (أو واجهة برمجة التطبيقات الأصلية للتطبيق المقابل).
ومع ذلك ، كنا نبحث عن حل شامل لأتمتة تنظيف الصور لفرق مختلفة باستخدام سجلات مختلفة ...
طريقنا إلى تنظيف الصورة العالمي
من أين تأتي هذه الحاجة؟ الحقيقة هي أننا لسنا مجموعة منفصلة من المطورين ، ولكننا فريق يخدم العديد منهم في وقت واحد ، مما يساعد على حل مشكلات CI / CD بشكل شامل. والأداة التقنية الرئيسية لذلك هي أداة werf مفتوحة المصدر . تكمن خصوصيته في أنه لا يؤدي وظيفة واحدة ، ولكنه يرافق عمليات التسليم المستمرة في جميع المراحل: من التجميع إلى النشر.
يعد نشر الصور إلى السجل * (فور إنشائها) وظيفة واضحة لهذه الأداة المساعدة. ونظرًا لأن الصور موضوعة هناك للتخزين ، إذن - إذا كانت مساحة التخزين لديك غير محدودة - فأنت بحاجة إلى أن تكون مسؤولاً عن تنظيفها اللاحق. كيف حققنا النجاح في هذا ، وتلبية جميع المعايير المحددة ، ستتم مناقشتها بشكل أكبر.
* على الرغم من أن السجلات نفسها قد تكون مختلفة (Docker Registry ، GitLab Container Registry ، Harbour ، إلخ) ، يواجه مستخدموها نفس المشكلات. الحل الشامل في حالتنا لا يعتمد على تنفيذ التسجيل ، منذ ذلك الحين تعمل خارج السجلات نفسها وتقدم نفس السلوك للجميع.
على الرغم من حقيقة أننا نستخدم werf كمثال للتنفيذ ، نأمل أن تكون الأساليب المستخدمة مفيدة للفرق الأخرى التي تواجه صعوبات مماثلة.
لذلك ، تناولنا الخارجتنفيذ آلية لتنظيف الصور - بدلاً من الإمكانات المضمنة بالفعل في سجلات الحاويات. كانت الخطوة الأولى هي استخدام Docker Registry API لإنشاء جميع السياسات البدائية نفسها من خلال عدد العلامات ووقت إنشائها (المذكور أعلاه). تمت إضافة قائمة السماح إليها بناءً على الصور المستخدمة في البنية التحتية المنتشرة ، أي كوبرنيتيس. بالنسبة للأخير ، كان يكفي استعراض جميع الموارد المنشورة من خلال Kubernetes API والحصول على قائمة بالقيم
image.
أغلق هذا الحل البسيط المشكلة الأكثر أهمية (المعيار رقم 1) ، لكنه كان مجرد بداية رحلتنا لتحسين آلية التنظيف. كانت الخطوة التالية - والأكثر إثارة للاهتمام - هي قرار ربط الصور المنشورة بتاريخ Git .
مخططات وضع العلامات
بادئ ذي بدء ، اخترنا أسلوبًا يجب أن تخزن فيه الصورة النهائية المعلومات الضرورية للتنظيف ، وقمنا ببناء العملية على مخططات وضع العلامات. عندما نشر صورة، المستخدم اختيار خيار وضع علامات معينة (
git-branch، git-commitأو git-tag) واستخدام القيمة المقابلة. في أنظمة CI ، تم تعيين هذه القيم تلقائيًا بناءً على متغيرات البيئة. في الأساس ، ارتبطت الصورة النهائية مع Git بدائية معينة ، وتخزين البيانات اللازمة للتنظيف في الملصقات.
نتج عن هذا النهج مجموعة من السياسات التي سمحت باستخدام Git كمصدر وحيد للحقيقة:
- عند حذف فرع / علامة في Git ، تم أيضًا حذف الصور المرتبطة في السجل تلقائيًا.
- يمكن التحكم في عدد الصور المرتبطة بعلامات Git والالتزامات من خلال عدد العلامات المستخدمة في المخطط المختار ووقت إنشاء الالتزام المرتبط.
بشكل عام ، حقق التنفيذ الناتج احتياجاتنا ، ولكن سرعان ما انتظرنا تحدٍ جديد. الحقيقة هي أنه أثناء استخدام أنظمة وضع العلامات لأولياء Git ، واجهنا عددًا من أوجه القصور. (نظرًا لأن وصفهم خارج نطاق هذه المقالة ، يمكن للجميع قراءة التفاصيل هنا .) لذلك ، بعد أن قررنا الانتقال إلى نهج أكثر فاعلية لوضع العلامات (العلامات القائمة على المحتوى) ، كان علينا مراجعة تنفيذ تنظيف الصورة.
خوارزمية جديدة
لماذا ا؟ عند تمييزها على أنها قائمة على المحتوى ، يمكن لكل علامة أن تستوعب التزامات متعددة في Git. عند تنظيف الصور ، لم يعد بإمكانك الاعتماد فقط على الالتزام الذي تمت إضافة العلامة الجديدة فيه إلى السجل.
بالنسبة لخوارزمية التنظيف الجديدة ، فقد تقرر الابتعاد عن مخططات العلامات وبناء العملية على الصور الوصفية ، كل منها يخزن مجموعة من:
- الالتزام الذي تم إجراء النشر عليه (لا يهم إذا تمت إضافة الصورة أو تغييرها أو بقيت كما هي في سجل الحاوية) ؛
- والمعرف الداخلي الخاص بنا المطابق للصورة المبنية.
بمعنى آخر ، تم ربط العلامات المنشورة بعمليات الإيداع في Git .
التكوين النهائي والخوارزمية العامة
عند تكوين التنظيف ، يمكن للمستخدمين الآن الوصول إلى السياسات التي يتم من خلالها اختيار الصور الفعلية. يتم تعريف كل سياسة من هذا القبيل:
- مراجع متعددة ، أي علامات Git أو فروع Git المستخدمة أثناء الزحف ؛
- وحدود الصور المطلوبة لكل مرجع من المجموعة.
للتوضيح ، هذه هي الطريقة التي بدأ بها تكوين السياسة الافتراضية في الظهور:
cleanup:
keepPolicies:
- references:
tag: /.*/
limit:
last: 10
- references:
branch: /.*/
limit:
last: 10
in: 168h
operator: And
imagesPerReference:
last: 2
in: 168h
operator: And
- references:
branch: /^(main|staging|production)$/
imagesPerReference:
last: 10
يحتوي هذا التكوين على ثلاث سياسات تتوافق مع القواعد التالية:
- احفظ صورة لآخر 10 علامات Git (حسب تاريخ إنشاء العلامة).
- حفظ ما لا يزيد عن صورتين تم نشرهما في الأسبوع الماضي بما لا يزيد عن 10 فروع مع نشاط خلال الأسبوع الماضي.
- حفظ 10 صور لكل فرع
main،stagingوproduction.
يتم تقليل الخوارزمية النهائية إلى الخطوات التالية:
- الحصول على بيانات من سجل الحاوية.
- باستثناء الصور المستخدمة في Kubernetes بسبب لقد حددناها مسبقًا بالفعل من خلال استطلاع رأي K8s API.
- مسح محفوظات Git واستبعاد الصور لسياسات محددة.
- إزالة الصور المتبقية.
بالعودة إلى الرسم التوضيحي الخاص بنا ، إليك ما يحدث مع werf:
ومع ذلك ، حتى إذا لم تستخدم werf ، يمكن تطبيق نهج مشابه للتنظيف المتقدم للصور - في تطبيق أو آخر (وفقًا للنهج المفضل لوضع علامات على الصور) - في أنظمة أخرى أيضًا. / خدمات. للقيام بذلك ، يكفي أن تتذكر المشاكل التي تنشأ وتجد تلك الفرص في مجموعتك التي تسمح لك ببناء حلها بأكثر الطرق سلاسة. نأمل أن يساعد المسار الذي سلكناه في النظر إلى حالتك الخاصة بتفاصيل وأفكار جديدة.
خاتمة
- عاجلاً أم آجلاً ، تواجه معظم الفرق مشكلة تجاوز التسجيل.
- عند البحث عن حلول ، أولاً وقبل كل شيء ، من الضروري تحديد معايير ملاءمة الصورة.
- تتيح الأدوات التي تقدمها خدمات تسجيل الحاويات الشهيرة عملية تنظيف بسيطة للغاية لا تأخذ في الاعتبار "العالم الخارجي": الصور المستخدمة في Kubernetes وخصائص مهام سير عمل الفريق.
- يجب أن تتمتع الخوارزمية المرنة والفعالة بفهم لعمليات CI / CD ، ولا تعمل فقط مع بيانات صورة Docker.
ملاحظة
اقرأ أيضًا على مدونتنا: