كيف تصف وظيفة 100 gitlab في 100 سطر على Jsonnet

استمرارًا للمقال السابق حول أدوات النشر في Kubernetes ، أريد أن أخبركم عن كيفية استخدام Jsonnet لتبسيط وصف المهمة في .gitlab-ci.yml



دانو


يوجد مونوريبا:


  • 10 عمال ميناء
  • 30 وصفها ينشر
  • 3 بيئات: التنمية ، التدريج والإنتاج

مهمة


قم بإعداد خط أنابيب:


  • يجب أن يتم إنشاء صور Docker عن طريق إضافة علامة git مع إصدار.
  • يجب إجراء كل عملية نشر عند الضغط على فرع البيئة وفقط عن طريق تغيير الملفات في دليل محدد
  • كل بيئة لها عداء gitlab خاص بها مع علامة منفصلة لا تؤدي إلا النشر في بيئتها.
  • لا ينبغي نشر جميع التطبيقات في كل من البيئات ؛ يجب أن نصف خط الأنابيب من أجل أن نكون قادرين على تقديم استثناءات.
  • تستخدم بعض عمليات النشر GIT_SUBMODULE_STRATEGY=normal git ويجب أن تبدأ مع المتغير المحدد GIT_SUBMODULE_STRATEGY=normal

قد يبدو وصف كل هذا جحيمًا حقيقيًا ، لكننا لا نحبط ونسلح بـ Jsonnet ، فسنقوم بذلك بسهولة وبشكل طبيعي.


قرار


يحتوي gitlab-ci.yml على إمكانات مضمّنة لتقليل وصف الوظائف المتكررة ، على سبيل المثال ، يمكنك استخدام الامتدادات أو التضمين ، ولكنها لا توفر templating كامل ، والذي لا يسمح لك بوصف العمل الأكثر إيجازًا وفعالية.


لحل هذه المشكلة ، أقترح استخدام jsonnet ، والذي يتيح لك التخلص تقريبًا من تكرار التعليمات البرمجية عند وصف أي بنية بيانات.


عند العمل مع jsonnet ، أوصي بشدة بتثبيت مكون إضافي لمحررك

على سبيل المثال ، بالنسبة إلى vim ، يوجد مكون إضافي لـ vim-jsonnet يقوم بتشغيل تسليط الضوء على بناء الجملة ويقوم تلقائيًا بتنفيذ jsonnet fmt في كل مرة يتم حفظه (يتطلب تثبيت jsonnet).

دعونا نلقي نظرة على هيكل مستودعنا:


 . ├── 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 

سيتم بناء صور عامل الميناء باستخدام kaniko


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


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

حيث:


  • <app> - اسم طلبنا
  • <environment> هي إحدى بيئاتنا : devel أو stage أو prod .

في النهاية ، يجب أن تبدو وظائفنا كما يلي:


التجمع:


 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 

بدلاً من {{ image }} ، سيتم استبدال اسم الدليل من dockerfiles


نشر:


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

بدلاً من {{ app }} ، سيتم استبدال اسم الدليل من النشر ،
وبدلاً من {{ environment }} - اسم البيئة التي تريد نشرها.


دعونا وصف النماذج الأولية لوظائفنا على أنها كائنات في lib / jobs.jsonnet منفصلة


 { //    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 + '/**/*', ], }, }, } 

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


الآن سوف نصف .gitlab-ci.jsonnet لدينا:


 //    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', ] } 

انتبه إلى وظائف ref ، و tag ، و subodule في بداية الملف ؛ فهي تسمح لك بإنشاء كائن طاغ.


شرح بسيط: استخدام " +: " بدلاً من " : " لكائنات التجاوز يسمح لك بإضافة قيمة إلى كائن موجود أو قائمة.


على سبيل المثال " : " للحكام :


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

سيعود:


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

وهنا " +: " للحكام :


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

سيعود:


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

كما ترون ، فإن استخدام Jsonnet يسمح لك بوصف كائناتك ودمجها بكفاءة عالية ، في الإخراج ، ستحصل دائمًا على JSON الجاهزة ، والتي يمكننا الكتابة إليها على الفور .gitlab-ci.yml :


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

تحقق من عدد الخطوط:


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

في رأيي ، هذا جيد جدًا!


تستطيع أن ترى المزيد من الأمثلة وتشعر Jsonnet مباشرة على الموقع الرسمي: jsonnet.org
إذا كنت مثلي ، مثل Jsonnet ، فقم بالانضمام إلى مجموعتنا في telegram t.me/jsonnet_ru

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


All Articles