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

Recovery mode DevOps автоматизация инфраструктуры на примере Terraform, docker, bash, prometheus exporters, Gitlab и WireGuard

Всем привет.

Есть такие люди, которые работают с облачной инфраструктурой и не используют автоматизацию, потому что это долго, нужно вникать, а им надо фичи пилить. Накликали что-то там в UI, подключились по ssh, поставили всякого с помощью apt и т.д. и конфигурационные файлы ещё вручную поменяли. Документации конечно же написать времени не хватило или в ней много разных хитрых шагов и повторить настройку этой инфраструктуры в точности уже нельзя или очень сложно, а сервисы крутятся в проде. А потом человек забыл что и как делал в точности или вообще уволился.

Хочу показать на небольшом примере, что автоматизировать инфраструктуру, например в AWS, может быть достаточно просто и приятно, а получившийся результат достаточно прозрачен и сам по себе является документацией, т.к. это инфраструктура как код. Если конечно есть знания Terraform или желание его немного изучить.

К слову, крайне рекомендую для автоматизации много чего, но в особенности облачных провайдеров вроде AWS / GCP / Azure и т.д. использовать именно Terraform, т.к. это достаточно зрелый инструмент, у него большое сообщество и кроме всего прочего он поддерживает автоматизацию далеко не только каких-то облачных провайдеров, но и практически всего у чего есть API. К тому же инструмент open source и при желании можно реализовать что угодно самостоятельно. Для таких облаков, как AWS не рекомендую пытаться реализовывать автоматизации с помощью чистого питона и запросов к AWS API с помощью cli или Cloudformation.

Также у Terraform есть удобная возможность организовывать код в блоки называемые модулями и передавая в них только параметры легко создавать необходимое с другими настройками.

Для тех, кто совсем не знаком с Terraform упомяну, что если в одну папку положить несколько файлов с расширением .tf и запустить Terraform в этой папке, то Terraform прочитает и использует код из всех файлов, а не только одного. Это в том числе позволяет разбивать один большой main.tf файл с кучей ресурсов на какие-то удобные вам логические блоки.

Итак, например, встала задача развернуть vpn серверы WireGuard на базе Ubuntu 20.04 в нескольких регионах + немного мониторинга. Поддержка WireGuard сейчас есть в ядре linux, но дополнительные инструменты, которые можно поставить отдельно облегчают жизнь, поэтому поставим и их.

Весь код модуля выложен здесь.

Также этот модуль опубликован в реестре модулей здесь.

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

Итак, создаются необходимые для работы iam политики, роль и т.п.

Используем elastic ip, отдельный для сервера в каждом регионе, которые нужно прописать в dns для того, чтобы пользователь мог использовать единое имя для подключения к vpn серверу. Планировал использовать geo dns route53, чтобы при местоположении пользователя в оперделённом регионе ему бы отдавался ip vpn сервера в его регионе, но т.к. на этом проекте route53 пока не используется, то создание записей в нём пока не автоматизировал.

Создаются security groups с правилами, которые позволяют подключиться к vpn серверу извне по udp (Wireguard работает только по udp) + ssh + несколько портов для prometheus exporter'ов.

Создаётся собственно сервер / ec2 машина, но не просто отдельно стоящая, а входящая в auto scaling group, в данном примере в единственном варианте. Это сделано для того, чтобы если с сервером что-то не так, то Амазон автоматом пересоздаст его. Self healing.

Позже немного допилив конфигурацию и добавив в неё load balancer можно добиться того, для чего auto scaling groups отлично подходят: при повышенной нагрузке на какой-то из ресурсов сервера, например на cpu, можно реализовать автоматическое создание дополнительных vpn серверов, а соответственно при падении нагрузки уменьшать их количество.

Этот модуль можно использовать просто с Terraform, но лучше использовать Terragrunt, который позволяет делать некоторые удобные вещи и местами реализовывать концепцию Keep your Terraform code DRY, например параметризуя некоторые вещи в backend блоке, чего сам Terraform пока не умеет. Terraform хранит состояние инфраструктуры в специальном файле и принято хранить его не локально, а, чаще всего, в S3 бакете. Также, если вы работаете с этим кодом не в одиночку, то принято хранить локи в Dynamodb, чтобы случайно не применить какое-то изменение инфраструктуры несогласованно и не поломать всё.

Именно пример такого использования я привожу в примере здесь.

С помощью файла terragrunt.hcl в корне репозитория (https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/terragrunt.hcl) я могу, например, задать место для хранения state для всех поддиректорий, а потом ссылаться на этот файл в других terragrunt.hcl с помощью функции find_in_parent_folders() https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/us-east-1/terragrunt.hcl#L2

При этом key, т.е. файл, где будет храниться состояние инфраструктуры в конкретном регионе будет храниться отдельно, что достигается с помощью функции path_relative_to_include() https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/terragrunt.hcl#L11

Также я реализовал хранение/чтение переменных в yaml формате, что мне кажется более удобочитаемым с помощью функции yamldecode(file(...)) https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/eu-central-1/terragrunt.hcl#L9

Вот так выглядит пример передаваемых в модуль уникальных параметров (конечно YOUR_... нужно заменить на реальные значения): https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/us-east-1/values.yaml

Иногда удобно реализовать использование имени папки в качестве параметра, например в приведённом примере это мог бы быть параметр region и реализуется это с помощью, например, функций basename(get_terragrunt_dir()) и задавать его в values.yaml не пришлось бы, но по определённым причинам решил этого не делать.

В итоге в вашем приватном репозитории код из которого применяете либо вы, либо какой-то ci cd runner может лежать только содержимое похожее на мою папку example, т.е. только terragrunt.hcl и yaml файлы с параметрами, а модуль можно использовать как публичный и хорошо поддерживаемый, так и написать свой. Это позволяет отдать "пользователям" только задание параметров в yaml и в принципе ничего не знать про Terraform код.

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

Для того, чтобы изменения в коде open source модулей, как впрочем и в частных, не повлияли на работу вашей автоматизации принято фиксировать версии используемых модулей, например в моём коде это сделано с помощью source = "github.com/vainkop/terraform-aws-wireguard?ref=v1.2.0" здесь https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/eu-central-1/terragrunt.hcl#L6

Ну а если вы всё же не хотите зависеть от open source и чувствуете в себе силы поддерживать и развивать свой модуль самостоятельно, всегда можно форкнуть общественный и сделать всё, что хочется.

Например я реализовал cloud-init скрипт, который осуществляет предварительную установку и настройку софта на свежеразвёрнутый сервер и делает это каждый раз, когда сервер пересоздаётся в auto scaling group, что очень удобно: https://github.com/vainkop/terraform-aws-wireguard/blob/master/templates/user-data.txt

Ближе к концу скрипта устанавливается 2 prometheus exporter'а, которые позволяют как мониторить метрики самой ec2 машины, так и базовые метрики самого WireGuard, на основании которых можно построить удобные Dashboards и соответственно определённые alerts и т.п.

В частности я реализовал это для того, чтобы видеть к какому из vpn серверов подключён клиент, чтобы, например, была возможность подключиться к нему именно из его региона, т.к. связности между этими vpn серверами нет. Т.к. клиентские публичные ключи зашиты в каждый из серверов и серверные ключи одинаковые, то клиент будет автоматически переключаться между ними путешествуя между регионами на основании geo ip route53.

Также привожу пример кода из .gitlab-ci.yml и Dockerfile где можно увидеть какие команды используются для применения всего этого хозяйства с помощью Gitlab runner'а и какой docker контейнер можно использовать для этого runner'а.

$ cat .gitlab-ci.ymlstages:  - build  - plan  - apply  - destroyvariables:  GIT_DEPTH: 1.aws_configure: &aws_configure  before_script:    - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID    - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY    - aws configure set default.region $AWS_DEFAULT_REGIONbuild-terraform:  image: docker:19.03.15  services:    - docker:19.03.15-dind  stage: build  variables:    DOCKER_TLS_CERTDIR: ""    DOCKER_HOST: tcp://docker:2375    DOCKER_DRIVER: overlay2    TERRAFORM_VERSION: "0.13.6"    TERRAGRUNT_VERSION: "v0.28.9"  before_script:    - printenv    - docker info    - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin  script:    - cd docker    - docker build --build-arg TERRAFORM_VERSION=$TERRAFORM_VERSION --build-arg TERRAGRUNT_VERSION=$TERRAGRUNT_VERSION -t $CI_REGISTRY_IMAGE:$TERRAFORM_VERSION .    - docker push $CI_REGISTRY_IMAGE:$TERRAFORM_VERSION  rules:    - changes:        - docker/*plan-us-east-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: plan  <<: *aws_configure  script:    - cd wireguard/us-east-1    - terragrunt run-all plan --terragrunt-non-interactive -out $CI_PROJECT_DIR/wireguard/us-east-1/tfplan-$CI_COMMIT_SHA  artifacts:    paths:    - $CI_PROJECT_DIR/wireguard/us-east-1/tfplan-$CI_COMMIT_SHA    expire_in: 1 month  rules:    - changes:        - wireguard/us-east-1/*      allow_failure: trueplan-eu-central-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: plan  <<: *aws_configure  script:    - cd wireguard/eu-central-1    - terragrunt run-all plan --terragrunt-non-interactive -out $CI_PROJECT_DIR/wireguard/eu-central-1/tfplan-$CI_COMMIT_SHA  artifacts:    paths:    - $CI_PROJECT_DIR/wireguard/eu-central-1/tfplan-$CI_COMMIT_SHA    expire_in: 1 month  rules:    - changes:        - wireguard/eu-central-1/*      allow_failure: trueapply-us-east-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: apply  <<: *aws_configure  script:    - cd wireguard/us-east-1    - terragrunt run-all apply --terragrunt-non-interactive -auto-approve $CI_PROJECT_DIR/wireguard/us-east-1/tfplan-$CI_COMMIT_SHA  rules:    - changes:        - wireguard/us-east-1/*      when: manual      allow_failure: trueapply-eu-central-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: apply  <<: *aws_configure  script:    - cd wireguard/eu-central-1    - terragrunt run-all apply --terragrunt-non-interactive -auto-approve $CI_PROJECT_DIR/wireguard/eu-central-1/tfplan-$CI_COMMIT_SHA  rules:    - changes:        - wireguard/eu-central-1/*      when: manual      allow_failure: truedestroy-us-east-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: destroy  <<: *aws_configure  script:    - cd wireguard/us-east-1    - terragrunt run-all destroy --terragrunt-non-interactive -auto-approve  rules:    - changes:        - wireguard/us-east-1/*      when: manual      allow_failure: truedestroy-eu-central-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: destroy  <<: *aws_configure  script:    - cd wireguard/eu-central-1    - terragrunt run-all destroy --terragrunt-non-interactive -auto-approve  rules:    - changes:        - wireguard/eu-central-1/*      when: manual      allow_failure: true
$ cat docker/DockerfileFROM ubuntu:20.04USER rootARG DEBIAN_FRONTEND=noninteractiveARG TERRAFORM_VERSIONENV TERRAFORM_VERSION=$TERRAFORM_VERSIONARG TERRAGRUNT_VERSIONENV TERRAGRUNT_VERSION=$TERRAGRUNT_VERSIONRUN set -x && \    apt-get update && \    apt-get install -y \    apt-transport-https \    ca-certificates \    build-essential \    software-properties-common \    unzip \    net-tools \    wget \    curl \    python3 \    python3-dev \    python3-pip \    jq \    gettext-base \    git && \    rm -rf /var/lib/apt/lists/*RUN set -x && \    apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CC86BB64 && \    add-apt-repository ppa:rmescandon/yq && \    apt update && \    apt install -y yq && \    rm -rf /var/lib/apt/lists/*RUN set -x && \    pip3 install -U --no-cache-dir setuptools shyamlRUN set -x && \    ln -sf /usr/bin/python3 /usr/bin/python && ln -sf /usr/bin/pip3 /usr/bin/pipRUN set -x && \    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \    unzip awscliv2.zip && \    rm awscliv2.zip && \    ./aws/installRUN set -x && \    cd /tmp && \    curl -O https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \    unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /usr/local/bin && \    chmod +x /usr/local/bin/terraform && \    rm /tmp/terraform_${TERRAFORM_VERSION}_linux_amd64.zipRUN set -x && \    wget "https://github.com/gruntwork-io/terragrunt/releases/download/${TERRAGRUNT_VERSION}/terragrunt_linux_amd64" && \    mv terragrunt_linux_amd64 /usr/local/bin/terragrunt && \    chmod +x /usr/local/bin/terragruntRUN set -x && \    curl --version && \    envsubst --version && \    python --version && \    pip --version && \    shyaml --version && \    jq -V && \    yq -V && \    aws --version && \    terraform --version && \    terragrunt --versionENTRYPOINT ["/bin/bash", "-c"]

За код не ругайте, написал за несколько часов и решил поделиться.

Если есть конкретные замечания/предложения, то готов их выслушать либо в комментариях, либо в личке, например, в телеграм: @vainkop

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

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

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

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

Системное администрирование

Программирование

Git

Разработка под linux

Devops

Terraform

Iac

Docker

Prometheus

Bash

Aws

Terragrunt

Linux

Gitlab

Категории

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

  • Имя: Макс
    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