ru:https://highload.today/blogs/kak-v-luxoft-pishut-deploj-skripty-yazyki-razmetki-v-reliz-menedzhmente/ ua:https://highload.today/uk/blogs/kak-v-luxoft-pishut-deploj-skripty-yazyki-razmetki-v-reliz-menedzhmente/
logo
Решения      27/04/2021

Как писать деплой-скрипты: гайд от релиз-менеджера Luxoft

Виталий Корж BLOG

Lead Software Developer в Luxoft

Я не отношу себя к борцам с несуществующими проблемами, а больше нацелен на доработку того, что может быть улучшено. Одно из таких направлений — релиз-менеджмент.

По своим проектам я заметил, что часть рутинных задач по конфигурации пайплайна делается методом Сtrl+C/Сtrl+V. Получившиеся манускрипты своей массивностью пугают неискушенные умы программистов, что может приводить к неприятным последствиям.

Языки разметки — невероятно универсальный инструмент, овладев которым можно избавить себя от ежедневной рутины. Не стоит забывать, что сами по себе, без дополнительного слоя компиляции, они ничего не могут, но в связке с другими программами превращаются в мощный инструмент.

Думаю, что моя статья может быть интересна разработчикам и всем, кому интересно, как живет код-поле коммита; возможно, и DevOps почерпнут что-то в свой арсенал.

Языки разметки

Современную разработку невозможно представить без использования языков разметки. Форматы XML, YAML и JSON появились приблизительно в одно и то же время и вполне способны друг друга заменить. Разнообразие вариантов применения в описании и конфигурации различных систем выделяет их из числа языков разметки.

У каждого из них своя специфика. Мы не будем рассматривать семантику и изначальную документ-ориентированность форматов, а сконцентрируемся на сценариях использования. 

XML остается языком конфигурации в различных платформах и в различных своих спецификациях позволяет генерировать XHTML из XSLT и XML. YAML и JSON же занимают совершенно другое место в повседневной жизни каждого разработчика. 

Применение YAML

Чаще всего с этими языками мы сталкиваемся при использовании CI/CD-инструментов. Рассмотреть и сравнить различные решения можно по ссылке.

Я на своих проектах последние пару лет использую GitLab. Приложения деплоятся в Kubernetes, а инфраструктура может конфигурироваться с помощью CloudFormation. Эти продукты объединяет то, что для их конфигурации используется YAML/JSON. И если конфигурации Kubernetes и CloudFormation описывают систему и ничем не примечательны, то GilLab позволяет играть в некое подобие программирования. 

Знакомство с GitLab CI/CD

GitLab CI/CD позволяет управлять деливери-процессом через файл конфигурации. На первый взгляд файл не представляет собой ничего интересного, позволяя описать интересующие нас шаги и задать необходимые переменные, не забыв о исполняемых скриптах.

Курс UI/UX для геймдеву.
Зрозумієш, як працює людський мозок, і впровадиш Design thinking у свою роботу — від ресерчу до прототипу й тестування. Забереш головні фішки Figma та Adobe Photoshop для дизайну ігор.
Інформація про курс

Для переменных применимо наследование, помимо файла конфигурации их можно указать на уровне проекта или группы. Список переменных расширяется новыми на каждом уровне. Переменные группы переопределяются проектными, а те в свою очередь — указанными непосредственно в конфигурации. Помимо пользовательских переменных, доступен внушительный список предопределенных на все случаи жизни.

Базовый пайплайн может выглядеть следующим образом:

--- main.yml
stages:
 - test
 - build
 - deploy

variables:
 foo: bar
 hello: world

app-test:
 stage: test
 script:
   - application test

app-build:
 stage: build
 script:
   - application build
   - container push

app-deploy:
 stage: deploy
 variables:
   foo: baz
 script:
   - container deploy

GitLab/YAML-программирование

Наследованием переменных возможности конфигурации не ограничиваются. YAML предоставляет возможности наследования как блоков, так и списков, что позволяет переиспользовать определенные конструкции внутри одного файла:

nested-block: &some-ref
 foo: bar
 hello: world

nested-list: &list-ref
 - command
 - command param

app-block:
 stage: test
 <<: *some-ref
 script:
   - shell command
   - *list-ref

GitLab расширяет возможности наследования конструкциями includeи extends. Includeпозволяет импортировать интересующий файл как с локального, так и с удаленного репозитория.

Наследование по умолчанию позволяет дополнять и переопределять определенные блоки. Extends, в свою очередь, позволяет наследовать уже существующие блоки, создавая новую логику на их основании, и работает с импортированными сущностями. Блоки с точкой в начале имени скрыты от системы и не отображаются на графическом конвейере. В то же время их можно использовать как основу или дополнение к существующей конфигурации.

--- example.yml
include:
 - local: main.yml


.app-build:
 variables:
   foo: bar


app-build:
 variables:
   fiz: baz

app-redeploy:
 extends:
   - .app-deploy
   - app-deploy
 when: manual

Каждая из этих техник позволяет навести порядок в наших проектах, но наибольший эффект достигается, если использовать их вместе. 

Чтобы не мусорить в своих проектах и максимально упростить процедуру апгрейда, я использую отдельный проект с пайплайнами, которые стандартизуют процедуру. Самая простая структура такого проекта может разниться, но в общих чертах выглядит так:

/ci-project
    /services
        java.yml
        node.yml
    basic.yml

Для использования в проекте нам будет достаточно сослаться на нужный файл:

include:
 - project: '/ci-project'
   ref: 'master'
   file: 'services/java.yml'

В таком случае каждый сервис расширяет базовый документ, который включает в себя общие определения. Такого подхода вполне достаточно, когда систем немного и все, что мы хотим контролировать, — это однообразие процесса.

Но что будет, если мы захотим регламентировать не только языки, но и различные реализации build-test-deploy? Для этого пригодится ключевое слово rules. Rules позволяет настраивать различные условия для наших стейджей, тем самым изменив порядок наследования:

.node-apps:
 rules:
   - if: $LANGUAGE == "node"

В результате мы получаем более гибкую структуру с единой точкой входа main.yml:

/ci-project
    /services
        java.yml
        node.yml
    /deploy
        k8s.yml
        ec2.yml
    /build
        java.yml
        node.yml
    main.yml

Использование версионирования добавит стабильности пайплайнов. А файл с проектными особенностями позволит отделить логику от импортов:

include:
 - project: 'ci-project'
   ref: 'tag-version'
   file: 'main.yml'
 - local: '/.local-ci.yml'

Шаблонизация деплоя

В то время как тестирование и сборка артефактов регулируются командами, процесс деплоя для распределенных систем описывается документом, в котором от сервиса к сервису изменяется лишь пара строк.

В качестве примера рассмотрим деплой сервиса на Kubernetes. В зависимости от типа сервиса количество различных компонентов будет отличаться, но значащими параметрами будут: образ приложения в реестре, переменные окружения, иногда сертификаты, публичные адреса, параметры авторизации…

Чтобы все работало, стоит унифицировать подходы, использовать одинаковые имена для секретов и переменных окружения, а также пути к сертификатам, что позволит упростить настройку окружения.

Реализовать шаблонизацию можно по-разному. Я выделю два варианта:

  • использование «настоящего» программирования (Python + Jinja), что требует дополнительных манипуляций с образом сборщика;
  • использование консольных команд (jq), требующее установки нескольких пакетов.

Полноценное приложение, упакованное в образ по сборке контекста, предпочтительнее в большинстве ситуаций, так как повышает гибкость используемых решений.

Вариант с jq наименее требователен к кастомизации исходного образа и способен решать главную задачу: он упрощает работу разработчика. По сути, он представляет собой не что иное, как JSON-программирование.

3D-Ммодел У Blender.
Курс для тих, хто хоче швидко освоїти Blender та розпочати свій шлях у геймдеві.

Вот вариант с кастомизацией CronJob:

--- main.yml
variables:
 TEMPLATE: > #сворачивает текст в строку
   {
     "apiVersion": "batch/v1beta1",
     "kind": "CronJob",
     "metadata": {
       "name": .name
     },
     "spec": {
       "schedule": .schedule,
       "concurrencyPolicy": "Forbid",
       "startingDeadlineSeconds": 1800,
       "successfulJobsHistoryLimit": 1,
       "failedJobsHistoryLimit": 1,
       "jobTemplate": {
         "spec": {
           "template": {
             "spec": {
               "containers": [
                 {
                   "name": "container-name",
                 }
               ],
               "restartPolicy": "Never"
             }
           }
         }
       }
     }
   }

.template: &template-ref
 - SECRETS_VAL=$(kubectl get secret $SECRET -o json | jq -c --arg secret $SECRET '.data | keys | map({"name":.,"valueFrom":{"secretKeyRef":{"name":$secret,"key":.}}})')
 - JOB=$(echo $JOBS | jq -c "[.[] | map_values(.) | $TEMPLATE]")
 - JOB=$(echo $JOB | jq -c --arg namespace $NAMESPACE --arg app $PROJECT_NAME '.items[].metadata += {"namespace":$namespace,"labels":{"group":$app}} | .items[].spec += {successfulJobsHistoryLimit:1}')
 - JOB=$(echo $JOB | jq -c --arg image $IMAGE --argjson env $SECRETS_VAL '.items[].spec.jobTemplate.spec.template.spec.containers[] +=  {"image":$image,"env":$env}')
 - echo $JOB | kubectl apply -f -

deploy:
 script:
   - *template-ref

--- .local-ci.yml
deploy:
 variables:
   NAMESPACE: space
   IMAGE: image.registry/image
   JOBS: >
     [
         {"name":"a", "schedule":"* * * * *"},
         {"name":"b", "schedule":"0 0 * * *"}
     ]

Все, что требуется от разработчика в этом примере, — определить переменные JOB, которые он хочет создать.

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Курс QA.
Найпростіший шлях розпочати кар'єру в ІТ та ще й з гарантованим працевлаштуванням.
Приєднатися

Этот материал – не редакционный, это – личное мнение его автора. Редакция может не разделять это мнение.

Топ-5 самых популярных блогеров февраля

Всего просмотровВсего просмотров
181
#1
Всего просмотровВсего просмотров
181
Senior Project Manager at Nemesis
Всего просмотровВсего просмотров
92
#2
Всего просмотровВсего просмотров
92
Software Architect at Devlify
Всего просмотровВсего просмотров
88
#3
Всего просмотровВсего просмотров
88
Всего просмотровВсего просмотров
68
#4
Всего просмотровВсего просмотров
68
Android Team Lead у Balancуй Team
Всего просмотровВсего просмотров
46
#5
Всего просмотровВсего просмотров
46
Рейтинг блогеров

Ваша жалоба отправлена модератору

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: