إنشاء ونشر ديناميكي لصور Docker مع werf في مثال موقع التوثيق الذي تم إصداره

لقد تحدثنا بالفعل عن أداة GitOps الخاصة بنا أكثر من مرة werf، وهذه المرة نود أن نشارك تجربة إنشاء موقع مع توثيق المشروع نفسه - werf.io (نسخته الروسية هي en.werf.io). هذا موقع ثابت عادي ، لكن بنائه مثير للاهتمام لأنه مبني باستخدام عدد ديناميكي من القطع الأثرية.

إنشاء ونشر ديناميكي لصور Docker مع werf في مثال موقع التوثيق الذي تم إصداره

انتقل إلى الفروق الدقيقة في بنية الموقع: إنشاء قائمة مشتركة لجميع الإصدارات ، وصفحات تحتوي على معلومات حول الإصدارات ، وما إلى ذلك. - لن نفعل. بدلاً من ذلك ، دعنا نركز على قضايا وخصائص التجميع الديناميكي وقليلاً على عمليات CI / CD ذات الصلة.

مقدمة: كيف يعمل الموقع

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

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

من أجل إخفاء كل هذا "المطبخ الداخلي" عن المستخدم ، قدمنا ​​له شيئًا "يعمل فقط" ، فعلنا أداة تثبيت وتحديث منفصلة - هو متعدد الوظائف. تحتاج فقط إلى تحديد رقم الإصدار وقناة الاستقرار التي أنت جاهز لاستخدامها ، وسيقوم multiwerf بالتحقق مما إذا كان هناك إصدار جديد على القناة وتنزيله إذا لزم الأمر.

تتوفر أحدث إصدارات werf في كل قناة في قائمة اختيار الإصدار على الموقع. بشكل افتراضي ، في werf.io/documentation يتم فتح إصدار القناة الأكثر استقرارًا لأحدث إصدار - كما تتم فهرستها بواسطة محركات البحث. يتوفر توثيق القناة في عناوين منفصلة (على سبيل المثال ، werf.io/v1.0-beta/documentation لإصدار بيتا 1.0).

إجمالاً ، يحتوي الموقع على الإصدارات التالية المتاحة:

  1. الجذر (يفتح افتراضيًا) ،
  2. لكل قناة تحديث نشطة لكل إصدار (على سبيل المثال ، werf.io/v1.0-beta).

لإنشاء نسخة محددة من الموقع ، في الحالة العامة ، يكفي تجميعها باستخدام جيكلعن طريق التشغيل في الدليل /docs werf مع الأمر المقابل (jekyll build) ، بعد التبديل إلى علامة Git للإصدار المطلوب.

يبقى فقط لإضافة ما يلي:

  • يتم استخدام الأداة المساعدة نفسها (werf) للتجميع ؛
  • يتم إنشاء عمليات CI / CD على رأس GitLab CI ؛
  • وكل هذا ، بالطبع ، يعمل في Kubernetes.

المهام

نقوم الآن بصياغة المهام التي تأخذ في الاعتبار جميع التفاصيل الموضحة:

  1. بعد تغيير إصدار werf على أي قناة تحديث يجب تحديث الوثائق الموجودة على الموقع تلقائيًا.
  2. من أجل التطوير ، يجب أن تكون قادرًا في بعض الأحيان عرض معاينات الموقع.

يجب إجراء إعادة تجميع الموقع بعد تغيير الإصدار على أي قناة من علامات Git المقابلة ، ولكن في عملية بناء الصورة ، سنحصل على الميزات التالية:

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

تبين أن يعتمد التجميع على تغيير البيانات الخارجية.

تطبيق

اختيار النهج

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

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

لنكون أكثر دقة ، نقوم ببناء صورتين: واحدة لدائرة الإنتاج ، والثانية هي صورة إضافية لدائرة التطوير. تُستخدم الصورة الإضافية (تم إطلاقها) فقط في حلقة dev مع الصورة الرئيسية وتحتوي على إصدار الموقع من التزام المراجعة ، ويتم إجراء التوجيه بينهما باستخدام موارد Ingress.

