כבר דיברנו על כלי ה-GitOps שלנו יותר מפעם אחת. , והפעם נרצה לשתף את החוויה של בניית אתר אינטרנט עם תיעוד הפרויקט עצמו - (הגרסה הרוסית שלה היא זהו אתר סטטי רגיל, אך הרכבתו מעניינת בכך שהוא נבנה באמצעות מספר דינמי של ארטיפקטים.

לא ניכנס לניואנסים של מבנה האתר: יצירת תפריט משותף לכל הגרסאות, דף עם מידע על מהדורות וכו'. במקום זאת, נתמקד בנושאים ובתכונות של הרכבה דינמית וקצת בתהליכי CI/CD הנלווים.
מבוא: איך האתר עובד
נתחיל עם העובדה שתיעוד ה-werf מאוחסן יחד עם הקוד שלו. זה מטיל דרישות מסוימות על הפיתוח, שבדרך כלל חורגות מתחום מאמר זה, אבל לפחות נוכל לומר ש:
- אין לשחרר פונקציות werf חדשות ללא עדכון התיעוד, ולהפך, כל שינוי בתיעוד מרמז על שחרור גרסה חדשה של werf;
- לפרויקט יש פיתוח אינטנסיבי למדי: גרסאות חדשות יכולות לצאת מספר פעמים ביום;
- כל פעולה ידנית לפריסת אתר עם גרסה חדשה של התיעוד היא לפחות מייגעת;
- הפרויקט מאמץ גישה סמנטית , עם 5 ערוצי יציבות. תהליך השחרור כולל מעבר רציף של גרסאות דרך ערוצים לפי סדר יציבות גוברת: מאלפא ליציבות מוצקה כסלע;
- לאתר יש גרסה בשפה הרוסית, אשר "חיה ומתפתחת" (כלומר, תוכנה מתעדכן) במקביל לגרסה הראשית (כלומר בשפה האנגלית).
כדי להסתיר את כל "הפעולות הפנימיות" הללו מהמשתמש, ולהציע לו משהו ש"פשוט עובד", יצרנו כלי נפרד להתקנה ועדכון של werf - האם אתם רק צריכים לציין את מספר הגרסה ואת ערוץ היציבות שאתם מוכנים להשתמש בו, ו-multiwerf יבדוק אם יש גרסה חדשה בערוץ ויוריד אותה במידת הצורך.
הגרסאות האחרונות של werf זמינות בכל ערוץ בתפריט בחירת הגרסאות באתר. כברירת מחדל, ב גרסת הערוץ היציבה ביותר עבור המהדורה האחרונה נפתחת - היא גם מאונדקסת על ידי מנועי חיפוש. תיעוד עבור הערוץ זמין בכתובות נפרדות (לדוגמה, עבור גרסת בטא 1.0).
בסך הכל, באתר יש את הגרסאות הבאות:
- root (נפתח כברירת מחדל),
- עבור כל ערוץ עדכון פעיל של כל מהדורה (למשל ).
כדי ליצור גרסה ספציפית של אתר, באופן כללי, מספיק לקמפל אותו באמצעות , פועל בספרייה /docs פקודה מתאימה למאגר werf (jekyll build), לאחר שעבר בעבר לתג Git של הגרסה הנדרשת.
נותר רק להוסיף ש:
- התועלת עצמה (werf) משמשת להרכבה;
- תהליכי CI/CD בנויים על בסיס GitLab CI;
- וכל זה, כמובן, פועל בקוברנטס.
משימות
כעת ננסח את המשימות אשר לוקחות בחשבון את כל הפרטים המתוארים:
- לאחר שינוי גרסת ה-werf בכל ערוץ עדכון התיעוד באתר צריך להתעדכן אוטומטית.
- כדי להתפתח אתה צריך להיות מסוגל לפעמים צפה בתצוגות מקדימות של האתר.
יש לקמפל מחדש את האתר לאחר שינוי הגרסה בכל ערוץ מתגיות ה-Git המתאימות, אך במהלך תהליך הרכבת התמונה נקבל את התכונות הבאות:
- מכיוון שרשימת הגרסאות בערוצים משתנה, יש צורך רק לבנות מחדש את התיעוד עבור הערוצים שבהם הגרסה השתנתה. אחרי הכל, לבנות מחדש הכל מאפס זה לא נחמד במיוחד.
- ייתכן שקבוצת הערוצים עבור גרסאות תשתנה. בשלב מסוים, לדוגמה, ייתכן שלא תהיה גרסה בערוצים יציבה יותר מגרסת 1.1 בגישה מוקדמת, אך הם יופיעו עם הזמן - במקרה הזה אי אפשר לשנות את הגרסה באופן ידני, נכון?
מתברר כי ההרכבה תלויה בשינוי נתונים חיצוניים.
Реализация
בחירת גישה
לחלופין, ניתן להריץ כל גרסה נדרשת כפוד נפרד ב-Kubernetes. אפשרות זו מרמזת על מספר גדול יותר של אובייקטים באשכול, אשר יגדל עם העלייה במספר גרסאות ה-werf היציבות. וזה, בתורו, מרמז על תחזוקה מורכבת יותר: לכל גרסה יש שרת HTTP משלה, עם עומס קטן. כמובן, זה כרוך גם בעלויות משאבים גדולות יותר.
הלכנו באותה דרך בניית כל הגרסאות הנדרשות בתמונה אחתהסטטיסטיקות המקומפלות של כל גרסאות האתר נמצאות במכולה עם NGINX, והתעבורה לפריסה המתאימה מגיעה דרך NGINX Ingress. מבנה פשוט - יישום חסר מצב - מאפשר לך להגדיל בקלות את הפריסה (בהתאם לעומס) באמצעות Kubernetes עצמו.
ליתר דיוק, אנו בונים שתי תמונות: אחת עבור מעגל הייצור, השנייה נוספת עבור מעגל הפיתוח. התמונה הנוספת משמשת (מופעלת) רק במעגל הפיתוח יחד עם התמונה הראשית ומכילה את גרסת האתר מ-review commit, והניתוב ביניהן מתבצע באמצעות משאבי Ingress.
שיבוט וארטיפקטים של Werf לעומת Git
כפי שצוין, כדי ליצור סטטיסטיקות אתר עבור גרסה ספציפית של התיעוד, עליך לבנות על ידי מעבר לתג המאגר המתאים. ניתן גם לעשות זאת על ידי שכפול המאגר בכל פעם שאתה בונה, בחירת התגים המתאימים מהרשימה. עם זאת, זוהי פעולה עתירת משאבים למדי, ובנוסף דורשת כתיבת הוראות לא טריוויאליות... חיסרון רציני נוסף הוא שבגישה זו, אין דרך לשמור שום דבר במטמון במהלך הבנייה.
כאן כלי השירות werf עצמו בא לעזרתנו, ומייישם אחסון חכם במטמון ומאפשר לך להשתמש שימוש ב-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— ה-hash של קובץ ה-commit לבדיקה שממנו יש לבנות את הגרסה עבור מעגל הבדיקה.
משתנים אלה יאוכלסו בצינור CI של GitLab, וכיצד בדיוק מתואר להלן.
קודם כל, לשם נוחות, נגדיר 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— commit hash, אם הארטיפקט נוצר עבור 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 }}אבל עליכם להבין שכאשר מייבאים מארטיפקטים, תצטרכו להתייחס לאותם שמות.
בעת תיאור ארטיפקט, נעשה שימוש בתכונת הוורף הבאה: הרכבה עם ספריית שירות שצוינה build_dir מאפשר לך לשמר את מטמון Jekyll בין ריצות צינור, אשר מאיץ משמעותית את ההרכבה מחדש.
ייתכן ששמת לב גם לשימוש בקובץ releases.yml — הוא קובץ YAML עם נתוני שחרור שנדרשו מ (ארטיפקט המתקבל בעת ביצוע צינור). הוא נחוץ בעת קומפילציה של אתר, אך בהקשר של המאמר, הוא מעניין אותנו מכיוון שמצבו תלוי ב הרכבה מחדש של חפץ אחד בלבד — ארטיפקט של גרסת השורש של האתר (אין צורך בארטיפקטים אחרים).
זה מיושם באמצעות האופרטור המותנה. if תבניות ומבנים עבור {{ $Root.Files.Get "releases.yml" | sha256sum }} בבמה זה עובד כך: בעת בניית ארטיפקט עבור גרסת הבסיס (משתנה .Channel שווה ל root) גיבוב קובץ releases.yml משפיע על החתימה של כל השלב, מכיוון שהוא רכיב של שם המשימה של Ansible (פרמטר name). לכן, כאשר משתנים תוֹכֶן файла releases.yml החפץ המתאים יורכב מחדש.
אנא שימו לב גם לעבודה עם מאגר חיצוני. בתמונת החפץ מ , רק הספרייה מתווספת /docs, ובהתאם לפרמטרים המועברים, הנתונים של התג או ה-review הנדרשים מתווספים באופן מיידי.
כדי להשתמש בתבנית הארטיפקט כדי ליצור תיאור ארטיפקט של גרסאות ומהדורות הערוצים שהועברו, אנו מארגנים לולאה לפי משתנה .WerfVersions в werf.yaml:
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ dict "Version" $VersionsDict._1 "Channel" $VersionsDict._0 "Root" $Root | include "doc_artifact" }}
---
{{ end -}} מכיוון שהמחזור ייצור מספר ארטיפקטים (אנו מקווים שכן), יש צורך לקחת בחשבון את המפריד ביניהם - הרצף --- (למידע נוסף על תחביר קובץ התצורה, ראה כפי שהגדרנו קודם לכן, בעת קריאה לתבנית בלולאה, אנו מעבירים את פרמטרי הגרסה, כתובת ה-URL וההקשר של ה-root.
באופן דומה, אך ללא המחזור, אנו קוראים לתבנית הארטיפקט עבור "מקרים מיוחדים": עבור גרסת הבסיס, כמו גם עבור הגרסה מ-commit הסקירה:
{{ 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 }} שים לב שהארטיפקט עבור commit הסקירה ייבנה רק אם המשתנה מוגדר. .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 }} כפי שצוין לעיל, הארטיפקט עבור commit הסקירה ייווצר רק בעת הפעלת משתנה הסביבה שנקבע. REVIEW_SHAניתן יהיה לא ליצור את תמונת werf-dev כלל אם אין משתנה סביבה. REVIEW_SHA, אבל כדי ש תמונות Docker ב-werf עבדו עבור תמונת werf-dev, נשאיר אותה להיבנות רק עם ארטיפקט גרסת ה-root (היא כבר בנויה בכל מקרה), כדי לפשט את מבנה הצינור.
הבנייה מוכנה! בואו נעבור ל-CI/CD ולניואנסים חשובים.
צינור ב-GitLab CI ותכונות של בנייה דינמית
בעת הרצת הבנייה, עלינו להגדיר את משתני הסביבה המשמשים ב- werf.yamlזה לא חל על המשתנה REVIEW_SHA, אותו נגדיר בעת קריאה ל-pipeline מה-hook של GitHub.
נעביר את יצירת הנתונים החיצוניים הדרושים לסקריפט Bash 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 מחשב במהלך ההרכבה, ולדוגמה, הפריסה, יהיו שונות. זה יוביל לשגיאת פריסה, מכיוון שהתמונה הנדרשת לפריסה תחסר.
במילים אחרות, אם במהלך הרכבת תמונת האתר המידע על מהדורות וגרסאות זהה, ובזמן הפריסה משוחררת גרסה חדשה ומשתני הסביבה בעלי ערכים שונים, אז הפריסה תסתיים בשגיאה: אחרי הכל, הארטיפקט של הגרסה החדשה טרם הורכב.
אם דור werf.yaml תלוי בנתונים חיצוניים (לדוגמה, רשימה של גרסאות עדכניות, כמו במקרה שלנו), אזי יש לתעד את ההרכב והערכים של נתונים כאלה בתוך הצינור. זה חשוב במיוחד אם פרמטרים חיצוניים משתנים לעתים קרובות למדי.
אנו קליטה ורישום של נתונים חיצוניים בשלב הראשון של הצינור ב-GitLab (בנייה מוקדמת) ולהעביר אותם הלאה בצורה ארטיפקטים של 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לאחר תיקון נתונים חיצוניים בארטיפקט, ניתן לבנות ולפרוס באמצעות השלבים הסטנדרטיים של צינור ה-CI של GitLab: בנייה ופריסה. אנו משיקים את הצינור עצמו באמצעות ווים ממאגר ה-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), אשר לאחר מכן משמשות בתבניות תרשימי Helm. לא נספק את תוכן התבניות, מכיוון שאין שום דבר מעניין בנושא הנדון, אך ניתן למצוא אותו ב .
המגע הסופי
מכיוון שגרסאות 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 (לטוקן המונפק אוטומטית של משימת CI של GitLab אין הרשאות כאלה). יש ליצור את הטוקן ב-GitLab מראש ויש לציין את ערכו במשתנה הסביבה. WERF_IMAGES_CLEANUP_PASSWORD פרוייקט (הגדרות CI/CD -> משתנים).
הוספת משימת ניקיון עם לוח הזמנים הנדרש מתבצעת ב CI/CD ->
לוחות זמנים.
זהו זה: פרויקט Docker Registry שלך לא יגדל עוד כל הזמן מתמונות שאינן בשימוש.
לסיכום החלק המעשי, ברצוני להזכיר לכם שהרשימות המלאות מהמאמר זמינות ב :
- ;
- .
תוצאה
- קיבלנו מבנה הרכבה לוגי: ארטיפקט אחד לכל גרסה.
- ההרכבה היא אוניברסלית ואינה דורשת שינויים ידניים כאשר גרסאות חדשות של werf יוצאות: התיעוד באתר מתעדכן אוטומטית.
- שתי תמונות נאספות עבור קווי מתאר שונים.
- זה עובד מהר מכיוון ששימוש במטמון (caching) נעשה בו שימוש מקסימלי - כאשר גרסה חדשה של Werf יוצאת או כאשר hook של GitHub נקרא לצורך commit לסקירה, רק הארטיפקט המתאים עם הגרסה שהשתנתה נבנה מחדש.
- אין צורך לדאוג לגבי מחיקת תמונות שאינן בשימוש: ניקוי מבוסס מדיניות werf ישמור על סדר וניקיון הרישום של Docker שלך.
ממצאים
- שימוש ב-werf מאפשר לבנייה לעבוד במהירות הודות לאחסון במטמון של הבנייה עצמה וגם לאחסון במטמון בעת עבודה עם מאגרים חיצוניים.
- עבודה עם מאגרי Git חיצוניים מבטלת את הצורך לשכפל את המאגר בכל פעם לחלוטין או להמציא את הגלגל מחדש בעזרת לוגיקת אופטימיזציה מסובכת. werf משתמש במטמון ומשכפל פעם אחת בלבד, ולאחר מכן משתמש
fetchורק כשצריך. - יכולת להשתמש בתבניות Go בקובץ תצורת הבנייה
werf.yamlמאפשר לך לתאר אסמבלי שתוצאתו תלויה בנתונים חיצוניים. - שימוש ב-mounting ב-werf מאיץ משמעותית את איסוף הארטיפקטים - בזכות המטמון, המשותף לכל הצינורות.
- werf מאפשר הגדרת ניקוי בקלות, דבר שחשוב במיוחד עבור בניות דינמיות.
נ.ב.
קרא גם בבלוג שלנו:
- «";
- «";
- «";
- «".
מקור: www.habr.com
