Русский
Русский
English
Статистика
Реклама

Стенды разработки без очередей и простоев

Цель статьи - показать один из возможных подходов для организации гибкого развёртывания dev/test стендов. Показать какие преимущества предоставляет нам IaC подход в сочетании с современными инструментами.


Предыстория

Имеется несколько стендов для разработчиков - devs, tests, production. Новые версии компонентов продукта появляются несколько раз в день.

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

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

Задача

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

Стек

Gitlab CI, Terraform, Bash, любое приватное/публичное облако.

Технические сложности:

  1. Terraform state file - из коробки у нас нет возможности использовать переменную в значенииимени state файла. Нужно что-то придумывать или использовать другой продукт.

  2. Subnets - каждое новое окружение должно быть создано в изолированной подсети. Нужно контролировать свободные/занятые подсети, некий аналог DHCP, но для подсетей.

Алгоритм

  1. Gitlab CI выполняет pipeline. Связывает все остальные компоненты воедино.

  2. Terraform создаёт и удаляет экземпляры виртуальных машин.

  3. Configuration manager(CM) - разворачивает сервисы.

  4. Bash сценарии подготавливают конфигурационные файлы специфичные для каждого стенда.

Структура репозитория

development-infrastructure/  deploy/    env1/      main.tf      backend.tf     ansible-vars.json       subnets.txt     env2/    ...  cm/    ...  modules/    azure/      main.tf      variables.tf  scripts/    env.sh    subnets.txt   .gitlab-ci.yml
  • deploy - содержит специфичные для каждого окружения файлы - файл с переменными для terraform и CM, файл содержащий адрес подсети стенда.

  • cm - в моём случае, тут хранятся Ansible плейбуки для настройки ОС и разворачивания сервисов.

  • modules - модули terraform которые будут получать в качестве параметров имя окружения и адрес подсети

  • scripts - bash сценарии для создания и удаления стендов и их конфигураций

.gitlab-ci.yml:

stages:  - create environment  - terraform apply  - cm  - destroy environment .template: variables: ENV: $NAME_ENV  when: manual tags: [cloudRunner01]  only:   refs:    - triggers Create environment:  stage:create environment  extends: .template script:   - ./scripts/create_env.sh -e $ENV -a create  artifacts:   paths:    - deploy/${ENV}/backend.tf    - deploy/${ENV}/main.tf    - deploy/${ENV}/vars.json Create instances:  stage: terraform apply extends: .template  script:   - cd ./deploy/$ENV   - terraform init -input=false   - terraform validate   - terraform plan -input=false -out=tf_plan_$ENV   - terraform apply -input=false tf_plan_$ENV Deploy applications:  stage: cm  extends: .template  script:   - # мы можем передать имя окружения в качестве параметра нашей CM   - # в моём случае, на основе переменной $ENV генерируются сертификаты,   - # конфигурируется обратный прокси сервер и т.п.   - # также мы можем использовать данные из terraform Destroy instances and environment:  stage:destroy environment  extends: .template  script:   - cd ./deploy/$ENV   - terraform init -input=false   - terraform destroy -auto-approve   - ./scripts/delete_env.sh -e $ENV -a delete 

Остановимся подробнее на каждом шаге нашего пайплайна:

  • Create environment - на основе имени окружения, полученного из переменно NAME_ENV, создаём уникальные для окружения файлы, после чего помещаем их в наш git репозиторий.

  • Create instances - создаём инстансы(виртуальные машины) и подсети, которые будут использоваться окружением.

  • Deploy applications - разворачиваем наши сервисы с помощью любимого Configuration Manager.

  • Destroy instances and environment - с помощью bash сценария данный шаг удалит наши инстансы, после чего удалит из репозитория каталог с файлами окружения. Освободившаяся подсеть будет возвращена в файл scripts/subnets.txt.

Запуск пайплайна происходит с объявлением переменной NAME_ENV, содержащей имя нового стенда:

Разработчики не имеют доступа к Git репозиторию и могут вносить в него изменения только через запуск pipeline.

modules/base/main.tf:

# лучшие практики и личный опыт настоятельно рекомендуют фиксировать версию провайдера provider "azurerm" { version = "=1.39.0" }  # создаём новую группу ресурсов, это особенность Azure. Имя группы уникально, в этом случае будет удобно использовать имя окружения resource "azurerm_resource_group" "product_group" { name= "${var.env_name}" location = "East Europe" } # создаем сеть resource "azurerm_virtual_network" "vnet" { name= "product-vnet" resource_group_name = azurerm_resource_group.product_group.name location= azurerm_resource_group.product_group.location address_space= [var.vnet_address] } #используем подсеть полученную с помощью bash сценария resource "azurerm_subnet" "subnet" { name= "product-subnet" resource_group_name= azurerm_resource_group.product_group.name virtual_network_name = azurerm_virtual_network.vnet.name address_prefix= var.subnet_address } # теперь можем создать виртуальную машинуresource "azurerm_virtual_machine" "product_vm" { name= "main-instance" location= azurerm_resource_group.product_group.location resource_group_name= azurerm_resource_group.product_group.name network_interface_ids = [azurerm_network_interface.main_nic.id]   } # прочие ресурсы и виртуальные машины... 

