Cara menggambarkan pekerjaan 100 gitlab dalam 100 baris di Jsonnet

Sebagai kelanjutan dari artikel sebelumnya tentang alat penyebaran di Kubernetes, saya ingin memberi tahu Anda tentang bagaimana Anda dapat menggunakan Jsonnet untuk menyederhanakan deskripsi pekerjaan di .gitlab-ci.yml Anda



Diberikan


Ada monorepa di mana:


  • 10 buruh pelabuhan
  • 30 dijelaskan menyebarkan
  • 3 lingkungan: devel , pementasan dan produksi

Tantangan


Siapkan saluran pipa:


  • Membangun gambar Docker harus dilakukan dengan menambahkan tag git dengan versi.
  • Setiap operasi penyebaran harus dilakukan ketika mendorong ke cabang lingkungan dan hanya dengan mengubah file di direktori tertentu
  • Setiap lingkungan memiliki gitlab-pelari sendiri dengan tag terpisah yang hanya melakukan penyebaran di lingkungannya.
  • Tidak semua aplikasi harus dikerahkan ke masing-masing lingkungan, kita harus menggambarkan pipa agar dapat membuat pengecualian.
  • Beberapa penyebaran menggunakan git submodule dan harus dimulai dengan variabel set GIT_SUBMODULE_STRATEGY=normal

Menggambarkan semua ini mungkin tampak seperti neraka yang nyata, tetapi kita tidak putus asa dan dipersenjatai dengan Jsonnet kita akan melakukannya dengan mudah dan alami.


Solusi


gitlab-ci.yml memiliki kemampuan bawaan untuk mengurangi deskripsi pekerjaan berulang, misalnya, Anda dapat menggunakan extends atau menyertakan , tetapi itu tidak menyediakan templating lengkap, yang tidak memungkinkan Anda untuk mendeskripsikan pekerjaan yang paling ringkas dan efisien.


Untuk mengatasi masalah ini, saya sarankan menggunakan jsonnet, yang memungkinkan Anda untuk hampir sepenuhnya menghilangkan pengulangan kode ketika menggambarkan setiap struktur data.


Ketika bekerja dengan jsonnet, saya sangat menyarankan untuk menginstal plugin untuk editor Anda

Misalnya, untuk vim ada plugin vim-jsonnet yang menyalakan penyorotan sintaks dan secara otomatis melakukan jsonnet fmt setiap kali disimpan (memerlukan jsonnet diinstal).

Mari kita lihat struktur repositori kami:


 . ├── deploy │  ├── analyse │  ├── basin │  ├── brush │  ├── copper │  ├── dinner │  ├── dirty │  ├── drab │  ├── drunk │  ├── education │  ├── fanatical │  ├── faulty │  ├── guarantee │  ├── guitar │  ├── hall │  ├── harmonious │  ├── history │  ├── iron │  ├── maniacal │  ├── mist │  ├── nine │  ├── pleasant │  ├── polish │  ├── receipt │  ├── shop │  ├── smelly │  ├── solid │  ├── stroke │  ├── thunder │  ├── ultra │  └── yarn └── dockerfiles ├── dinner ├── drunk ├── fanatical ├── guarantee ├── guitar ├── harmonious ├── shop ├── smelly ├── thunder └── yarn 

Gambar Docker akan dibangun menggunakan kaniko


Menyebarkan aplikasi ke cluster akan dilakukan menggunakan qbec . Setiap aplikasi dijelaskan untuk tiga lingkungan yang berbeda, untuk menerapkan perubahan pada cluster, itu cukup untuk melakukan:


 qbec apply <environment> --root deploy/<app> --yes 

dimana:


  • <app> - nama aplikasi kita
  • <environment> adalah salah satu dari lingkungan kami: devel , stage, atau prod .

Pada akhirnya, pekerjaan kita akan terlihat seperti ini:


Majelis:


 build:{{ image }}: stage: build tags: - build image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dockerfiles/{{ image }}/Dockerfile --destination $CI_REGISTRY_IMAGE/{{ image }}:$CI_COMMIT_TAG only: refs: - tags 

Di mana alih-alih {{ image }} , nama direktori dari dockerfiles akan diganti


Sebarkan:


 deploy:{{ environment }}:{{ app }}: stage: deploy tags: - {{ environment }} script: - qbec apply {{ environment }} --root deploy/{{ app }} --force:k8s-context __incluster__ --wait --yes only: changes: - deploy/{{ app }}/**/* refs: - {{ environment }} 

Di mana alih-alih {{ app }} , nama direktori dari deploy akan diganti,
dan alih-alih {{ environment }} - nama lingkungan yang ingin Anda gunakan.


Mari kita gambarkan prototipe pekerjaan kita sebagai objek dalam lib / jobs.jsonnet yang terpisah


 { //    docker- dockerImage(name):: { tags: ['build'], stage: 'build', image: { name: 'gcr.io/kaniko-project/executor:debug-v0.15.0', entrypoint: [''], }, script: [ 'echo "{\\"auths\\":{\\"$CI_REGISTRY\\":{\\"username\\":\\"$CI_REGISTRY_USER\\",\\"password\\":\\"$CI_REGISTRY_PASSWORD\\"}}}" > /kaniko/.docker/config.json', '/kaniko/executor --cache --context $CI_PROJECT_DIR/dockerfiles/' + name + ' --dockerfile $CI_PROJECT_DIR/dockerfiles/' + name + '/Dockerfile --destination $CI_REGISTRY_IMAGE/' + name + ':$CI_COMMIT_TAG --build-arg VERSION=$CI_COMMIT_TAG', ], }, //    qbec- qbecApp(name): { stage: 'deploy', script: [ 'qbec apply $CI_COMMIT_REF_NAME --root deploy/' + name + ' --force:k8s-context __incluster__ --wait --yes', ], only: { changes: [ 'deploy/' + name + '/**/*', ], }, }, } 

Harap dicatat bahwa saya sengaja tidak menentukan refs dan tags untuk membuat perpustakaan kami lebih fleksibel dan sepenuhnya menunjukkan kemampuan jsonnet kepada Anda, kami akan menambahkannya nanti dari file utama.


Sekarang kita akan menggambarkan .gitlab-ci.jsonnet kami :


 //    local jobs = import 'lib/jobs.libsonnet'; //    local ref(x) = { only+: { refs: [x] } }; local tag(x) = { tags: [x] }; local submodule(x) = { variables+: { GIT_SUBMODULE_STRATEGY: x } }; { // C docker- ['build:' + x]: jobs.dockerImage(x) + tag('build') + ref('tags') for x in [ 'dinner', 'drunk', 'fanatical', 'guarantee', 'guitar', 'harmonious', 'shop', 'smelly', 'thunder', 'yarn', ] } + { //         'prod' ['deploy:prod:' + x]: jobs.qbecApp(x) + tag('prod') + ref('prod') for x in [ 'dinner', 'hall', ] } + { //   git-submodule ['deploy:' + env + ':' + app]: jobs.qbecApp(app) + tag(env) + ref(env) + submodule('normal') for env in ['devel', 'stage', 'prod'] for app in [ 'brush', 'fanatical', 'history', 'shop', ] } + { //    ['deploy:' + env + ':' + app]: jobs.qbecApp(app) + tag(env) + ref(env) for env in ['devel', 'stage', 'prod'] for app in [ 'analyse', 'basin', 'copper', 'dirty', 'drab', 'drunk', 'education', 'faulty', 'guarantee', 'guitar', 'harmonious', 'iron', 'maniacal', 'mist', 'nine', 'pleasant', 'polish', 'receipt', 'smelly', 'solid', 'stroke', 'thunder', 'ultra', 'yarn', ] } 

Perhatikan fungsi ref , tag, dan submodule di awal file, mereka memungkinkan Anda untuk membuat objek override.


Penjelasan kecil: menggunakan " +: " bukannya " : " untuk menimpa objek memungkinkan Anda menambahkan nilai ke objek atau daftar yang ada.


Misalnya " : " untuk referensi :


 local job = { script: ['echo 123'], only: { refs: ['tags'] }, }; local ref(x) = { only+: { refs: [x] } }; job + ref('prod') 

akan kembali:


 { "only": { "refs": [ "prod" ] }, "script": [ "echo 123" ] } 

Dan inilah " +: " untuk referensi :


 local job = { script: ['echo 123'], only: { refs: ['tags'] }, }; local ref(x) = { only+: { refs+: [x] } }; job + ref('prod') 

akan kembali:


 { "only": { "refs": [ "prod", "tags" ] }, "script": [ "echo 123" ] } 

Seperti yang Anda lihat, menggunakan Jsonnet memungkinkan Anda untuk mendeskripsikan dan menggabungkan objek Anda dengan sangat efisien, hasilnya selalu berupa JSON siap pakai, yang dapat segera kami tulis ke file .gitlab-ci.yml kami :


 jsonnet .gitlab-ci.jsonnet > .gitlab-ci.yml 

Periksa jumlah baris:


 # wc -l .gitlab-ci.jsonnet lib/jobs.libsonnet .gitlab-ci.yml 77 .gitlab-ci.jsonnet 24 lib/jobs.libsonnet 1710 .gitlab-ci.yml 

Menurut saya itu sangat bagus!


Anda dapat melihat lebih banyak contoh dan merasakan Jsonnet langsung di situs web resmi: jsonnet.org
Jika Anda, seperti saya, menyukai Jsonnet, maka bergabunglah dengan grup kami di telegram t.me/jsonnet_ru

Source: https://habr.com/ru/post/id483626/


All Articles