werf مقابل git clone والتحف

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

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

نظرًا لأن Jekyll هي أداة لتجميع الإحصائيات وليست ضرورية في الصورة النهائية ، فسيكون من المنطقي التحويل إلى قطعة أثرية، وفي الصورة النهائية استيراد نتيجة التجميع فقط.

نكتب werf.yaml

لذلك ، قررنا أننا سنجمع كل نسخة في قطعة أثرية منفصلة. ومع ذلك، فإننا لا نعرف عدد هذه القطع الأثرية أثناء التجميع، لذلك لا يمكننا كتابة تكوين بناء ثابت (بالمعنى الدقيق للكلمة ، يمكننا ذلك ، لكنه لن يكون فعالًا للغاية).

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

يتم تمرير البيانات الخارجية من خلال متغيرات البيئة. هنا تكوينهم:

  • RELEASES - سلسلة مع قائمة الإصدارات والإصدار الحالي المقابل من werf ، كقائمة مفصولة بمسافة من القيم في التنسيق <НОМЕР_РЕЛИЗА>%<НОМЕР_ВЕРСИИ>. مثال: 1.0%v1.0.4-beta.20
  • CHANNELS - سطر مع قائمة القنوات والإصدار الحالي المقابل من werf ، في شكل قائمة مفصولة بمسافة من القيم في التنسيق <КАНАЛ>%<НОМЕР_ВЕРСИИ>. مثال: 1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22
  • ROOT_VERSION - نسخة من إصدار werf ليتم عرضها افتراضيًا على الموقع (ليس من الضروري دائمًا عرض الوثائق بأعلى رقم إصدار). مثال: v1.0.4-beta.20
  • REVIEW_SHA - تجزئة الالتزام بالمراجعة ، والتي تحتاج من خلالها إلى إنشاء إصدار لحلقة الاختبار.

سيتم ملء هذه المتغيرات في خط أنابيب GitLab CI ، وكيف تتم كتابتها بالضبط أدناه.

بادئ ذي بدء ، للراحة ، نحدد في werf.yaml انتقل إلى متغيرات القالب عن طريق تعيين قيم لها من متغيرات البيئة:

{{ $_ := set . "WerfVersions" (cat (env "CHANNELS") (env "RELEASES") | splitList " ") }}
{{ $Root := . }}
{{ $_ := set . "WerfRootVersion" (env "ROOT_VERSION") }}
{{ $_ := set . "WerfReviewCommit" (env "REVIEW_SHA") }}

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

  • Version - نسخة تم إنشاؤها (اسم العلامة) ؛
  • Channel - اسم قناة التحديث التي يتم إنشاء الأداة من أجلها ؛
  • Commit - الالتزام بالتجزئة ، إذا تم إنشاء الأداة لإجراء مراجعة ؛
  • سياق الكلام.

وصف قالب الأداة

{{- define "doc_artifact" -}}
{{- $Root := index . "Root" -}}
artifact: doc-{{ .Channel }}
from: jekyll/builder:3
mount:
- from: build_dir
  to: /usr/local/bundle
ansible:
  install:
  - shell: |
      export PATH=/usr/jekyll/bin/:$PATH
  - name: "Install Dependencies"
    shell: bundle install
    args:
      executable: /bin/bash
      chdir: /app/docs
  beforeSetup:
{{- if .Commit }}
  - shell: echo "Review SHA - {{ .Commit }}."
{{- end }}
{{- if eq .Channel "root" }}
  - name: "releases.yml HASH: {{ $Root.Files.Get "releases.yml" | sha256sum }}"
    copy:
      content: |
{{ $Root.Files.Get "releases.yml" | indent 8 }}
      dest:  /app/docs/_data/releases.yml
{{- else }}
  - file:
      path: /app/docs/_data/releases.yml
      state: touch
{{- end }}
  - file:
      path: "{{`{{ item }}`}}"
      state: directory
      mode: 0777
    with_items:
    - /app/main_site/
    - /app/ru_site/
  - file:
      dest: /app/docs/pages_ru/cli
      state: link
      src: /app/docs/pages/cli
  - shell: |
      echo -e "werfVersion: {{ .Version }}nwerfChannel: {{ .Channel }}" > /tmp/_config_additional.yml
      export PATH=/usr/jekyll/bin/:$PATH
{{- if and (ne .Version "review") (ne .Channel "root") }}
{{- $_ := set . "BaseURL" ( printf "v%s" .Channel ) }}
{{- else if ne .Channel "root" }}
{{- $_ := set . "BaseURL" .Channel }}
{{- end }}
      jekyll build -s /app/docs  -d /app/_main_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/tmp/_config_additional.yml
      jekyll build -s /app/docs  -d /app/_ru_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/app/docs/_config_ru.yml,/tmp/_config_additional.yml
    args:
      executable: /bin/bash
      chdir: /app/docs
git:
- url: https://github.com/flant/werf.git
  to: /app/
  owner: jekyll
  group: jekyll
{{- if .Commit }}
  commit: {{ .Commit }}
{{- else }}
  tag: {{ .Version }}
{{- end }}
  stageDependencies:
    install: ['docs/Gemfile','docs/Gemfile.lock']
    beforeSetup: '**/*'
  includePaths: 'docs'
  excludePaths: '**/*.sh'
{{- end }}

يجب أن يكون اسم الأداة فريدًا. يمكننا تحقيق ذلك ، على سبيل المثال ، بإضافة اسم القناة (قيمة المتغير .Channel) كلاحقة اسم الأداة: artifact: doc-{{ .Channel }}. لكن عليك أن تفهم أنه عند الاستيراد من القطع الأثرية ، ستحتاج إلى الإشارة إلى نفس الأسماء.

عند وصف قطعة أثرية ، يتم استخدام ميزة werf ، مثل تصاعد. التركيب مع دليل الخدمة build_dir يسمح لك بحفظ ذاكرة التخزين المؤقت Jekyll بين عمليات تشغيل خطوط الأنابيب ، والتي يسرع بشكل كبير إعادة التجميع.

أيضًا ، ربما لاحظت استخدام الملف releases.yml هو ملف YAML يحتوي على بيانات الإصدار ، والمطلوب بامتداد github.com (تم الحصول على الأداة عن طريق تنفيذ خط الأنابيب). إنها ضرورية عند تجميع الموقع ، ولكن في سياق المقال ، فهي مثيرة للاهتمام بالنسبة لنا لأنها تعتمد على حالتها إعادة بناء قطعة أثرية واحدة فقط - قطعة أثرية لموقع نسخة الجذر (ليست ضرورية في القطع الأثرية الأخرى).

يتم تنفيذ ذلك باستخدام عامل التشغيل الشرطي if اذهب الأنماط والتصاميم {{ $Root.Files.Get "releases.yml" | sha256sum }} في مرحلة مراحل. وهي تعمل على النحو التالي: عند إنشاء أداة لإصدار الجذر (متغير .Channel مساوي ل root) ملف تجزئة releases.yml يؤثر على توقيع المرحلة بأكملها ، نظرًا لأنه جزء من اسم وظيفة Ansible (المعلمة name). وهكذا ، عند التغيير محتوى ملف releases.yml سيتم إعادة بناء الأداة المقابلة.

انتبه أيضًا إلى العمل مع مستودع خارجي. في صورة قطعة أثرية من مستودع werf، يتم إضافة الدليل فقط /docs، واعتمادًا على المعلمات التي تم تمريرها ، تتم إضافة بيانات العلامة الضرورية فورًا أو الالتزام بالمراجعة.

لاستخدام القالب المصطنع لإنشاء وصف أثرى للإصدارات المقدمة من القنوات والإصدارات ، ننظم حلقة فوق المتغير .WerfVersions в werf.yaml:

{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ dict "Version" $VersionsDict._1 "Channel" $VersionsDict._0 "Root" $Root | include "doc_artifact" }}
---
{{ end -}}

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

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

{{ dict "Version" .WerfRootVersion "Channel" "root" "Root" $Root  | include "doc_artifact" }}
---
{{- if .WerfReviewCommit }}
{{ dict "Version" "review" "Channel" "review" "Commit" .WerfReviewCommit "Root" $Root  | include "doc_artifact" }}
{{- end }}

لاحظ أن الأداة الخاصة بالتزام المراجعة سيتم بناؤها فقط إذا تم تعيين المتغير .WerfReviewCommit.

القطع الأثرية جاهزة - حان الوقت لبدء الاستيراد!

الصورة النهائية المخصصة للتشغيل على Kubernetes هي NGINX العادي الذي يحتوي على ملف تكوين خادم مضاف إليه. nginx.conf وثابت من القطع الأثرية. بالإضافة إلى الأداة الخاصة بإصدار الجذر للموقع ، نحتاج إلى تكرار الحلقة فوق المتغير .WerfVersions لاستيراد عناصر إصدار القناة وإصدارها + اتبع قاعدة تسمية العناصر التي اعتمدناها سابقًا. نظرًا لأن كل قطعة أثرية تخزن إصدارات من الموقع بلغتين ، فإننا نقوم باستيرادها إلى الأماكن التي يوفرها التكوين.

وصف صورة werf-doc النهائية

image: werf-doc
from: nginx:stable-alpine
ansible:
  setup:
  - name: "Setup /etc/nginx/nginx.conf"
    copy:
      content: |
{{ .Files.Get ".werf/nginx.conf" | indent 8 }}
      dest: /etc/nginx/nginx.conf
  - file:
      path: "{{`{{ item }}`}}"
      state: directory
      mode: 0777
    with_items:
    - /app/main_site/assets
    - /app/ru_site/assets
import:
- artifact: doc-root
  add: /app/_main_site
  to: /app/main_site
  before: setup
- artifact: doc-root
  add: /app/_ru_site
  to: /app/ru_site
  before: setup
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ $Channel := $VersionsDict._0 -}}
{{ $Version := $VersionsDict._1 -}}
- artifact: doc-{{ $Channel }}
  add: /app/_main_site
  to: /app/main_site/v{{ $Channel }}
  before: setup
{{ end -}}
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ $Channel := $VersionsDict._0 -}}
{{ $Version := $VersionsDict._1 -}}
- artifact: doc-{{ $Channel }}
  add: /app/_ru_site
  to: /app/ru_site/v{{ $Channel }}
  before: setup
{{ end -}}

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

image: werf-dev
...
import:
- artifact: doc-root
  add: /app/_main_site
  to: /app/main_site
  before: setup
- artifact: doc-root
  add: /app/_ru_site
  to: /app/ru_site
  before: setup
{{- if .WerfReviewCommit  }}
- artifact: doc-review
  add: /app/_main_site
  to: /app/main_site/review
  before: setup
- artifact: doc-review
  add: /app/_ru_site
  to: /app/ru_site/review
  before: setup
{{- end }}

كما هو مذكور أعلاه ، سيتم إنشاء الأداة الخاصة بالتزام المراجعة فقط عند تعيين متغير البيئة للتشغيل REVIEW_SHA. سيكون من الممكن عدم إنشاء صورة werf-dev على الإطلاق إذا لم يكن هناك متغير بيئة REVIEW_SHA، ولكن من أجل التنظيف حسب السياسة عملت صور Docker في werf على صورة werf-dev ، وسنتركها ليتم بناؤها فقط باستخدام نسخة الجذر الأثرية (تم بناؤها بالفعل على أي حال) ، لتبسيط هيكل خط الأنابيب.

التجميع جاهز! دعنا ننتقل إلى CI / CD والفروق الدقيقة المهمة.

خط الأنابيب في GitLab CI وميزات التجميع الديناميكي

عند تشغيل الإنشاء ، نحتاج إلى ضبط متغيرات البيئة المستخدمة فيها werf.yaml. لا ينطبق هذا على المتغير REVIEW_SHA ، الذي سنقوم بتعيينه عند استدعاء خط الأنابيب من خطاف GitHub.

سننقل تشكيل البيانات الخارجية الضرورية إلى سكربت باش generate_artifacts، والتي ستنشئ اثنين من القطع الأثرية لخط أنابيب GitLab:

  • ملف releases.yml مع بيانات الإصدار
  • ملف common_envs.shيحتوي على متغيرات البيئة للتصدير.

محتويات الملف generate_artifacts ستجد في موقعنا المستودعات مع الأمثلة. الحصول على البيانات نفسها ليس موضوع المقال ، ولكن الملف common_envs.sh مهم بالنسبة لنا ، لأنه يعتمد عليه. مثال على محتواه:

export RELEASES='1.0%v1.0.6-4'
export CHANNELS='1.0-alpha%v1.0.7-1 1.0-beta%v1.0.7-1 1.0-ea%v1.0.6-4 1.0-stable%v1.0.6-4 1.0-rock-solid%v1.0.6-4'
export ROOT_VERSION='v1.0.6-4'

يمكنك استخدام إخراج مثل هذا البرنامج النصي ، على سبيل المثال ، باستخدام وظيفة Bash source.

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

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

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

سنقوم تلقي البيانات الخارجية وإصلاحها في المرحلة الأولى من خط الأنابيب في جيت لاب (البناء المسبق) وتمريرها بشكل أكبر في النموذج الأداة GitLab CI. سيسمح لك ذلك ببدء وإعادة تشغيل مهام خطوط الأنابيب (الإنشاء والنشر والتنظيف) بنفس التكوين في werf.yaml.

محتوى المرحلة البناء المسبق ملف .gitlab-ci.yml:

Prebuild:
  stage: prebuild
  script:
    - bash ./generate_artifacts 1> common_envs.sh
    - cat ./common_envs.sh
  artifacts:
    paths:
      - releases.yml
      - common_envs.sh
    expire_in: 2 week

بعد إصلاح البيانات الخارجية في قطعة أثرية ، يمكنك الإنشاء والنشر باستخدام المراحل القياسية لخط أنابيب GitLab CI: الإنشاء والنشر. نقوم بتشغيل خط الأنابيب نفسه بواسطة خطافات من مستودع werf GitHub (أي عند إجراء تغييرات في مستودع GitHub). يمكن أخذ البيانات الخاصة بهم في خصائص مشروع GitLab في القسم إعدادات CI / CD -> مشغلات خط الأنابيب، ثم أنشئ Webhook المقابل في GitHub (الإعدادات -> Webhooks).

ستبدو مرحلة البناء كما يلي:

Build:
  stage: build
  script:
    - type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
    - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
    - source common_envs.sh
    - werf build-and-publish --stages-storage :local
  except:
    refs:
      - schedules
  dependencies:
    - Prebuild

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

في مرحلة النشر ، سنصف مهمتين - بشكل منفصل للنشر في دوائر الإنتاج والتطوير ، باستخدام نموذج YAML:

.base_deploy: &base_deploy
  stage: deploy
  script:
    - type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
    - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
    - source common_envs.sh
    - werf deploy --stages-storage :local
  dependencies:
    - Prebuild
  except:
    refs:
      - schedules

Deploy to Production:
  <<: *base_deploy
  variables:
    WERF_KUBE_CONTEXT: prod
  environment:
    name: production
    url: werf.io
  only:
    refs:
      - master
  except:
    variables:
      - $REVIEW_SHA
    refs:
      - schedules

Deploy to Test:
  <<: *base_deploy
  variables:
    WERF_KUBE_CONTEXT: dev
  environment:
    name: test
    url: werf.test.flant.com
  except:
    refs:
      - schedules
  only:
    variables:
      - $REVIEW_SHA

تختلف المهام بشكل أساسي فقط من خلال تحديد سياق الكتلة الذي يجب أن تنشر فيه werf (WERF_KUBE_CONTEXT) ، وتعيين متغيرات البيئة للمسار (environment.name и environment.url) ، والتي تُستخدم بعد ذلك في قوالب مخططات هيلم. لن نعطي محتوى القوالب لأن لا يوجد شيء مثير للاهتمام للموضوع قيد النظر ، ولكن يمكنك العثور عليها في مستودعات للمقال.