Чтобы сократить листинг я убрал большую часть обязательных, но, в нашем случае, неважных ресурсов.

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

scripts/env.sh:

#!/bin/bash set -eu CIDR="24" DEPLOY_DIR="./deploy" SCRIPT_DIR=$(dirname "$0") usage() { echo "Usage: $0 -e [ENV_NAME] -a [create/delete]" echo "-e: Environment name" echo "-a: Create or delete" echo "-h: Help message" echo "Examples:" echo "$0 -e dev-stand-1 -a create" echo "$0 -e issue-1533 -a delete" } while getopts 'he:a:' opt; do case "${opt}" in e) ENV_NAME=$OPTARG ;; a) ACTION=$OPTARG ;; h) usage; exit 0 ;; *) echo "Unknown parameter"; usage; exit 1;; esac done if [ -z "${ENV_NAME:-}" ] && [ -z "${ACTION:-}" ]; then usage exit 1 fi # приводим имя окружения к нижнему регистру ENV_NAME="${ENV_NAME,,}" git_push() { git add ../"${ENV_NAME}" case ${1:-} in create) git commit -am "${ENV_NAME} environment was created" git push origin HEAD:"$CI_COMMIT_REF_NAME" -o ci.skip echo "Environment ${ENV_NAME} was created.";; delete) git commit -am "${ENV_NAME} environment was deleted" git push origin HEAD:"$CI_COMMIT_REF_NAME" -o ci.skip echo "Environment ${ENV_NAME} was deleted.";; esac } create_env() { # создаём каталог для нового окружения if [ -d "${DEPLOY_DIR}/${ENV_NAME}" ]; then echo "Environment ${ENV_NAME} exists..." exit 0 else mkdir -p ${DEPLOY_DIR}/"${ENV_NAME}" fi # получаем адрес подсети NET=$(sed -e 'a$!d' "${SCRIPT_DIR}"/subnets.txt) sed -i /"$NET"/d "${SCRIPT_DIR}"/subnets.txt echo "$NET" > ${DEPLOY_DIR}/"${ENV_NAME}"/subnets.txt if [ -n "$NET" ] && [ "$NET" != "" ]; then echo "Subnet: $NET" SUBNET="${NET}/${CIDR}" else echo "There are no free subnets..." rm -r "./${DEPLOY_DIR}/${ENV_NAME}" exit 1 fi   pushd "${DEPLOY_DIR}/${ENV_NAME}" || exit 1 # Создаем main.tf terraform файл с нужными нам переменными нового окружения cat > main.tf << END module "base" { source = "../../modules/azure" env_name = "${ENV_NAME}" vnet_address = "${SUBNET}" subnet_address = "${SUBNET}" } END # Cоздаём backend.tf terraform файл , в котором указываем имя нового state файла cat > backend.tf << END terraform { backend "azurerm" { storage_account_name = "terraform-user" container_name = "environments" key = "${ENV_NAME}.tfstate" } } END } delete_env() { # удаляем каталог окружения и высвобождаем подсеть if [ -d "${DEPLOY_DIR}/${ENV_NAME}" ]; then NET=$(sed -e '$!d' ./${DEPLOY_DIR}/"${ENV_NAME}"/subnets.txt) echo "Release subnet: ${NET}" echo "$NET" >> ./"${SCRIPT_DIR}"/subnets.txt pushd ./${DEPLOY_DIR}/"${ENV_NAME}" || exit 1 popd || exit 1 rm -r ./${DEPLOY_DIR}/"${ENV_NAME}" else echo "Environment ${ENV_NAME} does not exist..." exit 1 fi } case "${ACTION}" in create) create_env git_push "${ACTION}" ;; delete) delete_env git_push "${ACTION}" ;; *) usage; exit 1;; esac 
  1. Сценарий env.shпринимает два параметра - имя окружения и действие(создание\удаление).

  2. При создании нового окружения:

  3. В каталоге DEPLOY_DIRсоздаётся директория с именем окружения.

  4. Из файла scripts/subnets.txt мы извлекаем одну свободную подсеть.

  5. На основе полученных данных генерируем конфигурационные файлы для Terraform.

  6. Для фиксации результата отправляем каталог с файлами окружения в git репозиторий.

  7. При удалении -сценарий удаляет каталог с файлами окружения и возвращает освободившуюся подсеть в файл scripts/subnets.txt

scripts/subnets.txt:

172.28.50.0172.28.51.0172.28.52.0...

В данном файле мы храним адреса наши подсетей. Размер подсети определяется переменной CIDR в файлеscripts/create_env.sh

Результат

  1. Мы получили фундамент который позволяет нам развернуть новый стенд путём запуска piplinea в Gitlab CI.

  2. Снизили затраты нашей компании на инфраструктуру.

  3. Разработчики не простаивают и могут создавать и удалять стенды когда им это потребуется.

  4. Также получили возможность создания виртуальных машин в любом облаке написав новый модуль Terraform и немного модифицировав сценарий созданиях\удаления окружений

  5. Можем поиграться с триггерами Gitlabи разворачивать новые стенды из пайплайнов команд разработчиков передавая версии сервисов.

Источник: habr.com
К списку статей
Опубликовано: 23.03.2021 08:12:20
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

It-инфраструктура

Devops

Terraform

Gitlab-ci

Bash

Development

Infrastructure

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru