Perakitan dinamis dan penerapan image Docker dengan werf menggunakan contoh situs dokumentasi berversi

Kami telah membicarakan alat GitOps kami lebih dari sekali. wer, dan kali ini kami ingin berbagi pengalaman kami dalam merakit situs dengan dokumentasi proyek itu sendiri - werf.io (versi Rusianya adalah en.werf.io). Ini adalah situs statis biasa, tetapi perakitannya menarik karena dibangun menggunakan sejumlah artefak yang dinamis.

Perakitan dinamis dan penerapan image Docker dengan werf menggunakan contoh situs dokumentasi berversi

Pelajari nuansa struktur situs: pembuatan menu umum untuk semua versi, halaman dengan informasi tentang rilis, dll. - kita tidak akan. Sebaliknya, mari kita fokus pada isu dan fitur perakitan dinamis dan sedikit pada proses CI/CD yang menyertainya.

Pendahuluan: cara kerja situs

Pertama-tama, dokumentasi werf disimpan beserta kodenya. Hal ini membebankan persyaratan pembangunan tertentu yang umumnya berada di luar cakupan pasal ini, namun setidaknya dapat dikatakan bahwa:

  • Fungsi werf baru tidak boleh dirilis tanpa memperbarui dokumentasi dan, sebaliknya, setiap perubahan dalam dokumentasi menyiratkan rilis versi werf yang baru;
  • Proyek ini mengalami pengembangan yang cukup intensif: versi baru dapat dirilis beberapa kali sehari;
  • Operasi manual apa pun untuk menyebarkan situs dengan dokumentasi versi baru setidaknya membosankan;
  • Proyek ini mengadopsi pendekatan semantik pembuatan versi, dengan 5 saluran stabilitas. Proses rilis melibatkan penerusan versi secara berurutan melalui saluran untuk meningkatkan stabilitas: dari alfa hingga sekuat batu;
  • Situs ini memiliki versi bahasa Rusia, yang β€œhidup dan berkembang” (yaitu, kontennya diperbarui) secara paralel dengan versi utama (yaitu, bahasa Inggris).

Untuk menyembunyikan semua β€œdapur bagian dalam” ini dari pengguna, menawarkan kepadanya sesuatu yang β€œberfungsi”, kami melakukannya alat instalasi dan pembaruan werf terpisah - Apakah multiwerf. Anda hanya perlu menentukan nomor rilis dan saluran stabilitas yang siap Anda gunakan, dan multiwerf akan memeriksa apakah ada versi baru di saluran tersebut dan mengunduhnya jika perlu.

Pada menu pemilihan versi di website, tersedia versi terbaru werf di setiap saluran. Secara default, berdasarkan alamat werf.io/documentation versi saluran paling stabil untuk rilis terbaru terbuka - saluran tersebut juga diindeks oleh mesin pencari. Dokumentasi untuk saluran tersebut tersedia di alamat terpisah (misalnya, werf.io/v1.0-beta/documentation untuk rilis beta 1.0).

Secara total, situs ini memiliki versi berikut yang tersedia:

  1. root (terbuka secara default),
  2. untuk setiap saluran pembaruan aktif dari setiap rilis (misalnya, werf.io/v1.0-beta).

Untuk menghasilkan versi tertentu dari suatu situs, secara umum cukup mengkompilasinya menggunakan Jekylldengan menjalankan di direktori /docs perintah yang sesuai dengan repositori werf (jekyll build), setelah beralih ke tag Git dari versi yang diperlukan.

Tinggal menambahkan bahwa:

  • utilitas itu sendiri (werf) digunakan untuk perakitan;
  • Proses CI/CD dibangun berdasarkan GitLab CI;
  • dan semua ini, tentu saja, berjalan di Kubernetes.

tugas

Sekarang mari kita merumuskan tugas-tugas yang mempertimbangkan semua hal spesifik yang dijelaskan:

  1. Setelah mengubah versi werf pada saluran pembaruan apa pun dokumentasi di situs harus diperbarui secara otomatis.
  2. Untuk pengembangan terkadang Anda harus mampu melihat versi pratinjau situs.

Situs harus dikompilasi ulang setelah mengubah versi pada saluran mana pun dari tag Git yang sesuai, tetapi dalam proses pembuatan gambar kita akan mendapatkan fitur berikut:

  • Karena daftar versi saluran berubah, yang perlu dilakukan hanyalah membuat ulang dokumentasi untuk saluran yang versinya telah diubah. Lagi pula, membangun kembali semuanya tidaklah baik.
  • Kumpulan saluran untuk rilis dapat berubah. Pada suatu saat, misalnya, mungkin tidak ada versi di saluran yang lebih stabil daripada rilis akses awal 1.1, namun seiring berjalannya waktu, versi tersebut akan muncul - dalam hal ini, bukankah sebaiknya Anda mengubah rakitan secara manual?