اللمسة النهائية

نظرًا لإصدار إصدارات werf في كثير من الأحيان ، سيتم إنشاء صور جديدة بشكل متكرر ، وسينمو Docker Registry باستمرار. لذلك ، من الضروري تكوين التنظيف التلقائي للصور وفقًا للسياسات. من السهل جدا القيام بذلك.

سيتطلب التنفيذ:

  • أضف خطوة تنظيف إلى .gitlab-ci.yml;
  • إضافة تنفيذ مهمة التنظيف الدورية ؛
  • قم بتعيين متغير بيئة باستخدام رمز وصول للكتابة.

إضافة خطوة تنظيف .gitlab-ci.yml:

Cleanup:
  stage: cleanup
  script:
    - type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
    - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
    - source common_envs.sh
    - docker login -u nobody -p ${WERF_IMAGES_CLEANUP_PASSWORD} ${WERF_IMAGES_REPO}
    - werf cleanup --stages-storage :local
  only:
    refs:
      - schedules

لقد رأينا بالفعل كل هذا أعلى قليلاً - فقط للتنظيف ، تحتاج أولاً إلى تسجيل الدخول إلى Docker Registry باستخدام رمز له حقوق لحذف الصور في Docker Registry (رمز مهمة GitLab CI الذي تم إصداره تلقائيًا لا يحتوي على مثل هذا حقوق). يجب إدخال الرمز المميز في GitLab مسبقًا ويجب تحديد قيمته في متغير البيئة WERF_IMAGES_CLEANUP_PASSWORD مشروع (إعدادات CI / CD -> المتغيرات).

تتم إضافة مهمة تنظيف بالجدول الزمني المطلوب CI / CD ->
جداول
.

كل شيء: لن ينمو المشروع في Docker Registry باستمرار من الصور غير المستخدمة.

في نهاية الجزء العملي ، اسمحوا لي أن أذكرك أن القوائم الكاملة من المقالة متوفرة في بوابة:

نتيجة

  1. لقد حصلنا على بنية بناء منطقية: قطعة أثرية واحدة لكل إصدار.
  2. التجميع عالمي ولا يتطلب تغييرات يدوية عند إصدار إصدارات جديدة من werf: يتم تحديث الوثائق الموجودة على الموقع تلقائيًا.
  3. يتم تجميع صورتين لخطوط مختلفة.
  4. يعمل بسرعة لأن يتم استخدام التخزين المؤقت إلى الحد الأقصى - عند إصدار إصدار جديد من werf أو استدعاء خطاف GitHub لإجراء مراجعة - يتم إعادة بناء الأداة المقابلة مع الإصدار المعدل فقط.
  5. لا داعي للتفكير في حذف الصور غير المستخدمة: التنظيف بواسطة سياسات werf سيحافظ على سجل Docker بالترتيب.

النتائج

  • يسمح استخدام werf للتجميع بالعمل بسرعة بسبب التخزين المؤقت لكل من التجميع نفسه والتخزين المؤقت عند العمل مع المستودعات الخارجية.
  • يعمل العمل مع مستودعات Git الخارجية على التخلص من الحاجة إلى استنساخ المستودع في كل مرة بالكامل أو إعادة اختراع العجلة بمنطق تحسين صعب. يستخدم werf ذاكرة التخزين المؤقت ويقوم بالاستنساخ مرة واحدة فقط ثم يستخدم fetch وفقط عند الحاجة.
  • القدرة على استخدام قوالب Go في ملف تكوين البناء werf.yaml يسمح لك بوصف التجميع الذي تعتمد نتيجته على البيانات الخارجية.
  • يؤدي استخدام mount in werf إلى تسريع مجموعة القطع الأثرية بشكل كبير - بسبب ذاكرة التخزين المؤقت ، وهو أمر شائع في جميع خطوط الأنابيب.
  • يجعل werf من السهل تخصيص التنظيف ، وهذا ينطبق بشكل خاص على الإنشاءات الديناميكية.

PS

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

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

إضافة تعليق