Ternyata bahwa perakitan tergantung pada perubahan data eksternal.

Implementasi

Memilih Pendekatan

Alternatifnya, Anda dapat menjalankan setiap versi yang diperlukan sebagai pod terpisah di Kubernetes. Opsi ini menyiratkan lebih banyak objek dalam cluster, yang akan bertambah seiring dengan peningkatan jumlah rilis werf yang stabil. Dan ini, pada gilirannya, menyiratkan pemeliharaan yang lebih kompleks: setiap versi memiliki server HTTP sendiri, dan dengan beban yang kecil. Tentu saja, hal ini juga memerlukan biaya sumber daya yang lebih besar.

Kami mengambil jalan yang sama merakit semua versi yang diperlukan dalam satu gambar. Statika yang dikompilasi dari semua versi situs ditempatkan dalam wadah dengan NGINX, dan lalu lintas ke Deployment terkait datang melalui NGINX Ingress. Struktur sederhana - aplikasi tanpa kewarganegaraan - memungkinkan Anda menskalakan Deployment dengan mudah (bergantung pada beban) menggunakan Kubernetes itu sendiri.

Untuk lebih tepatnya, kami mengumpulkan dua gambar: satu untuk sirkuit produksi, yang kedua adalah gambar tambahan untuk sirkuit pengembangan. Gambar tambahan digunakan (diluncurkan) hanya di sirkuit pengembang bersama dengan yang utama dan berisi versi situs dari tinjauan komit, dan perutean di antara keduanya dilakukan menggunakan sumber daya Ingress.

werf vs git clone dan artefak

Seperti yang telah disebutkan, untuk menghasilkan statika situs untuk versi dokumentasi tertentu, Anda perlu membangun dengan beralih ke tag repositori yang sesuai. Anda juga dapat melakukan ini dengan mengkloning repositori setiap kali Anda membangun, memilih tag yang sesuai dari daftar. Namun, ini adalah operasi yang membutuhkan banyak sumber daya dan, terlebih lagi, memerlukan penulisan instruksi yang tidak sepele... Kerugian serius lainnya adalah bahwa dengan pendekatan ini tidak ada cara untuk menyimpan sesuatu dalam cache selama perakitan.

Di sini utilitas werf sendiri datang membantu kami, mengimplementasikan cache yang cerdas dan memungkinkan Anda untuk menggunakannya repositori eksternal. Menggunakan werf untuk menambahkan kode dari repositori akan mempercepat pembangunan secara signifikan, karena werf pada dasarnya mengkloning repositori satu kali dan kemudian mengeksekusi hanya fetch jika diperlukan. Selain itu, saat menambahkan data dari repositori, kita hanya dapat memilih direktori yang diperlukan (dalam kasus kami ini adalah direktori docs), yang secara signifikan akan mengurangi jumlah data yang ditambahkan.

Karena Jekyll adalah alat yang dirancang untuk mengkompilasi data statis dan tidak diperlukan pada gambar akhir, maka logis untuk mengkompilasinya dalam artefak werf, dan menjadi gambar akhir impor hanya hasil kompilasi.

Kami menulis werf.yaml

Jadi, kami memutuskan bahwa kami akan mengkompilasi setiap versi dalam artefak werf terpisah. Bagaimanapun kita kami tidak tahu berapa banyak artefak yang akan ada selama perakitan, jadi kita tidak bisa menulis konfigurasi build yang tetap (sebenarnya, kita masih bisa, tapi ini tidak akan sepenuhnya efektif).

werf memungkinkan Anda untuk menggunakan Gunakan templat dalam file konfigurasi Anda (werf.yaml), dan ini memungkinkannya menghasilkan konfigurasi dengan cepat tergantung pada data eksternal (apa yang Anda butuhkan!). Data eksternal dalam kasus kami adalah informasi tentang versi dan rilis, yang menjadi dasar kami mengumpulkan jumlah artefak yang diperlukan dan sebagai hasilnya kami memperoleh dua gambar: werf-doc ΠΈ werf-dev untuk berjalan di sirkuit yang berbeda.

Data eksternal dilewatkan melalui variabel lingkungan. Berikut komposisinya:

  • RELEASES β€” baris dengan daftar rilis dan versi werf saat ini yang sesuai, dalam bentuk daftar nilai yang dipisahkan spasi dalam format <ΠΠžΠœΠ•Π _Π Π•Π›Π˜Π—Π>%<ΠΠžΠœΠ•Π _Π’Π•Π Π‘Π˜Π˜>. Contoh: 1.0%v1.0.4-beta.20
  • CHANNELS β€” baris dengan daftar saluran dan versi werf saat ini yang sesuai, dalam bentuk daftar nilai yang dipisahkan spasi dalam format <ΠšΠΠΠΠ›>%<ΠΠžΠœΠ•Π _Π’Π•Π Π‘Π˜Π˜>. Contoh: 1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22
  • ROOT_VERSION β€” versi rilis werf untuk ditampilkan secara default di situs (tidak selalu perlu menampilkan dokumentasi dengan nomor rilis tertinggi). Contoh: v1.0.4-beta.20
  • REVIEW_SHA β€” hash dari komit tinjauan yang darinya Anda perlu membuat versi untuk loop pengujian.

Variabel-variabel ini akan diisi di pipeline GitLab CI, dan cara tepatnya ditulis di bawah ini.

Pertama-tama, untuk kenyamanan, kami mendefinisikannya werf.yaml Buka variabel templat, berikan nilai dari variabel lingkungan:

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

Deskripsi artefak untuk mengkompilasi versi statis situs umumnya sama untuk semua kasus yang kita perlukan (termasuk membuat versi root, serta versi untuk sirkuit dev). Oleh karena itu, kami akan memindahkannya ke blok terpisah menggunakan fungsi tersebut define - untuk penggunaan kembali selanjutnya include. Kami akan meneruskan argumen berikut ke templat:

  • Version β€” versi yang dihasilkan (nama tag);
  • Channel β€” nama saluran pembaruan tempat artefak dibuat;
  • Commit β€” komit hash, jika artefak dihasilkan untuk komit tinjauan;
  • konteks.

Deskripsi Templat Artefak

{{- 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 }}

Nama artefak harus unik. Kita dapat mencapai hal ini, misalnya dengan menambahkan nama saluran (nilai variabel .Channel) sebagai akhiran nama artefak: artifact: doc-{{ .Channel }}. Namun Anda perlu memahami bahwa saat mengimpor dari artefak, Anda harus merujuk ke nama yang sama.

Saat mendeskripsikan artefak, fitur werf berikut digunakan: pemasangan. Pemasangan menunjukkan direktori layanan build_dir memungkinkan Anda menyimpan cache Jekyll di antara proses pipeline, yang mana secara signifikan mempercepat perakitan kembali.

Anda mungkin juga telah memperhatikan penggunaan file tersebut releases.yml adalah file YAML dengan data rilis yang diminta github.com (artefak yang diperoleh saat mengeksekusi pipeline). Ini diperlukan saat menyusun situs, tetapi dalam konteks artikel ini menarik bagi kami karena bergantung pada statusnya perakitan kembali hanya satu artefak β€” artefak versi root situs (tidak diperlukan di artefak lain).

Ini diimplementasikan menggunakan pernyataan kondisional if Gunakan templat dan desain {{ $Root.Files.Get "releases.yml" | sha256sum }} di panggung tahapan. Ini berfungsi sebagai berikut: saat membuat artefak untuk versi root (variable .Channel sama dengan root) hash berkas releases.yml mempengaruhi tanda tangan seluruh tahapan, karena ini adalah bagian dari nama tugas yang Mungkin (parameter name). Jadi, ketika berubah isi mengajukan releases.yml artefak yang sesuai akan dipasang kembali.

Harap perhatikan juga bekerja dengan repositori eksternal. Dalam gambar artefak dari repositori werf, hanya direktori yang ditambahkan /docs, dan bergantung pada parameter yang diteruskan, data tag yang diperlukan atau penerapan tinjauan akan segera ditambahkan.

Untuk menggunakan templat artefak guna menghasilkan deskripsi artefak versi saluran dan rilis yang ditransfer, kami mengatur loop pada variabel .WerfVersions Π² werf.yaml:

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

Karena loop akan menghasilkan beberapa artefak (kami harap demikian), perlu memperhitungkan pemisah di antara mereka - urutan --- (Untuk informasi lebih lanjut tentang sintaks file konfigurasi, lihat dokumentasi). Seperti yang didefinisikan sebelumnya, saat memanggil templat dalam satu lingkaran, kami meneruskan parameter versi, URL, dan konteks root.

Demikian pula, tetapi tanpa loop, kami memanggil templat artefak untuk β€œkasus khusus”: untuk versi root, serta versi dari review 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 }}

Harap perhatikan bahwa artefak untuk peninjauan komit hanya akan dibuat jika variabel disetel .WerfReviewCommit.

Artefak sudah siap - saatnya mulai mengimpor!

Gambar terakhir, yang dirancang untuk dijalankan di Kubernetes, adalah NGINX biasa dengan tambahan file konfigurasi server nginx.conf dan statis dari artefak. Selain artefak versi root situs, kita perlu mengulangi perulangan pada variabel .WerfVersions untuk mengimpor artefak versi saluran dan rilis + ikuti aturan penamaan artefak yang kami adopsi sebelumnya. Karena setiap artefak menyimpan versi situs untuk dua bahasa, kami mengimpornya ke tempat yang disediakan oleh konfigurasi.

Deskripsi gambar akhir 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 -}}

Gambar tambahan, yang, bersama dengan gambar utama, diluncurkan di sirkuit dev, hanya berisi dua versi situs: versi dari tinjauan komit dan versi root situs (ada aset umum dan, jika Anda ingat , rilis data). Jadi, gambar tambahan akan berbeda dari gambar utama hanya di bagian impor (dan, tentu saja, di namanya):

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 }}

Seperti disebutkan di atas, artefak untuk penerapan tinjauan hanya akan dihasilkan ketika variabel lingkungan yang disetel dijalankan REVIEW_SHA. Gambar werf-dev tidak dapat dibuat sama sekali jika tidak ada variabel lingkungan REVIEW_SHA, tetapi untuk pembersihan berdasarkan kebijakan Gambar Docker di werf berfungsi untuk gambar werf-dev, kami akan membiarkannya dibuat hanya dengan artefak versi root (lagipula sudah dibuat), untuk menyederhanakan struktur pipa.

Perakitan sudah siap! Mari beralih ke CI/CD dan nuansa penting.

Pipeline di GitLab CI dan fitur build dinamis

Saat menjalankan build kita perlu mengatur variabel lingkungan yang digunakan werf.yaml. Ini tidak berlaku untuk variabel REVIEW_SHA, yang akan kita atur saat memanggil pipeline dari hook GitHub.

Kami akan menghasilkan data eksternal yang diperlukan dalam skrip Bash generate_artifacts, yang akan menghasilkan dua artefak pipeline GitLab:

  • file itu releases.yml dengan data rilis,
  • file itu common_envs.sh, berisi variabel lingkungan yang akan diekspor.

Isi berkas generate_artifacts Anda akan menemukannya di kami repositori dengan contoh. Penerimaan datanya sendiri bukanlah subjek artikelnya, melainkan filenya common_envs.sh penting bagi kami, karena pekerjaan werf bergantung padanya. Contoh isinya:

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'

Anda dapat menggunakan output dari skrip tersebut, misalnya menggunakan fungsi Bash source.

Sekarang tiba bagian menyenangkan. Agar pembuatan dan penerapan aplikasi berfungsi dengan benar, hal itu perlu dipastikan werf.yaml itu sama paling sedikit dalam satu pipa. Jika kondisi ini tidak terpenuhi, maka tanda tangan tahapan yang dihitung selama perakitan dan, misalnya, penerapan, akan berbeda. Ini akan menyebabkan kesalahan penerapan, karena... gambar yang diperlukan untuk penerapan akan hilang.

Dengan kata lain, jika selama perakitan gambar situs informasi tentang rilis dan versi adalah sama, dan pada saat penerapan versi baru dirilis dan variabel lingkungan memiliki nilai yang berbeda, maka penerapan akan gagal dengan kesalahan: lagipula, artefak versi baru belum dibuat.

Jika generasi werf.yaml bergantung pada data eksternal (misalnya, daftar versi saat ini, seperti dalam kasus kami), maka komposisi dan nilai data tersebut harus dicatat dalam pipeline. Hal ini sangat penting jika parameter eksternal cukup sering berubah.

Kami akan menerima dan mencatat data eksternal pada tahap pertama pipeline di GitLab (Pra-bangun) dan mengirimkannya lebih lanjut dalam formulir Artefak GitLab CI. Ini akan memungkinkan Anda menjalankan dan memulai ulang pekerjaan pipeline (build, deploy, cleanup) dengan konfigurasi yang sama werf.yaml.

Isi panggung Pra-bangun mengajukan .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

Setelah mengambil data eksternal dalam artefak, Anda dapat membangun dan menerapkan menggunakan tahapan pipeline GitLab CI standar: Build dan Deploy. Kami meluncurkan pipeline itu sendiri menggunakan hook dari repositori GitHub werf (yaitu, ketika ada perubahan dalam repositori di GitHub). Data untuk mereka dapat ditemukan di properti proyek GitLab di bagian tersebut Pengaturan CI/CD -> Pemicu saluran pipa, lalu buat Webhook yang sesuai di GitHub (Pengaturan -> Webhook).

Tahap pembuatannya akan terlihat seperti ini:

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 akan menambahkan dua artefak dari tahap ke tahap pembangunan Pra-bangun, jadi kita mengekspor variabel dengan data masukan yang sudah disiapkan menggunakan konstruk source common_envs.sh. Kami memulai tahap pembangunan dalam semua kasus, kecuali meluncurkan pipeline sesuai jadwal. Sesuai jadwal, kami akan menjalankan pipa untuk dibersihkan - dalam hal ini tidak perlu melakukan perakitan.

Pada tahap penerapan, kami akan menjelaskan dua tugas - secara terpisah untuk penerapan ke sirkuit produksi dan pengembangan, menggunakan templat 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

Tugas-tugas tersebut pada dasarnya berbeda hanya dalam menunjukkan konteks cluster di mana werf harus melakukan penerapan (WERF_KUBE_CONTEXT), dan mengatur variabel lingkungan perulangan (environment.name ΠΈ environment.url), yang kemudian digunakan dalam templat bagan Helm. Kami tidak akan memberikan isi templatenya, karena... tidak ada yang menarik di sana untuk topik yang dimaksud, tetapi Anda dapat menemukannya di repositori untuk artikel tersebut.

Sentuhan terakhir

Karena versi werf cukup sering dirilis, image baru akan sering dibuat, dan Docker Registry akan terus berkembang. Oleh karena itu, sangat penting untuk mengonfigurasi pembersihan gambar otomatis berdasarkan kebijakan. Ini sangat mudah dilakukan.

Untuk menerapkannya, Anda memerlukan:

  • Tambahkan langkah pembersihan ke .gitlab-ci.yml;
  • Tambahkan pelaksanaan tugas pembersihan secara berkala;
  • Siapkan variabel lingkungan dengan token akses tulis.

Menambahkan tahap pembersihan ke .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

Kita telah melihat hampir semua ini sedikit lebih tinggi - hanya untuk membersihkannya Anda harus terlebih dahulu masuk ke Docker Registry dengan token yang memiliki hak untuk menghapus gambar di Docker Registry (token tugas GitLab CI yang dikeluarkan secara otomatis tidak mempunyai hak seperti itu). Token harus dibuat terlebih dahulu di GitLab dan nilainya harus ditentukan dalam variabel lingkungan WERF_IMAGES_CLEANUP_PASSWORD proyek (Pengaturan CI/CD -> Variabel).

Menambahkan tugas pembersihan dengan jadwal yang diperlukan dilakukan di CI/CD ->
Jadwal
.

Itu saja: proyek di Docker Registry tidak akan lagi terus berkembang dari image yang tidak digunakan.

Di akhir bagian praktis, izinkan saya mengingatkan Anda bahwa daftar lengkap dari artikel tersebut tersedia di pergi:

Hasil

  1. Kami menerima struktur perakitan logis: satu artefak per versi.
  2. Perakitannya bersifat universal dan tidak memerlukan perubahan manual ketika versi baru werf dirilis: dokumentasi di situs web diperbarui secara otomatis.
  3. Dua gambar dirangkai untuk kontur yang berbeda.
  4. Ini bekerja dengan cepat, karena Caching digunakan sebanyak mungkin - ketika versi baru werf dirilis atau hook GitHub dipanggil untuk melakukan tinjauan, hanya artefak terkait dengan versi yang diubah yang dibuat ulang.
  5. Tidak perlu berpikir untuk menghapus gambar yang tidak digunakan: membersihkan sesuai dengan kebijakan werf akan menjaga Docker Registry tetap teratur.

Temuan

  • Menggunakan werf memungkinkan rakitan bekerja dengan cepat karena caching rakitan itu sendiri dan caching saat bekerja dengan repositori eksternal.
  • Bekerja dengan repositori Git eksternal menghilangkan kebutuhan untuk mengkloning seluruh repositori setiap kali atau menemukan kembali roda dengan logika optimasi yang rumit. werf menggunakan cache dan melakukan kloning hanya sekali, lalu menggunakannya fetch dan hanya jika diperlukan.
  • Kemampuan untuk menggunakan templat Go dalam file konfigurasi build werf.yaml memungkinkan Anda mendeskripsikan rakitan yang hasilnya bergantung pada data eksternal.
  • Menggunakan mount di werf secara signifikan mempercepat pengumpulan artefak - karena cache, yang umum untuk semua pipeline.
  • werf memudahkan konfigurasi pembersihan, yang sangat penting saat membangun secara dinamis.

PS

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komentar