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

Terraform

Перевод Как я сломал и починил кластер Kubernetes, работающий на Raspberry Pi

21.04.2021 20:21:36 | Автор: admin

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

Мой домашний кластерёнок вырос в зрелый кластер из шести нод (всё благодаря супруге, которая знала, что мне подарить на день рождения, естественно, Raspberry Pi, и не один!), и я встал перед выбором либо ещё раз выполнить собственные инструкции из статьи об установке кластера Kubernetes на Raspberry Pi, либо, применив системную инженерию (DevOps и SRE), полностью автоматизировать процессы переделки кластера и создания системы управления кластером. Эту статью можно считать прямым дополнением к моей первой статье Как я собрал домашний кластер Kubernetes на базе Raspberry Pi.


Соображения о времени и трудозатратах

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

Вариант 1

Встать с утра пораньше и повторить все операции вручную в соответствии с инструкциями из моей собственной статьи и, возможно, кое-что в процессе улучшить.

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

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

Вариант 2

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

Конечно, для этого потребуется куда больше времени. Но светят и долгосрочные преимущества: мне больше не надо будет заботиться о самом кластере, я буду знать, что это решение стабильно и можно перенести на него всю свою домашнюю инфраструктуру.

Хроника автоматизации. Начало

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

Принцип 1. Настройка кластера Kubernetes на Raspberry Pi выполняется в три этапа: это настройка карты памяти, настройка нод на системном уровне и развёртывание ресурсов Kubernetes.

Принцип 2. На моём старом Intel NUC работает NFS-сервер, подключённый к хранилищу DROBO. Было бы заманчиво использовать его в качестве постоянного общего хранилища для всех нод.

Принцип 3. Кластер Raspberry Pi работает в моей домашней сети VLAN, поэтому вопросы безопасности меня волнуют не особо. Все службы и ноды должны быть легко доступны без всяких хитростей с именами и паролями.

Итак, держа всё это в голове, я приступил к программированию моего маленького Франкенштейна. Для повторения результатов (то есть для того, чтобы система заработала) вам понадобятся:

  • Mac (для форматирования карты). Если выберу время для установки Linux VM, попытаюсь обновить скрипт обнаружения платформы.

  • Ansible (я использовал версию 2.10.6).

  • Terraform (я использовал версию 0.13.4, но 0.14.8 тоже подойдёт).

  • Make, полезный инструмент, чтобы не колдовать над параметрами.

Кластер rPi. Первый шаг

В качестве жёсткого диска Raspberry Pi использует карту памяти. Возможно, это не вполне оптимальное и не самое быстрое решение для чтения и записи, но его должно быть достаточно для игр и любительских проектов.

Что происходит на первом шаге?

  • Форматируется карта памяти.

  • Карта памяти делится на два раздела: 1 ГБ плюс то, что останется.

  • Образ Alpine Linux копируется на карту памяти.

  • Создаётся системный оверлей.

Системный оверлей настраивает eth0 на "неразборчивый" (promisc) режим, это нужно для работы MetalLB, и разрешает подключение SSH к нодам Raspberry Pi без пароля.

Важно: проверьте источник 001-prepare-card.sh и убедитесь, что /dev/disk5 это именно вставленная карта памяти, иначе можно потерять данные.

Результат: подготовка шести карт памяти займёт около одной минуты.

Кластер rPi. Второй шаг

Начинается самое интересное. Итак, вы вставили в Raspberry Pi карты памяти, подсоединили все кабели (сетевые и питания) и загрузили систему. Теперь нужно получить IP-адреса устройств. Это можно сделать, либо подключив экран к каждому из них и запустив команду ifconfig eth0, либо зайдя в маршрутизатор и проверив информацию на нём. Введите в файл pi-hosts.txt соответствующие значения.

[masters]pi0 ansible_host=192.168.50.132 # Pi0[workers]pi1 ansible_host=192.168.50.135 # Pi1pi3 ansible_host=192.168.50.60  # Pi3pi4 ansible_host=192.168.50.36  # Pi4pi2 ansible_host=192.168.50.85  # Pi2pi5 ansible_host=192.168.50.230 # Pi5

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

Добавьте в файл ~/.ssh/config следующую строку, она даст root-доступ для всех нод с именами pi*.

Host pi?  User root  Hostname %h.local

Теперь наши микровычислители (вот видите, насколько я стар!) готовы, и нам нужно подготовить их к запуску Ansible. Это можно легко сделать с помощью скрипта 001-prepare-ansible.sh, который подключиться по ssh к каждому определённому в файле pi-hosts серверу, на каждом сервере настроит chrony для NTP и установит интерпретатор Python.

Важно: возможно, потребуется открыть файл rpi.yaml и изменить раздел vars в соответствии с вашими предпочтениями. Я поступил именно так.

После этого шага запускаем на Ansible команду ansible-playbook rpi.yaml -f 10, которая выполнит следующие действия:

ОБЩИЕ:

  • Установит необходимые пакеты.

  • Разобьёт на разделы и отформатирует карту памяти RPI.

  • Настроит параметры "большого" раздела как системного диска.

  • Добавит записи в файл fstab.

  • Подтвердит изменения.

  • Перезапустит Pi, чтобы тот загрузился с "постоянного" раздела.

KUBEMASTER:

  • Настроит мастер-ноду с помощью kubeadm.

  • Сохранит токены локально (в файле static/token_file).

  • Определит на Pi пользователя с правами root с доступом к kubectl.

  • Сохранит настройки Kubernetes локально (в файле static/kubectl.conf).

KUBEWORKER:

  • Скопирует токены на рабочие ноды.

  • После этого через файл токенов рабочие ноды будут присоединены к мастер-ноде.

  • Скопирует kubectl.conf на root-пользователей рабочих нод.

БАЗОВЕ:

  • Снимет отметку с мастер-ноды, что позволит ей принимать рабочие нагрузки.

  • Установит на ноды py3-pip, PyYaml и Helm.

Если вы дошли до этого места, мои поздравления! Вы только что создали базовый кластер Kubernetes, который делать пока ничего не умеет, но готов научиться, если уделить ему немного внимания. Всё оказалось довольно элементарно нужно просто запустить несколько скриптов и дождаться их завершения. Я считаю, что это определённо лучшее решение, чем возиться руками.

Важно: скрипты можно запускать сколько угодно раз. Переформатировать карты памяти после каждого раза не нужно.

Результат: подготовка шести нод с базовой установкой Kubernetes занимает пару минут, в зависимости от скорости подключения к Интернету.

Кластер rPi. Третий шаг

После успешного выполнения двух предыдущих шагов кластер Pi готов к первым развёртываниям. Настройка осуществляется в несколько шагов, и, конечно, эти шаги также можно автоматизировать, об этом позаботится Terraform.

Вначале посмотрим на конфигурацию.

# Variables used for barebone kubernetes setupnetwork_subnet    = "192.168.50"net_hosts = {  adguard = "240"  adguard_catchall = "249"  traefik = "234"  torrent_rpc = "245"}nfs_storage = {  general = "/media/nfs"  torrent = "/mnt/drobo-storage/docker-volumes/torrent"  adguard = "/mnt/drobo-storage/docker-volumes/adguard"}# ENV variable: TRAEFIK_API_KEY sets traefik_api_key# ENV variable: GH_USER, GH_PAT for authentication with private containers

Кластер запускается в сети по адресу 192.168.50.0/24, но по умолчанию MetalLB будет использовать "конец" пула сетевых адресов с адресами 200-250. Поскольку у меня есть домашний торрент-сервер и DNS от Adguard, мне нужно задать для них конкретные адреса. Также мне нужен обслуживающий дашборды и прочие инструменты балансировщик нагрузки Traefik.

Важные замечания:

Значения nfs_*_path должны быть совместимы с настройками, заданными на втором шаге.

Убедитесь, что в конфигурационный файл Kubernetes ~/.kube/config is добавлены данные из файла static/kubernetes.conf. В качестве контекстного имени я использую home-k8s.

Что делает Terraform?

Устанавливает flannel, а также патч конфигурационных параметров для host-gw; устанавливает metalLB и задает сетевые параметры var.network_subnet 200250.

Устанавливает прокси Traefik и открывает к нему доступ в домашней сети через балансировщик нагрузки metalLB. Доступ к самому дашборду Traefik осуществляется по traefik.local.

Дашборд Traefik запускается на кластере Pi.Дашборд Traefik запускается на кластере Pi.

Устанавливает DNS-службу Adguard с запросами к хранилищам данных (persistent volumes claims) с использованием NFS; открывает доступ к дашборду (adguard.local) через Traefik и к самой службе через выделенный в домашней сети IP-адрес.

Adguard Home запускается на кластере Pi.Adguard Home запускается на кластере Pi.

Устанавливает и развёртывает на всех нодах стек мониторинга Prometheus и Grafana. Вносит изменения в DaemonSet Prometheus, устраняя необходимость в монтировании томов. Также через Traefik определяет Grafana как grafana.local. Имя и пароль пользователя Grafana по умолчанию admin:admin. В Grafana уже есть предустановленный плагин devopsprodigy-kubegraf-app. Я считаю его лучшим для мониторинга кластеров.

На кластере Pi запускается дашборд Grafana.На кластере Pi запускается дашборд Grafana.

Устанавливает дашборд Kubernetes и через Traefik определяет его как k8s.local.

Дашборд Kubernetes запускается на кластере Pi.Дашборд Kubernetes запускается на кластере Pi.

Устанавливает и развёртывает торрент-сервер (rTorrent) с веб-интерфейсом Flood. Дашборд отображается как torrent.local. Для хранения данных (в том числе конфигурационных) дашборд использует множество точек монтирования. Причина, по которой значение репликации должно быть установлено в 1, объясняется просто. У rTorrent есть проблемы с файлами блокировки, и, поскольку эта программа использует разделяемый каталог, она просто не запустится, если будет обнаружен файл блокировки. У меня rTorrent настроен на прослушивание на порте 23340.

Поскольку Raspberry Pi запускается с карты памяти, эта карта из-за постоянных операций чтения-записи со временем может выйти из строя. Поэтому я решил регулярно делать резервные копии etcd на NFS. Программа резервного копирования запускается раз в сутки с параметрами, устанавливаемыми Terraform. Каждая резервная копия весит около 32 мегабайт.

Запуск Terraform

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

TRAEFIK_API_KEY // Traefik API keyGH_USER // Github userGH_PAT // Github Personal Access Token

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

ADDITIONAL_ARGS=-var 'traefik_api_key=$(TRAEFIK_API_KEY)' -var "github_user=$(GH_USER)" -var "github_pat=$(GH_TOKEN)"apply:cd infrastructure; terraform apply $(ADDITIONAL_ARGS) -auto-approve -var-file ../variables.tfvarsplan:cd infrastructure; terraform plan $(ADDITIONAL_ARGS) -var-file ../variables.tfvarsdestroy:cd infrastructure; terraform destroy $(ADDITIONAL_ARGS) -var-file ../variables.tfvarsdestroy-target:cd infrastructure; terraform destroy $(ADDITIONAL_ARGS) -var-file ../variables.tfvars -target $(TARGET)refresh:cd infrastructure; terraform refresh $(ADDITIONAL_ARGS) -var-file ../variables.tfvarsinit:cd infrastructure; rm -fr .terraform; terraform initimport:cd infrastructure; terraform import $(ADDITIONAL_ARGS) -var-file ../variables.tfvars $(ARGS)lint:terraform fmt -recursive infrastructure/

Заключительные замечания

Полный код можно взять на GitHub. Им можно свободно пользоваться и менять как угодно (как обычно, ваши комментарии и замечания горячо приветствуются). Я также опубликовал переделанные образы Docker (rTorrent и Flood) с multiarch-архитектурой, поддерживающей процессоры ARM64. Я довольно часто вычищаю весь кластер и делаю сборку с нуля, используя упомянутый репозиторий, а по мере появления новых функций я буду вносить в него соответствующие изменения.

Автоматизация экономит время и нервы и надо признать! хорошо выполняет свою работу. Именно поэтому DevOps-инженеров так ценят на рынке (зарплаты с пятью нулями в месяц уже обычное дело). Если хотите так же приходите учиться, помимо современных учебных программ, у нас есть менторы из ведущих компаний Рунета, которые поделятся с вами своим практическим опытом.

Узнайте, как прокачаться и в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Что такое Immutable Infrastructure

02.09.2020 12:08:46 | Автор: admin

Меня зовут Никита, я системный инженер в компании SEMrush. И в этой статье я расскажу вам, что такое Immutable Infrastructure, какие у этого подхода есть преимущества и недостатки и как мы его используем в компании.



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


Что это такое


Immutable Infrastructure подход к созданию неизменяемой инфраструктуры. Идея его не нова в мире, хоть и не слишком распространена. Мы начали его использовать, когда поняли, что не все можно запустить в Kubernetes, и нам нужны виртуальные машины.


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


Ниже мы рассмотрим преимущества и недостатки этого подхода, но прежде я хотел бы вставить небольшую оговорку.


Мы в компании активно используем облако GCP, поэтому не админим железо, на котором запускаются виртуалки. У GCP есть мощный API и множество SaaS продуктов, использование которых делает возможным применение Immutable подхода. Если у вас KVM-хосты, и вы выкатываете виртуалки скриптиком, то вряд ли вам подойдет такое решение. Но при использовании любого облака (Openstack, AWS, Azure и т.д.), можно имплементировать данный подход. Я опишу его применение совместно со всей мощью облака, где, например, создание виртуалки происходит POST-запросом, а увеличение диска производится на лету.


Преимущества Immutable


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


  1. Повторяемое окружение
    Обычно на сервер устанавливается операционная система определенной версии, настраивается окружение для приложения и происходит деплой самого приложения. Но если вы захотите через какое-то время развернуть точно такой же сервер с вашим приложением, то точно такой же у вас никак не получится: какие-то пакеты устарели, на другие пакеты выпущены security патчи, ядро уже тоже обновилось. В итоге вы получаете два похожих сервера. И вот эта разница часто является ключевой и может привести к багам и ошибкам. С Immutable Infrastructure у вас всегда есть образ виртуальной машины, который точно запустится и будет повторять реальное окружение точь-в-точь. В нем уже все предустановлено: все системные пакеты и библиотеки одной версии, а окружение приложения не изменится со временем. Вы можете повторно развернуть или масштабировать сервис спустя годы, лишь бы у вас был образ.
  2. Инфраструктура как код
    Immutable infrastructure всегда описана как код, потому что на каждый коммит (релиз) нам нужно создавать новый образ виртуальной машины, а также проводить его через пайплайны CI/CD. Это не получится делать руками.
  3. Неизменяемое окружение
    Как и в случае с Docker контейнером, виртуальная машина не может быть изменена. Не придет какой-нибудь configuration management инструмент или unattended upgrades, которые установят новые версии пакетов и все сломают. Там просто нет этих механизмов. Они не нужны и даже специально отключаются, потому что все, что нужно для функционирования приложения, уже установлено в системе. Окружение неизменяемо во времени и всегда одно и то же, пока не произошел релиз новой версии приложения.
  4. Отсутствие configuration drift
    Может быть такое, что у вас есть 100 серверов, на которые нужно вылить новый апдейт, и на несколько из них выкладка зафейлилась по какой-то причине. Тогда ваша конфигурация разъезжается, и вы не имеете одинакового окружения на всех машинах в вашей системе. Или у вас работает unattended upgrade, который периодически ставит обновления безопасности, и где-то ему удалось поставить пакет, а где-то нет. Immutable же гарантирует неизменяемость виртуалок во времени, а также то, что на них одна одинаковая версия всех приложений, зависимостей и операционной системы.
  5. Независимость от внешних источников
    В ходе настройки окружения приложению необходимы различные зависимости, которые тянутся из внешних источников. Если внешний источник недоступен, то создание новых инстансов может быть зафейлено. С Immutable такого не произойдет. Все зависимости уже установлены в образе, что гарантирует работоспособность приложения после старта. С таким подходом мы выносим failure point на этап билда образа, а не на этап деплоя, когда что-то пошло не так при обновлении на production VM. После того, как образ собран, мы точно знаем, что виртуалка рабочая, и осталось задеплоить ее как обычно.
  6. Отсутствие устаревших систем
    С Immutable нет проблемы "старых" серверов с высоким аптаймом, которые страшно не только обновить, но и даже перезагрузить. Любое изменение это новый билд образа и новая виртуалка.
  7. Простое масштабирование
    Всегда есть некий срез во времени вашего приложения, поднять новый инстанс которого можно по щелчку пальцев.
  8. Все плюсы облака
    В облаке дешево и легко создавать новые ресурсы, запрашивать столько CPU и RAM, сколько необходимо. Кроме того, можно интегрировать виртуалки с другими сервисами GCP: Load balancers, GCS для бэкапов, Autoscaler, Cloud SQL и т.д.
  9. Трансформация разработки
    Такой подход к инфраструктуре и осознание того, что инфраструктурная часть неотделима от самого кода и приложения, что минимальная единица это виртуальная машина, заставляет изменить и подход к разработке приложения. Нужно проектировать свое приложение исходя из того, что оно будет immutable. Приложение должно "осознавать" свою эфемерность и быть готовым быть замененным новой версией самого себя. Деплой таких приложений тоже отличается, поэтому нужно предусмотреть нюансы на этапе проектирования.
  10. Базовые образы
    Можно создать образы виртуальных машин различных ОС с предустановленным ПО, которые будут являться базовыми. Далее их можно расширять, устанавливая туда конкретные приложения и окружения для них. Все по аналогии с Docker образами.
  11. Простые откаты
    Чтобы откатиться на предыдущую версию, достаточно просто поднять виртуалку с предыдущим образом. Как будто бы запускаешь контейнер.
  12. Идентичные окружения
    Вы собираете новый образ виртуальной машины и запускаете его в Dev окружении на тестирование. Если тестирование прошло успешно, вы запускаете ТОТ ЖЕ САМЙ ОБРАЗ (только с другим конфигом для provisioner) в Prod окружении.

Но есть нюансы


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


  1. Более сложный деплой
    Immutable подразумевает, что каждый раз при любом изменении вы создаете новый образ, на основе которого запускаете виртуалку. После этого вам может понадобится сконфигурировать приложение (чтобы оно получило свои переменные, конфиги, вступило в кластер и т.д.). Это все необходимо автоматизировать и это может быть достаточно сложно. Пайплайн обновления и его логика могут получаться развесистыми.
  2. Даунтайм при обновлениях
    Если есть приложение, которое крутится на виртуалке и использует какие-то данные, хранящиеся локально, то выкладка новой версии приложения подразумевает ряд процессов: выключение текущей виртуалки, отсоединение от нее диска, поднятие нового инстанса, подключение диска к нему. Понятно, что это ведет к даунтайму (по правде сказать, в таком случае перерыв в работе сервиса, но просто более короткий, был бы даже если бы и не использовался Immutable подход). Узкие места: единственный инстанс и локальный storage. Решить это можно через системы динамической конфигурации, несколько инстансов (горячий, холодный резерв или одновременная работа), удаленный storage (но тут уже будет возможный downgrade производительности дисковой подсистемы). Все это зависит от конкретного кейса и архитектуры приложения. Если это Stateless воркеры, то для них данная концепция подходит как никакая другая. А у нас, например, на инфраструктурных сервисах есть SLA, в рамках которого мы иногда можем сделать даунтайм для обновления.
  3. Отсутствие постоянных апдейтов
    Как это ни странно, но у Immutable есть обратная сторона своего же преимущества это отсутствие постоянных апдейтов, security патчей и т.д., которые в обычной системе могут быть настроены на автоматическую установку. В образе не обновится ничего, пока вы не соберете и не задеплоите обновленный вами образ.

Выше я описал данный подход как идеальный случай. Мы стараемся придерживаться Immutable идеологии по максимуму, но на сколько полно получится реализовать идею, зависит от приложения, его сложности, архитектуры, особенностей деплоя и т.д. Иногда не получится автоматизировать прям всё-всё (или это будет дорого и трудозатратно), поэтому всегда нужно придерживаться здравого смысла. Не надо делать Immutable ради Immutable. В первую очередь нужно понимать, какие преимущества вы получите и достаточно ли их. И готовы ли вы к недостаткам.


Push и Pull модели


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


Push


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


Pull


При таком подходе может работать автоскейлинг, а виртуалки будут в инстанс группе (ну или использовать схожий механизм). Это значит, что создание новой виртуалки будет происходить автоматически, а не по воли оператора или процесса CI. Новосозданная машина должна иметь в себе все необходимое для само конфигурации. То есть конфигурация происходит изнутри пуллится самой виртуалкой (в себя).


В зависимости от модели нужно по-разному подходить к проектированию CI/CD пайплайна и процесса деплоя.


В главных ролях


При работе с неизменяемой инфраструктурой нам помогают эти инструменты:


  1. Packer программа от Hashicorp, которая позволяет создавать образы виртуальных машин, на базе разных облачных провайдеров. Packer берет указанный базовый образ, создает из него виртуалку в нужном облачном провайдере, накатывает в нее конфигурацию с помощью любого из множества провижинеров, а в конце создает из ее диска установочный образ, который можно использовать в выбранном облаке.
  2. Terraform еще одна утилита от Hashicorp, которая, наверное, уже не нуждается в представлении. Позволяет описать необходимые инфраструктурные ресурсы нужного облачного провайдера и, используя этот манифест, приводит конфигурацию облака к описанному в конфиге.
  3. Ansible инструмент, с которым также знакомы почти все. Он нам нужен для того, чтобы делать provision образа и создаваемой виртуалки настраивать окружение.
  4. Gitlab CI мы используем Gitlab, поэтому и всю автоматизацию пишем на нем.
  5. GCP собственно, облако, которое делает запуск виртуалки легким и простым, а также позволяет создавать множество других ресурсов.

Immutable Images


Образ VM является основным артефактом деплоя. У нас есть собственные базовые образы, которые собираются на основе образов Google, специально заточенных под работу в их облаке, образы приложений с каким-то предустановленным, но не сконфигуренным ПО (nginx, mysql, mongodb и т.д.), и продуктовые образы. Последние содержат в себе все необходимое для работы конкретного продукта или его компонента (это может быть образ с настроенной БД, вэб-сервером, бэкэндом). Как можно понять, каждый образ в иерархии базируется на каком-то родителе и расширяет его. Для конфигурации образов (подготовки окружения) мы используем Ansible отличный инструмент, позволяющий доставлять one-shot конфигурацию.


Если вы разрабатываете концепцию образов виртуальных машин, важно как можно раньше придумать и внедрить конвенцию именования образов. Имя образа должно четко и однозначно определять ОС, на базе которого он собран, и его основную функцию (ПО, его версия), для чего он был собран. Тогда в дальнейшем будет намного проще и удобнее с ними работать.


Image Family


У образа в GCP есть имя, метки, статус, а также принадлежность к какой-то Image Family.


Image Family удобный механизм, объединяющий все версии одного образа под одной "семьей". Это упрощает использование базовых образов если вам не нужно точно знать, какую вы используете версию образа, его название, которое включает дату и т.д., вы просто указываете image family, на базе которого вы хотите собраться, и все. Это аналог тега latest в докере.


Однако, если при сборке образа использование Image Family вполне оправдано, то при деплое вам обязательно нужно использовать Image Name и указывать конкретный образ, который вы хотите задеплоить (только что собранный). Как и latest в докере, использование family может привести к дрифту версий или неожиданным изменениям на проде.


Кратко принцип работы с Image Family выглядит так:
У вас есть image-v1 это самая последняя версия образа вашего приложения. my-image-family указывает на данный образ


gcloud compute images create image-v1 \    --source-disk disk-1 \    --source-disk-zone us-central1-f \    --family my-image-familygcloud compute images describe-from-family my-image-familyfamily: my-image-familyid: '50116072863057736'kind: compute#imagename: image-v1

Вы создаете новый образ image-v2, и теперь my-image-family указывает на него.


gcloud compute images create image-v2 \    --source-disk disk-2 \    --source-disk-zone us-central1-f \    --family my-image-familygcloud compute images describe-from-family my-image-familyfamily: my-image-familyid: '50116072863057756'kind: compute#imagename: image-v2

По какой-то причине нужно откатиться на предыдущую версию, и теперь my-image-family снова указывает на image-v1:


gcloud compute images deprecate image-v2 \    --state DEPRECATED \    --replacement image-v1gcloud compute images describe-from-family my-image-familyfamily: my-image-familyid: '50116072863057736'kind: compute#imagename: image-v1

Обновление и ротация базовых образов


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


У образов виртуальных машин в GCP есть текущее состояние:
READY образ готов к использованию
DEPRECATED образ признан deprecated. Такие образы не отображаются в веб-консоли по-умолчанию, но доступны для gcloud и terraform. В случае их использования выдается предупреждение.
OBSOLETE образ в этом статусе уже недоступен для использования.
DELETED образ помечен удаленным, но еще существует физически.
REALLY_DELETED такого статуса в реальности нет, но спустя некоторое время, как образ был помечен DELETED, он будет удален по-настоящему.


Используя эти статусы, мы создали процесс ротации образов. На картинке ниже представлен жизненный цикл образа и его основные этапы.



Для базовых образов мы делаем автообновление. Раз в сутки производится автоматическая проверка наличия обновления пакетов, входящих в состав образа. Если обновления найдены, производится сборка новой версии образа и указатель image-family сдвигается на нее. После этого происходит ротация всех образов, относящихся к данной image-family.


Для автоматизации жизненного цикла мы написали скрипт image-rotator, который в ближайшее время мы выложим в публичный доступ (в статью будет добавлена ссылка). Его принцип работы следующий:


  1. Скрипту передаются нужные переменные, главной из которых является --image-family. Так он понимает, с чем ему нужно работать
  2. Скрипт находит все образы, принадлежащие данной Image Family, и дальше работает со всеми этими образами КРОМЕ последнего актуального образа, на который указывает Image Family в данный момент
  3. Далее среди этих образов он делает следующее:
    • Все READY образы делает DEPRECATED и проставляет им дату, когда они должны стать OBSOLETE
    • Все DEPRECATED образы, у которых дата obsolete меньше текущей даты, переводит в состояние OBSOLETE и выставляет дату, когда образ должен стать DELETED
    • Все OBSOLETE образы обрабатывает по аналогии с DEPRECATED
    • То же самое с DELETED. Если у DELETED образа подошла дата удаления, то скрипт удаляет образ навсегда

Схема пайплайна


Итак, теперь, когда мы разобрались с основными моментами, можно рассмотреть общий процесс деплоя.


На рисунке ниже, схематично, представлен данный процесс.


Мы подразумеваем, что сначала деплоим приложение в Dev-среду из Master-ветки (название ветки здесь не принципиально), где оно тестируется. После чего, деплоим тот же самый образ на Prod-окружение из другой ветки stable, посредством синхронизации двух веток через Merge Request.


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


  • Интеграция с Hashicorp Vault для получения секретов
  • Использование снапшотов дисков с данными Prod-инстанса для создания Dev окружения
  • Использование последнего бэкапа CloudSQL (примечание: база данных как сервис от Google (MySQL, PostgreSQL)) Prod-инстанса для создания базы данных в Dev-окружении
  • Удаление Dev-окружения в конце тестирования (это же облако, нам не хочется тратить лишние деньги)

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


Заключение


На этом с теорией покончено. И к сожалению (или к счастью для тех, кто не любит много буков), на самом интересном я заканчиваю свое изложение, так как статья уже получилась достаточно объемной, и реальный пример сервиса, разворачиваемого с помощью данной концепции, она уже не вместит. Напишите в комментариях, если статья получилась интересной/полезной, и хочется посмотреть, как это сделано на практике: с кодом, реальным CI/CD и пояснениями. Я буду благодарен вам за обратную связь.


Immutable Infrastructure подход, который имеет свои плюсы и минусы. Подход, который подойдет не для каждого сервиса или приложения. И я повторюсь, использовать его надо, понимая и принимая все его плюсы и минусы. И конечно, пусть всегда торжествует здравый смысл. Вы всегда можете взять какую-то его часть и использовать только ее, если это дает вам преимущества.


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

Подробнее..

Как управлять облачной инфраструктурой с помощью Terraform

24.09.2020 10:22:34 | Автор: admin

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

Обо всем подробно и в три этапа:

1. Terraform описание, преимущества и составляющие

Terraform это IaC (Infrastructure-as-Code) инструмент для построения и управления виртуальной инфраструктурой с помощью кода .

В работе с инструментом мы отметили несколько преимуществ:

  • Скорость развертывания новых тенантов (пользовательских виртуальных сред). Обычно, чем больше новых клиентов, тем больше "кликов" требуется сделать сотрудникам технической поддержки для публикации новых ресурсов. С Terraform пользователи могут изменять параметры виртуальных машин (например, автоматически выключать ОС и увеличивать раздел виртуального диска ) без участия технической поддержки и выключения самой машины.

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

  • Возможность описывать большинство популярных облачных платформ. Вы можете использовать инструмент от Amazon и Google Cloud, до частных платформ на базе VMware vCloud Director, предлагающих услуги в рамках IaaS, SaaS и PaaS решений.

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

  • Удобное использование для создания демо-стендов под тестирование и отладку программного обеспечения. Вы можете создавать и передавать стенды для отдела тестирования, параллельно проверять ПО в разных средах, а также моментально изменять и удалять ресурсы, создав всего лишь один план построения ресурсов

"Террариум" Terraform

Кратко рассказали про преимущества инструмента, теперь разберем его на составляющие

Providers (провайдеры).

В Terraform практически любой тип инфраструктуры можно представить в качестве ресурса. Связь между ресурсами и платформой API обеспечивается providers модулями, которые позволяют создавать ресурсы в рамках определённой платформы, например, Azure или VMware vCloud Director.

В рамках проекта вы можете взаимодействовать с разными провайдерами на разных платформах.

Resources (описание ресурсов).

Описание ресурсов позволяет управлять компонентами платформы, например виртуальными машинами или сетями.

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

Provisioners.

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

Переменные Input и Output.

Input переменные входные переменные для любых типов блоков.

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

States (состояния).

States-файлы хранят информацию о конфигурации ресурсов платформы провайдера. При первом создании платформы никаких сведений о ресурсах нет и перед любой операцией Terraform обновляет состояние с реальной инфраструктурой уже описанных ресурсов.

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

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

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

2. Создание инфраструктуры

Составляющие разобрали, теперь с помощью Terraform мы поэтапно создадим инфраструктуру с тремя виртуальными машинами. Первая с установленным прокси-сервером nginx, вторая с файловым хранилищем на базе Nextcloud и третья с CMS Bitrix.

Писать код и исполнять его мы будем на примере нашего облака на VMware vCloud Director. У нас пользователи получают учётную запись правами Organization Administrator, если вы используете учетную запись с теми же правами в другом облаке VMware, то сможете воспроизвести код из наших примеров. Поехали!

Сначала создадим для нашего нового проекта директорию, в которой будут размещены файлы с описанием инфраструктуры.

mkdir project01

Затем опишем компоненты инфраструктуры. Terraform создаёт связи и обрабатывает файлы на основании описания в файлах. Сами файлы можно именовать исходя из целевого назначения описываемых блоков, например, network.tf - описывает сетевые параметры для инфраструктуры.

Для описания компонентов нашей инфраструктуры, мы создали следующие файлы:

Список файлов.

main.tf - описание параметров для виртуальной среды - виртуальные машины, виртуальные контейнеры;

network.tf - описание параметров виртуальной сети и правил NAT, Firewall;

variables.tf - список переменных, которые используем;

vcd.tfvars - значения переменных проекта для модуля VMware vCloud Director.

Язык конфигурации в Terraform является декларативным и порядок блоков не имеет значения, кроме блоков provisioner, т.к. в этом блоке мы описываем команды для выполнения при подготовке инфраструктуры и они будут выполнятся по порядку.

Структура блоков.

<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {

# Block body

<IDENTIFIER> = <EXPRESSION> # Argument

}

Для описания блоков используется собственный язык программирования HCL (HashiCorp Configuration Language), возможно описывать инфраструктуру и с помощью JSON. Подробнее о синтаксисе можно прочитать на сайте разработчика.

Конфигурация переменной окружения, variables.tf и vcd.tfvars

Сначала создадим два файла, которые описывают список всех используемых переменных и их значений для модуля VMware vCloud Director. Первым создадим файл variables.tf.

Cодержимое файла variables.tf.

variable "vcdorguser" {

description = "vCD Tenant User"

}

variable "vcdorgpassword" {

description = "vCD Tenant Password"

}

variable "vcdorg" {

description = "vCD Tenant Org"

}

variable "vcdorgvdc" {

description = "vCD Tenant VDC"

}

variable "vcdorg_url" {

description = "vCD Tenant URL"

}

variable "vcdorgmaxretrytimeout" {

default = "60"

}

variable "vcdorgallowunverifiedssl" {

default = "true"

}

variable "vcdorgedgename" {

description = "vCD edge name"

}

variable "vcdorgcatalog" {

description = "vCD public catalog"

}

variable "vcdtemplateoscentos7" {

description = "OS CentOS 7"

default = "CentOS7"

}

variable "vcdorgssdsp" {

description = "Storage Policies"

default = "Gold Storage Policy"

}

variable "vcdorghddsp" {

description = "Storage Policies"

default = "Bronze Storage Policy"

}

variable "vcdedgelocalsubnet" {

description = "Organization Network Subnet"

}

variable "vcdedgeexternalip" {

description = "External public IP"

}

variable "vcdedgelocalipnginx" {}

variable "vcdedgelocalipbitrix" {}

variable "vcdedgelocalC11Cnextcloud" {}

variable "vcdC12Cexternal_network" {}

Значения переменных, которые мы получаем от провайдера.
  • vcd_org_user - имя пользователя с правами Organization Administrator,

  • vcd_org_password - пароль пользователя,

  • vcd_org - название организации,

  • vcd_org_vdc - название виртуального дата-центра,

  • vcd_org_url - API URL,

  • vcd_org_edge_name - название виртуального маршрутизатора,

  • vcd_org_catalog - название каталога с шаблонами виртуальных машин,

  • vcd_edge_external_ip - публичный IP-адрес,

  • vcd_edge_external_network - название внешней сети,

  • vcd_org_hdd_sp - название политики хранения HDD,

  • vcd_org_ssd_sp - название политики хранения SSD.

И вводим свои переменные:

  • vcdedgelocalipnginx - IP-адрес виртуальной машины с NGINX,

  • vcdedgelocalipbitrix - IP-адрес виртуальной машины с 1С: Битрикс,

  • vcdedgelocalipnextcloud - IP-адрес виртуальной машины с Nextcloud.

Вторым файлом создаем и указываем переменные для модуля VMware vCloud Director в файле vcd.tfvars: Напомним, что в нашем примере мы используем собственное облако mClouds, если вы работаете с другим провайдером уточните значения у него.

Содержимое файла vcd.tfvars.

vcdorgurl = "https://vcloud.mclouds.ru/api"

vcdorguser = "orgadmin"

vcdorgpassword = "*"

vcd = "org"

vcdorgvdc = "orgvdc"

vcdorgmaxretrytimeout = 60

vcdorgallowunverifiedssl = true

vcdorgcatalog = "Templates"

vcdtemplateos_centos7 = "CentOS7"

vcdorgssdsp = "Gold Storage Policy"

vcdorghddsp = "Bronze Storage Policy"

vcdorgedgename = "MCLOUDS-EDGE"

vcdedgeexternalip = "185.17.66.1"

vcdedgelocalsubnet = "192.168.110.0/24"

vcdedgelocalipnginx = "192.168.110.1"

vcdedgelocalipbitrix = "192.168.110.10"

vcdedgelocalipnextcloud = "192.168.110.11"

vcdedgeexternal_network = "NET-185-17-66-0"

Сетевая конфигурация, network.tf.

Переменные окружения заданы, теперь настроим схему подключения виртуальных машин к каждой виртуальной машине назначим приватный IP-адрес и с помощью Destination NAT "пробрасываем" порты во внешнюю сеть. Для ограничения доступа к портам управления установим доступ только для нашего IP-адреса.

Схема сети для создаваемой Terraform платформыСхема сети для создаваемой Terraform платформы

Создаем виртуальную организационную сеть с названием net_lan01, шлюзом по умолчанию: 192.168.110.254, а также с адресным пространством: 192.168.110.0/24.

Описываем виртуальную сеть.

resource "vcdnetworkrouted" "net" {

name = "netlan01"

edgegateway = var.vcdorgedgename

gateway = "192.168.110.254"

dns1 = "1.1.1.1"

dns2 = "8.8.8.8"

staticippool {

startaddress = "192.168.110.1"

end_address = "192.168.110.253"

}

}

Создадим правила для межсетевого экрана, которое позволяет предоставить виртуальным машинам доступ в сеть Интернет. В рамках этого блока все виртуальные ресурсы в облаке будут иметь доступ в сеть Интернет:

Описываем правила для доступа VM в интернет.

resource "vcdnsxvfirewallrule" "fwinternetaccess" {

edgegateway = var.vcdorgedgename

name = "Internet Access"

source {

gatewayinterfaces = ["internal"]

}

destination {

gatewayinterfaces = ["external"]

}

service {

protocol = "any"

}

dependson = [vcdnetworkrouted.net]

}

Установив зависимость, что после обработки блока vcdnetworkrouted.net мы приступаем к конфигурации блока vcdnsxvfirewallrule, с помощью dependson. Используем эту опцию, так как некоторые зависимости могут быть распознаны неявно в конфигурации.

Далее создадим правила разрешающее доступ к портам из внешней сети и указываем наш IP-адрес для подключения по SSH к серверам. Любой пользователь сети Интернет имеет доступ к портам 80 и 443 на веб-сервере и пользователь с IP-адресом 90.1.15.1 имеет доступ к портам SSH виртуальных серверов.

Разрешаем доступ к портам из внешней сети.

resource "vcdnsxvfirewallrule" "fwnatports" {

edgegateway = var.vcdorgedgename

name = "HTTPs Access"

source {

gatewayinterfaces = ["external"]

}

destination {

gateway_interfaces = ["internal"]

}

service {

protocol = "tcp"

port = "80"

}

service {

protocol = "tcp"

port = "443"

}

dependson = [vcdnetworkrouted.net]

}

resource "vcdnsxvfirewallrule" "fwnatadminports" {

edgegateway = var.vcdorgedgename

name = "Admin Access"

source {

ipaddresses = [ "90.1.15.1" ]

}

destination {

gatewayinterfaces = ["internal"]

}

service {

protocol = "tcp"

port = "58301"

}

service {

protocol = "tcp"

port = "58302"

}

service {

protocol = "tcp"

port = "58303"

}

depends_on = [vcdnetworkrouted.net]

}

Создаём правила Source NAT для доступа в сеть Интернет из облачной локальной сети:

Описываем правила Source NAT.

resource "vcdnsxvsnat" "snatlocal" {

edgegateway = var.vcdorgedgename

networktype = "ext"

networkname = var.vcdedgeexternalnetwork

originaladdress = var.vcdedgelocalsubnet

translatedaddress = var.vcdedgeexternalip

dependson = [vcdnetwork_routed.net]

}

И в завершении конфигурации сетевого блока добавляем правила Destination NAT для доступа к сервисам из внешней сети:

Добавляем правила Destination NAT.

resource "vcd_nsxv_dnat" "dnat_tcp_nginx_https" { edge_gateway = var.vcd_org_edge_name network_name = var.vcd_edge_external_network network_type = "ext"

description = "NGINX HTTPs"

original_address = var.vcd_edge_external_ip original_port = 443

translated_address = var.vcd_edge_local_ip_nginx translated_port= 443 protocol = "tcp"

depends_on = [vcd_network_routed.net]}resource "vcd_nsxv_dnat" "dnat_tcp_nginx_http" { edge_gateway = var.vcd_org_edge_name network_name = var.vcd_edge_external_network network_type = "ext"

description = "NGINX HTTP"

original_address = var.vcd_edge_external_ip original_port = 80

translated_address = var.vcd_edge_local_ip_nginx translated_port= 80 protocol = "tcp"

depends_on = [vcd_network_routed.net]

}

Добавляем правило NAT для трансляции портов к SSH-серверу под Nginx.

resource "vcd_nsxv_dnat" "dnat_tcp-nginx_ssh" { edge_gateway = var.vcd_org_edge_name network_name = var.vcd_edge_external_network network_type = "ext"

description = "SSH NGINX"

original_address = var.vcd_edge_external_ip original_port = 58301

translated_address = var.vcd_edge_local_ip_nginx translated_port= 22 protocol = "tcp"

depends_on = [vcd_network_routed.net]

}

Добавляем правило NAT для трансляции портов к SSH-серверу с 1С-Битрикс.

resource "vcd_nsxv_dnat" "dnat_tcp_bitrix_ssh" { edge_gateway = var.vcd_org_edge_name network_name = var.vcd_edge_external_network network_type = "ext"

description = "SSH Bitrix"

original_address = var.vcd_edge_external_ip original_port = 58302

translated_address = var.vcd_edge_local_ip_bitrix translated_port= 22 protocol = "tcp"

depends_on = [vcd_network_routed.net]

}

Добавляем правило NAT для трансляции портов к SSH-серверу с Nextcloud.

resource "vcd_nsxv_dnat" "dnat_tcp_nextcloud_ssh" { edge_gateway = var.vcd_org_edge_name network_name = var.vcd_edge_external_network network_type = "ext"

description = "SSH Nextcloud"

original_address = var.vcd_edge_external_ip original_port = 58303 translated_address = var.vcd_edge_local_ip_nextcloud translated_port= 22 protocol = "tcp"

depends_on = [vcd_network_routed.net]

}

Конфигурация виртуальной среды main.tf

Как мы и планировали в начале статьи, создадим три виртуальные машины. Они будут подготовлены с помощью "Guest Customization". Сетевые параметры пропишем согласно указанным нами настройками, а пароль от пользователя генерируется автоматически.

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

Конфигурация виртуальных машинКонфигурация виртуальных машин

Создадим контейнер vApp. Чтобы мы могли сразу же подключить vApp и ВМ к виртуальной сети также добавляем параметр depends_on:

Создаем контейнер

resource "vcd_vapp" "vapp" { name = "web" power_on = "true" depends_on = [vcd_network_routed.net]

}

Создадим виртуальную машину с описанием

resource "vcd_vapp_vm" "nginx" {

vapp_name = vcd_vapp.vapp.name

name = "nginx"

catalog_name = var.vcd_org_catalog

template_name = var.vcd_template_os_centos7

storage_profile = var.vcd_org_ssd_sp

memory = 8192

cpus = 1

cpu_cores = 1

network {

type = "org"

name = vcd_network_routed.net.name

is_primary = true

adapter_type = "VMXNET3"

ip_allocation_mode = "MANUAL"

ip = var.vcd_edge_local_ip_nginx

}

override_template_disk {

bus_type = "paravirtual"

size_in_mb = "32768"

bus_number = 0

unit_number = 0

storage_profile = var.vcd_org_ssd_sp

}

}

Основные параметры в описании VM:

  • name - имя виртуальной машины,

  • vappname - название vApp в который добавить новую ВМ,

  • catalogname / templatename - название каталога и название шаблона виртуальной машины,

  • storageprofile - политика хранения по умолчанию.

Параметры блока network:

  • type - тип подключаемой сети,

  • name - к какой виртуальной сети подключить ВМ,

  • isprimary - основной сетевой адаптер,

  • ipallocation_mode - режим выделения адреса MANUAL / DHCP / POOL,

  • ip - IP-адрес для виртуальной машины, укажем вручную.

Блок override_template_disk:

  • sizeinmb - размер boot-диска для виртуальной машины

  • storage_profile - политика хранения для диска

Создадим вторую VM с описанием файлового хранилища Nextcloud

resource "vcd_vapp_vm" "nextcloud" {

vapp_name = vcd_vapp.vapp.name

name = "nextcloud"

catalog_name = var.vcd_org_catalog

template_name = var.vcd_template_os_centos7

storage_profile = var.vcd_org_ssd_sp

memory = 8192

cpus = 1

cpu_cores = 1

network {

type = "org"

name = vcd_network_routed.net.name

is_primary = true

adapter_type = "VMXNET3"

ip_allocation_mode = "MANUAL"

ip = var.vcd_edge_local_ip_nextcloud

}

override_template_disk {

bus_type = "paravirtual"

size_in_mb = "32768"

bus_number = 0

unit_number = 0

storage_profile = var.vcd_org_ssd_sp

}

}

resource "vcd_vm_internal_disk" "disk1" {

vapp_name = vcd_vapp.vapp.name

vm_name = "nextcloud"

bus_type = "paravirtual"

size_in_mb = "102400"

bus_number = 0

unit_number = 1

storage_profile = var.vcd_org_hdd_sp

allow_vm_reboot = true

depends_on = [ vcd_vapp_vm.nextcloud ]

}

В секции vcdvminternal_disk опишем новый виртуальный диск, который подключается к виртуальной машине.

Пояснения по блоку vcdvminternaldisk:

  • bustype - тип дискового контроллера

  • sizeinmb - размер диска

  • busnumber / unitnumber - место подключения в адаптере

  • storage_profile - политика хранения для диска

Опишем последнюю VM на Битрикс

resource "vcd_vapp_vm" "bitrix" {

vapp_name = vcd_vapp.vapp.name

name = "bitrix"

catalog_name = var.vcd_org_catalog

template_name = var.vcd_template_os_centos7

storage_profile = var.vcd_org_ssd_sp

memory = 8192

cpus = 1

cpu_cores = 1

network {

type = "org"

name = vcd_network_routed.net.name

is_primary = true

adapter_type = "VMXNET3"

ip_allocation_mode = "MANUAL"

ip = var.vcd_edge_local_ip_bitrix

}

override_template_disk {

bus_type = "paravirtual"

size_in_mb = "81920"

bus_number = 0

unit_number = 0

storage_profile = var.vcd_org_ssd_sp

}

}

Обновление ОС и установка дополнительных скриптов

Сеть подготовлена, виртуальные машины описаны. Перед импортом нашей инфраструктуры мы можем заранее провести первоначальный провижининг с помощью provisioners блоков и без использования Ansible.

Рассмотрим как обновить ОС и запустить установочный скрипт CMS Bitrix с помощью provisioner блока.

Сначала выполним установку пакетов обновления CentOS.

resource "null_resource" "nginx_update_install" {

provisioner "remote-exec" {

connection {

type = "ssh"

user = "root"

password = vcd_vapp_vm.nginx.customization[0].admin_password

host = var.vcd_edge_external_ip

port = "58301"

timeout = "30s"

}

inline = [

"yum -y update && yum -y upgrade",

"yum -y install wget nano epel-release net-tools unzip zip" ]

}

}

}

Обозначение составляющих:

  • provisioner "remote-exec" - подключаем блок удаленного "провижининга"

  • В блоке connection описываем тип и параметры для подключения:

  • type - протокол, в нашем случае SSH;

  • user - имя пользователя;

  • password - пароль пользователя. В нашем случае указываем на параметр vcdvappvm.nginx.customization[0].admin_password, который хранит сгенерированный пароль от пользователя системы.

  • host - внешний IP-адрес для подключения;

  • port - порт для подключения, который ранее указывали в настройках DNAT;

  • inline - перечисляем список команд, которые будут вводится. Команды будут введены по порядку, как и указано в этой секции.

Как пример, дополнительно выполним скрипт установки 1С-Битрикс. Вывод результата выполнения скрипта будет доступен во время выполнения плана. Для установки скрипта, сначала опишем блок:

Опишем установку 1С-Битрикс.

provisioner "file" {

source = "prepare.sh"

destination = "/tmp/prepare.sh"

connection {

type = "ssh"

user = "root"

password = vcd_vapp_vm.nginx.customization[0].admin_password

host = var.vcd_edge_external_ip

port = "58301"

timeout = "30s"

}

}

provisioner "remote-exec" {

inline = [

"chmod +x /tmp/prepare.sh", "./tmp/prepare.sh"

]

}

И сразу же опишем обновление Битрикс.

Пример провижининга 1С-Битрикс.

resource "null_resource" "install_update_bitrix" {

provisioner "remote-exec" {

connection {

type = "ssh"

user = "root"

password = vcd_vapp_vm.bitrix.customization[0].admin_password

host = var.vcd_edge_external_ip

port = "58302"

timeout = "60s"

}

inline = [

"yum -y update && yum -y upgrade",

"yum -y install wget nano epel-release net-tools unzip zip",

"wget http://repos.1c-bitrix.ru/yum/bitrix-env.sh -O /tmp/bitrix-env.sh",

"chmod +x /tmp/bitrix-env.sh",

"/tmp/bitrix-env.sh"

]

}

}

Важно! Скрипт может не сработать, если не отключить заранее SELinux! Если вам требуется подробная статья по установке и настройке CMS 1С-Битрикс с помощью bitrix-env.sh, оо вы можете воспользоваться нашей статьей в блоге на сайте.

3. Инициализация инфраструктуры

Инициализация модулей и плагиновИнициализация модулей и плагинов

Для работы мы используем простой джентельменский набор: лэптоп с ОС Windows 10 и дистрибутив с официального сайта terraform.io. Распакуем и проинициализируем с помощью команды: terraform.exe init

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

  1. Выполняем команду - terraform plan -var-file=vcd.tfvars.

  2. Получаем результат - Plan: 16 to add, 0 to change, 0 to destroy. То есть по этому плану будет создано 16 ресурсов.

  3. Запускаем план по команде - terraform.exe apply -var-file=vcd.tfvars.

Виртуальные машины будут созданы, а затем выполняются перечисленные нами пакеты в рамках секции provisioner ОС будет обновлена и установится CMS Bitrix.

Получение данных для подключения

После выполнения плана мы хотим получить в текстовом виде данные для подключения к серверам, для этого оформим секцию output следующим образом:

output "nginxpassword" {

value = vcdvappvm.nginx.customization[0].adminpassword

}

И следующий вывод сообщает нам пароль от созданной виртуальной машины:

Outputs: nginx_password = F#4u8!!N

В итоге мы получаем доступ к виртуальным машинам с обновлённой операционной системой и предустановленными пакетами для нашей дальнейшей работы. Все готово!

Но что если у вас уже есть существующая инфраструктура?

3.1. Работа Terraform с уже существующей инфраструктурой

Всё просто, вы можете импортировать текущие виртуальные машины и их vApp контейнеры с помощью команды import.

Опишем ресурс vAPP и виртуальную машину.

resource "vcd_vapp" "Monitoring" {

name = "Monitoring"

org = "mClouds"

vdc = "mClouds"

}

resource "vcd_vapp_vm" "Zabbix" {

name = "Zabbix"

org = "mClouds"

vdc = "mClouds"

vapp = "Monitoring"

}

Следующий шаг, это выполнить импорт свойств ресурсов vApp в формате vcdvapp.<vApp> <org>.<orgvdc>.<vApp>, где:

  • vApp - имя vApp;

  • org - название организации;

  • org_vdc - название виртуального дата-центра.

Импорт свойств ресурса vAPPИмпорт свойств ресурса vAPP

Выполним импорт свойств ресурсов VM в формате: vcdvappvm.<VM> <org>.<orgvdc>.<vApp>.<VM>, в котором:

  • VM - имя VM;

  • vApp - имя vApp;

  • org - название организации;

  • orgvdc - название виртуального дата-центра.

Импорт прошел успешно

C:\Users\Mikhail\Desktop\terraform>terraform import vcd_vapp_vm.Zabbix mClouds.mClouds.Monitoring.Zabbix

vcd_vapp_vm.Zabbix: Importing from ID "mClouds.mClouds.Monitoring.Zabbix"...

vcd_vapp_vm.Zabbix: Import prepared!

Prepared vcd_vapp_vm for import

vcd_vapp_vm.Zabbix: Refreshing state... [id=urn:vcloud:vm:778f4a89-1c8d-45b9-9d94-0472a71c4d1f]

Import successful!

The resources that were imported are shown above. These resources are now inyour Terraform state and will henceforth be managed by Terraform.

Теперь мы можем посмотреть на новый импортированный ресурс:

Импортированный ресурс

> terraform show

...

# vcd_vapp.Monitoring:

resource "vcd_vapp" "Monitoring" {

guest_properties = {}

href = "https://vcloud.mclouds.ru/api/vApp/vapp-fe5db285-a4af-47c4-93e8-55df92f006ec"

id = "urn:vcloud:vapp:fe5db285-a4af-47c4-93e8-55df92f006ec"

ip = "allocated"

metadata = {}

name = "Monitoring"

org = "mClouds"

status = 4

status_text = "POWERED_ON"

vdc = "mClouds"

}

# vcd_vapp_vm.Zabbix:

resource "vcd_vapp_vm" "Zabbix" {

computer_name = "Zabbix"

cpu_cores = 1

cpus = 2

expose_hardware_virtualization = false

guest_properties = {}

hardware_version = "vmx-14"

href = "https://vcloud.mclouds.ru/api/vApp/vm-778f4a89-1c8d-45b9-9d94-0472a71c4d1f"

id = "urn:vcloud:vm:778f4a89-1c8d-45b9-9d94-0472a71c4d1f"

internal_disk = [

{

bus_number = 0

bus_type = "paravirtual"

disk_id = "2000"

iops = 0

size_in_mb = 122880

storage_profile = "Gold Storage Policy"

thin_provisioned = true

unit_number = 0

},

]

memory = 8192

metadata = {}

name = "Zabbix"

org = "mClouds"

os_type = "centos8_64Guest"

storage_profile = "Gold Storage Policy"

vapp_name = "Monitoring"

vdc = "mClouds"

customization {

allow_local_admin_password = true

auto_generate_password = true

change_sid = false

enabled = false

force = false

join_domain = false

join_org_domain = false

must_change_password_on_first_login = false

number_of_auto_logons = 0

}

network {

adapter_type = "VMXNET3"

ip_allocation_mode = "DHCP"

is_primary = true

mac = "00:50:56:07:01:b1"

name = "MCLOUDS-LAN01"

type = "org"

}

}

Теперь точно готово - мы закончили с последним моментом (импорт в существующую инфраструктуру) ирассмотрели все основные моменты работы с Terraform.

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

При этом независимость от окружения дает возможность работать с локальными, облачными ресурсами, так и, заканчивая управлением платформой. А при отсутствии поддерживаемой платформы и желании добавления нового, можно написать свой провайдер и использовать его.

Подробнее..

AWS Meetup Terraform amp Terragrunt. Антон Бабенко (2020)

12.10.2020 10:15:25 | Автор: admin


Terraform это популярный инструмент компании Hashicorp, для управления вашей облачной инфраструктурой в парадигме Infrastructure as a Code.


Terragrunt это wrapper для Terraform, которая предоставляет дополнительные инструменты для хранения ваших конфигураций Terraform, работы с несколькими модулями Terraform и управления удаленным состоянием.


Видео:




Ссылки:



Я являюсь AWS Community Hero. Я сертифицированный Terraform-фанатик, потому что я прошел сертификацию Terraform. Есть такое понятие, как HashiCorp-сертификация.


Я являюсь активным участником open source движения. Я много трачу своего времени, энергии на создание и поддержание Terraform-проектов, community-modules, aws-modules. Может быть, кто-то из вас даже чем-то пользуется из этого.


Я делаю много утилит таких, как, например, Pre-commit-terraform. Это утилита для автоматического форматирования кода документации, форматирования кода и т. д.


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


Если у вас есть Твиттер, GitHub и вы не рекрутер, то Linkedin для вас. Рекрутеры мне ну нужны, потому что все в open source, и мы все находим работу исключительно в open source.



  • All-things Terraform + AWS + DevOps.


  • Consulting.


  • Workshops.


  • Trainings.


  • Mentorship.



Open source это бесплатная чаще всего вещь. Мои проекты open source. Они мне дают обычно заказчиков, которые говорят: Можешь сделать то же самое? Можешь научить нас пользоваться этим?. И это называется консалтинг.


Если есть какая-то команда, которая использует Terraform, и в Terraform используют Terraform workspace, то я говорю: Давайте я вам workshops проведу и скажу, что это зло?. Это называется workshops.


Если люди пишут код в течение недели-двух и не совсем понимают правильно ли они делают, т. е., может быть, какое-то решение есть получше, тогда они обращаются ко мне, и я примерно час-два в неделю занимаюсь тем, что я их консультирую, смотрю pull request, обсуждаю решения и говорю, как это можно сделать по-другому. Не всегда лучше, иногда просто по-другому.


У меня есть email: anton [собака] antonbabanko.com. Вы всегда можете писать, я, скорее всего отвечу, т. е. я отвечаю, но иногда с задержкой, потому что я сейчас очень много путешествую.


Компания называется Betajob.com. Я в ней единственный сотрудник.



https://github.com/terraform-aws-modules


https://registry.terraform.io/modules/terraform-aws-modules


Terraform AWS модули это один из основных моих проектов, который я начал в 2017-ом году, потому что мне нравилось делать что-то такое, что нужно большому количеству людей. Например, так или иначе настраивают VPC в Amazon. Я подумал, что надо сделать это как-то правильно. И вместо того, чтобы взять еще один модуль, который кто-то написал, я взял тот, который был самым популярным у меня. Потратил на него несколько сотен часов. И выложил это все в открытый доступ.


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


Тоже самое касается и поддержания этих сервисов, модулей. Я не трачу на них огромное количество времени. Но все равно достаточное.



https://github.com/sponsors/antonbabenko


Было 7 000 000 загрузок, больше 1 000 pull requests и множество issues было пофиксено. И частично это все благодаря этим 6 аватаркам, которые спонсируют меня на GitHub. Если ваша компания пользуется из этого чем-нибудь, то вы можете присоединиться, и ваш аватар будет тут тоже. Вам все равно, а мне приятно.



Еще один проект, с которым я связан, называется Cloudcraft. Это такая утилита, которая в браузере позволяет все это визуализировать, т. е. нарисовать инфраструктуру, соединить все компоненты. В общем, сделать все классно, как мы можем понять.



Cloudcraft дает возможность это все экспортировать как картинку, посмотреть, сколько это стоит или втянуть в существующую AWS-инфраструктуру.



https://dzone.com/articles/infrastructure-as-code-the-benefits


Я понимаю, что когда это все красиво смотрится, это может впечатлить начальников, менеджеров и дать больше денег, но когда мы возвращаемся к работе, то мы все равно пропагандируем здоровый образ жизни, т. е. инфраструктуру как код. Мы не может ничего сделать с картинкой, т. е. она классно выглядит, ее все пихают во все презентации. Но в реальности инфраструктура должна быть как код, а не инфраструктура как Powerpoint. Или еще хуже, когда инфраструктура как clickops, когда в консоли клац, клац, готово. И никто не знает, как это работает, зачем это сделано.


И давайте договоримся, что инфраструктура как код это хорошо, потому что мы ее отслеживаем, мы видим, кто поменял и что поменял. Мы можем четко посмотреть на файлы и понять, какая конфигурация прямо сейчас находится в проекте. К этому надо стремиться. Не всегда это получается. Для этого существуют сервисы cndb, Systems Manager от Amazon. Но это хорошая цель.



О чем мы будем сегодня говорить?


Есть Terraform 0.12 и Terraform 0.11.



Начнем с того, зачем Terraform появился. Я понимаю, что вы многие это уже знаете. Terraform довольно часто упоминается на большом количестве докладов. Тут ничего удивительно нет, потому что Terraform появился неспроста.


Amazon в 2011-ом году сказал: Вот вам CloudFormation. На нулевой день люди поняли, что это круто. На первый день люди начали писать Spectrum, Fogs и т. д., чтобы собирать эти кусочки JSON, YAML и т. д., т. е. как-то их организовывать. Они придумывали разные DSL и т. д. Вы можете зайти на GitHub и погуглить, например, orchestration-cloudformation. И вы увидите большое разнообразие утилит. Spectrum это одна из тех, о которой я сегодня здесь слышал от кого-то.


В общем, Google сказал, что все фигня, мы будем, как программисты, людям давать возможность писать на Python, пусть используют Jinja Tempating, будут описывать свою инфраструктуру. Это вполне здравомыслящий подход от Google.


Но Azure тоже сказал, что это все фигня, потому что нет ничего лучше, чем JSON. И ничего, что программисты не понимают, что там происходит. Программисты пользуются этим, плюются. Большинство программистов переходит из Azure ARM в Terraform в одностороннем порядке. Я ни разу не слышал, чтобы кто-то сказал, что Terraform фигня, я обожаю JSON, я люблю мазахизм.


И по историческим причинам у нас есть Chef, Ansible, Puppet, которые так или иначе умеют всем управлять. У них есть миллион ресурсов, моделей, плейбуков. Там все здорово.


Из этого следует логичный вывод: если можно управлять каким-то одним ресурсом, то можно управлять и public cloud ресурсами Amazon, Google, Azure и т. д. У большинства configuration management утилит уже есть какие-то модули, решения, поэтому все классно. Поэтому сейчас мы видим, что есть куча решений: есть решения, которые сделаны одним провайдером, либо одно решение работает на разных провайдерах.



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



И поэтому появился Terraform, в котором сейчас поддерживается больше, чем 250 провайдеров и используется один и тот же язык для настройки, т. е. используется HashiCorp Configuration Language, где достаточно знать один язык, и можно одинаково работать с ресурсами совершенно на любом провайдере.


И Terraform является первой из существующих программ, утилит, которая позволяет работать с ресурсами на более высоком уровне. В Terraform есть концепция модуля, которая заложена в самую-самую основу. Буквально на второй день использования Terraform, так или иначе возникнет желание этот код использовать. И у Terraform есть такая возможность. У CloudFormation с самого начала этой возможности не было. Конечно, сейчас CloudFormation уже не такой, какой он был в 2013-2014-ом году, но все равно не так все радужно.


Также Terraform не работает со всеми доисторическими mainframes, workers и т. д. Поддерживается то, что существовало, начиная с 2014-го года. Если вы хотите администрировать то, что не администрируется, то вам нужно самому написать API к этому, и написать в Terraform провайдер. И тогда у вас будет Terraform администрировать неадминистрируемое. Это тоже нормальный use cases.



https://www.terraform.io/docs/providers/index.html


Но на самом деле API есть у всего, т. е. от создания email в Google до управления файлами и permeation в Dropbox, и до заказов пиццы. Наверное, многие уже знают, что пиццу тоже можно через Terraform заказывать. Это нормальный use cases.


Но мне больше нравится use cases, где в основу принята концепция взаимодействия. Представьте, что у вас в Minecraft есть земля и есть овца. И если мы бросаем овцу, то овца будет падать-падать. И в конце концов упадет на землю. Если мы уберем землю, то овца упадает и умрет. Поэтому что надо сделать, если мы мыслим как Terraform? Надо сделать так, чтобы овца зависела от земли. И когда мы это описываем внутри hsale, то мы описываем, что есть ресурс овца и ресурс земля. И делаем так, что ресурс овца принимает как аргумент землю. Таким образом мы даем Terraform понять, что сначала сделай землю, а потом брось туда овцу, иначе все пропадет. Это пример того, как можно использовать зависимость в реальном мире.


Это примерно по той же причине, зачем мы придумали объектно-ориентированное программирование. Мы посмотрели вокруг себя и увидели, что у нас много объектов. И решили придумать им какие-нибудь ключевые слова, объекты, наследования и т. д. Тоже самое происходит с Terraform. В Terraform можно описать все, где есть API и есть зависимости.


Если у вас много свободного времени, то можете посмотреть список провайдеров по данной ссылке и представить, какую часть инфраструктуры в своей компании вы можете автоматизировать. На вскидку могу сказать, что весь процесс создания, когда кто-то приходит в компанию, и вы ему создаете email, создаете доступы в GitHub-репозитории, доступы в Jira. Это все в нормальных компаниях автоматизирован с помощью одного pull requests в Terraform. И точно так же происходит при создании.



Если вы начинаете учить Terraform, то я рекомендую всего лишь 3 ресурса:


  • Terraform.io почитать документацию, потому что документация дает информацию о том, что существует.


  • Learn.hashicorp.com потом потыкать это здесь.


  • Terraform-best-practices.com когда вы уже узнали, что есть 100-500 фич разных в Terraform, вы попробовали из них половину, поняли, что что-то тут попахивает и начинаете думать, что есть best practices. Вы пишете в Google Terraform best practices и попадаете на мой сайт.



Я этот сайт написал, потому что люди спрашивали меня: Как это сделать правильно?. Люди спорили best practices это или нет. И понял, что best practices это то, что опубликовано на сайте terraform-best-practices. Я так и сделал. Т. е. написал то, что я считаю самым важным. Например, как структурировать код, какие основные фичи в Terraform и вообще при работе с инфраструктурой как код надо учитывать. Я написать еще кучу примеров кода, как это работает для маленьких, для средних, для больших и очень больших компаний в зависимости от количества ресурсов, провайдеров. И я написал это, потому что мне не хочется, чтобы люди делали что-то неправильно.


Теперь, спустя полтора года, люди туда заходят в большом количестве и очень мало людей сопротивляется. Очень мало людей мне говорит: Ты не прав тут, т. е., пожалуйста, если кто-то не согласен с тем, что там написано, напишите на email или откройте pull request и скажите, что так не работает. Потому что там есть места, которые уже не работают, потому что работали полтора года назад. С тех пор я кое-что там изменил.


Можете изучать эти ресурсы. И важно, чтобы вы понимали, что весь функционал Terraform это не то, что надо вашей компании. И это, пожалуй, один из важных моментов, который я хочу сегодня донести в докладе. Потому что Terraform очень большой проект, если его весь использовать, то того и гляди вы еще work space начнете использовать.



Что это знает?



В Terraform 0.11 выглядели вот так конфигурационные файлы, т. е. мы описывали инфраструктуру. В данном случае мы создаем s3_bucket.



В Terraform 0.12 все вот так вот. Это все, что надо знать. Оно и так будет работать. Но меняется то, что меньше надо символов писать.



https://www.hashicorp.com/blog/announcing-terraform-0-1-2-beta


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


Если вы использовали Terraform 0.11, то вы, наверное, помнили тот ужас, когда надо было написать выражение, которое и в try, и в false было адекватно правильно написано. И это одна из тех фич, которая мне сделала жизнь сложнее. Correct conditional operators означает, что если выражение истина, то берется левое значение, если не истина, то правое значение. Я поддерживаю большое количество Terraform AWS модулей. И вот эта конкретная штука сделала мою жизнь сложнее.


Почему? Как было раньше? У меня есть 100 -500 ресурсов, которые создаются в зависимости от разных условий. И когда я запускал Terraform plan, Terraform apply в своих тестовых environment, мне не так важно было проверять левую часть отдельно от правой части. Мне главное, чтобы это выражение не содержало ошибок и все. Сейчас мне надо писать test cases для двух разных условий: когда левая часть проверена и правая часть проверена отдельно. Т. е. мне надо писать в два раза больше кода и надо в два раза больше думать. А я люблю, когда Terraform думает за меня. Т. е. я люблю, когда Terraform проверяет значения и выдает какой-то вид ошибки без моего участия, а именно, когда я делаю код review, мне не надо запускать этот код в голове.


Много всего появилось. Все классно. Если вы следили за тем, как появлялся Terraform, т. е. вот этот блокпост на сайте HashiCorp появился примерно за полгода до релиза. И очень много людей думали, что сейчас Terraform 0.12 родится, и мы заживем.


Он родился спустя полгода. За это время было много гневных комментариев от людей в Твиттере, что HashiCorp плохая компания, потому что она анонсировала, а продукт не готов. Люди были очень расстроены. Это реальность жизни в open source.



https://www.terraform.io/upgrade-guides/0-12.html


Для тех людей, которые хотят обновить с 0.11 на 0.12 вот это самый важный слайд.


Во-первых, есть upgrade guide, где описано, что конкретно поменяется в коде, на что надо обращать внимание, как запускать. Все там классно написано. Если вы прочитаете, то я на 90 % уверен, что миграция у вас пройдет гладко.


Если есть проекты или части проекта, в которых вы не можете использовать Terraform 0.12, но можете использовать 0.11 последней версии, то у вас есть возможность читать Terraform state файлы, созданные версией 0.12. Это основное отличие в самой распространенной ситуации, когда вы обновили что-то, а потом пытаетесь использовать старую версию, а вам говорят, что этот state файл был создан новой версии, пожалуйста, обновите это.


В данном случае это решено специально для того, чтобы была возможность плавно мигрировать части инфраструктуры. Какая-то часть уже на 0.12, а какая-то часть на старой версии, до которой руки не дошли или которую вы собираетесь удалить, поэтому вам не надо ее переписывать.



https://github.com/tfutils/tfenv


Если вы хотите контролировать версии, то есть такая утилита как tfenv. Тут все просто.



https://www.terraform.io/docs/configuration/terraform.html


Есть возможность указания версии провайдеров, о которой не многие знают, хотя она написана в документации. Можно указывать версии того провайдера, в котором работает ваша архитектура. Как часто делают люди? Берут провайдер-блок. Допустим, провайдер AWS. И там написан регион, и там же указана версия провайдера. Можно так делать. Но когда у вас есть один Terraform-блок, то вы выносите в самый верх своей инфраструктуры. И там указываете все свои зависимости. Так намного проще работать.



Если вы обновились, а потом подумали: Ой, кошмар, что я сделал?, то вот такую команду запустите и она вам вернет предыдущий Terraform state файл поверх того, что у вас сейчас есть. Эта команда спасла не один проект.



Теперь поговорим о том, как структурировать Terraform конфигурации и вообще, как с этим жить.



Когда мы написали все в ресурсах, потом мы осознали, что есть Terraform модули, потому у нас есть куча Terraform моделей. И мы начинаем думать, как их вызывать.



Есть такой способ, как all-in-one, когда мы в tf файлы запихиваем вызовы Terraform-модулей. И преимущество у такого подхода заключается в том, что нам нужно меньше объявлять переменных, меньше outputs. Но когда мы работаем с таким проектом, у нас refresh занимает много времени, plan тоже занимает много времени. И мы работаем с инфраструктурой как с одним большим целом.



Второй способ это, когда мы делаем 1-in-1. Таким образом у нас намного меньше вызов. И когда мы работаем с каким-то конкретным стеком, мы можем перейти в ту папку и сделать какие-то изменения, и все. Мы работаем в довольно изолированном виде, все намного быстрее.



Представьте свой проект на работе. Как он выглядит: all-in-one или 1-in-1? Многие, когда я задаю этот вопрос, думают, что all-in-one это кошмар, а 1-in-1 норма.



На самом деле MFA (Most Frequent Answer) это посередине.



Потому что, когда начинаем работать над каким-то проектом, у нас есть несколько вариантов. Мы либо идем в Google и спрашиваем: Google, дай мне какой-нибудь готовый кусок кода, который я сейчас сюда вкину, либо идем на terraform.io, берем оттуда какой-то проект и прикручиваем его к себе all-in-one. Мы потом берем другие ресурсы, подключаем это все вместе. Запускаем Terraform plan 20 раз. Мы начинаем работать с all-in-one.


Потом мы понимаем, что вот эта целая штука, которая была all-in-one закончена, она тесно между собой связана. Мы это делаем, допустим, как модуль. И дальше уже встраиваем либо в другой проект, либо в другой environment. Т. е. как-то стараемся это переиспользовать.


А структура 1-in-1 является классным примером, когда у нас есть уже готовые куски кода. Например, мы зашли Registry на сайте terraform.io, взяли готовый VPC-модуль. Понятно, что мы его не будем переписывать, дописывать, расширять. Мы будем его просто использовать. И когда у нас есть возможность что-то готовое использовать, намного удобнее работать. Это 1-in-1.


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


Также, если вы знаете, что такое Terragrunt, то 1-in-1 для этого.



Какой тип окристрации между модулями вы знаете?



Представьте, что у нас есть проект all-in-one. И мы пишем Terraform plan. Ждем 15 минут. Он весь интернет сканирует. Потом мы видим, что там какой-то ресурс должен быть изменен. Мы запускаем Terraform apply, ждем 15 минут, пишем Yes, все классно.


Потом мы понимаем, что есть такой вариант, как main targets. Мы пишем terraform apply -targets = module.vpc. И вся наша область деятельности ограничена только модулем VPC. Также мы можем написать оболочку, shell-скрипт, makefile, PowerShell и это будет как-то подсказывать Terraform, какие аргументы передавать, либо какие war-файлы загружать, либо какие таргеты использовать. Многое чего можно делать.


Если мы используем 1-in-1, то примером такого mikefile может быть следующее. Мы можем запустить Terraform apply в одной папочке, потом перейти в другую папочку и запустить Terraform apply еще раз. И вот так последовательно это будет запускаться. Т. е. мы заходим в самый верхний уровень, пишем make terraform apply и ждем какое-то время. И все изменения применяются.


Какие еще варианты бывают? Да, мы можем использовать state файл как input для другого скрипта. Это, по сути, реализовано внутри shell-скрипта, который занимается тем, что создает инфраструктуру в одном месте. Потом, когда переходим в другую папку, запускаем Terraform apply, и там используется data-source для того, чтобы прочитать Terraform remote state из известного места. Это тоже способ. Так или иначе это все ограничивается shell-скриптами, makefiles.



А как вам такой вариант? Кто хочет так использовать? Он же работает. Можно до бесконечности все усложнять. Terraform используется для запуска Terraform.



Не надо так делать, конечно. Это плохо. Почему это плохо? Потому что Terraform предназначен для линейной работы. Т. е. мы отредактировали один файл, запустили команду Terraform apply. Подождали чуть-чуть, увидели результат. Потом зашли и изменили снова этот файл, снова запустили команду.


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



Есть такая штука, которая называется Terragrunt. Это чуть получше.



https://github.com/gruntwork-io/terragrunt


https://github.com/antonbabenko/terragrunt-reference-architecture


Основная цель этой утилиты это помочь пользователям Terraform легче обращаться с Terraform-модулями.


Основной компонент, который используется внутри Terragrunt, это Terraform-модули. Не индивидуальные ресурсы, не настройки, а именно Terraform-модули. Terragrunt апеллирует исключительно Terraform-модулями.


Его можно расширять до посинения, но не надо. Terragrunt работает только как оркестратор именно этих инфраструктурных модулей.


Можете почитать документацию, посмотреть код, нажать star на GitHub, там уже больше 3 000 звездочек. Это значит, что людям этот проект нужен. И это здорово.


Единственное, что не здорово, это то, что это отдельный проект. Но об этом чуть попозже.


Если вы почитали документацию и думаете, что это сложно начинается, то вот вам еще одна ссылочка со всеми фичами. Я в этот проект Terragrunt-reference-architecture вкинул все фичи, которые я использую на настоящих проектов. Это настоящий проект, я только поменял название заказчика. Все зависимости, все файлы, все папки там есть. Советую посмотреть, если вы сомневаетесь или пытаетесь начать с нуля и можете наломать своих граблей, а потом расстроиться.



Вот это конфигурационный файл в Terragrunt. Файл с расширением .hcl. Вы можете заметить, что он чем-то похож на Terraform файл, но он со своими расширениями.


Основная строка 3 указывает, какой версии модуль взять. И блок inputs на 14-ой строчке указывает, какие аргументы передать в этот модуль. По сути, это все, что надо знать о Terragrunt.


План действий: вы заходите на registry, находите модуль. Пишите, какой модуль вы хотите использовать в строке 3. Читаете документацию, какие параметры принимает этот модуль. Пишите их в строчке 14. Нажимаете terragrunt apply и все.


Вам не надо знать ни Terraform, ни то, как он взаимодействует с ресурсами. Самое главное вам не надо разбираться, почему в AutoScaling модуле около 200-300 строк, что они там делают.


Вам надо понимать, что есть самый низкий уровень, это когда вы смотрите в исходники Terraform, AWS SDK, либо, когда вы смотрите повыше уровнем.


Если я работаю с людьми, которые не знают специфику Amazon, DevOps, инфраструктуры, то я всегда их отгораживают от Terraform-внутренностей. Максимум, что я рекомендую им смотреть, это: скажи мне какой модуль и какие значения передать.


Но не волнуйтесь: Terragrunt вас не заменит, никто вас не уволит, даже если вы будете это использовать, для вас всегда найдется работа.



Есть много разных фич внутри Terragrunt. Самая важная из них заключается в том, что есть возможность запуска hooks до и после определенных команд. Таким образом можно расширять функционал до бесконечности. Другое дело, когда вы будете слишком много hooks добавлять, вы сами споткнетесь в них и будет уже сложнее работать. Но один-два hooks ничего плохого не сделают.



И также есть возможность указания зависимости. На этом слайде в строчке 10 указано, что для того, чтобы создать autoscaling group, нам надо создать VPC. Где находится код для создания VPC? В строчке 11 указано, что он находится в папке VPC. Для того чтобы создать autoscaling group, нам надо взять список public subnet и передать его в этот список. Это делается на строчке 20 указанием dependency.vpc.outputs.public_subnets.


Наверное, кто-то думает: А зачем так делать, если можно использовать data-source и data-sourceм брать какое-то значение из state файла?. Преимуществом в том, что внутри используется нативный terraform output. Что делает Terragrunt? Он переходит в папку, которая указана тут (.vpc) и там запускает terraform outputs.public_subnets. Получают список subnets и подставляют вместо этого значения dependency.vpc. Таким образом здесь указана мягкая ссылка в значении vpc_zone_identifier. И это значение будет получено без использования data-source и т. д.


Также есть возможность запуска конфигурации на самом верхнем уровне. Если у вас инфраструктура описана как 1-in-1, когда у вас есть куча разных блоков, то вы, конечно, не хотите заходить в каждый блок и писать terragrunt apply, и ждать, пока что-то произойдет, нажимать Yes и т. д. Можно зайти в папку уровнем выше и написать terragrunt apply all, тогда он проверит все папки, которые внизу, поймет от какой папки зависит. И спросит: Действительно ли ты хочешь это сделать?. Нажимаем Да. И таким образом он создает все, что надо.


Также в Terragrunt есть поддержка pre-commit. И pre-commit hooks позволяют валидировать синтаксис Terragrunt конфигов, а также обновлять документацию.


Есть такой веб-сайт, где написана документация. Можете почитать, если разберетесь. По-моему, она сейчас написана очень плохо. До этого она была в одном файле, в котором можно было искать. Сейчас ее впихнули в красивый веб-сайт, на котором ничего не понятно.



Да, есть и плохое в Terragrunt, например, Terraform Cloud. Что это значит? Terragrunt работает здорово, когда у вас есть доступ к тому месту, где вы его запускаете.


Если вы хотите использовать Terraform Cloud, то Terragrunt тут не поможет вам. Terraform Cloud стоит много денег. И функционал, который он представляет, стоит от 0 до 70 долларов за человека в месяц. По-моему, это много денег.


И даже если прочитать документацию, проникнуться и сказать, что Terraform Cloud это классно, а потом у вас закончатся деньги, то вы не сможете легко мигрировать в open source. Есть определенный функционал, который доступен в enterprise. Он классный, но его нет в open source версии, поэтому вам надо будет писать большое количество shell-скриптов. И опять-таки workspaces. Они работают по-разному в open source версии и в enterprise, поэтому их лучше вообще не использовать.



Что такое workspaces?



Представьте, что у вас есть одна папка с конфигурацией Terraform, вы запускаете Terraform apply. Создается там инфраструктура, все классно. И тут вы думаете, что я хочу создать эту же инфраструктуру только с чуть-чуть другими значениями. Для этого вы пишите Terraform workspaces new и переключаетесь на другой workspace. Потом вы пишите Terraform plan. И Terraform plan говорит: Я не знаю ни про какие ресурсы. Т. е. у вас есть ресурсы, которые в дефолт workspace, которые вы уже создали, и какой-то новый workspace. Новый workspace вы только создали, поэтому там ничего нет. В этом возникает 100 проблем.



Первая проблема это то, что workspaces никак не отражены в коде. Можно написать shell-скрипты, посмотреть в bucket по названию, по имени файла догадаться.


Вторая проблема для того чтобы правильно работать с инфраструктурой в зависимости от workspaces, в значениях должны писать условие. Например, если Terraform.workspaces = prod, то значение 5, иначе 25. Хорошо, вы так сделали для двух значений. Потом вы осознали, что у вас есть 5 environment и вы, конечно, используете lookup функцию. И берете lookup из ассоциативного массива по ключу, который называется Terraform workspaces. Все классно, вы сами себе усложняете жизнь.


Дальше приходит Вася и спрашивает: Когда этот workspaces был задеплоен? Этот код в production или QA environment?. И вы: Не знаю, надо спросить в slack. Начинается кошмар. А потом кто-то спрашивает: А какая разница между staging и production environment в конфигурации?. На эти вопросы вы не сможете ответить мгновенно.


Смысл работы с инфраструктурой как код в том, что, когда вы открываете файл, то как можно быстрее и в нужном месте вы видите все значения без запуска Terraform в голове. Раньше мы открывали файл Terraform.tfvars, чтобы посмотреть, какие значения там указаны. Мы видим там версии, instances. У нас есть представление.


Когда мы используем workspaces, то мы как бы размазываем информацию по всему. Мы размазываем ее по S3_bucket, в разных state файлах она будет хранится.


И самое главное, мы вводим еще одну ось. У нас есть ось времени и сложности. И мы: Нам этого мало, мы введем еще одну ось, которая называется workspaces name. И мы уже можем запутаться.


Основная плохая штука в workspaces заключается в том, что workspaces это просто ненужный функционал. Можете со мной поспорить. Если вы работаете с workspaces и не потратили на работу с workspaces достаточно много времени на написание shell-скриптов, AWS-утилит, которые смотрят, подчищают ресурсы, то вам это все еще предстоит.


Есть один единственный use cases, когда workspaces имеют смысл. Я его специально сюда не написал, но я о нем иногда рассказываю. Я его не написал, потому что люди начнут говорить, что раз я его написал, значит его можно использовать.


Этот use cases имеет смысл, когда у вас есть инфраструктура, которая живет в течение всего pull request. Т. е. у вас открылся pull request, вы переключили на какой-то workspaces, создали временную инфраструктуру, задеплоили туда что-то, отправили эту ссылку в GitHub. Кто-то посмотрел, что там произошло, смержили код. И удалили эту инфраструктуру, и удалили workspaces. Таким образом, эта инфраструктура заведомо создана, чтобы быть удаленной. Для этого надо написать кое-какие утилиты. И тогда есть смысл брать инфраструктуру, которая задеплоена для production environment и просто переключать workspaces.


Я могу еще экстремальный use cases подсказать. Есть такой бэкенд, который нигде не задокументирован. Он называется inmem. Это следующая стадия за workspaces. Т. е. когда мы создаем workspaces и создаем ресурсы, то они хоть как-то где-то отражены. Если вы не хотите париться, что есть такое понятие, как Terraform state, то можете указать Terraform backend configuration type и там inmem (в памяти). Документации на официальном сайте нет, но это работает.



Решением для большинства проблем с workspaces является то, что мы делаем код, с которым работаем, более повторяющимся. И мы используем модули, конфигурация которого хранится в файле или отдельной папке, вместо излишней магии, которая называется workspaces. Таким образом, у нас есть workspaces, которые вы создаете для чего-то временного. Можно создать папку, которая называется Feature 1. В нее положить код, запустить terraform apply. Создать это все, закоммитить это все. И когда у вас эта фича отжила, написать terraform destroy.


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


Terraform workspaces никак не отражены в коде. И это большая проблема. Я не могу посмотреть в код и сказать, что у нас есть 20 сервисов таких, 10 сервисов таких. Когда вы используете не workspaces, много проблем можно избежать. Используйте модули и будет счастье.



Вот этот слайд, наверное, надо было поставить в самом начале. В данной комнате сидят люди, которые занимаются не только Terraform. Я больше чем уверен, что здесь есть люди, которые занимаются программированием.



Terraform developers сидят в типичной компании. Если вы хотите, чтобы у вас была приличная зарплата, то вы называетесь DevOps-инженерами.


DevOps-инженеры должны использовать все фичи Terraform 0.12, т. е. циклы, динамические блоки, условия, вложенности. Для чего они делают эту всю магию? Для того чтобы показать, как юзерам внутри их компании, пользоваться всем этим.


Артефактом у DevOps-инженеров или Terraform developers является reference architectures, которую они создают. Например, если вы внутри своей компании занимаетесь ICS-сервисами, то есть 100 видов, как задеплоить сервис на Amazon с таким load balancer, с сяким и т. д. Много вариантов. Ваш cloud-архитектор или DevOps-инженер должен понимать, что нам 100 видов не надо, потому что у нас есть один способ, как мы это деплоим. Он пишет этот код, поддерживает его, вкладывает свое время и душу в него, делает его безопасным, думает, как это все будет интегрироваться. И в конце концов артефактом от этого человека будет Terraform-модуль, который он дает своему frontend-разработчику, который вообще не понимает, что такое Terraform. И говорит: Если тебе надо будет задеплоить сервис, ты вызови этот модуль-блок и передай ему вот эти значения. Все, четкое разделение.



А Terraform юзер, который frontend developer, из 0.12 должен радоваться только тем 5 символам, которые изменились. Раньше он писал в двойных кавычках, доллар, фигурная скобка. А сейчас ему не надо их писать. Все остальные фичи Terraform 0.12 это радость того Terraform developer, это все ему.


Не надо заставлять людей, что ты будешь full stack developer и поэтому ты должен выучить Terraform. Он хорошо разбирается в своей какой-то области, он знает, как писать frontend application. Ему не надо расширять функционал просто потому, что вы захотели. Для выполнения своей работы ему не надо в это углубляться.



Когда я провожу воркшопы, то я начинаю с простого, потом усложняю и усложняю. И когда где-то посередине люди отсеиваются, потому что все сложно, то это люди, которые frontend developer, backend developer, machine learning эксперты и т. д. А DevOps-инженеры продолжают дальше слушать, им нормально, им все понятно. Вот это как раз та граница.



Modules.tf. Что это такое? Люди это все визуализируют.



И где-то 2 года назад я подумал, что классно они там все навизуализировали, а теперь мне надо из этого сделать код.


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



https://github.com/antonbabenko/modules.tf-lambda


https://github.com/antonbabenko/modules.tf-demo


И я сделал такой генератор инфраструктура как код именно из визуальных диаграмм. На самом деле мне все равно из чего генерировать их, можно из визуальных диаграмм, можно из текстовых файлов, хоть из аудиофайлов, главное, чтобы это была какая-то структурированная штуковина с зависимостями.


Пример кода можете посмотреть modules.tf.demo.



Берем визуальную штуку, берем готовые строительные компоненты Terraform AWS модуля. И делаем Terragruntом оркестрацию вызовов этих модулей.



В принципе, все просто, да еще и бесплатно. Это open source проект.



https://asciinema.org/a/32rkyxIBJ2K4taqZLSlKYNDDI


На asciinema.org можно посмотреть, как это все работает.



Код, который появляется, подходит для того, чтобы начать работать с проектом. Туда вживлены все Terraform best practices относительно того, как взаимодействуют компоненты между собой, как используются динамические связи внутри Terragrunt.


В конечном результате код, который был сгенерирован, не содержит в себе Terraform файлов, ресурсов. Там используется только Terragrunt вызов такой-то и такой-то и все.


Советую посмотреть, если вам интересно, как можно работать с кодом как пользователь. Если вы хотите посмотреть, как оно работает внутри, как работают модули, как это все пишется, то все это open source, заходите и смотрите, отправляйте pull requests, issues и т. д.



Часто люди говорят, что это все классно, но надо сначала нарисовать, а потом это все появится в коде. Да, это так. Зато это появится в коде, вы можете это запустить. Когда вы это запустите, это появится в Amazon. Когда оно появится в Amazon, оно появится на графике у вас. Все более-менее связано. Я уверен, что многие люди хотят этого. Это довольно насыщенный рынок. Сейчас я знаю около 10 компаний в мире, которые делают похожие штуки, т. е. они все визуализируют, кто-то делает это в close course проектах.


Генерация из Terraform в визуальные диаграммы это одна из запрашиваемых фич. Технически реализовать это несложно, если вы писали бы все в одном стиле Terraform-код, т. е. выкинули 99 % фич Terraform и все писали без использования циклов, сложных вещей. Тогда это легко было бы визуализировать. Но вы наслушаетесь моих докладов, потом вы используете модули и т. д.



https://github.com/sponsors/antonbabenko


У меня все. Есть несколько ссылок. Меня легко найти везде. Пишите, приходите завтра на конференцию Delivery excellence.


Вопросы


Спасибо за доклад! Было интересно. Небольшой коммент насчет того, что Terraform Cloud это плохо, дорого. На самой деле там есть бесплатная фича Terraform backend. Там можно бесплатно хранить tfstate, лог файлов. Это даже лучше, чем на S3, потому что там есть Diff, а также удобно работать с командой, либо с CI. Еще есть один способ использовать Terraform pipeline. У вас был слайд all-in-one, 1-in-1. Terraform анонсировал depends_on, т. е. зависимость между модулями. Возможно, скоро Terragrunt будет бесполезен. Что вы думаете по этому поводу?


Да, это все правильно. Понятно, что Terraform Cloud существует, потому что у него есть пользователи. Но я, как представитель open source community, вижу, как 99 % функционала Terraform Cloud люди реализовывают в течение того времени, сколько я этим занимаюсь. Есть такие штуки, как Atlantis, GitHub-actions. Люди используют это очень-очень радостно.


Когда мы используем Terraform Cloud, я переживаю больше не про цену. Я переживаю, что мы насильно привязываем себя к этому функционалу, который нам не нужен. Remote state на сервере Terraform в конечном счете хранится на S3.


Эта штука классная, вопросов нет, но есть очень много решений других. Если вы хотите посмотреть на варианты, которые не Terraform Cloud, то очень рекомендую использовать Atlantis, который позволяет запускать Terraform из pull request. Т. е. открываете pull request, пишите atlantis plan. Terraform запускается не на вашем компьютере, не на каком-то Jenkins. В моем случае запускается на AWS forget instance. И ответ Terraform plan возвращается ко мне в pull request. Я вижу все это в одном месте.


Разработчик Atlassian присоединился к команде Terraform. И он сам советовал в своем блокпосте использовать бэкенд Terraform Cloud. Это бесплатно. Это тоже удобная штука.


Я знаю Люка хорошо.


Писали вы ли своих кастомных провайдеров? Если да, то насколько это сложно сделать?


По трезвому нет. У меня было интересное задание, которое я реализовывал, использовал от MasterCard REST Provider. Это настройка над провайдером, которой подсовываешь swagger файл. И он делает динамически Terraform-провайдер на основании этого swagger файл. Я ему подсовывал swagger файл и те команды, которые описаны внутри swagger файла, они работали. Это был самый простой способ начала писания. А так я иногда там что-то коммичу, но ничего серьезного.


Там есть интересная проблема. Если вы работали с Amazon, то у вас возникали ситуации, когда какая-то issue сидит в провайдере очень долго, и никто не знает, что происходит. Там upload больше сотни, народ пишет: Что происходит? Когда эта фича будет смержена?. Люди потратили время и написали какой-то код, и провайдер уже почти готов, а Brian ничего не может сделать. Ситуаций очень много, поэтому проблем с провайдерами тоже очень много.


Спасибо за такой оживленный доклад, который расшевелил аудиторию. И хочу задать вопрос относительно рисовалки, которую вы представляли. Она тоже open source?


Cloudcraft?


Да.


Cloudcraft не open source.


И второй момент. Вы показали, что можно, нарисовав просто структуру, трансформировать в Terraform, а затем в AWS. Такое ощущение, что какой-нибудь менеджер может нарисовать картинку и все это поднять в AWS. Насколько это сложный процесс?


Я, надеюсь, что менеджер этого делать не будет, потому что это дает только начальные данные. По идее, я должен месяц назад был закончить это, но не успел. Т. е. как сделать так, чтобы в визуальном виде запрашивать у людей больше информации? Например, когда рисуешь EC2 instance, ты можешь еще указать 50 параметров: IP-адреса, в какой subnet и т. д. Т. е. какие-то мета-данные ты должен предоставить. И это очень нетривиальная задача. Пока не знаю, но это не open source решение. Есть drowto.io, который open source, который совместимый с Cloudcraft, можно его использовать.


Спасибо за доклад! Вопрос, может быть, немного не по теме. Я хотел бы задать вопрос по поводу Terraform-модулей. Можно ли Terraform модули рассматривать в качестве замены Helm Charts?


Надеюсь, что нет.


И имею в виду в плане развития самих модулей и провайдера.


Провокационный вопрос. Terraform-модули и сам Terraform хорошо работают в создании инфраструктуры. Все, что касается provisioning, запуска сервисов, запуска shell-скриптов это очень стремная тема для Terraform. Можно много, что делать. Можно Helm Charts создавать и запускать. В общем, есть какие-то решения. Но каждый раз, когда я работаю с Helm из Terraform, у меня какая-то боль возникает. И потом, когда я разговариваю с людьми, они мне говорят, чтобы с ним не работать. А я люблю использовать Terraform намного больше, чем я сейчас рассказал. Т. е. и Helm, и Kubernetes, и все-все применяю, используя Terraform apply. Ты запустил Terraform apply и ушел на год. Это мое видение.


Понятно, что есть необходимость для создания образов. По-прежнему есть Helm, который тоже развивается как сумасшедший. Там есть открытая issue Helm 3 provider для Terraform, где очень оживленная дискуссия, что вот-вот будет это готово. Но об этом я, по-моему, слышу уже полгода. Там очень много проблем.


Насколько я знаю, есть Kubernetes-провайдер для Terraform. Правда, я не видел, чтобы его активно использовал.


В том то и дело. Оно все есть, но пользуется далеко не все или в каких-то ограниченных use cases. По-моему, эта проблема со всем Kubernetes-движением. Ты можешь использовать одну утилиту сегодня, завтра что-то другое выйдет, либо она отвалится. Terraform сам по себе развивается в ту сторону, чтобы дать людям возможность легко писать провайдеры, дать больше функционала для описания ресурсов. И когда приходят такие большие штуки, как Kubernetes, то они не вписываются в Terraform вообще никак. И поэтому возникает куча проблем.


Спасибо за доклад! У меня практический вопрос. Какой есть лучший способ, как в модуле считать count по output других модулей, если я передаю это list или map?


Т. е. есть модуль, который возвращает какое-то значение?


Например, если у нас есть дефолтный VPC и еще несколько VPC, которые мы создаем на основе какого-то модуля, а потом в другом модуле я хочу применить restrictions security group для всех VPC. Я передаю list.


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


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


Один способ, как я иногда это решаю. Я пишу terraform apply -target и указываю один модуль, а потом пишу terragrunt apply и все остальное. Но это я пишу только тогда, когда не могу использовать Terragrunt. Т. е. надо использовать target и надеяться, что оно не рассыплется. Оно рассыплется, скорее всего, в другом месте, но, по крайней мере, это сработает.


Антон, спасибо за доклад! У меня есть вопрос по поводу all-in-one и 1-in-1. Допустим, есть платформа. Платформа состоит из компонентов. Компоненты состоят из ресурсов AWS. Мы, например, создаем модули для ресурсов AWS, версионируем их. Дальше используем подход all-in-one и описываем компонент с помощью версионируемых модулей. И получается модуль для компонента. Дальше мы через Terragrunt, используя один файл, мы деплоим целый компонент. Почему это нелогично? Потому что я понял из твоего разговора, что логичный переход это с all-in-one на 1-in-1.


Нет, там был слайд MFA somewhere in between. Это означает, что это ситуация, когда тебе надо использовать и то и другое. Один из use cases это когда тебе надо управлять большим количеством маленьких вещей. Например, у тебя есть 100-500 AM userов и ты не хочешь под каждого из них создавать отдельный модуль. Ты пишешь один мастер-модуль и передаешь туда список этих юзеров. В таком случае у тебя all-in-one внутри используется. Эта ситуация разделения all-in-one, 1-in-1 достаточно относительная.


И я больше хотел показать, что есть такие способы. Есть один способ, есть второй способ. И ты знаешь преимущество и одного, и второго способа. И тогда можно придумать третий способ, который где-то посередине. В живых проектах полностью all-in-one я не встречал. Если до фанатизма все разделять, то получается непрактично. И получается много кода, который можно сгруппировать.

Подробнее..

Паттерны в Terraform для борьбы с хаосом и ручной рутиной. Максим Кострикин (Ixtens)

23.10.2020 10:09:29 | Автор: admin


Казалось бы, разработчики Terraform предлагают достаточно удобные best practices для работы с AWS-инфраструктурой. Только есть нюанс. Со временем количество окружений увеличивается, в каждом появляются особенности. Появляется почти копия стека приложений в соседнем регионе. И Terraform-код нужно аккуратно скопировать и отредактировать согласно новым требованиям или сделать снежинку.


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


Видео:




Мне 40, я 20 лет в IT. 12 лет работаю в компании Ixtens. Мы занимаемся ecommerce-driven-development. И 5 лет практикую DevOps-практики.



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


Цифры на слайде указаны для того, чтобы понимать масштаб проекта. И все, что я буду дальше говорить, связано с Amazon.



Я присоединился к этому проекту 4 года назад. И в самом разгаре проходил рефакторинг инфраструктуры, потому что проект вырос. И те паттерны, которые использовались, они уже не подходили. И учитывая весь планируемый рост проекта, нужно было что-то придумать новое.


Спасибо Матвею, который вчера рассказал, что у них происходило в Додо Пицца. Это то, что происходило у нас 4 года назад.


Пришли разработчики и стали делать инфраструктурный код.


Самые очевидные моменты, почему это требовалось, нужно было time to market. Нужно было сделать так, чтобы DevOps-команда не была узким местом при выкатке. И кроме всего прочего на самом первом уровне использовались Terraform и Puppet.



Terraform это open source проект компании HashiCorp. И для тех, кто вообще не в курсе, что это, следующие несколько слайдов.



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


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



После этого в консоли настроим доступ к Amazon. И попросим Terraform plan. Terraform plan скажет: Ок, для вашего ресурса мы можем сделать вот такие штуки. И, как минимум, один ресурс будет добавлен. И никаких изменений не предвидится.



После того, как вас все устроило, вы можете попросить Terraform apply и Terraform создаст вам instance, и вы получите виртуальную машину в вашем облаке.



Далее наш проект развивается. Мы добавляем туда какие-то изменения. Мы просим больше instances, мы добавляем 53 запись.



И повторяем. Просим plan. Видим, какие изменения планируются. Применяем. И таким образом наша инфраструктура растет.


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



Эти state-файлы первоначально были просто файлами. И мы их хранили в Git, что было крайне неудобно. Постоянно кто-то забывал прокоммитить изменения, и возникало много конфликтов.


Сейчас есть возможность использовать бэкенд, т. е. Terraform указывается в какой bucket, по какому ключу нужно сохранить state-файл. И Terraform сам позаботится о том, чтобы достать этот state-файл, сделать всю магию и положить обратно финальный результат.



Наша инфраструктура растет. Вот наш код. И мы теперь не хотим просто создавать виртуальную машину, мы хотим иметь тестовое окружение.



Terraform позволяет сделать такую штуку как модуль, т. е. тоже самое описать в какой-то папке.



И, например, в тестинге вызвать этот модуль и получить тоже самое как будто мы выполняли Terraform apply в самом модуле. Для тестинга будет вот такой код.



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



И дальше я вернусь обратно в проект. Была сложная задача, инфраструктура планировалась очень большой. И нужно было как-то разместить весь код, чтобы это было удобно для всех: и для тех, кто производит maintenance над этим кодом, и для тех, кто вносит изменения. А планировалось, что любой разработчик может пойти и поправить инфраструктуру так, как нужно для его части платформы.


Это дерево каталогов, которое рекомендуется самим HashiCorp, если у вас большой проект и есть смысл разделить всю инфраструктуру на какие-то маленькие кусочку, и каждые кусочки описывать в отдельной папочке.


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



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


Terraform беспокоится обо всех зависимостях. И всегда создает ресурсы в той последовательности, чтобы можно было получить IP-адрес, например, от свежесозданного instance, и получить этот IP-адрес в route53 запись.


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


И мы автоматизировали это дело. И Jenkins job позволял запускать стек. В нем нужно было запускать pull request с изменениями, которые хочет разработчик протестировать, указать все нужные опции, компоненты, а также размеры. Если он хочет performance тестирование, то он может побольше instances взять. Если ему нужно просто проверить, что какая-то формочка открывается, то мог стартануть на минималках. А также указать нужен кластер или не нужен и т. д.


И потом Jenkins толкал shell-скрипт, который немножко модифицировал код в папке Terraform. Убирал ненужные файлы, добавлял нужные файлы. И потом одним прогоном Terraform apply стек поднимался.


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



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


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


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


По сути, Terraform это не настоящий язык. Это декларация. Если нам нужно что-то задекларировать, то мы это декларируем. И все это работает.


В какой-то момент, когда обсуждался один из моих pull request, один из коллег сказал, что не нужно плодить снежинки. Я заинтересовался, что он имеет в виду. Есть такой научный факт, что в мире не существует двух одинаковых снежинок, все они чуть-чуть, да отличаются. И как только я это услышал, я сразу ощутил всю тяжесть Terraform-кода. Потому что когда требовалось перейти с версии на версию, то Terraform требовал breaking chain изменения, т. е. код больше не был совместим со следующей версией. И приходилось делать pull request, который покрывал почти половину файлов в инфраструктуре, чтобы привести инфраструктуру к следующей версии Terraform.


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


Для внешнего разработчика, который вне operation, для него это не имеет большого значения, потому что он сделал pull request, его ресурс запустился. И все, дальше не его забота. А команде DevOps, которые следят за тем, чтобы все было Ок, требуется делается делать все эти изменения. И стоимость этих изменений очень-очень сильно возрастала с каждой дополнительной снежинкой.



Есть такая история про то, как студент на семинаре рисует мелом на доске два идеальных круга. И преподаватель удивляется, как ему удалось так ровно без циркуля нарисовать. Студент отвечает: Очень просто, я два года в армии крутил мясорубку.


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



Первое, с чего я хотел бы начать, это Symlinks. Terraform имеет много повторяющегося кода. Например, вызов провайдера практически в каждой точке, где мы создает кусочек инфраструктуры, один и тот же. И логично вынести его в отдельную папочку. И везде, где требуется провайдер делать Symlinks на этот файлик.



Например, у вас в production используется assume role, который позволяет вам получить права доступа на какой-то внешний Amazon-аккаунт. И поменяв один файлик, все оставшиеся, которые в дереве ресурсов, будут иметь требуемые права, чтобы Terraform знал к какому Amazon-сегменту обращаться.



Где Symlinks не работают? Как и говорил, в Terraform есть state-файлы. И они очень-очень классные. Но дело в том, что Terraform инициализирует бэкенд в самом первом. И он не может использовать в этих параметрах какие-либо переменные, их всегда нужно писать текстом.


И как результат, когда кто-то делает новый ресурс, он копирует часть кода из других папочек. И он может ошибиться с ключом или с bucket. Например, он из sandbox делает sandbox-штуку, а потом делает в production. И так может оказаться, что bucket в production будет использоваться из sandbox. Конечно, это быстро найдут. Можно будет это как-то исправить, но тем не менее это потеря времени и в какой-то степени ресурсов.



Что мы можем сделать далее? Перед тем, как работать с Terraform надо его проинициализировать. В момент инициализации Terraform выкачивает все плагины. Они в какой-то момент из монолита разбились на более микросервисную архитектуру. И всегда нужно делать Terraform init, чтобы он подтянул все модули, все плагины.


И можно использовать shell-скрипт, который, во-первых, сможет достать все переменные. Shell-скрипт ничем не ограничен. А, во-вторых, пути. Если мы всегда используем тот путь, который в репозитории как ключ к state-файлу, то, соответственно, ошибка здесь будет исключена.



Откуда достать данные? JSON-файл. Terraform позволяет записывать инфраструктуру не только в hcl (HashiCorp Configuration Language), но и в JSON.


JSON легко читается из shell-скрипта. Соответственно, можно в какое-то место положить конфигурационный файл с bucket. И использовать этот bucket и в Terraform-коде, и в shell-скрипте для инициализации.



Почему важно иметь bucket для Terraform? Потому что есть такая штука как remote state-файлы. Т. е. когда я поднимаю какой-то ресурс, мне для того, чтобы сказать Amazon: Подними, пожалуйста, instance, нужно указать очень много обязательных параметров.


И эти идентификаторы хранятся в какой-то другой папочке. И я могу взять и сказать: Terraform, сбегай, пожалуйста, в state-файл того самого ресурса и достань мне эти идентификаторы. И таким образом появляется некая унификакция между различными регионами или environments.


Не всегда можно использовать удаленный state-файл. Например, вы руками создали VPC. И тот Terraform-код, который создает VPC, создает настолько непохожий VPC, что очень долго и нужно вам придется подстраивать одно под другое, поэтому можно использовать следующую фишку.



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



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



Сейчас немножко про тестирование. Что в Terraform можно тестировать? Наверное, многое можно, но я буду говорить про вот эти 4 штучки.


У HashiCorp есть понимание, как нужно форматировать Terraform-код. И Terraform fmt позволяет вам отформатировать код, который вы редактируете в соответствие с этой верой. Соответственно, тесты должны обязательно проверить, а соответствует ли форматирование тому, что завещал HashiCorp, чтобы не приходилось менять расположение скобочек и т. д.



Следующий это Terraform validate. Он делает немножко большее, чем проверку синтаксиса аля, все ли скобки парные. Что здесь важно? У нас инфраструктура очень развесистая. В ней очень много различных папочек. И в каждой нужно запустить Terraform validate.


Соответственно, чтобы ускорить тестирование, мы запускаем несколько процессов параллельно, используя параллель.


Параллель это очень классная штука, пользуйтесь.


Но каждый раз, когда происходит инициализация Terraform, он идет на HashiCorp и спрашивает: Какие последние версии плагинов? А тот плагин, который у меня кэше он тот или не тот?. И это на каждом шаге давало свое замедление.



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



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



Следующее это Terraform plan. Как и говорил, разработка циклична. Мы делаем код с изменениями. И потом нужно узнать, какие изменения планируются на инфраструктуру.


И когда инфраструктура очень-очень большая, можно поменять один модуль, починить какое-то тестовое окружение или какой-нибудь конкретный регион и сломать какой-нибудь соседний. Поэтому Terraform plan должен делаться на всю инфраструктуру и показывать, какие изменения планируются.


Делать это можно по умному. Мы, например, написали скрипт на Python, который разрезолвивает зависимости. И в зависимости оттого, что было изменено: Terraform-модуль или просто какой-то конкретный компонент, он делает планы на все зависимые папочки.


Terraform plan должны делать по запросу. По крайней мере, это то, что делаем мы.


Тесты, конечно, хорошо делать на каждое изменение, на каждый коммит, но планы это достаточно дорогая штука. И мы в pull request говорим: Пожалуйста, дай мне планы. Запускается робот. И присылает в комменты или в attach все планы, которые предполагаются от ваших изменений.


План вещь достаточно дорогая. Она занимает время, потому что Terraform идет в Amazon и спрашивает: А этот instance еще существует? А у этого autoscale точно такие параметры?. И для того чтобы это ускорить, можно использовать такой параметр, как refresh=false. Это значит, что Terraform выкачает из S3 state. И будет верить, что state будет точно соответствовать тому, что находится в Amazon.


Такой Terraform plan проходит гораздо быстрее, но state должен соответствовать вашей инфраструктуре, т. е. где-то, когда-то должен запуститься Terraform refresh. Terraform refresh делает именно то, чтобы state соответствовал тому, что находится в реальной инфраструктуре.


И нужно сказать о безопасности. С этого и надо было начинать. Там, где вы запускаете Terraform, и Terraform работает с вашей инфраструктурой, есть уязвимость. Т. е. вы, по сути, выполняете код. И если pull request содержит какой-то вредоносный код, то он может исполниться на инфраструктуре, которая имеет слишком много доступа. Поэтому будьте внимательны, где вы запускаете Terraform plan.



Следующее, о чем я хотел бы рассказать, это тестирование user-data.


Что такое user-data? В Amazon, когда мы создаем instance, мы можем с instance отправить некое письмо мета-данные. Когда instance запускается, обычно cloud init всегда присутствует на этих instances. Cloud init считывает это письмо и говорит: Ок, сегодня я load balancer. И в соответствие с этими заветами производит какие-то действия.



Но, к сожалению, когда мы делаем Terraform plan и Terraform apply, user-data выглядит, как вот такая кашица из цифр. Т. е. он просто присылает вам хэш. И все, что вы можете посмотреть в плане, это будут ли какие-то изменения или хэш останется тем же самым.


И если на это не обращать внимание, то на Amazon, на реальную инфраструктуру может уйти какой-то побитый текстовый файлик.



Как вариант, можно при выполнении указать не всю инфраструктуру, а только template. И в коде сказать: Пожалуйста, выведи мне на экран этот template. И в итоге можно получить распечатку, как будет выглядеть ваши данные на Amazon.



Другой вариант это использовать модуль для генерации user-data. Вы примените этот модуль. Получаете файл на диске. Сравниваете его с референсным. И таким образом, если какой-то джун решит поправить немножко user-data, то ваши тесты скажут: Ок, вот здесь и здесь какие-то изменения это нормально.



Следующее, о чем я хотел бы рассказать, это Automate Terraform apply.


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


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


В production, sandbox и других окружениях, которые более важны для бизнеса, можно применять частично некоторые ресурсы достаточно безопасно, потому что это не приводит к тому, что кто-то умирает. Это: autoscale-группы, security-группы, roles, route53 и там список может быть достаточно большой. Но следите за тем, что происходит, читайте отчеты об автоматических применениях.


Там, где применять опасно или боязно, например, если это какие-то ресурсы с persistent, с базы данных, то получайте отчеты о том, что в каком-то кусочке инфраструктуры есть не примененные изменения. И инженер уже под надзором запускает jobs, чтобы применить или делает это со своей консоли.


В Amazon есть такая штука как Terminate protection. И она может защитить в некоторых случаях от нетребуемых для вас изменений. Т. е. Terraform пошел на Amazon и говорит: Мне нужно убить этот instance, чтобы сделать другой. А Amazon говорит: Sorry, не сегодня. У нас стоит Terminate protection.



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


И это очень сложно читаемо. На это очень сложно делать review. И очень часто получается так, что какие-то параметры проходят review и они не совсем те, которые нужны. А это стоит времени и денег, чтобы потом исправить.



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



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


В этом модуле можно сделать некие вычисления, используя такую свежую фичу в Terraform, как locals. И потом одним outputом выдать какой-то сложный параметр, который может включать в себе хэши массивы и т. д.



На этом все самые лучшие находки, которые у меня есть закончились. И хотел бы рассказать байку про Колумба. Когда он искал деньги на свою экспедицию, чтобы открыть Индию (как тогда он думал), ему никто не верил и считали, что это невозможно. Тогда он сказал: Сделайте так, чтобы яйцо не упало. Все банкиры, очень богатые и, наверное, умные люди, пытались каким-то образом поставить яйцо, и оно все время падало. Тогда Колумб взял яйцо, немножко на него надавил. Скорлупа смялось, и яйцо осталось неподвижным. Они сказали: О, это слишком просто!. И Колумб ответил: Да, это слишком просто. И когда я открою Индию, все будут использовать этот торговый путь.


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



Подведем итоги:


  • Постарайтесь избегать снежинок. И чем меньше снежинок, тем меньше ресурсов вам потребуется, чтобы делать какие-то изменения на всей вашей большой инфраструктуре.
  • Постоянные изменения. Т. е. когда в коде произошли какие-то изменения, нужно как можно быстрее привести вашу инфраструктуру в соответствие с этими изменениями. Не должно быть ситуации, когда кто-то через два-три месяца приходит, чтобы посмотреть Elasticsearch, делает Terraform plan, а там куча изменений, которых он не ожидал. И тратится очень много времени для того, чтобы привести обратно все в порядок.
  • Тесты и автоматизация. Чем больше у вас код покрыт тестами и фишками, то тем больше у вас уверенность в том, что вы все делаете правильно. А автоматическая доставка увеличит вашу уверенность многократно.
  • Код для тестового и production-окружения должен быть практически одинаковым. Практически, потому что все-таки production немножко другой и там все равно будут какие-то нюансы, которые будут выходить за рамки тестового окружения. Но тем не менее плюс-минус можно это обеспечить.
  • И если у вас очень много Terraform-кода и на поддержку этого кода в актуальном состоянии требуется очень много времени, то никогда не поздно сделать refactoring и привести его в хорошую форму.


  • Immutable infrastructure. Доставка AMI по расписанию.
  • Структура для route53, когда у вас записей очень много и вам хочется, чтобы они были в согласованном порядке.
  • Борьба с API rate limits. Это когда Amazon говорит: Все-все, больше я не могу принимать запросов, пожалуйста, подождите. И половина конторы ждет, пока она сможет запустить свою инфраструктуру.
  • Spot instances. Amazon недешевое мероприятия и spots позволяют достаточно много экономить. И там можно рассказать целый доклад об этом.
  • Безопасность и IAM roles.
  • Поиск потерянных ресурсов, когда у вас в Amazone есть instances непонятного происхождения, они кушают деньги. Даже если instances стоит 100-150 долларов в месяц за год это 1 000 с лишним. Поиск таких ресурсов это прибыльное дело.
  • И зарезервированные instances.


На этом у меня все. Terraform это очень круто, пользуетесь. Спасибо!


Вопросы


Спасибо за доклад! У вас state-файл лежит в S3, а как вы решаете проблему, что несколько человек могут взять этот state-файл и попытаться развернуться?


Во-первых, мы не торопимся. Во-вторых, есть flags, в котором мы сообщаем о том, что мы работаем над каким-то участком кода. Т. е. несмотря на то, что инфраструктура очень большая, это не значит, что постоянно кто-то что-то применяет. И когда была активная фаза это было проблемой, у нас state-файлы в Git хранились. Это было важно, иначе кто-то сделает state-файл, и нам приходилось вручную их собирать в кучу, чтобы все дальше продолжалось. Сейчас такой проблемы нет. А вообще, Terraform решил эту задачу. И если постоянно что-то меняется, то можно использовать locks, которые предотвращают то, что вы сказали.


Вы используете открытую версию или enterprise?


Никакого enterprise, т. е. все, что можно пойти и скачать бесплатно.


Меня зовут Станислав. Я хотел сделать маленькое дополнение. Вы рассказали про фичу Amazon, которая позволяет сделать instance неубиваемым. Это есть и в самом Terraform, в блоке Life Second можно прописать запрет на изменение, либо запрет на уничтожение.


Во времени был ограничен. Хорошее замечание.


Еще хотел спросить две вещи. Во-первых, вы рассказали про тестирование. Пользовались ли вы какими-то инструментами для тестирования? Я слышал про плагин Test Kitchen. Возможно, есть что-то еще. И хотел бы еще спросить про Local Values. Чем они в принципе отличаются от Input Variables? И почему я не могу параметризировать что-то только через Local Values? Я пытался разобраться с этой темой, но как-то не разобрался сам.


Мы можем поподробней поговорить за этим залом. Инструменты для тестирования это у нас полный самопал. Там ничего такого нет, чтобы протестировать. А вообще, есть варианты, когда автоматические тесты поднимают инфраструктуру где-то, проверяют, что она Ок, а потом все уничтожают с отчетом, что ваша инфраструктура все еще в хорошей форме. У нас этого нет, потому что тестовые стеки запускаются каждый день. И этого достаточно. И если что-то начало ломаться, то оно начнет ломаться без того, что мы еще где-то это проверим.


По поводу Local Values давайте продолжим разговор за залом.


Привет! Спасибо за доклад! Очень познавательно. Ты говорил, что у вас очень много однотипного кода для описания инфраструктуры. Не рассматривали ли вы вариант генерации этого кода?


Отличный вопрос, спасибо! Дело в том, что, когда мы используем инфраструктуру как код, мы предполагаем, что мы смотрим на код и понимаем, какая инфраструктура за этим кодом лежит. Если код генерируется, то нам нужно представить, какой код сгенерируется, чтобы понять, какая инфраструктура там будет. Либо мы генерируем код, коммитим его и, по сути, получается то же самое. Поэтому мы пошли по тому пути, как мы написали, мы это получили. Плюс генераторы появлялись несколько позже, когда мы начали делать. И уже поздно было менять.


Про jsonnet слышал что-нибудь?


Нет.


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


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


Просто посмотри. Спасибо!


Меня зовут Максим, я из Сбербанка. Вы немного рассказали, что пытались привести Terraform к аналогу языка программирования. Не проще пользоваться Ansible?


Это очень разные вещи. Можно и Ansible создавать ресурсы, и Puppet можно создавать ресурсы в Amazon. Но Terraform прямо заточен.


У вас только Amazon?


Дело не в том, что у нас только Amazon. У нас почти только Amazon. Но ключевая фича в том, что Terraform помнит. В Ansible, если сказать: Подними мне 5 instances, то он поднимет, а потом ты говоришь: А теперь мне нужно 3. И Terraform скажет: Ок, 2 убью, а Ansible скажет: Ок, вот тебе 3. Итого 8.


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


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


Вопрос такой. Вы используете Remote backend, вы используете S 3. Почему официальный бэкенд не используете?


Официальный?


Terraform Cloud .


Когда он появился?


Месяца 4 назад.


Если бы он появился 4 года назад, то, наверное, я бы ответил на ваш вопрос.


Там есть уже встроенная функция и locks, и можно хранить state -файл. Попробуйте. Но я тоже не тестировал.


Мы едем в большом поезде, который движется с большой скоростью. И нельзя просто взять и выкинуть несколько вагонов.


Вы говорили про снежинки, а почему вы не использовали branch? Почему не получилось так сделать?


У нас такой подход, что вся инфраструктура в одном репозитории. Terraform, Puppet, все скрипты, которые хоть как-то к этому относятся, они все в одном репозитории. Таким образом, можем гарантировать, что инкрементальные изменения протестированы один за другим. Если бы это было куча branches, то такой проект практически невозможно обслуживать. Проходят полгода, и они настолько расходятся, что это просто наказание какое-то. Это то, от чего захотелось убежать до рефакторинга.


Т. е. это не работает?


Это вообще не работает.


В branch я вырезал слайд папки. Т. е. если сделать на каждый тестовый стек, например, у команды А у нее своя папочка, у команды Б своя папочка, то это тоже не работает. Мы сделали унифицированный код тестового окружения, который был достаточно гибкий, чтобы подходить всем. Т. е. мы один код обслуживали.


Привет! Меня зовут Юра! Спасибо за доклад! Вопрос о модулях. Вы говорите, что вы используете модули. Как решаете вопрос, если в одном модуле внесли изменения, которые не совместимы с изменением другого человека? Как-то версионируете модули или пытаетесь привести вундервафлю, чтобы соответствовать двум требованиям?


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


Т. е. пока никак не решается?


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


Здравствуйте! Спасибо за доклад! Хотел бы уточнить. За кадром осталась большая куча, ради которой я пришел. Каким образом интегрированы Puppet и раздача ролей?


User-data.


Т. е. просто выплевываете файлик и по нему как-то выполняете?


User-data это записка, т. е. когда мы делаем клон образа, то там поднимается Daemon и пытаясь разобраться, кто он, читает записку, что он load balancer.


Т. е. это какой-то отдельный процесс, который отдается?


Не мы его изобрели. Мы им пользуемся.


Здравствуйте! У меня как раз вопрос про User data. Вы сказали, что там есть проблемы, что кто-то может что-то не туда передать. Есть какой-то способ хранения user data в том же самом Git, чтобы всегда было понятно, на что ссылается User-data?


Мы User-data генерируем из template. Т. е. туда прибегает какое-то количество переменных. И Terraform генерирует финальный результат. Поэтому нельзя просто так посмотреть на template и сказать, что получится, потому что все проблемы связаны с тем, что разработчик думает, что он в этой переменной передает строчку, а там прибегает массив. И у него бац и я тот-то, тот-то, следующая строчка, и все сломалось. Если это новый ресурс и человек поднимает его, видит, что что-то не работает, то это быстро решается. А если это autoscale-группа обновилась, то в какой-то момент instances в autoscale-группе начинают подменяться. И хлоп, что-то не работает. Это обидно.


Получается, что единственное решение это тестировать?


Да, вы видите проблему, вы туда добавляете тестовые шаги. Т. е. outputом тоже можно тестировать. Может быть, не так удобно, но тоже можно какие-то метки поставить проверяйте, что User-data тут гвоздями прибита.


Меня зовут Тимур. Очень классно, что есть доклады про то, как правильно организовывать Terraform .


Я даже не начинал.


Я думаю, что в следующей конференции, может быть, будет. У меня есть простой вопрос. Почему вы хардкодите значение в отдельном модуле, а не используете tfvars, т. е. чем лучше модуль со значениями, чем tfvars ?


Т. е. мне здесь (слайд: Production/environment/settings.tf) написать: domain = переменная, domain vpcnetwork, переменная vpcnetwork и stvars достать тоже самое?


Мы же точно так делаем. Ссылаемся на модуль setting source, например.


По сути, это такой tfvars. Tfvars очень удобен в testing-окружении. У меня есть tfvars для больших instances, для маленьких. И я один файлик кинул в папку. И получил то, что я хотел. Когда мы инфраструктуру пилим, мы хотим, чтобы можно было посмотреть и сразу все понять. А так получается, что надо глянуть сюда, потом глянуть в tfvars.


Получается, чтобы все было в одном месте?


Да, tfvars это когда у вас один код. И он используется в нескольких разных местах с разными нюансами. Тогда вы бы tfvars кинули и получили ваши нюансы. А мы это инфраструктура как код в чистом виде. Посмотрел и понял.


Здравствуйте! Сталкивались с такими ситуациями, когда облачный провайдер вмешивается в то, что вы сделали Terraform ом? Допустим, мы мета-данную правим. Там ssh -ключи. А Google постоянно туда подсовывает свои мета-данные, свои ключи. И Terraform всегда пишет, что у него есть изменения. После каждого прогона, даже если ничего не меняется, он всегда говорит, что он сейчас это поле будет обновлять.


С ключами, но да, часть инфраструктуры поражена такой штукой, т. е. Terraform поменять ничего не может. Мы руками тоже поменять ничего не можем. Пока живем с этим.


Т. е. вы с таким сталкивались, но ничего не придумали, он как делает и делает сам?


К сожалению, да.


Здравствуйте! Меня зовут Старков Станислав. Mail. ru Group. Как решаете проблему с генерацией тега на , как вы его передаете внутрь? Я так понимаю, через User data, чтобы указать host name, Puppet натравить? И вторая часть вопроса. Как вы решаете этот вопрос в SG, т. е. когда вы генерируете SG, сотня однотипных instances, как их правильно наименовать?


Те instances, которые нам очень важны, мы их наименуем красиво. Те, которые не нужны, там приписка, что это autoscale-группа. И по идее это можно прибить, и получить новый.


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


Про что еще вопрос был?


Когда SG создает сотню instances, их нужно как-то различать?


Нет, не надо. На каждом instance есть агент, который сообщает, что у меня проблема. Если агент сообщает, то про него агент знает и, как минимум, его IP-адрес существует. Уже можно сбегать. Во-вторых, у нас используется Consul для Discovery, там, где не Kubernetes. И Consul тоже показывает IP-адрес instance.


Т. е. вы ориентируетесь именно на IP, а не на host name ?


Невозможно ориентироваться по host name, т. е. их очень много. Есть идентификаторы instance AE и т. д. Его можно где-нибудь найти, можно его в поиск кинуть.


Привет! Я понял, что Terraform это хорошая штука, заточенная под облака.


Не только.


Именно этот вопрос мне и интересен. Если вы решите переезжать, допустим, на Bare Metal массово со всеми своими instances? Не будет никаких проблем? Либо все-таки придется использовать другие продукты, например, тот же Ansible, который был здесь упомянут?


Ansible немножко про другое. Т. е. Ansible работает уже тогда, когда instance запустился. А Terraform работает до того, как instance запустился. Переход на Bare Metal нет.


Сейчас нет, а придет бизнес и скажет: Давай.


Переход на другое облако да, но тут немножко другая фишка. Нужно писать так Terraform-код, чтобы с меньшей кровью можно было перейти на какое-то другое облако.


Изначально ставилась такая задача, что у нас вся инфраструктура агностик, т. е. любое облако должно подойти, но в какой-то момент бизнес сдался и сказал: Ок, в ближайшие N лет мы никуда не уйдем, можно использовать сервисы от Amazon.


Terraform позволяет создавать в Front-End jobs, конфигурировать PagerDuty, data doc и т. д. У него очень много хвостов. Он практически может контролировать весь мир.


Спасибо за доклад! Я уже тоже 4 года кручу Terraform. На этапе плавного перехода к Terraform, к инфраструктуре, к декларативному описанию, мы сталкивались с ситуацией, когда кто-то что-то делал руками, а ты пытался сделать plan. И получал там какую-то ошибку. Как вы такие проблемы разбираете? Как находите потерянные ресурсы, которые были указаны?


В основном руками и глазами, если мы видим в отчете что-то странное, то мы анализируем, что там происходит, либо просто убиваем. А вообще, pull requests это обычное дело.


Если есть ошибка, делаете ли вы rollback? Пробовали такое делать?


Нет, это решение человека в моменте, когда он видит проблему.

Подробнее..

Перевод Используем Ansible вместе с Terraform

30.10.2020 18:08:58 | Автор: admin


Недавно я начал применять Terraform для создания облачной лабы для тестов, и это довольно круто. Буквально за несколько дней я поднялся с никогда не использовал AWS до я умею декларативно создавать изолированную инфраструктуру в облаке. Я поставил парочку серверов в выделенной сети в VPC с security group и отдельными ключами SSH, все это заняло у меня несколько сотен строк кода.


Все приятно и прельстиво, но после создания сервера из некоторого базового AMI мне надо его развернуть. Мой типовой инструмент для этого Ansible, но, к сожалению, у Terraform нет встроенного модуля для Ansible (есть обратный, начиная с Ansible 2.5, прим. переводчика), в отличие от Chef и Salt. Это не похоже на Packer, имеющий ansible (удаленный) и ansible-local, который я использовал для сборки образов Docker.


Так что я потратил немножко времени и нашел несколько способов подружить Terraform и Ansible, о чем расскажу в этой статье. Но сначала поговорим о развертывании.


Нужно ли развертывание в облаке?


Вы, конечно же, можете сделать свой собственный AMI вместо использования типовых пустых, и, следовательно, пропустить полностью развертывание, но у этого способа есть фатальный недостаток. Каждое минимальнейшее изменение потребует пересоздания всего сервера. Если надо что-то поправить на базовом уровне, придется перезаливать все сервера. Это быстро надоедает в случае развертывания, установки обновлений безопасности, добавления или удаления пользователей, изменения настроек и прочих простых вещей.


Далее если делаете свои AMI, вам все равно нужно как-то запускать развертывание, так что опять появляются такие вещи, как Ansible. Ну и опять же, я рекомендую использовать Packer вместе с Ansible.


Получается, что в большинстве случаев развертывание нужно, потому что оно неизбежно.


Как использовать Ansible вместе с Terraform


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


Встроенный inventory с IP сервера


Наиболее очевидное и хакерское решение запускать Ansible с помощью local-exec, например так:


provisioner "local-exec" {    command = "ansible-playbook -i '${self.public_ip},' --private-key ${var.ssh_key_private} provision.yml"}

Просто и приятно, но тут сразу же есть нюанс. local-exec запускается без ожидания запуска сервера, так что в большинстве случаев это не сработает, потому что на момент подключения еще некуда подключаться.


В качестве изящного обходного способа вы можете предварительно использовать remote-exec, который будет ожидать соединения с сервером, а затем запускать local-exec.


В результате у меня получилась следующая вещь, запускающая роль Ansible provisioner:


provisioner "remote-exec" {    inline = ["sudo dnf -y install python"]    connection {      type        = "ssh"      user        = "fedora"      private_key = "${file(var.ssh_key_private)}"    }  }  provisioner "local-exec" {    command = "ansible-playbook -u fedora -i '${self.public_ip},' --private-key ${var.ssh_key_private} provision.yml"  }

Чтобы ansible-playbook работал, вам надо иметь код для Ansible рядом с кодом для Terraform:


$ ll infradrwxrwxr-x. 3 avd avd 4.0K Mar  5 15:54 roles/-rw-rw-r--. 1 avd avd  367 Mar  5 15:19 ansible.cfg-rw-rw-r--. 1 avd avd 2.5K Mar  7 18:54 main.tf-rw-rw-r--. 1 avd avd  454 Mar  5 15:27 variables.tf-rw-rw-r--. 1 avd avd   38 Mar  5 15:54 provision.yml

Встроенный inventory будет работать в большинстве случаев, кроме тех, когда необходимо иметь несколько серверов в inventory. Например, если вы устанавливаете агент Consul, вам нужен список серверов для создания файла настроек, это как правило можно найти в обычном репозитории. Но в приведенном выше способе это не сработает, поскольку у нас всего один сервер в inventory.


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


Динамический inventory после работы Terraform


Еще одно простое решение для раскатки инфраструктуры, созданной Terraform не связывать вместе Terraform и Ansible. Создаем инфраструктуру с помощью Terraform, а затем используем Ansible с динамическим inventory без привязки к тому, как сервера были созданы.


Так что вы сначала создаете инфраструктуру с помощью terraform apply, затем запускаете ansible-playbook -i inventory site.yml, где inventory каталог, содержащий скрипты динамического inventory.


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


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


Inventory, создаваемая из состояния Terraform


Есть еще одна интересная штука, которая, возможно, будет у вас работать создание статического inventory из состояния Terraform.


Terraform при работе поддерживает состояние инфраструктуры, содержащее все, включая ваши сервера. При использовании local backend это состояние сохраняется в файле JSON, который можно потом легко разобрать и сконвертировать в inventory для Ansible.


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


Первый


[all]52.51.215.84[all:vars][server]52.51.215.84[server.0]52.51.215.84[type_aws_instance]52.51.215.84[name_c10k server]52.51.215.84[%_1]52.51.215.84

Второй


$ ~/soft/terraform.py --root . --hostfile## begin hosts generated by terraform.py ##52.51.215.84        C10K Server## end hosts generated by terraform.py ##

Дополнение Ansible для Terraform, которое у меня не заработало


Наконец, есть несколько проектов, которые пытаются внедрить поддержку Ansible в Terraform, как это уже, например, сделано для Chef.


Первая попытка сделать дополнение, но, к сожалению, он уже не поддерживается автором и даже больше не поддерживается актуальной системой дополнений Terraform.


Вторая, более свежая и поддерживаемая, позволяет такой вариант развертывания:


...provisioner "ansible" {    plays {        playbook = "./provision.yml"        hosts = ["${self.public_ip}"]    }    become = "yes"    local = "yes"}...

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


Заключение


Terraform и Ansible мощная связка, которую я использую для развертывания облачной инфраструктуры. Для типовых облачных серверов я запускаю Ansible через local-exec, позднее я запускаю Ansible отдельно с динамическим inventory.


Примеры можно найти здесь.


Благодарю за внимание и до новых встреч!

Подробнее..

KubeHelper -упростите множество повседневных задач с Kubernetes через веб-интерфейс

15.02.2021 18:22:10 | Автор: admin

KubeHelper - это продукт который упрощает решение многих ежедневных задач связанных с управлением Kubernetes через веб интерфейс. Поиск, анализ, запуск команд, cron jobs, репорты, фильтры, git синхронизация и многое другое.

KubeHelper это не ещё одна попытка отобразить Kubernetes API в графическом интерфейсе. Не попытка заменить Lens, официальный Dashboard или другие продукты. Это мой скромный вклад в Kubernetes Open Source сообщество. Проект не имеет какого-то узко специализированного направления и содержит довольно много различных функций которые будут полезны в ежедневной работе с Kubernetes.

Итак, го к описанию и возможностям.

Некоторые термины тяжело переводить, поэтому я вместо непонятного/корявого перевода буду писать английское слово.

Мотивация

Считаю Kubernetes замечательным и революционным продуктом. Много лет изучаю и пользуюсь, но очень часто возникала надобность иметь под рукой много различных функций и команд. Каждый раз набирать в командной строке длинные команды, искать в истории, прописывать aliases и так д. конечно же, можно, но очень часто нет возможности залогинится в консоль, или не сохранилась история, или новый хост. Или много других причин.

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

Многие десктопные клиенты требуют сертификата для коннекта к серверу. И держать сертификат от кластера на локальной машине, не 100% безопасно.

А что если нет возможности проинсталлировать клиент на локальной машине, снова же надо создавать aliasesили копировать команды из сниппетов. Очень часто вижу, что люди ищут те или иные команды, выходят статьи с несколькими различными командами, но их сотни, а вариаций тысячи. Конечно же все эти задачи можно автоматизировать и наверняка каждый пользователь/администратор кластера уже тем или иным образом решил для себя эти задачи, но я уверен что есть и такие которе ещё этого сделалась не успели.

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

Также постарался на ресурсы посмотреть с другой стороны. Многие готовые решения показывают ресурсы по namespace, ещё несколько полезных функций и на этом гибкость веб интерфейсов заканчивается и чтоб сделать что-то отличное чем просто показать список ресурсов в namespace, снова же приходится обращаться к консоли. Например group labels, find selector, view RBACs и так д

Тут у меня и возникла идея помочь сообществу организовать много команд в едином интерфейсе, установить kubectl, плагины, утилиты и сделать для пользования командной строкой графический web интерфейс. Внедрить другие функции которые будут полезны в ежедневной работе с Kubernetes кластером. Внести свой скромный вклад в Open Source сообщество. Ну и конечно же чтоб еще лучше познать и узнать Kubernetes. Вот что из этого получилось.

Общие принципы и понятия

На данный момент я подготовил 3 возможности инсталляции: kubectl, Helm, Terraform. Посмотреть инсталляции и настроить их можно здесь. Позже добавлю в публичный Helm Chart Repository и в Terraform Registry.

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

По умолчанию KubeHelper устанавливается с правами на чтение и просмотр. (get, list). Поэтому с уверенностью можно сказать, что вы ничего не поломаете используя его у себя в кластере. Но при инсталляции вы можете изменить ClusterRole под свои нужды, аж до статуса cluster-admin. Подробная настройка в Wiki.

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

Возможности и интерфейс

Dashboard

Здесь собрана общая информация о кластере. Общее количество процессорного времени, хостов(нод), памяти и так д. Отображена общая техническая информация о хосте(ноде), количество, имена и размеры docker images.

Search

Часто приходится искать что-то в кластере для этого нужно знать где искать и часто писать не тривиальные скрипты или команды. Поиск по всему кластеру или в определённой namespace по ключевому слову и выбранным ресурсам решает эту задачу.

Принцип довольно прост и интуитивен. Выбираем namespace(all = all namespaces) в котором мы хотим найти ресурсы по ключевому слову. Выбираем ресурсы нажимаем поиск, применяем фильтры.Также при нажатии на кнопку в столбце "Raws" можно посмотреть ресурс в различных форматахJava POJO, YAML или JSON.

Подробное описание всех функций и принцип работы вы можете почитать в Wiki.

Ips and Ports

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

Security

Этот раздел состоит из 6 секций. Каждая секция имеет одни и те же кнопки для выбора namespace и поиска соответственных ресурсов в ней.

Также при нажатии на кнопку в столбце "Raws" можно посмотреть ресурс в различных форматахJava POJO, YAML или JSON.

Секция "Roles": Поиск ролей в отдельном namespace или во всех namespaces. Просмотр subjects и role rules для каждого verb.Фильтр и группировка результатов.

Секция"RBAC: Построение матрицы доступа к ресурсам на основании ролей и правил.Фильтр и группировка результатов.

Секция"Pod Security Contexts: ПоказатьPodSecurityContext объекты в отдельной namespace или во всех namespaces.

Секция"Container Security Contexts": Показать ContainerSecurityContext объекты в отдельной namespace или во всех namespaces.

Секция"Service Accounts": Показать"Service Accounts" в отдельном namespace или во всех namespaces.

Секция"Pod Security Policies": Показать"Pod Security Policies" в отдельном namespace или во всех namespaces.

Labels Annotations Selectors

Поискlabels, selectors и annotations по выделенным ресурсам. Фильтр и группирование результатов.

Вкладка Grouped: На основании поиска labels, selectors и annotations будут сагрегированы и сгруппированы

Commands

Идея секции Commands сделатьKubeHelper гибко настраиваемый для каждого пользователя. Каждый пользователь может исполнять свои kubectl и shell команды с различных консолей. Просматривать результаты исполнения. Экспортировать свои подборки команд с git репозитория и многое другое. KubeHelper уже имеет много готовых к использованию команд.

Секция "Commands": Окно разделено на 3 части, команды которые можно фильтровать и искать. Окно редактирования выделенной команды и окно вывода результатов исполнения.

Секция "Management": В этой секции вы имеете возможность редактировать и создавать свои команды, а также просматривать уже имеющиеся команды.

СекцияHistory: В этой секции вы можете посмотреть все исполненные команды и результат их исполнения. Для удобности, история сохраняется по дням. Присутствует несколько удобных фильтров.

Cron Jobs

Идея секции Cron Jobs: сделать исполнение регулярных задач, проверки безопасности, построение и просмотр репортов исполнения команд - более простым и тривиальным заданием.

Секция "Jobs": Окно разделено на 3 части, команды которые можно фильтровать и искать. Окно редактирования выделенной команды и поля для создания новой cron job. Таблица со списком активных и остановленных cron jobs, кнопки управления.

Секция"Reports": Для каждой "cron job создаётся папка в которую по дням будут сохраняться выполненияcron jobs.Присутствует несколько удобных фильтров.

Configurations

Идея секции Configurations дать возможность пользователю синхронизировать свой конфигурационный файл с git также быстрее определить или изменить нужные cron jobs. Здесь же находятся функции для управление пользовательским репозиторием. Подробное описане можно почитать в Wiki.

Versions

ВKubeHelper уже предустановлен kubectl, огромное количество плагинов, утилит, командных оболочек и так д.. Эта вкладка отображает весь список предустановленных программ, их версии и другую информацию.

Вопрос к дочитавшим:

Какие новые функции вы бы добавили в первую очередь? Какая новая функция сделает вашу ежедневную работу легче?

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

Достаточно оставить комментарий с приоритетом в виде номеров или своё предложение.

Для предложения новой функции есть соответствующий Issue.

P.S.1 Буду рад репосту, звёздочке на GitHub. Пользуйтесь, делитесь информацией с коллегами, друзьями, знакомыми.

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

Всем спасибо!

Подробнее..

Перевод Terraform в AWS несколько аккаунтов и другие хитрости

19.03.2021 08:14:45 | Автор: admin


В этой статье поговорим о нюансах использования Terraform от HashiCorp, в частности о том, как использовать Terraform при управлении несколькими аккаунтами Amazon Web Services (так делают все чаще из-за размера организации или предпочтений команды DevOps). По сути, AWS сами намекают клиентам, что неплохо было бы использовать несколько аккаунтов, и недавно даже выпустили для этого несколько сервисов.


Зачем нужно несколько аккаунтов AWS?


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


Управлять безопасностью в этом случае определенно проще, чем когда у вас есть один гигантский аккаунт AWS с запутанной структурой разрешений IAM. По умолчанию отдельные аккаунты AWS не имеют доступа к ресурсам друг друга.


На практике крупные организации из-за своих размеров уже используют несколько аккаунтов AWS, но эти аккаунты никак не связаны. Это серьезно усложняет жизнь отделам закупок на каждый аккаунт AWS нужен отдельный счет, причем организация может группировать счета в соответствии со своими внутренними правилами или нормативными требованиями. Чтобы упростить работу, можно использовать AWS Organizations для управления иерархией аккаунтов и объединения счетов по группам. Недавно AWS представили AWS Control Tower для подготовки новых аккаунтов с предустановленным набором ресурсов и централизованным управлением всеми аккаунтами.


Новый тренд


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


Нужно много времени, чтобы настроить разрешения IAM вместо дефолтного админского доступа для этих пользователей. Причем нет гарантий, что принцип наименьших привилегий будет соблюдаться. С другой стороны, по умолчанию у администратора одного аккаунта AWS нет доступа к другому аккаунту, даже в той же организации. Это безопасно, но нужно поработать над разрешениями IAM, чтобы пользователь из одного аккаунта при необходимости имел доступ к ресурсам в другого. Команда DevOps в таких случаях, скорее всего, будет применять принцип наименьших привилегий.


Этот тренд влияет на Инфраструктуру как код (IaC) например, при использовании Terraform. Инструменты IaC обычно по умолчанию привязаны к одному аккаунту AWS. С самого начала в Terraform могло быть несколько так называемых провайдеров в одном скрипте, чтобы получать доступ к нескольким аккаунтам AWS или даже других облачных вендоров.


Инфраструктура как код с несколькими аккаунтами


Управление ресурсами в разных аккаунтах


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


По умолчанию блок провайдера AWS работает в аккаунте, данные которого использовались для подключения к AWS API. Например, если вы используете идентификатор ключа доступа/секретный ключ доступа определенного пользователя AWS, Terraform будет ссылаться на аккаунт этого пользователя. Код Terraform:


provider aws {region = us-east-1}

Чтобы создавать ресурсы в разных аккаунтах, используйте параметр assume_role блока провайдера, чтобы назначить роль в другом аккаунте и получить доступ к нему:


provider aws {  region = us-east-1  assume_role {    role_arn = arn:aws:iam::123456789012:role/iac  }}

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


Промежуточная роль для доступа к третьему аккаунту


Второй вариант использования продолжает первый: назначенная роль может иметь разрешения на создание, обновление и удаление ресурсов в третьем аккаунте AWS. Для этого нужно настроить разрешения IAM в финальном аккаунте AWS, чтобы промежуточный аккаунт мог создавать, обновлять и удалять ресурсы в нём. Схематично это выглядит так:



Рис. 1. Схема промежуточной роли для доступа к финальному аккаунту AWS


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


Другие продвинутые стратегии Terraform


Несколько стейтов


Если ресурсов относительно много, можно разделить скрипты Terraform на несколько стейтов особенно при использовании continuous deployment (CD). Управление всеми ресурсами в одном стейте имеет недостатки:


  • Каждый раз, когда мы вносим даже незначительные изменения, мы боимся, что Terraform затронет базовые ресурсы, которые трогать не надо.
  • Ошибочные изменения в базовых ресурсах, примененные вслепую в рамках continuous deployment, могут иметь плачевные последствия.
  • Разрешения IAM, которые нужны для выполнения скрипта Terraform, будут затрагивать самые разные задачи. Их будет больше, чем требуется для CD.
  • На применение изменений нужно очень много времени, потому что Terraform будет собирать стейт всех ресурсов, которыми управляет стейт, даже если в большинстве из них ничего не поменялось.
  • Если при деплойменте произойдет сбой, последствия могут быть обширными.

Обычно базовые ресурсы редко меняются. Речь идет о VPC, подсетях, Transit Gateways, VPN, базах данных RDS и балансировщиках нагрузки. Эти ресурсы принадлежат базовому стейту, который почти не меняется, а если и меняется, то руками человека.


Некоторые ресурсы, наоборот, меняются постоянно. Это инстансы EC2, автоскейлинг группы, сервисы в ECS и EKS. Обычно такие ресурсы деплоятся (или обновляются) через пайплайны CD и помещаются в другой стейт, отдельно от базовых ресурсов. Этот отдельный набор скриптов Terraform будет управлять лишь небольшой, быстро меняющейся группой ресурсов, и вам потребуется гораздо меньше разрешений. Такое разделение стейтов Terraform идеально подойдет для автоматизированных деплоев.


Интересный пример такой конфигурации кластер Kubernetes, управляемый базовым стеком, где деплоями Kubernetes управляет стек CD.


Модули


Terraform упрощает разбивку кода IaC на модули. Просто поместите код в другой каталог и используйте директиву module:


provider aws {region = us-east-1}module mymodule {source = ./modules/my_modulevariable1 = value1variable2 = value2}

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


Модули Terraform позволяют соблюдать принцип DRY (Dont Repeat Yourself не повторяйся). Но все равно остается шаблонный код (определения в бэкенде и вызовы к самим модулям), который нельзя поместить в модуль.


Окружения


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


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


Есть и другое решение составить разные наборы скриптов для разных окружений, но это громоздко, и будет много повторяющих друг друга фрагментов даже при использовании модулей. Это одна из причин создания Terragrunt (подробнее об этом один из основателей рассказывает здесь).


Заключение


Большие (и не очень) организации часто используют несколько аккаунтов AWS, и, если постараться, вполне можно наладить Terraform в такой системе. По сути, Terraform специально разработан как мультиоблачный инструмент и поддерживает множество провайдеров, которые могут использоваться в определенном наборе скриптов.


С помощью советов в этой статье можно создать аккуратный код Terraform в соответствии с принципами DRY.

Подробнее..

Интенсив по работе с Terraform 2425 апреля

22.03.2021 14:08:01 | Автор: admin


Запускаем запись на двухдневный интенсив по Terraform, обучение пройдет 2425 апреля. Интересно будет всем, кто работает или планирует работать с облачной инфраструктурой и продолжает разворачивать её в ручном режиме.


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


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


Результат обучения: знания по работе с Terraform, умение строить с помощью него инфраструктуру корпоративного масштаба, умение работать с Terraform в команде.


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


1 День (24 апреля, суббота)


  • Что такое Terraform и практика Infrastructure as a Code. Для чего их применяют.
  • Чем отличается Terraform от других инструментов конфигурации, в чем его преимущества и недостатки.
  • Terraform State что это такое.
  • Создание проекта с Terraform. Основные команды при работе с Terraform, основные концепции Terraform: providers, resources, variables, locals, data sources, outputs.

2 День (25 апреля, воскресенье)


Создание модулей для Terraform инфраструктурной абстракции.


  • Разделение проекта на несколько частей remote state. Организация работы с state в команде.
  • Использование одного и того же кода для разных окружений Terraform Workspaces.
  • Обновление между версиями Terraform.
  • Продвинутые команды и функции Terraform.
  • Best-practices по использованию Terraform в компании.

Стоимость обучения: 15 000 рублей.


Подробности и регистрация

Подробнее..

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

23.03.2021 08:12:20 | Автор: admin

Цель статьи - показать один из возможных подходов для организации гибкого развёртывания 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и разворачивать новые стенды из пайплайнов команд разработчиков передавая версии сервисов.

Подробнее..

Перевод Как создать инфраструктуру в разных окружениях с помощью Terraform

09.04.2021 06:22:09 | Автор: admin

Terraform это опенсорс-инструмент IaC (инфраструктура как код), который предоставляет согласованный рабочий процесс в CLI для управления сотнями облачных сервисов. Terraform преобразует облачные API в декларативные файлы конфигурации.


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


image


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


Введение


Каждое приложение проходит через несколько окружений до деплоймента в продакшен. Эти окружения должны быть максимально похожи друг на друга. Воспроизводить баги и быстро исправлять их будет несложно чего не скажешь о воспроизведении аналогичной инфраструктуры в каждом окружении вручную. Terraform упрощает создание инфраструктуры в мультиоблачном окружении.


Раз Terraform это инструмент IaC, мы прописываем инфраструктуру в коде, поэтому ее можно приспособить для разных окружений с помощью модульного подхода.
Рассмотрим способы создания инфраструктуры в нескольких окружениях.


Предварительные требования


Если у вас еще нет опыта работы с Terraform, сначала лучше почитать эту статью.


Используем папки метод 1


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


Папка представляет отдельное окружение. У вас может быть бэкэнд в каждой папке, а может не быть ничего общего между папками. В каждой папке могут находиться файлы outputs.tf, providers.tf, variables.tf и т. д. При выполнении команд terraform приходится переходить в соответствующую папку и выполнять три команды: init, plan, apply.


image
Использование папок (метод 1)


Преимущества:


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

Недостатки:


  • дублирование кода;
  • если нужно изменить ресурс, приходится делать это во всех окружениях.

Используем папки метод 2


Здесь у нас одна и та же инфраструктура в общих файлах, но для каждого окружения есть отдельный файл terraform.tfvars. Это не идеальный вариант, если у вас разные инфраструктуры во всех окружениях.


Раз файлы main.tf и variables.tf у нас одинаковые, при выполнении команд terraform мы передаем разные переменные в зависимости от окружения. Например, если у нас три окружения, для создания инфраструктуры мы должны выполнить следующие три команды:


// Dev Environmentterraform plan --var-file="tfvars/environment/dev.tfvars"// QA Environmentterraform plan --var-file="tfvars/environment/qa.tfvars"// Prod Environmentterraform plan --var-file="tfvars/environment/prod.tfvars"

image
Использование папок (метод 2)


Преимущества:


  • код не дублируется;
  • если нужно изменить ресурс, не приходится делать это во всех окружениях.

Недостатки:


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

Воркспейсы


Terraform начинается с одного воркспейса с именем default. Это дефолтный воркспейс, который, в отличие от остальных, невозможно удалить. Если вы никогда явно не использовали воркспейсы, значит, вы работали только в воркспейсе default.
Воркспейсы управляются командами terraform workspace. Существует целый набор таких команд. Например, terraform workspace new создает воркспейс.


Модули


Модуль это контейнер для нескольких ресурсов, которые используются вместе. В каждой конфигурации Terraform есть хотя бы один модуль root-модуль. Root-модуль обычно состоит из ресурсов, определенных в файлах с расширением .tf в главном рабочем каталоге.


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


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


image
Несколько окружений


Terragrunt


Terragrunt это тонкая обертка, которая предоставляет дополнительные инструменты для соблюдения принципа DRY в конфигурациях, работы с несколькими модулями Terraform и управления удаленным стейтом.


Подробнее об этом на их официальном сайте.


Итоги


  • Terraform это опенсорс-инструмент IaC, который предоставляет согласованный рабочий процесс в CLI для управления сотнями облачных сервисов.
  • Обычно мы деплоим инфраструктуру в нескольких окружениях, которые мы используем для разработки, стейджинга, тестирования и продакшена.
  • Есть пять способов написать многоразовый код для разных окружений в Terraform.
  • Самый популярный из них папки. Работать с папками можно двумя методами.
  • Terraform начинается с одного воркспейса с именем default. Это дефолтный воркспейс, который, в отличие от остальных, невозможно удалить.
  • Модуль это контейнер для нескольких ресурсов, которые используются вместе. Использование модулей можно настроить таким образом, чтобы один и тот же модуль подходил для разных окружений без изменения кода.
  • Terragrunt это тонкая обертка, которая предоставляет дополнительные инструменты для соблюдения принципа DRY в конфигурациях, работы с несколькими модулями Terraform и управления удаленным стейтом.

Итак, мы рассмотрели несколько способов создать инфраструктуру для разных окружений с помощью Terraform. У каждого из них свои преимущества и недостатки. Эти способы можно сочетать друг с другом.

Подробнее..

Перевод Как импортировать существующие виртуальные машины VMWare в Terraform

11.12.2020 18:19:05 | Автор: admin

Будущих учащихся на курсе "Infrastructure as a code in Ansible", а также всех желающих приглашаем принять участие в открытом вебинаре на тему "Управление Kubernetes при помощи Kubespray".


И по устоявшейся традиции делимся с вами переводом полезной статьи.


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

Первоначально опубликовано в блоге techbeatly; там же доступны другие статьи по теме.

Читайте также:Программа обучения и советы по прохождению экзамена HashiCorp Certified Terraform Associate.

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

Шаг 1. Получение сведений о существующей виртуальной машине из VMWare vCenter

Выполните вход в VMWare vCenter и найдите данные виртуальной машины. Вам потребуются такие данные, какцентр обработки данных,папка виртуальной машины,имя виртуальной машины,ЦП,память,диски т.д.

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

Шаг 2. Создание кода Terraform для существующей виртуальной машины

В Terraform нет возможности импортировать существующую инфраструктуру в код Terraform. Вместо этого приходится писать конфигурацию Terraform, соответствующую имеющейся инфраструктуре, и импортировать ее.

Ниже приведен код Terraform, который я написал для виртуальной машины со следующим путем и именем:/DC1/vm/DEV/DEV2.

См. содержимое файлаvmware-import-vm.tf.

provider "vsphere" {  user           = var.vsphere_user  password       = var.vsphere_password  vsphere_server = var.vsphere_server  # If you have a self-signed cert  allow_unverified_ssl = true}data "vsphere_datacenter" "dc" {  name = "DC1"}data "vsphere_datastore" "datastore" {  name          = "datastore1"  datacenter_id = data.vsphere_datacenter.dc.id}data "vsphere_compute_cluster" "cluster" {  name          = "AZ1"  datacenter_id = data.vsphere_datacenter.dc.id}data "vsphere_network" "network" {  name          = "VM Network"  datacenter_id = data.vsphere_datacenter.dc.id}resource "vsphere_virtual_machine" "vm" {  name             = "DEV2"  resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id  datastore_id     = data.vsphere_datastore.datastore.id  wait_for_guest_net_timeout = 0  wait_for_guest_ip_timeout  = 0  # only if you DO NOT want to wait for an IP address  wait_for_guest_net_routable = false  num_cpus = 1  memory   = 2048  #guest_id = "other3xLinux64Guest"  network_interface {    network_id = data.vsphere_network.network.id  }    disk {    label            = "disk0"    size             = 20    thin_provisioned = false  }}

Я также объявил несколько переменных для передачи учетных данных VMWare.

$ cat variables.tf variable "vsphereuser" {}variable "vspherepassword" {}

В этом примере я передаю свои учетные данные VMWare vCenter с помощью переменных среды (см. пример ниже).

$ export TFVARvsphereuser='Administrator@lab.local'$ export TFVARvspherepassword='mypassword'

Шаг 3. Инициализация кода Terraform

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

$ terraform initInitializing the backend...Initializing provider plugins...- Finding latest version of hashicorp/vsphere...- Installing hashicorp/vsphere v1.24.2...- Installed hashicorp/vsphere v1.24.2 (signed by HashiCorp)The following providers do not have any version constraints in configuration,so the latest version was installed.To prevent automatic upgrades to new major versions that may contain breakingchanges, we recommend adding version constraints in a required_providers blockin your configuration, with the constraint strings suggested below.* hashicorp/vsphere: version = "~> 1.24.2"Terraform has been successfully initialized!You may now begin working with Terraform. Try running "terraform plan" to seeany changes that are required for your infrastructure. All Terraform commandsshould now work.If you ever set or change modules or backend configuration for Terraform,rerun this command to reinitialize your working directory. If you forget, othercommands will detect it and remind you to do so if necessary.

Проверим текущее состояние, управляемое Terraform:

$ terraform showNo state.

Да, мы пока еще не выполнили запуск.

Примечание. Что произойдет, если я выполню командуterraform apply? Все просто, система попытается выделить ресурсы для виртуальной машины, но эта попытка завершится ошибкой. Система сообщит, что виртуальная машина с именемDEV2уже существует. Как бы то ни было, в данном примере это не наш случай.

Шаг 4. Импорт виртуальной машины в состояние Terraform

Итак, теперь все готово к импорту имеющейся у нас виртуальной машины в состояние Terraform.

$ terraform import vsphere_virtual_machine.vm /DC1/vm/DEV/DEV2vsphere_virtual_machine.vm: Importing from ID "/DC1/vm/DEV/DEV2"...vsphere_virtual_machine.vm: Import prepared!  Prepared vsphere_virtual_machine for importvsphere_virtual_machine.vm: Refreshing state... [id=4219040f-5842-ba52-b7e4-cd9064c1f36c]Import successful!The resources that were imported are shown above. These resources are now inyour Terraform state and will henceforth be managed by Terraform.

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

Это можно проверить, выполнив командуterraform showеще раз.

$ terraform show# vsphere_virtual_machine.vm:resource "vsphere_virtual_machine" "vm" {    boot_delay                              = 0    boot_retry_delay                        = 10000    boot_retry_enabled                      = false    change_version                          = "2020-11-03T08:33:13.180937Z"    cpu_hot_add_enabled                     = false    cpu_hot_remove_enabled                  = false    cpu_limit                               = -1    cpu_performance_counters_enabled        = false    cpu_reservation                         = 0    cpu_share_count                         = 1000    cpu_share_level                         = "normal"    custom_attributes                       = {}    datastore_id                            = "datastore-13"    efi_secure_boot_enabled                 = false    enable_disk_uuid                        = false    enable_logging                          = true    ept_rvi_mode                            = "automatic"    extra_config                            = {}    firmware                                = "bios"    folder                                  = "DEV"    force_power_off                         = true    guest_id                                = "rhel7_64Guest"    guest_ip_addresses                      = []    hardware_version                        = 14    host_system_id                          = "host-12"    hv_mode                                 = "hvAuto"    id                                      = "4219040f-5842-ba52-b7e4-cd9064c1f36c"    ide_controller_count                    = 2    imported                                = true    latency_sensitivity                     = "normal"    memory                                  = 2048    memory_hot_add_enabled                  = false    memory_limit                            = -1    memory_reservation                      = 0    memory_share_count                      = 20480    memory_share_level                      = "normal"    migrate_wait_timeout                    = 30    moid                                    = "vm-47"    name                                    = "DEV2"    nested_hv_enabled                       = false    num_cores_per_socket                    = 1    num_cpus                                = 1    pci_device_id                           = []    poweron_timeout                         = 300    reboot_required                         = false    resource_pool_id                        = "resgroup-8"    run_tools_scripts_after_power_on        = true    run_tools_scripts_after_resume          = true    run_tools_scripts_before_guest_reboot   = false    run_tools_scripts_before_guest_shutdown = true    run_tools_scripts_before_guest_standby  = true    sata_controller_count                   = 1    scsi_bus_sharing                        = "noSharing"    scsi_controller_count                   = 1    scsi_type                               = "pvscsi"    shutdown_wait_timeout                   = 3    swap_placement_policy                   = "inherit"    sync_time_with_host                     = false    tags                                    = []    uuid                                    = "4219040f-5842-ba52-b7e4-cd9064c1f36c"    vapp_transport                          = []    vmware_tools_status                     = "guestToolsRunning"    vmx_path                                = "DEV2/DEV2.vmx"    wait_for_guest_ip_timeout               = 0    wait_for_guest_net_routable             = true    wait_for_guest_net_timeout              = 5    cdrom {        client_device  = false        datastore_id   = "datastore-13"        device_address = "sata:0:0"        key            = 16000        path           = "ISO/rhel-server-7.7-x86_64-dvd.iso"    }    disk {        attach           = false        controller_type  = "scsi"        datastore_id     = "datastore-13"        device_address   = "scsi:0:0"        disk_mode        = "persistent"        disk_sharing     = "sharingNone"        eagerly_scrub    = false        io_limit         = -1        io_reservation   = 0        io_share_count   = 1000        io_share_level   = "normal"        keep_on_remove   = true        key              = 2000        label            = "disk0"        path             = "DEV2/DEV2.vmdk"        size             = 20        thin_provisioned = false        unit_number      = 0        uuid             = "6000C29b-c4f0-764a-9054-a042931350c4"        write_through    = false    }}

Заключение

Если вы планируете управлять конфигурацией внутри операционной системы виртуальной машины, помните о том, что нужно использовать соответствующиесредства выделения ресурсов (provisioners).

Подробные сведения см. в документации по ресурсу vsphere_virtual_machine.

Полный код приведен на GitHub в репозиторииterraform-vmware-demos.


Узнать подробнее о курсе "Infrastructure as a code in Ansible".

Зарегистрироваться на открытый урок на тему "Управление Kubernetes при помощи Kubespray".

ЗАБРАТЬ СКИДКУ

Подробнее..

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

16.12.2020 20:13:35 | Автор: admin


Для будущих студентов курса Infrastructure as a code in Ansible и всех интересующихся подготовили перевод полезного материала.

Также приглашаем записаться на открытый урок по теме Управление Kubernetes при помощи Kubespray.





С возвращением! Это очередная техническая статья из серии заметок о terraform и kubernetes на тему инфраструктуры как кода, подготовленных компанией Contino.

TL;DR
Размер команды не имеет значения. В любом случае реализация хорошего анализа конфигурации инфраструктуры на базе terraform и сквозного тестирования ее разумности не обязательно должна быть длительным и сложным процессом.

Мне подвернулась интереснейшая задача: изучить, разработать и представить подходящую платформу тестирования с открытым кодом для базы кода terraform в рамках конвейера выпуска инфраструктуры. Принцип контроль качества во всем далеко не нов. Но его реализация зависит от зрелости инфраструктуры организации и допустимого уровня риска до стадии выхода на [сколь-либо] готовый продукт.

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

image

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

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

  • Контроль качества кода terraform fmt -check и terraform validate.
  • Предварительный просмотр terraform plan.
  • Построение TFLOG=debug terraform apply для дотошной проверки.

Средства статического анализа кода Terraform


Прочесывание Google выявило весьма обширный перечень потенциально пригодных средств тестирования terraform.

Но сначала пройдемся по списку наших требований.

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

* Отсутствие экземпляров ec2, открытых миру 0.0.0.0/0, и так далее.

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

  • Требование, определенное в большей степени личным опытом, платформа тестирования по возможности должна сокращать инженерные трудозатраты, а не увеличивать их, с учетом имеющихся навыков. Разумеется, я прекрасно понимаю, что после создания такие тестовые платформы в дальнейшем требуют значительных инженерных трудозатрат на поддержание их работы и расширение.

  • Поддержка сообщества важна, когда дело касается программного обеспечения с открытым исходным кодом. Ну и самое последнее, любые выбранные платформы должны быть написаны на распространенном языке программирования, таком как Go или Python. Если понадобится углубиться в платформу и написать собственные методы, найти инженера с опытом работы с одним языком будет, пожалуй, проще, чем с двумя. Любой предыдущий опыт работы с подобными инструментами, который может быть у имеющихся сотрудников группы и организации в целом, также будет полезен. Итак, теперь я готов отправиться на поиски правильного средства тестирования и платформ для выполнения этой работы.

Подборка: анализ и сравнение средств и платформ тестирования Terraform

Надеюсь, что приведенный далее список облегчит ваши труды по статическому анализу инфраструктуры как кода и контролю качества. Обращаю внимание, это полный список всех найденных мной соответствующих инструментов тестирования terraform, представляющий собой смесь средств тестирования обоснованности конфигурации, контроля качества кода и передовых методов, ориентированных на secOps, с модульными тестами. Далее вашему вниманию предлагается этот список.



Выбранные средства тестирования


Подытожим. Я старался найти стандартизированный модульный тест для компонентов ресурсов terraform и более настраиваемый набор тестов, которые берут конфигурацию ресурсов для валидации по результатам terraform plan.

Рассмотрев преимущества и недостатки каждой платформы, я остановил свой выбор на инструменте checkov и платформе с очень подходящим названием terraform-compliance обе они написаны на python. Они удовлетворяли всем моим описанным выше требованиям.

Конвейер выпуска инфраструктуры как кода в общих чертах выглядит примерно так.

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

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


Модульное тестирование Checkov от BridgeCrew


www.checkov.io

Checkov это инструмент статического анализа кода для инфраструктуры как кода.

Он сканирует облачную инфраструктуру, подготовленную с помощью Terraform, Cloudformation, Kubernetes, Serverless или шаблонов ARM, и выявляет неправильную конфигурацию с точки зрения безопасности и соблюдения нормативных требований.

Есть несколько модульных тестов, выполняемых по умолчанию при сканировании репозитория кода terraform, которые показывают отклонения от передовых методов например, когда согласно конфигурации безопасности у вас есть виртуальная машина на порту 22, открытом миру (0.0.0.0/0).

Все тесты можно найти по этой ссылке на GitHub.

Начать работать с платформой очень просто.

  • Установите двоичный файл.
  • Инициализируйте каталог terraform командой terraform init.
  • Запустите chechov для этого каталога.

Список всех модульных тестов, выполняемых по умолчанию, можно вывести в командной строке. Кроме того, при работе checkov платформа по умолчанию выдает все пройденные и непройденные модульные тесты. Очень удобно, начать использовать просто. Передовые методы terraform проверяются, но не все. Это фундаментальное отличие.

Chechov с радостью оценит ТОЛЬКО ваш код terraform. Платформа может работать сразу после terraform init. Ей нет дела до вашего terraform plan со всеми преимуществами и недостатками. Платформа выполняет то, что заявлено, а именно статический анализ кода. Помните о возможных последствиях, а также любых соображениях относительно логики для ваших ресурсов.

image

image

Вывод после работы checkov с указанием пройденных и непройденных проверок.


Если вы готовы заниматься углубленной разработкой на Python, то сможете написать дополнительные модульные тесты. Язык разработки платформы входил в число моих требований, поскольку иногда мне приходится анализировать базу кода тестов, чтобы прикинуть, насколько трудно будет [при необходимости] создать подобные дополнительные методы. Этот момент в сочетании с вопросами обслуживания для группы в целом стал основным фактором выбора этой платформы вместо альтернативной, позволяющей получить такой же результат.

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

С другой стороны, в качестве решения я могу реплицировать модульный тест и жестко прописать параметры моей подсети/IP-адреса. А что тогда делать, если у меня несколько экземпляров и проектов, пропускать этот тест, даже если он нужен? Может быть. А может и нет.

Вот здесь-то в игру и вступает вторая платформа тестирования terraform-compliance.

Terraform-compliance


terraform-compliance.com

Terraform-compliance это облегченная платформа тестирования, предназначенная для проверки безопасности и соблюдения нормативных требований в terraform для обеспечения совместимости вашей инфраструктуры как кода с отрицательным тестированием.

Предыстория


Еще раз отмечу, сквозная разработка через тестирование поведения (BDD) стала использоваться как платформа тестирования недавно, подчеркнув потребность в универсальной платформе тестирования. Но это не единственная польза.Простота.

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

И хотя с помощью кода можно описать, по сути, все на свете, в конечном счете все упирается в управляемость, возможности постичь сложность кода (для чего может потребоваться подготовка обширной документации), не говоря уже о поддержке и обслуживании.Здесь можно подробнее познакомиться с BDD.

Cucumber.io это не просто язык, это система, упрощающая работу по тестированию за счет применения подхода WYSIWYG к созданию тестов, пониманию их работы и обслуживанию. Эти примеры определяются до начала разработки и используются в качестве критериев приемки.

Они являются частью определения.

Тестирование с помощью Terraform-Compliance


Каждая платформа рассматривается по своим достоинствам с углубленным исследованием того, где ее особенности и нюансы можно использовать с наибольшей пользой. Забегая вперед, скажу, что использовать можно обе платформы.

Вот пример такого теста, разработанного с помощью платформы terraform-compliance с применением BDD. Он позволяет выполнять достаточно сложное сквозное тестирование.

Платформа terraform-compliance использует вывод terraform plan. В результате это позволяет формировать полные планы выпусков и тщательно тестировать их. Например, контролировать использование правильной пары ключей шифрования [для вашего поставщика облачных услуг] для учетной записи, среды и т.п. У вас будет большая свобода для творчества, и самое важное работать с платформой очень просто.

Просто ознакомьтесь с приведенными ниже действиями и примерами.

  • Шаг 1. Инициализируйте каталог terraform:# terraform init
  • Шаг 2. Можно быстро сформировать terraform plan следующей командой: #terraform plan -out=plan.out
  • Шаг 3. Напишите несколько тестов. Дело нехитрое уже есть папка с примерами. Давайте пройдемся по моим собственным примерам тестов, приведенным ниже, написанным на основе моего вывода terraform plan.

Это фрагмент плана terraform конфигурации terraform, которая создает EKS с указанной группой запуска. Давайте удостоверимся, что в нашем коде инфраструктуры terraform не применяется instancetype, а используется одобренный вариант a1.xlarge или a1.2xlarge.

Теперь я намеренно изменю его на t2.small, чтобы имитировать непрохождение теста.

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

  • Шаг 4. Давайте заставим terraform-compliance оценить плат с использованием тестовых сценариев: #terraform-compliance -p plan.out -f ./<test-cases-folder>


Выполнение тестов


Пример результата с прохождением и непрохождением

image

Если в нашем коде инфраструктуры Terraform используется правильный instancetype, то все результаты будут зелеными SUCCESS.

Если же наш код инфраструктуры Terraform нарушает требование из-за наличия неправильного instancetype, то результаты будут красными FAIL.

Давайте напишем еще больше тестов

image

Еще несколько простых тестов, взятых из каталога примеров:

image

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

Результаты тестов


После выполнения всех тестов отображается удобная итоговая сводка по всем пройденным и непройденным тестам, в которой также указываются пропущенные тесты. Она мне нравится тем, что позволяет написать длинный список тщательных тестов, а также найти в конце четкие сведения о том, какие тесты не были пройдены и когда. Кроме того, в случае непрохождения некоторые тесты могут быть пропущены с указанием тега @warning, как показано в примере ниже.
habrastorage.org/getpro/habr/upload_files/c22/910/cb9/c22910cb95fb4ccc7555d44bd8b5436b

Итоги


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

Я получил удовольствие, рассматривая обе эти платформы, и был особенно удивлен простотой интеграции checkov, а также потрясающей валидацией e2e terraform plan и вариантами нестандартного тестирования, которые предлагает terraform-compliance.

Последняя напоминает мне поведение behave, еще одной великолепной платформы тестирования BDD e2e kubernetes, с которой я работал в прошлом.

Полностью написанные на Python платформы тестирования упрощают общий обмен знаниями Python между платформами и сокращают объем интеллектуального труда для обслуживания и разработки тестов в будущем.

Если вам требуется проверка конфигурации на соответствие передовым методам, когда не требуется terraform plan, то, возможно, checkov это то, что вам нужно. В иных случаях ответом может быть платформа terraform-compliance, имеющая более богатый набор функций для валидации terraform plan. Лучше всего то, что, будучи платформой BDD, terraform-compliance очень проста в освоении.

Модульное тестирование прежде всего. Проще простого. Платформа Checkov от bridgecrewio позволяет выполнять проверку соответствия передовым методам без дополнительной настройки.

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

P.S. В компании Contino реализуется порядочное количество фантастических проектов. Если вам хотелось бы поработать над суперсовременными инфраструктурными проектами или вы ищете серьезные задачи свяжитесь с нами! Мы нанимаем персонал и ищем светлые умы на всех уровнях. Мы в компании Contino гордимся тем, что разрабатываем передовые проекты по трансформации облачных систем, предназначенные как для компаний среднего размера, так и для крупных предприятий.
Узнать подробнее о курсе Infrastructure as a code in Ansible.

Записаться на открытый урок по теме Управление Kubernetes при помощи Kubespray.

Подробнее..

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

16.03.2021 12:09:05 | Автор: admin

Всем привет.

Есть такие люди, которые работают с облачной инфраструктурой и не используют автоматизацию, потому что это долго, нужно вникать, а им надо фичи пилить. Накликали что-то там в 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

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

Подробнее..

GitOps Определение дрейфа вашей инфраструктуры Terraform Terragrunt

18.03.2021 14:16:42 | Автор: admin

Всем привет.

Дисклеймер: сказу скажу, что пишу статью по-ходу дела, "код" в ней рабочий, но не претендует на какие-либо best practices, поэтому не придирайтесь :) Цель статьи: донести до интересующейся русскоязычной части населения общие принципы, возможно разбудить интерес поразбираться самостоятельно и сделать что-то гораздо лучше и интереснее. Итак поехали!

Допустим Вы работаете с Terraform / Terragrunt (второе здесь непринципиально, но лучше изучайте, если ещё не используете) и автоматизируете инфраструктуру, например, в AWS (но совершенно необязательно AWS). Инфраструктура в коде репозитория, разворачивается из него же, казалось бы вот оно GitOps счастье :)

Всё идёт хорошо, пока какой-то пользователь не поменял что-то руками через консоль / UI и конечно забыл об этом кому-либо сказать. А то и сделал что-то нехорошее намеренно. И вот он ваш дрейф: код и инфраструктура больше не совпадают! :(

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

Как обычно, есть много различных путей добиться желаемого. Например, недавно на горизонте появилась неплохо развивающаяся утилита https://github.com/cloudskiff/driftctl , которая может даже больше, чем предложу Вашему вниманию чуть ниже я, но на момент написания статьи driftctl как минимум не поддерживает работу с aws provider v2, а также не умеет в multi region, что делает его использование невозможным в большинстве серьёзных проектов. Но ребята обещают доделать её через месяц-два.

А пока что опишу и приведу пример небольшого количества кода для следующей очень простой схемы:

1) создаём pipeline, который или по расписанию (в Gitlab можно воспользоваться Pipeline schedules) или по кругу будет делать terraform plan

2) при нахождении дрейфа (diff в плане) pipeline будет, например, отправлять сообщение с его содержанием в Slack.

Аналогично можно реализовать и, например, создание issue в любом из используемых вами репозиториев, где поддерживается их создание через api и любое другое действие, например apply, который вернёт инфраструктуру к её эталонному состоянию. Или всё-таки импортировать изменение в state, если оно действительно необходимо.

Допустим есть репозиторий содержащий код для вашей live инфраструктуры, т.е. код, которому она должна соответствовать и откуда она и была развёрнута с такой структурой:

account_1/ eu-central-1  dev   eks    terragrunt.hcl    values.yaml   s3-bucket       terragrunt.hcl       values.yaml  prod   eks    terragrunt.hcl    values.yaml   s3-bucket       terragrunt.hcl       values.yaml  staging      eks       terragrunt.hcl       values.yaml      s3-bucket          terragrunt.hcl          values.yaml us-east-1  dev   eks    terragrunt.hcl    values.yaml   s3-bucket       terragrunt.hcl       values.yaml  prod   eks    terragrunt.hcl    values.yaml   s3-bucket       terragrunt.hcl       values.yaml  staging      eks       terragrunt.hcl       values.yaml      s3-bucket          terragrunt.hcl          values.yaml terragrunt.hcl

В приведённом выше примере в папке account_1 находятся 2 папки: us-east-1 и eu-central-1 , по имени регионов AWS. Иногда удобно организовать структуру именно так и тогда имена папок можно использовать как значение для передачи в модуль с помощью Terragrunt функции/й, например, таких "${basename(get_terragrunt_dir())}"

Аналогичная логика с папками имеющими в названии окружение и далее идут названия самих компонентов, которых в этом примере 2: eks и s3-bucket

Если смотреть от корня репозитория, то путь до каждого из файлов внутри папки компонента

<account_name>/<region>/<environment>/<component>/*

Т.е. "в общих чертах" */*/*/<component>/*

Выберем, например, компонент s3-bucket (на самом деле конечно можно реализовать это для всего сразу, но бывают нюансы и здесь интересно показать принцип).

Не забудьте подключить Incoming WebHooks в Slack и записать полученный Webhook URL. Делается это так: https://api.slack.com/messaging/webhooks

Тогда вот такой скрипт может выполнять требуемое планирование в pipeline и отправку в Slack diff'а при его нахождении:

#!/bin/bashROOT_DIR=$(pwd)plan () {  echo -e "$(date +'%H-%M-%S %d-%m-%Y') $F"  CURRENT_DIR=$(pwd)  PLAN=$CURRENT_DIR/plan.tfplan  terragrunt run-all plan --terragrunt-non-interactive -lock=false -detailed-exitcode -out=$PLAN 2>/dev/null || ec=$?    case $ec in    0) echo "No Changes Found"; exit 0;;    1) printf '%s\n' "Command exited with non-zero"; exit 1;;    2) echo "Changes Found! Reporting!";          MESSAGE=$(terragrunt show -no-color ${PLAN} | sed "s/\"/'/g");    # let's replace the double quotes from the diff with single as double quotes "break" the payload       curl -X POST --data-urlencode "payload={\"channel\": \"#your-slack-channel-here\", \"username\": \"webhookbot\", \"text\": \"DRIFT DETECTED!!!\n ${MESSAGE}\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/YOUR/WEBHOOK/URL_HERE;;  esac}N="$(($(grep -c ^processor /proc/cpuinfo)*4))"    # any number suitable for your situation goes herefor F in */*/*/s3-bucket/*; do  ((i=i%N)); ((i++==0)) && wait    # let's run only N jobs in parallel to speed up the process  cd $ROOT_DIR  cd $F  plan &    # send the job to background to start the new onedone

Меняем что-нибудь руками, запускаем pipeline или ждём его выполнения и радуемся :)

На этом на сегодня всё!

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

P.S. имхо проект https://github.com/cloudskiff/driftctl мне лично кажется действительно полезным и решающим правильную задачу и хороших аналогов ему нет, так что прошу поддержать ребят, а по-возможности внести свою лепту ибо open source.

Всем хорошего настроения!

Подробнее..

Перевод Как использовать HashiCorp Waypoint для совместной работы с GitLab CICD

22.10.2020 06:11:39 | Автор: admin


HashiCorp показала новый проект Waypoint на HashiCorp Digital. Он использует файл на основе HCL для описания сборки, поставки и выпуска приложений для различных облачных платформ, начиная от Kubernetes и заканчивая AWS и Google Cloud Run. Можно представить, что Waypoint это сложенные вместе Terraform и Vagrant для описания процесса сборки, поставки и выпуска ваших приложений.


Не изменяя себе, HashiCorp выпустила Waypoint с открытым исходным кодом, также к нему прилагается множество примеров. Уровень оркестратора остается за вами, Waypoint поставляется в виде исполняемого файла, который вы можете запустить прямиком на вашем ноутбуке или из выбранного вами инструмента оркестрации CI/CD. Цель для развертывания приложений также выбирается вами, поскольку Waypoint поддерживает Kubernetes, Docker, Google Cloud Run, AWS ECS и другие.


Почитав улетную документацию и шикарнейшие примеры приложений, предоставленные HashiCorp, мы решили взглянуть поближе на оркестровку Waypoint с помощью GitLab CI/CD. Чтобы это сделать, мы возьмем простое приложение Node.js, запускаемое на AWS ECS, из репозитория примеров.


После клонирования репозитория посмотрим структуру приложения, отображающего одну страницу:



Как вы могли заметить, в этом проекте нет Dockerfile. Они не добавлены в примере, поскольку они в принципе и не нужны нам, ведь Waypoint позаботится о них за нас. Давайте рассмотрим детальнее файл waypoint.hcl, чтобы понять, что он будет делать:


project = "example-nodejs"app "example-nodejs" {  labels = {    "service" = "example-nodejs",    "env" = "dev"  }  build {    use "pack" {}    registry {    use "aws-ecr" {        region = "us-east-1"        repository = "waypoint-gitlab"        tag = "latest"    }    }  }  deploy {    use "aws-ecs" {    region = "us-east-1"    memory = "512"    }  }}

На этапе сборки Waypoint использует Cloud Native Buildpacks (CNB), чтобы определить язык программирования проекта и создать образ для Docker без использования Dockerfile. В принципе, это та же самая технология, которая используется GitLab в части Auto DevOps на шаге Auto Build. Приятно видеть, что CNB от CNCF получает все большее распространение у пользователей из отрасли.


Как только образ собран, Waypoint автоматически выгрузит его в нашу AWS ECR registry, чтобы он был готов к поставке. По окончанию сборки шаг поставки использует дополнение AWS ECS для развертывания нашего приложения в нашу учетную запись AWS.


С моего ноутбука все просто. Я ставлю Waypoint, который уже аутентифицирован в моей учетной записи AWS, и оно просто работает. Но что будет, если я захочу выйти за пределы моего ноутбука? Или вдруг я хочу автоматизировать это развертывание в виде части моего общего конвейера CI/CD, где запускаются мои текущие интеграционные тесты, тесты безопасности и прочие? Это та часть рассказа, где появляется GitLab CI/CD!


N.B. Если вы еще только планируете внедрение CI/CD или хотите начать применять лучшие практики построения пайплайнов, обратите внимание на новый курс Слёрма CI/CD на примере Gitlab CI. Сейчас он доступен по цене предзаказа.

Waypoint в GitLab CI/CD


Для оркестровки всего этого в GitLab CI/CD давайте посмотри, что нам понадобится в нашем файле .gitlab-ci.yml:


  • В первую очередь, нужен базовый образ для запуска внутри него. Waypoint работает на любом дистрибутиве Linux, ему нужен только Docker, так что мы может запускаться с generic образа Docker.
  • Далее надо установить Waypoint в этот образ. В будущем мы можем собрать образ meta build и контейнеризировать этот процесс для себя.
  • Наконец мы запустим команды Waypoint

Выше расписано все, что понадобится нашему конвейеру для запуска нужных для выполнения развертывания скриптов, но для развертывания в AWS нам понадобится еще одна вещь: мы должны авторизоваться в нашей учетной записи AWS. В описании Waypoint есть планы об аутентификации и авторизации. HashiCorp на этой неделе также выпустила впечатляющий проект Boundary. Но на данный момент мы можем просто взять и самостоятельно обработать аутентификацию и авторизацию.


Для аутентификации GitLab CI\CD в AWS есть несколько вариантов. Первый вариант использование встроенного HashiCorp Vault. Он подойдет, если ваша команда уже пользуется Vault для управления учетными данными. Еще один способ, который подходит, если ваша команда управляет авторизацией с помощью AWS IAM проверьте, что задачи поставки запускаются через GitLab Runner, авторизованный для запуска развертывания через IAM. Но если вы просто хотите ознакомиться с Waypoint и хотите это сделать побыстрее, есть последний вариант добавить ваши ключи AWS API и Secret в переменные окружения GitLab CI/CD AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY.


Собираем все вместе


Как только мы разобрались с аутентификацией, можно начинать! Наш окончательный .gitlab-ci.yml выглядит так:


waypoint:  image: docker:latest  stage: build  services:    - docker:dind  # Define environment variables, e.g. `WAYPOINT_VERSION: '0.1.1'`  variables:    WAYPOINT_VERSION: ''    WAYPOINT_SERVER_ADDR: ''    WAYPOINT_SERVER_TOKEN: ''    WAYPOINT_SERVER_TLS: '1'    WAYPOINT_SERVER_TLS_SKIP_VERIFY: '1'  script:    - wget -q -O /tmp/waypoint.zip https://releases.hashicorp.com/waypoint/${WAYPOINT_VERSION}/waypoint_${WAYPOINT_VERSION}_linux_amd64.zip    - unzip -d /usr/local/bin /tmp/waypoint.zip    - rm -rf /tmp/waypoint*    - waypoint init    - waypoint build    - waypoint deploy    - waypoint release

Вы видите, что мы начинаем с образа docker:latest и устанавливаем несколько переменных окружения, требуемых для Waypoint. В разделе script мы скачиваем последнюю версию исполняемого файла Waypoint и ставим его в /usr/local/bin. Поскольку наш runner уже авторизован в AWS, далее мы просто запускаем waypoint init, build, deploy и release.


Вывод задачи по сборке покажет нам endpoint, куда мы раскатили приложение:



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


Совместные решения, разработанные HashiCorp и GitLab, помогают компаниям найти лучший способ разработки приложений, обеспечивая согласованное управление потоками поставки и инфраструктурой. Waypoint сделали еще один шаг в верном направлении, и мы с нетерпением ожидаем дальнейшего развития проекта. Вы можете узнать больше о Waypoint здесь, также стоит изучить документацию и план развития проекта. Мы добавили полученные нами знания в документацию GitLab CI\CD. Если вы хотите попробовать все в работе самостоятельно, можете взять полный работоспособный пример в этом репозитории.


Понять принципы CI/CD, освоить все тонкости работы с Gitlab CI и начать применять лучшие практики можно, пройдя видеокурс CI/CD на примере Gitlab CI. Присоединяйтесь!

Подробнее..

Перевод Что такое Waypoint и какие возможности дает его использование

26.10.2020 16:12:51 | Автор: admin


Пару недель назад я посмотрела демонстрацию Waypoint нового инструмента, который представила 15 октября 2020 года компания Hashicorp. Инструмента, который предназначен для создания легкого, интуитивного и настраиваемого под пользователя рабочего процесса сборки, развертывания и релиза.


Эта статья не будет ни учебным руководством, ни инструкцией по использованию продукта, поскольку официальная документация и обучающие материалы прекрасно разъясняют, как настраивать и использовать инструмент. В этой статье я объясню, почему, на мой взгляд, с философской точки зрения модель Waypoint перспективна и имеет большой потенциал.


Чем Waypoint не является


Наверное, будет проще в начале пояснить, чем Waypoint не является.


Waypoint не:


  • автоматическая система сборки программ (как make, npm, maven и т.д.)
  • диспетчер пакетов (как helm, pip и т.д.)
  • система непрерывной интеграции (как Jenkins, GitHub Actions и т.д.)
  • registry артефактов (как Artifactory, Docker Registry и т.д.)
  • среда выполнения (как OCI images, Docker containers, buildpacks, машинный код, архивы и т.д.)
  • кластерный оркестратор или кластерная платформа (как Kubernetes, EC2, EKS и т.д.)

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


Что же такое Waypoint?


Согласно описанию производителя, Waypoint это инструмент, призванный значительно упростить разработку и запуск сервисов. Пользователи могут запустить свои приложения с минимальными трудозатратами на любой облачной платформе, создавая декларативные настройки для развертывания и запуская несколько команд.


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


Waypoint был построен для простоты использования. Больше не надо писать Dockerfiles, YAML и т.д.У нас есть дополнения для автоматического определения вашего языка, построения образа и развертывания. Да, вам придется немного настроить его, но мы сейчас говорим примерно о пятнадцати сроках текста для одного инструмента в сравнении с сотнями строк в разных инструментах на разных языках программирования.

Лично я бы описала Waypoint как минималистичный, без жестких предписаний, широко кастомизируемый инструмент для построения и развертывания, который снимает наибольшую сложность цикла разработкатестированиеразвертываниерелиз в пользу уже имеющихся базовых инструментов и сервисов разработки/тестирования/развертывания, в то же время предлагая конечным пользователям униформный и декларативный интерфейс для описания процессов разработкатестированиеразвертываниерелиз в подходящей для упомянутых базовых инструментов манере. Проще говоря, это лучшее ПО для обеспечения связности инфраструктуры.


Довольно много слов, и изрядное их количество требует объяснения. Остаток статьи как раз будет посвящен расшифровке того, что все это значит.


Переосмысление схемы работы разработкатестированиеразвертываниевыпуск


Я использую термин схема работы от разработки до релиза, а не непрерывная интеграция и развертывание программного обеспечения (CI/CD), потому что не каждая организация научилась массово использовать CI/CD, даже если все компании действительно разрабатывают и выпускают программное обеспечение с разной периодичностью.
Непрерывно или нет, все схемы работы от разработки до релиза традиционно состоят из различный типовых компонентов:


Разработка: включает в себя сборку исполняемых файлов и библиотек, содержащих изменения кода. Большая часть языков программирования имеют собственный набор системы сборки кода. Большинство вычислительных рабочих окружений имеют собственные поддерживаемые форматы артефактов, как Docker/OCI images, ELF binaries, ZIP archives, платформенно-ориентированные артефакты (как AWS Lambda Layers), и это далеко не полный перечень. Любая схема работы с комплексом инструментальных средств, которая имеет целью обслуживать максимально обширное сообщество разработчиков, вынуждена приспосабливаться к сборке кода и предпочтительного формата артефакта, по возможности используя уже существующие ориентированные на конкретный язык встроенные инструментальные средства.


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


Развертывание: чтобы начать обслуживать новый трафик, новые артефакты должны внедряться в эксплуатационную (или тестовую) среду. Часто для этого артефакты устанавливаются на сервера, где запускаются соответствующие исполняемые файлы. В своей карьере я работала с инструментами развертывания, которые охватывали весь спектр: начиная от простых развертываний на основе git (Heroku), до лабиринтообразных скриптов оболочки, до безагентных инструментов удаленного выполнения на основе ssh, как Fabric/Capistrano/Ansible, до систем, запускающих агентов на узлах, которые следят за новыми развертываниями, до (после 2015) сервисов кластерных оркестраторов, как Nomad или Kubernetes. Новому инструменту нецелесообразно заново изобретать платформу/runtime/механизмы развертывания, уже имеющиеся у поставщика облачных услуг, поскольку поставщики облачных услуг уже предоставляют собственные безапелляционные API специальные инструменты и рабочие процессы для развертывания кода.


Выпуск: я всегда верила, что нельзя отождествлять развертывание кода с его релизом. Релиз кода включает в себя управление трафиком, обновление DNS или балансировщиков нагрузки, постепенное отключение существующих сервисов, канареечные и зелено-голубые развертывания и прочее. И здесь тоже у большинства платформ уже есть собственные безапелляционные API, программы настройки и парадигмы, чтобы этого достичь.


Hashicorp (я никак с ней не связана) с самого начала была компанией с особым сверхъестественным умением выпускать инфраструктурные проекты, соответствующие (за редким исключением) рынку. Это позволило компании процветать, не ввязываясь в схемы с повторным лицензированием, чем массово занимались другие компании, выпускающие инфраструктуры с открытым исходным кодом, а особенно с open-core.


Специалисты, идущие в ногу со временем и использующие продукты Hashicorp так же долго, как и я, возможно, заметят, что Waypoint не первый заход Hashicorp в сферу развертывания или рабочих процессов. Одной из предыдущих попыток был проект Otto, который должен был стать абстракцией высокого уровня для разработки и развертывания приложений. Atlas также был экспериментом для предоставления интегрированных инструментов и общего рабочего пространства как для разработчиков, так и для операторов; от внедрения кода приложения до создания артефакта развертывания, конфигурирования инфраструктуры и в конечном итоге управления жизненным циклом приложения в процессе его работы.


Теперь, по прошествии времени, становится понятно, почему ни один из инструментов не справился и оба были в итоге свернуты или стали частью других предложений. На мой взгляд, и Otto, и Atlas должны были одни махом решить слишком много разношерстных задач. Хотя такой подход мог сработать в случае Consul, который может использоваться в качестве распределенного хранилища данных типа ключ-значение, сервиса распределенных блокировок, сервисной сетки, системы обнаружения сервисов и многого другого (и я за годы работы действительно использовала Consul для многих из этих разнообразных целей), рабочий процесс разработчика или даже рабочий процесс развертывания, требующий использования полного набора инструментов Hashicorp, был не совсем подходящим продуктом для решения такой серьезной проблемы как рабочий процесс, и особенно не в то время (начиная с 2015 года), когда индустрия видела невообразимый всплеск в количестве специализированных инструментов инфраструктуры, систем, платформ, API, парадигм и экосистем. Когда у пользователей есть выбор из множества вариантов, продуктам, нацеленным на объединение разрозненных проблем, пожалуй, труднее найти соответствие продукта и рынка без интеграции с широким спектром доступных решений.


Здесь напрашивается вопрос, чем же третья попытка одолеть эту проблемную задачу отличается от предыдущих?
Начнем с того, что Waypoint намного более узко сфокусирован, чем были Otto и Atlas за все время своего существования. Waypoint призван унифицировать опыт разработчика, не давая предписаний или обязуя пользователей прибегать к другим продуктам Hashicorp, таким как Vagrant, Terraform или Packer.


Во-вторых, складывается ощущение, что Waypoint перенял кое-что у Terraform. Подобно тому как Terraform успешно абстрагировался от различных облачных провайдеров, облачных API, платформ, систем и инструментов с открытым кодом, предоставил пользователям язык (HCL) для определения, настройки, обновления, поддержки и развития исходных конфигураций инфраструктуры и для интеграции, Waypoint стремится предоставить пользователям ориентированную на HCL декларативную спецификацию и простой CLI-интерфейс для управления и развития рабочего процесса сборки и развертывания. Как и проводники в Terraform, так и плагины в Waypoint позволяют проводить интеграцию с внешними и API системами.


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


Наконец, несмотря на то, что доказательство универсальности идет вишенкой на торте, архитектура Waypoint теоретически достаточно гибка, чтобы быть масштабированной до службы целой команде инженеров (создав удаленный сервер Waypoint и удаленных раннеров).


Заключение


В настоящее время развертывание кода является нетривиальной задачей не в связи с недостатком API или систем, особенно хорошо адресующих частные проблемы. Это связано, скорее, с тем, сколько усилий требуется на соединение всех компонентов вместе во что-то пригодное для работы.


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


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


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


От редакции: приглашаем на курс Слёрма CI/CD на примере Gitlab CI. Сейчас курс находится в разработке и его можно купить по цене предзаказа. Кроме того, вы сможете стать консультантом-тестером: получить ранний доступ к урокам, задать свои вопросы спикерам и повлиять на итоговую программу курса.

Подробнее..

Перевод Что такое модули Terraform и как они работают?

21.04.2021 14:19:32 | Автор: admin

Многие новички пропускают настройку модулей Terraform, чтобы облегчить процесс настройки. По крайней мере, они так думают, что облегчили себе задачу. Рассмотрим что такое модули Terraform и как они работают.


Я предполагаю, что вы уже знаете некоторые основы Terraform и даже пытались использовать его раньше. Если нет, ознакомьтесь с этим обзором Terraform и этим видеоуроком, прежде чем продолжить чтение.


Обратите внимание: я намеренно не использую реальные примеры кода с некоторыми конкретными поставщиками, такими как AWS или Google для простоты понимания.


Модули Terraform


Вы уже пишете модули


Даже если вы не создаете модуль намеренно, если вы используете Terraform, вы уже пишете модуль так называемый корневой модуль.


Любой файл конфигурации Terraform (.tf) в каталоге, даже один, образует модуль.


Что делает модуль?


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


Предположим, у нас есть виртуальный сервер с некоторыми функциями, размещенными в облаке. Какой набор ресурсов может описывать этот сервер? Например:


  • сама виртуальная машина, созданная из некоторого образа


  • подключенное блочное устройство указанного размера для дополнительного хранилища


  • статический общедоступный IP-адрес, сопоставленный с виртуальным сетевым интерфейсом сервера


  • набор правил брандмауэра, который будет прикреплен к серверу


  • другие вещи, такие как другое блочное устройство, дополнительный сетевой интерфейс и т. д.




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


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


Вызвать модуль означает использовать его в файле конфигурации.


Здесь мы создаем 5 экземпляров сервера, используя единый набор конфигураций (в модуле):


module "server" {    count         = 5    source        = "./module_server"    some_variable = some_value}

Terraform поддерживает "счетчик" для модулей, начиная с версии 0.13.


Организация модуля: дочерний и корневой


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


  • сеть, подобная виртуальному частному облаку (VPC)


  • хостинг статического контента (т.е. bucket)


  • балансировщик нагрузки и связанные с ним ресурсы


  • конфигурация журналирования


  • или что-то еще, что вы считаете отдельным логическим компонентом инфраструктуры



Допустим, у нас есть два разных модуля: серверный модуль и сетевой модуль. В модуле под названием сеть мы определяем и настраиваем нашу виртуальную сеть и размещаем в ней серверы:


module "server" {    source        = "./module_server"    some_variable = some_value}module "network" {      source              = "./module_network"    some_other_variable = some_other_value}

Два разных дочерних модуля, вызываемые в корневом модуле


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



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


  • локальные пути


  • официальный реестр Terraform если вы знакомы с другими реестрами, такими как реестр Docker, то вы уже понимаете идею


  • репозиторий Git (пользовательский или GitHub/BitBucket)


  • HTTP URL-адрес архива .zip с модулем



Но как передать сведения о ресурсах между модулями?


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


Вот тут и появляется инкапсуляция.


Инкапсуляция модуля


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


Scope (область видимости) модуля


Все экземпляры ресурсов, имена и, следовательно, видимость ресурсов изолированы в области действия модуля. Например, модуль A по умолчанию не видит и не знает о ресурсах в модуле B.


Видимость ресурсов, иногда называемая изоляцией ресурсов, гарантирует, что ресурсы будут иметь уникальные имена в пространстве имен модуля. Например, с нашими 5 экземплярами модуля сервер:


module.server[0].resource_type.resource_namemodule.server[1].resource_type.resource_namemodule.server[2].resource_type.resource_name...

Адреса ресурсов модуля, созданные с помощью мета-аргумента count


С другой стороны, мы могли бы создать два экземпляра одного и того же модуля с разными именами:


module "server-alpha" {        source        = "./module_server"    some_variable = some_value}module "server-beta" {    source        = "./module_server"    some_variable = some_value}

Обратите внимание на аргумент источника он остается прежним, это тот же исходный модуль


В этом случае имя или адрес ресурсов будет следующим:


module.server-alpha.resource_type.resource_namemodule.server-beta.resource_type.resource_name

Явное раскрытие ресурсов


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


По умолчанию наш модуль сервер не знает о сети, которая была создана в модуле сеть.



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


Модуль сервер должен объявить variable, которая будет использоваться позже в качестве входных данных:



Имена output и variable могут отличаться, но для ясности я предлагаю использовать одни и те же имена.


Это явное объявление вывода это способ предоставить некоторый ресурс (или информацию о нем) извне в область видимости корневого модуля, чтобы сделать его доступным для других модулей.


Затем, когда мы вызываем дочерний модуль сервер в корневом модуле, мы должны назначить вывод из сетевого модуля переменной модуля сервер:


network_id = module.network.network_id

Обратите внимание на выходной адрес 'network_id' здесь мы указываем, где он находится


Вот как будет выглядеть окончательный код для вызова наших дочерних модулей:


module "server" {    count         = 5    source        = "./module_server"    some_variable = some_value    network_id    = module.network.network_id}module "network" {      source              = "./module_network"    some_other_variable = some_other_value}

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


Подведение итогов


Теперь вы должны понять, что такое модули и для чего они нужны.


Если вы находитесь в самом начале пути к Terraform, вот несколько советов по дальнейшим действиям.


Я рекомендую вам ознакомиться с этим коротким руководством от HashiCorp, создателя Terraform, о модулях: "Organize Configuration".


Кроме того, есть отличное комплексное учебное пособие, охватывающее все, от новичка до продвинутых понятий о Terraform: "Study Guide Terraform Associate Certification".


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


Если вам понравилась статья, подпишитесь на меня в Twitter (@vasylenko), где я иногда делюсь своими выводами и советами по Terraform, AWS, Ansible и другим технологиям, связанным с DevOps.

Подробнее..

Перевод Знакомство с типичными примерами использования встроенных функций Terraform

18.01.2021 10:10:41 | Автор: admin

Небольшая инструкция по использованию Terraform, чтобы изучить и применить различные типы встроенных функций, в том числе Numeric, String, и Date, и Time в этом инструменте IaC.


ИТ-команды могут использовать Terraform от HashiCorp для развертывания облачных и локальных ресурсов и управления ими. Чтобы оптимизировать использование инструмента, изучите и установите функции Terraform.


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


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


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


name(arg-1, arg-2,  arg-n)

Например, чтобы получить отметку времени, используйте функцию timestamp(), чтобы увидеть текущую дату и время:


> timestamp()2019-12-07T07:44:12Z

Чтобы прочитать содержимое из файла по заданному пути и вернуть это содержимое в виде строки, используйте функцию file() и укажите путь к файлу в качестве аргумента:



Поддержка интерполяции для функций Terraform


Язык конфигурации Terraform поддерживает интерполяцию, которая позволяет администраторам передавать функции в виде строки для выполнения различных операций. Эти интерполяции заключены в специальный синтаксис $ {builtinfunction ()}, как показано в следующем примере:


resource "myinstance" "web" {    tags = ["${var.env == "prod" ? var.prod_subnet : var.dev_subnet}"]}

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


Давайте посмотрим на пример. В этом руководстве по Terraform у нас есть переменные с именем environment и мы сопоставляем различные среды, такие как тестирование и production, с зонами доступности AWS (AZs). Используйте другую переменную с именем availzone, чтобы сопоставить эти зоны с зонами доступности, например, us-east-1a, us-east-1b и us-east-1c. Это значения, разделенные запятыми, как вы можете видеть ниже:


variable "environment" {default = {    "test" = "us-east-1"    "prod" = "us-west-2"  }}variable "availzone" {  description = "Availability Zones Mapping"  default = {    "us-east-1" = "us-east-1a,us-east-1b,us-east-1c"    "us-west-2" = "us-west-2a,us-west-2b,us-east-1c"  }}

Чтобы захватить одну AZ, сначала используйте функцию lookup(), чтобы получить список значений, разделенных запятыми, а затем разделите его запятой (,) и функцией split().


Наконец, используйте функцию element() для захвата определенного индекса выбора. Это вернет AZ в виде строки. Поместите все эти функции внутри $ {}, как показано ниже, чтобы язык конфигурации Terraform понимал, что эти функции должны быть интерполированы перед развертыванием.


output "availabiltyzones" {  value = "${element(split(",", lookup(var.availzone,var.environment.prod)), 1)}"}

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



Список встроенных функций Terraform


Функции Terraform можно разделить на одну из следующих категорий в зависимости от сценария использования.


Числовые функции


Эти функции выполняют числовые операции, такие как вычисление максимума, минимума, степени / экспоненты и логарифма, как показано в следующем примере:



Строковые функции


Язык Terraform также предоставляет встроенные функции для управления строками. Например, функции title(), lower() и upper() изменяют регистр входных строк:



ИТ-специалисты также могут разделить строку, объединить две или более строк и заменить одну подстроку другой:



Функции даты и времени


Функции даты и времени полезны для захвата и отображения отметок времени при применении конфигурации Terraform. Как мы видели в предыдущем примере, встроенная функция timestamp() возвращает дату и время:



Используйте встроенную функцию formatdate(), чтобы расположить дату и время в более удобном формате:



Функции кодирования


Terraform имеет несколько встроенных функций, которые выполняют кодирование и декодирование строки. Например, функция base64encode('string') возвращает строку в кодировке Base64, которая полезна для развертывания ресурсов Azure, которые принимают настраиваемые сценарии в кодировке Base64 для настройки виртуальных машин. В приведенном ниже примере функция file() возвращает содержимое сценария в виде обычного текста, который затем кодируется функцией Base64encode() и передается в атрибут сценария ресурса:


resource "azurerm_virtual_machine_extension" "Example" {  name                 = "MyVM"  location             = "${azurerm_resource_group.test.location}"  resource_group_name  = "${azurerm_resource_group.test.name}"  virtual_machine_name = "${azurerm_virtual_machine.test.name}"  publisher            = "Microsoft.Azure.Extensions"  type                 = "CustomScript"  type_handler_version = "2.0"  settings = <

Функции Сбора (Collections)


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


length([1,12,31,14,5,2])length("this is a string")

Вы также можете ограничить возврат, чтобы найти только отдельные элементы в списке, или выполнить поиск в списке для определенного элемента:


Подробнее..
Категории: Devops , Terraform

Почему я советую людям не учить Ansible. Андрей Девяткин

12.05.2021 10:23:58 | Автор: admin

Комментарий автора: Основная цель доклада рассказать про методы построения инфраструктуры (Configuration Synchronization/Immutable infra) и сравнить их. Ansible используется как пример одного из инструментов синхронизации конфигурации. С точки зрения автора мир движется в сторону immutable infrastructure и в докладе приводятся аргументы разъясняющие позицию автора. И так как мир движется в сторону immutable infrastructure учить инструменты использующие подход синхронизации конфигураций может быть не самым лучшим использованием времени. Повторю еще раз доклад не про инструменты, а про подходы и принятие решения от-проблемы, а не от-инструмента


Disclaimer: Этот доклад сложен тем, что готовится под российскую аудиторию, которая работает в несколько специфических условиях. Мы потрогаем все эти вещи во время презентации. В России специфичное использование инфраструктуры, потому что народ в основном живет не на Amazon. Есть компании, которые и там живут, но их мало. И это является ограничением. Это стоит учитывать во всех докладах, связанных с раскаткой инфраструктуры, чтобы не говорить: Ребята, поехали в облако, в AWS все будет отлично и тут сидит толпа людей, которые туда поехать не могут. Российская аудитория кажется очень специфичной. И те доклады, которые заходят в Европе, в России не всегда заходят. Возможно, это связано с особым восприятием данной аудитории.




Всем привет! Спасибо, что пришли послушать! Сегодня мы обсудить, почему я не рекомендую людям изучать Ansible. Давайте разбираться.



Что же все-таки не так с Ansible? Давайте разбираться.



Еще несколько дисклеймеров.


Первый дисклеймер это то, что в этой презентации нет цели сравнивать какие-то инструменты. Т. е. это не Ansible vs Terraform, Ansible против CloudFormation, Ansible против Chef и т. д.



Тогда вы сейчас, возможно, думаете: А о чем тогда это может быть?



Еще один дисклеймер:


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


И снова рассказываю не про Ansible?



Давайте поговорим про Ansible. Мы пойдем на страницу Ansible. Этот снапшот я сделал с нее 2 дня назад, так что он достаточно свежий. Мы можем попытаться разобраться, что же за инструмент такой Ansible и зачем его используют.


Мы видим из этой страницы, что его можно использовать для application deployment, менеджмента конфигурации, чтобы оркестровать таски. И это все работает либо через OpenSSH, либо WinRM.


Но это не отвечает на вопрос: Зачем нам его использовать, какую проблему он решает?.



Поэтому мы можем пойти на страницу use-cases. Те ссылки, которые я привожу, вы увидите в левом нижнем углу экрана.


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



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


А мы им говорим, что давайте пойдем от проблемы, поймем контекст.


Далее поймем методы, которые в этом контексте будут уместны.


И потом уже подберем инструмент, т. е. давайте не будем исходить из инструмента.



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


Соответственно, контекст, который они подразумевают, это либо железные сервера, либо виртуальные машины.


Метод, который предполагается использовать, это инфраструктура как код и синхронизация конфигурации.


И предлагают использовать инструмент Ansible.



Многие из вас думают, что с Ansible можно делать многое другое.


Можно еще AWS настроить.


Можно и Kubernetes.


Можно и HashiCorp Vault настроить.


Можно все сделать с помощью Ansible при желании.



Но тогда стоит задуматься будет ли Ansible решением той проблемы и в том контексте, которую вы решаете. Т. е. нужно идти от проблемы.



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



Мы не хотим быть в этой ситуации. Плюс каждый раз, когда вы немножко выходите из mainstream, нужно подумать о последствиях. Vendor, который предлагает вам инструмент, говорит, как его можно использовать. Вы можете пойти попробовать вправо-влево и сделать что-то по-другому. Но вам нужно всегда думать: Я это сделаю сейчас так, но тогда я начну что-то терять. Если я иду в другую сторону по сравнению с community, то я потеряю именно те вещи, которым community научится, т. е. какие-то инсайты я потеряю.


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


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



Именно поэтому Ansible в рамках этой конфигурации мы будем рассматривать, как инструмент менеджмента конфигурации, который используется для provisioning серверов, чтобы раскидать applications, приложения по этим серверам. Плюс можно запускать таски, он это умеет делать.



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


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



Меня зовут Андрей Девяткин.


Называю себя cloud engineering-специалистом.


Я занимаюсь в частности AWS и инструментами компании HashiCorp. Выступал на HashiConf этим летом, потому что было очень классно.


Также являюсь основателем консалтинг-бренда FivexL.


Часто выступаю на конференциях. И еще у нас есть англоязычный podcast DevSecOps, где я и два моих друга рассуждаем о том, что сейчас происходит и пытаемся разобраться во всем. Мы пытаемся разобраться, что работает, что не работает. Это честный разговор, который мы записываем.



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


На первом этапе мы будем говорить о том, что единственная константа это изменения.


На втором этапе мы поговорим, что синхронизация конфигурации это необходимое зло.


На третьем этапе мы поговорим про immutable-инфраструктуру и о том, что это, скорее всего, наиболее подходящая практика, которая у нас есть сегодня.


Поговорим о том, что появляются новые способы, новые контексты и новые методы.


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


Поехали, начнем с первого.



Мы посмотрим на большую картинку и попытаемся понять, почему происходят эти изменения в IT, которые нам надо автоматизировать.


Представьте ситуацию, что у потребителя, есть какое-то желание, которое ему нужно утолить.


И есть предприниматель. Предприниматель видит, что у потребителя есть какая-то потребность, которую он может утолить и получить за это деньги. Он тестирует какую-то бизнес-модель и предлагает продукт или услугу потребителю.


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


Но это не так. Потому у нас есть competition, т. е. есть люди, которые приходят на рынок, видят, что сделал предприниматель и делают примерно то же самое, а, может быть, даже лучше. И они пытаются занять рынок. Например, мы начали с AWS в облаках, потом пришел Google, потом пришел Amazon, Alibaba, Яндекс, Сбер и т. д. Если бы другие игроки не пришли, то у Amazon была бы полная монополия, он бы просто делал денег. Но этого не происходит.


Коментарий автора: пришел Google, потом пришел Amazon, Alibaba под Amazon имелся ввиду Azure


Поэтому постоянно приходится меняться, постоянно приходится соревноваться с другими. Плюс меняется сам рынок. Рынок может насыщаться. Могут происходить коренные изменения в рынке, например, как в этом году во время пандемии было тяжело всем перевозчикам и тем, кто зарабатывал на туризме. Для них рынок коренным образом изменился.


Поэтому бизнесу постоянно приходится меняться. И изменения постоянно будут продолжаться.



И каждое изменение приносит собой энтропию. Вы не можете просто изменить, у вас всегда будет элемент хаоса приходить вместе с изменением.



И если мы посмотрим словарь, то энтропия это мера хаоса, это процесс разрушения, процесс деградации, когда материя во Вселенной станет в ultimate state, т. е. когда все совсем уйдет в хаос.



Вы можете сейчас сидеть и думать: Как это все связано с Ansible?.



И тут нам надо задать вопрос: Как же мы позволим бизнесу меняться быстро, но при этом минимизируем энтропию?.



И тут мы можем подумать: DevOps!.


Infrastructure as code!


Ansible!, наконец.


Но что мы сейчас делаем? Мы просто выкрикиваем термины, которые всплывают в нашей голове.



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



Поэтому мы немножко обсудим конфигурацию синхронизации и энтропию.



В нашей области энтропию называют configuration drift. И первый раз я нашел это определение, когда читал книжку Keif Morris Инфраструктура как код. Он не является тем человеком, который придумал это определение. Первыми этот термин использовали PuppetLabs поэтому атрибутика идет им.


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



Потом за счет энтропии, за счет конфигурационного дрифта сервер может в какой-то момент прийти в состояние сервера-снежинки. Это что-то такое, что придумал Martin Fowler в свое время.


Сервер-снежинка это сервер, который прошел точку невозврата. Он уже настолько свой, что уже никто не знает, как его так сконфигурировали, т. к. там уже столько всего накопилось. И трогать каждый раз его страшно. Он уникальный и очень хрупкий. Я думаю, что у многих были такие моменты, когда они сталкивались с такими серверами-снежинками.



Почему это проблема? Это проблема, потому что нарушается стабильность системы, т. е. мы не можем устанавливать приложения на эти сервера и иметь 100%-ную гарантию, что все пройдет гладко, потому что всегда есть доля неизвестности.


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


Также это влияет на наш MTTR (mean time to recovery), т. е. насколько быстро мы можем восстановиться после инцидента.



Приведу вам несколько примеров. Например, вам могло прийти письмо счастья от AWS о том, что железо, на котором лежит ваш EC2 instance, деградировало, и они собираются его прибить. И если у вас там такой сервер-снежинка, то день может стать намного интересней, чем он был.


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


Например, у вас случился второй shellshock и вам нужно все резко пропатчить. И тут могут навалиться различные инциденты, потому что патчи не проходят, т. е. вам сложно это сделать.


У моего коллеги Артема была ситуация со серверами-снежинками, у которых были GPU-драйвера. Эти сервера как-то руками наконфигурировали, но как это сделали никто не знает. Нужно было обновить GPU-драйвера. И это было большим приключением. На это ушло гораздо больше времени, чем должно уходить.


Например, в вашей сети находится нарушитель. И вам нужно произвести расследование и понять, что происходило на этом сервере. Эти файлы должны быть здесь или это Вася их поставил? Они должны быть в таком состоянии и в такой директории или им свойства поменяли? Должно ли быть все так?



Мы говорим сейчас в контексте именно серверов и виртуальных машин. И джентльмены, про которых мы говорили до этого, в начале 2010-ых говорили в терминологии серверов и виртуальных машин.



И что мы с этим делаем?



Обычный способ это инфраструктура как код. И есть 4 принципа, сформулированные в книге Инфраструктура как код:


  1. Все элементы в инфраструктуре должны быть воспроизводимыми, т. е. у нас должна быть возможность их воспроизвести.
  2. За счет того, что мы можем их воспроизвести, у нас должна быть возможность их выкинуть. Они должны быть disposable.
  3. И за счет того, что мы конфигурируем как код, наша инфраструктура будет консистентной.
  4. Плюс у нее нет конечного состояния. Когда мы проектируем нашу инфраструктуру, мы понимаем, что то, что мы знаем сегодня ограниченно и завтра может измениться. Может измениться бизнес-контекст, могут измениться бизнес-нужды, поэтому то, что мы выстраиваем сегодня, это не что-то такое, что вырублено на камне. Это то, что будет меняться, поэтому нужно продумать, как мы это будем менять завтра. И нужно быть готовым это изменить.

Это 4 принципа, на которых держится инфраструктура как код.



И если мы посмотрим определение из Википедии, то там написано, что инфраструктура как код это когда мы описываем всю нашу инфраструктуру в файликах. Эти файлики machine-readable, т. е. какие-то инструменты могут эти файлики прочитать и потом перевести все, что в этих файликах написано, а потом пойти и сконфигурировать системы так, как мы это описали.



Технически мы применяем методы разработки software одна конфигурация. Все те же методики, т. е. так же, как мы разрабатывали код, как мы разрабатывали продукт, тоже самое мы делаем с инфраструктурой, применяя те же методики. Можем делать code review, можем запускать CI и так далее



И наш шаблон потихоньку заполняется, т. е. мы говорим в контексте железных серверов и виртуальных машин. Применяем infra as code.



И я обещал поговорить про синхронизацию конфигурации и давайте про нее поговорим.



Было несколько поколений инструментов для работы с конфигурациями.


Я не буду называть номер этого поколения, но было конкретно выделенное поколение: Puppet, Chef. Ansible и SaltStack пришли чуть попозже. Это именно те инструменты, которые работали с синхронизацией конфигурации. Мы сейчас увидим, что это значит.


Специфика этих инструментов в том, что они автоматизируют provisioning. И чаще всего им нужна небольшая дополнительная конфигурация. В случае некоторых инструментов нужно установить агента на сервер, в случаях других нужно открыть firewall для того, чтобы он туда мог пойти, например, по SSH-порту и сделать то, что он хочет сделать.



Вот эту картинку я взял из статей Martin Fowler. Это отличные картинки, ссылки внизу, если вы захотите всю статью прочитать. Это именно то, как работает конфигурация синхронизации.


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


Опасность здесь в том, что мы не следим за всеми файлами на сервере. У вас всегда есть вероятность, что кто-то пошел и руками поправил и это вне ответственности инструмента. Это все накапливается-накапливается.



И это может привести к спирали страха автоматизации.



Как это работает? Вы делаете изменения вне вашего инструмента, которым вы синхронизируете конфигурацию. Ваши сервера становятся немного не консистентными. И потом вам становится страшно запускать ваш инструмент, потому что что-то может пойти не так: что-то может сломаться, если вы его запустите. Поэтому в следующий раз, когда вам нужно сделать изменения, вы снова их делаете руками, сервера становятся еще более не консистентными, и вам еще более страшней запустить ваш инструмент. И таким образом ваш сервер по спирали уходит вниз к состоянию сервера-снежинки.



Давайте посмотрим, как эволюционировала человеческая мысль дальше.



Потом те же ребята из ThoughtWorks пришли с идеей о Phoenix server,



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



Мы можем сделать еще один шаг.



Мы можем все изменения, все конфигурации, которые у нас есть, поместить в образ сервера и уже накатывать это сразу на сервер. И после этого не делаем никаких изменений, и просто раз в какой-то промежуток времени его удаляем. Если нам нужно сделать какие-то новые изменения, мы делаем новый образ сервера, накатываем его на сервер. Т. е. мы не делаем синхронизацию конфигурации, мы либо понимаем новую виртуалку из нового образа или вайпаем (wipe, стереть) сервер и накатываем новый образ. И поэтому требуется несколько серверов, чтобы вы могли переключать трафик. Но за счет этого вы минимизируете количество конфигурационного дрифта.


И другой бенефит, который вы получаете от этого, у людей пропадает желание ходить на сервер по SSH, потому что они знают, что сервер будет уничтожен в какой-то момент и все изменения, которые они делают, пропадут. И вместо про то чтобы спрашивать вас о том где лежит SSH ключ они уже спрашивают вас о том, где лежит спека из которого будет собран образ для этого сервера. И это уже новый уровень диалога.



  • Если говорить еще о бенефитах, то, как мы уже говорили, у нас стремится к нулю конфигурационный дрифт.


  • У нас есть возможность масштабироваться быстро. Например, в рамках AWS у нас есть auto scaling группа. Вам нужно поднимать новые виртуалки. И вы не будете руками их запускать-запускать, а потом инструментом синхронизации конфигурации их настраивать, а потом только вводить в строй. Если у вас почти все заключено в ami (шаблон виртуальной машины), то тогда у вас auto scaling group может автоматически вам новые сервера легко поднимать, а также убивать. Вы ничего не теряете, потому что они всегда все одинаковые. Ничего нового здесь я не рассказываю. Это backing vs. frying, cattle vs pets. Все то что много раз рассказывалось на конференциях.


  • И у вас повышается уровень безопасности. Представьте, что в вашу сеть пробрался нарушитель. И вы это не заметили. А вы каждую неделю перекатываете все свои сервера. И таким образом все, что он установил, вы стираете. И ему придется каждую неделю повторять все те же мероприятия, чтобы хоть как-то закрепиться в вашей инфраструктуре.


    Плюс, что делают те, кто нападают? Они нападают и сидят очень тихо. И они делают нумерацию всего того, что у вас есть: Ага, веб-сервер на том IP-адресе, это на том IP-адресе. А у вас все меняется постоянно. У вас постоянно происходит ротация этих серверов, ротация IP-адресов, если вы в облаке. И им намного сложнее заниматься теми делами, которыми они пришли заниматься. Например, незаметные латеральные движения в вашей сети становится намного сложнее.


  • Плюс, за счет того, что вам минимальное время нужно на provisioning сервера, потому что все уже в образе находится, вы можете воспользоваться, если вы в облаке такими опциями, как EC2 spot instance. Если даже из-под вас spot instance выдернут, то ничего страшного. В другой зоне поднимется, потому что там осталось все по-прежнему, т. е. вы ничего не теряете. У вас будет 2 минуты для того, чтобы переключить трафик, чтобы убрать этот instance из ротации.




И тут вы можете подумать: Если я использую Ansible, но при этом достаточно часто убиваю свои сервера, то, может быть, этого достаточно?.



Может быть. Как я вам сказал, эта презентация очень практичная. И мы не идеалисты, мы практики. Умные книжки вам всегда рисуют красивую картинку, но жизнь всегда сложнее. Ты приходишь иногда к заказчику и думаешь: Боже мой, что же вы наворотили! Какой ужас!.


Конечно, этого нельзя людям в лицо говорить. Нужно пообщаться и понять, почему они так сделали. Скорее всего, у них были причины. Если бы у нас у всех были идеальные условия, то мы бы строили идеальные системы. Но условия не идеальные и часто приходится подстраиваться. И как хмурый котик нам сказал о том, что, может быть, это даст вам 80 % бенефитов за 20 % усилий.


Каждый для себя выбирает свою дорогу, основываясь на том фреймворке, о котором мы сейчас говорили.



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


И мы рекомендуем нашим заказчикам, что immutable-инфраструктура это более лучший подход.



Как ее имплементировать? Давайте поговорим про это.



В идеале перед тем, как вы начнете, вам надо посмотреть на ваши приложения. И будет очень хорошо, если ваши приложения будут соответствовать 12 факторам app.


Там очень полезные вещи написаны. И очень смешно, когда системные инженеры, которые занимаются инфраструктурой, выстраивают системы, приходят к девелоперам и говорят: Вы про 12 factor app слышали? Давайте так делать. И очень часто на них люди удивленно смотрят.


И если вы следуете этим рекомендациям и если ваше приложение сегодня не запускается в контейнерах, то переезд контейнера будет намного проще. Плюс вам будет намного проще имплементировать immutable-инфраструктуру.


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



Давайте подумаем о тех вещах, которые стоит учесть.


У нас есть 3 большие области, про которые стоит подумать:


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


Давайте разбираться с секретами сначала.



Нам нужно решить проблему нулевого секрета. И в зависимости от той среды, которую мы используем, применяются разные вещи. Например, если это AWS, то мы можем использовать instance-профайлы, которые нам дадут credentials, которые мы потом можем в дальнейшем использовать.


Если это Bare Metal, то там много разных систем.


SPIFFE все больше набирает популярность, чтобы давать серверам identity. И потом, чтобы они могли через identity аутентифицироваться в других системах.


Другой вариант вы можете запечь зашифрованные секреты в образ с учетом того, что ключ шифрования будет доступен, когда образ будет подниматься. Например, в AWS вы можете использовать KMS ключ, который доступен только в вашем аккаунте. Если ваш AMI утек, то его нельзя будет расшифровать, потому что нет доступа к ключу. В вашем дата-центре может быть HSM (hardware security module), в котором вы можете хранить ключи шифрования, которые будете использовать для того, чтобы расшифровывать секреты. Если у вас утечет образ, то ничего страшного, потому что ключи только там.


Также сейчас есть системы, которые позволяют затаскивать секреты вовнутрь, т. е. у вас приложение может подняться и прочитать все необходимые секреты, например, с HashiCorp Vault. Если вы бежите в AWS, то мы можете Secrets Manager использовать.


Также все больше и больше возможностей генерировать динамические credentials. Это не сильно относится к immutable-инфраструктуре, но это то, что мы всегда рекомендуем.


Плюс есть возможность пулить (pull) не только секреты, но и конфигурацию, например, используя Consul.



Что делать с людьми?



Нам нужно оставить возможность попасть на сервер, либо на виртуальную машину. Но сделать это так, чтобы люди наследили, когда они это делают. Грубо говоря, не надо гасить SSH-сервер, но SSH-порт стоит закрыть на firewall. И чтобы людям туда пойти, им сначала нужно открыть firewall. И у вас получится из этого какой-то event. Это зависит от того, как ваша инфраструктура выстроена. И на этот event вы потом можете настроить автоматическое убийство машин, потому что неизвестно, что человек там наделал.


И многие компании так делают. Если там кто-то что-то наделал ручками, то автоматически эта машина через 12 часов будет убрана из ротации и полностью очищена.



Как нам поступать с debug?



  • В первую очередь нужно вытаскивать все, что мы можем вытащить. Стримить логи наружу, а также все метрики, т. е. все то, что можно вытащить, нужно вытаскивать.
  • Дальше нам нужно подумать про безопасность немножко. Наши сервера умирают достаточно часто. И может быть так, что нам понадобиться пойти назад в историю. Может быть, у нас несколько месяцев сидит злоумышленник в нашей сети, и нам нужно провести исследование, что он делал и где он был. А если вы каждую неделю вращаете свои сервера и полностью их затираете, то вы можете потерять важные улики. Поэтому системные вызовы тоже стоит стримить с серверов. И, скорее всего, ваша служба безопасности этим занимается. Либо нужно делать какие-то снапшоты перед тем, как вы сервер убиваете. И потом эти снапшоты вы храните несколько месяцев. Это полезно.
  • Если людям нужно что-то протестировать, то у вас есть образ, который такой же, как и тот. Поднимите на стороне еще одну виртуалку, например, либо еще один сервер. Пустите немножко трафика и протестируйте там. Не ходите на те машины, которые на данный момент обслуживают production.
  • А если очень нужно, то ходите, а потом прибейте.


  • Лучшие практики. Если вы делаете continuous integration, то ничего нового. Все зависимости сохраняйте под системой контроля версий.
  • Автоматизируйте построение образов ваших виртуальных машин или серверов. Постарайтесь, чтобы люди вам их не собирали, чтобы это был повторяемый процесс, который у вас происходит на сервере.
  • Автоматизируйте тестирование, т. е. пробуйте автоматически все раскатывать.
  • Старайтесь промоутить вместо того, чтобы пересобирать. Эта важно. Старайтесь, чтобы это был тот же образ, просто, чтобы он был конфигурируемый между окружениями вместе того, чтобы пересобрать в каждом окружении свой. Иначе будет вероятность, что что-то пойдет не так или у вас будет тестирование отличное от условий production.
  • Часто деплойте. Как можно меньшую дельту накапливайте перед тем, как раскатываете. В идеале раскатываете на каждый commit, если у вас есть такая возможность. Особенно, если у вас система построена так, что вы без потери трафика можете переключать виртуальные машины. Это требует определенной работы, но вполне достижимо. И сейчас есть много инструментов, которые могут с этим помочь. В идеале каждый commit. Потому что, если что-то пошло не так, у вас дельта один commit, вы знаете, что пошло не так. Проблема в этом commit. Вы его откатили, вернули зеленое состояние. И человека, который сделал этот commit, есть время, чтобы разобраться и узнать, что пошло не так. На него нет давления, что он сломал что-то в CI. Т. е. просто откатили и человек спокойно разбирается.
  • Плюс я рекомендую перекатывать по расписанию. У вас может быть так, что commitов нет. Т. е. у вас какая-то такая система, в которой не так часто происходят изменения. Поэтому я рекомендую по таймеру перекатывать, т. е. делать каждую неделю перекатку. Можно делать это в выходные, либо в понедельник с утра.


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


HashiCorp Packer, я думаю, всем знаком. Это достаточно универсальный инструмент, который много где используется. Вы можете под облака собирать Packerом, можете под локальные виртуалки тоже. Есть много разных вариантов.


Если вы деплоите в cloud или вам предоставлен API, то Terraform классный инструмент. Это дело вкуса, конечно. Может быть, вам vendor предоставляет какой-то более хороший инструмент, т. е. я не пытаюсь вам говорить, что Terraform самый лучший инструмент в мире. PXE очень полезен для раскатки baremetal, если вам именно baremetal нужен.


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


Безопасность Audibeat, WAZUH и другие инструменты. Vault очень популярный инструмент. Если вы в облаке, то используйте облачные сервисы, потому что вам их не нужно будет настраивать самому.


И с debug я тоже привожу здесь какие-то инструменты, но все очень сильно зависит от вашего контекста. Это может быть Prometheus, Logstash. Если вы в облаке, то это может быть CloudWatch, Datadog.



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


Ansible занимается менеджментом конфигурации. Если мы делаем immutable-инфраструктуру, то Ansible больше не нужно этим заниматься, потому что это часть построения образа. Теоретически вы можете через Packer Ansible запустить. Но важно то, что вы запекаете конфигурацию в образ. И теперь именно вот этот инструмент за это отвечает.


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


Приложение, скорее всего, вы доставляете как часть образа, т. е. его не надо раздавать.


СI task? Почему бы не нет, если вам очень нравится Ansible.



Поговорим про другие пути и о том, что происходит сейчас.



Понятное дело, что сервера и виртуальные машины уже потихоньку уходят в прошлое. И появляется новый контекст это контейнеры.



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



Контейнеры сами по себе immutable изначально, т. е. docker-образ, docker images он immutable. Docker container mutable. Технически вы следуете принципам 12 factors app, когда вы строите docker container. И он (образ) будет immutable изначально. Вся ваша конфигурация туда будет приходить снаружи как переменное окружение. State вы будете монтировать снаружи, базы данных доступны по сети. Здесь у нас все хорошо. Мы используем лучшие практики, которые мы в предыдущем контексте наработали.


Есть еще одна классная штука с контейнерами. Они позволяют вам скрыть энтропию. Вы, когда уничтожаете контейнер и восстанавливаете, то все то, что вы в нем поменяли, остается в этом контейнере. Если вы его удалили, то удалили весь конфигурационный дрифт. При этом host, на котором бежит контейнер, остается намного чище. На нем почти не остается конфигурационного дрифта, если только там нет таких локальных volume.


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



Если вы используете оркестратор, то ваш контейнер часто будет переезжать между хостами, потому что что-то изменяется. У нас есть Kubernetes. У AWS есть ECS для тех, для кого Kubernetes слишком сложный. Если вы хотите соединять публичные clouds, prime clouds, hybrid clouds, то можно посмотреть в Nomad, хотя 2 дня тому назад на Reinvent Amazon сказал, что EKS и ECS теперь anywhere. Я не знаю, сколько это будет стоить. Но технически похоже, что EKS и ECS можно будет on-premises запускать и завязывать как-то с Amazon. Посмотрим, что будет.


Но Nomad это тоже солидное решение, которое используется большим количеством компаний (Cloudflare/CircleCI/Roblox), чтобы серьезное количество нагрузок запускать.


Плюс у нас есть целая аллея мертвецов. В 2015-ом году у нас была война оркестраторов. И победителем вышел Kubernetes, потому что CNCF вкачали в него максимальное количество маркетинговых денег. У нас есть Docker Swarm, который купил в итоге Mitrantis. И который теперь намекает всем своим заказчикам, что пора бы ехать на Kubernetes. OpenShift переделал все на Kubernetes.



Плюс у нас есть не только оркестратор, но и container OS, т. е. операционные системы, которые нацелены на то, чтобы работать с контейнерами. И зачастую эти операционные системы требуют минимальные настройки. Зачастую там уже все есть. Не надо ничего доставлять после.


Плюс многие из этих систем умеют самообновляться, т. е. вы ее подняли и забыли, там ничего не нужно делать после.



Таким образом, нам нужно расширить наш контекст. Мы не можем просто сказать контейнер, потому что это будет слишком широко. Потому что контейнеры ECS как оркестратор это совершенное другое. Поэтому давайте остановимся пока на Kubernetes, т. е. контейнеры и Kubernetes.


Метод у нас инфраструктура как код, чтобы взять Terraform и раскатать все, что вокруг kubernetes-кластера. Доставка в kubernetes-кластер приложений. Похоже, что community движется в сторону GitOps. У меня есть свои персональные вопросы к GitOps, но не хочу идти против течения. Как говорится, если ты не можешь остановить сумасшествие возглавь его. И сейчас у меня происходит некий нырок в GitOps.


И еще сейчас пошел новый хайповый тренд Infra as data, т. е. инфраструктура как дата. Это, по сути, тот же самый GitOps, только инфраструктура yaml написана, а не кодом.


Инструменты ArgoCD, про который на этой конференции достаточно много рассказывали. Helm, которым можно темплейтить kubernetesкие чарты и потом складывать в репозиторий. Terraform, чтобы поднимать все вокруг. Плюс есть операторы в AWS, которые позволяют Terraform запускать как часть, используя CRD в Kubernetes.


Достаточно много вопросов, как все это будет. Проблема все та же, контекст более-менее устоялся. Методология как будто бы сейчас начинает устанавливаться. Инструменты посмотрим, это зависит от методологии.



Если мы рассматриваем Ansible в контексте контейнеров, то менеджмент конфигурации происходит как часть build контейнера.


Server provisioning нам, в принципе, не нужен, потому что мы используем containers OS, которые настраивать не надо. Приложение приезжает само в контейнере и его притаскивает оркестратор. Зачастую наша операционная система будет все необходимое для оркестратора иметь. Нужно будет только сказать, где оркестратор и как к нему подключиться.



Не будем говорить про Serverless. Хотелось бы поговорить, но и так уже много информации. Это еще один контекст. Kubernetes это один контекст. Serverless это другой контекст. И в нем будут свои инструменты, свои подходы. Serverless я предлагаю пока оставить за пределами этой презентации. Может быть, у нас контекст контейнеров и Kubernetes немножко устаканится и в следующем году мы поговорим про Serverless, а сегодня пропустим.



И новый фронтир. Хотя он не совсем новый, люди это уже делают около 8 лет, но еще пока он не прошел ту точку, когда все про это говорят. Это MicroVM.


Вы, скорее всего, слышали про AWS Firecracker, который используется для запуска лямбды.


И Unikernels это когда ваша операционная система компилится вместе с вашим приложением. И вы запускаете то, что вы построили сразу на hypervisor, если у вас есть к нему доступ.


Это что-то такое, что может быть как контекст, интересный людям, которые живут в своих дата-центрах. Потому что у вас зачастую есть доступ напрямую к hypervisor. Тем людям, которые живут в облаках, сложнее. Потому что Amazon не даст доступ напрямую к своему Nitro. Может быть, он когда-нибудь придумает свою ручку, чтобы вы смогли там свои Unikernel запускать, но до этого еще нужно дожить.


И здесь много неизвестных. Контекст, в принципе, немного устоялся, но методология совсем непонятная. Не понятно, как мы их будем доставлять, не понятно, как мы будем их оркестрировать, не понятно, как мы ими будем управлять. Очень много вопросов еще, поэтому мы эту тему упомянем, но пропустим.



Чему мы можем научиться от Kubernetes? Давайте задумаемся. Kubernetes принес достаточно интересную концепцию как reconciliation loop, т. к. когда вы ему скармливаете свои yaml, он их принимает, персистит etcd и потом пытается сделать так, чтобы было так, как описано. Он постоянно идет по кругу и проверяет а оно так, а оно так? Например, pod убили, pod нет. И он поднимает новый, чтобы было так, как описано.


И, может быть, через 2-3-5 лет, провайдеры могут подумать: А почему бы нам не сделать такую же штуку? Т. е. сейчас мы постоянно запускаем Terraform, по сути вещей делаем что-то близкое к синхронизации конфигурации. И очень может быть, что cloud-провайдеры приготовят что-то такое для нас. Мы будем просто отдавать YAML, cloud будет сам это настраивать для нас так, как оно должно быть. Нам не нужно будет это постоянно запускать. Cloud сможет подстраивать свои ресурсы, сможет сам бороться с конфигурационным дрифтом. Таким образом, он автоматизирует большую часть нашей работы.



Есть еще другая идея, над которой вы можете после подумать а не идем ли мы назад? Не является ли GitOps новым Chef? Я предлагаю подумать в рамках такой метафоры: часто говорят, что Kubernetes новый Linux. Теперь Linux это такая платформа, поверх которой бежит Kubernetes. И Kubernetes это наш новый user space, где мы запускаем новые приложения. И с GitOps мы, по сути, делаем синхронизацию конфигурации. Т. е. у нас ArgoCD пуллит все то, что написано в наших репозиториях и apply на Kubernetes. По сути, делает все то же самое, что делал Chef в свое время.


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


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



История постоянно себя повторяет. И теоретически в какой-то момент мы придем к тому, что нам нужно будет придумать, как мы будем делать immutable-инфраструктуру для Kubernetes.


Может быть, пора уже убивать свои kubernetes-кластеры и полностью их пересоздавать с нуля? Хотя, в принципе, это рекомендовано. Когда Kubernetes выкатывает новую версию и если мы апгрейдим in-place, то очень часто новые security-фичи выключены, чтобы сохранить обратную совместимость. Поэтому рекомендуется свои кластера перекатывать (пересоздавать), таким образом вы убиваете весь тот мусор, который там накопился.



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



Вы можете сейчас подумать: Как же быть? Я уже потратил столько лет, работая с Ansible. Я так его хорошо знаю. Что делать?. Очень легко принести новые инструменты в организацию, но удалить их оттуда очень сложно.


Например, я вел 10 лет назад миграции с ClearCase на Git. И в больших организациях это мероприятие занимало года полтора, потому что очень много было построено вокруг него.


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


Плюс выбирать какую-то новую технологию это тяжело, это опасно. Например, в 2015-ом году все новые компании, которые стартовали, выбирали, как они будут строить свою внутреннюю платформу. Был Kubernetes, Nomad, Docker Swarm. Много всего было. И нужно было что-то выбрать. Прошло 2 года и те, кто выбрал Docker Swarm, возможно, начинают покусывать локти.


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



Вот, что я хочу вам показать. Я вчера сравнил Chef, Ansible и Terraform в Google Trends. Я понимаю, что когда я сравниваю Chef, Ansible и Puppet с Terraform, то я сравниваю яблоки и груши. Я не пытаюсь показать, что один инструмент лучше другого. Я хочу показать вам картинку немного в другом контексте.


Ansible лидирует. Terraform внизу. И это показывает адопцию cloud в России. Потому что в России только сейчас появляются более-менее серьезные игроки, на которые уже можно начинать полагаться.


Плюс некоторые могут пользоваться заграничными облачными решениями. И зеленую полоску поднятия Terraform я истолковываю, как показатель адопции cloud.



Я попробовал воспользоваться Yandex keyword-статистикой, что было не самым приятным опытом. И, как вы видите, Ansible 29 000.



Terraform около 6 000. Цифры примерно похожие с Google Trends.



А вот, что происходит в Штатах. Посмотрите, какой прыжок у Terraform. Ansible тоже был очень популярным, но адопция cloud в Штатах началась лет 5-6 назад. В начале 2010-ых это были только самые смелые, типа Netflix. Сейчас уже большие банки там. Если вы смотрите Reinvent, то приходит человек из большого банка и начинает рассказывать о том, как им хорошо жить в облаке. И сейчас там начинает подтягиваться длинный хвост. И именно это показывает график. Я не сравниваю инструменты. Я показываю вам график именно с точки зрения адопции cloud. Я думаю, что в ближайшие 3-5 лет это то, что мы увидим в России, даже если вы этого не хотите.



Давайте повторим о том, что мы обсудили.



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



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


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


Для этого хорошо подходили Ansible, Puppet, Chef и им подобные.



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



А что будет завтра? Это еще нужно понять, поэтому мы пока смотрим. Но проблема остается прежней, контекст меняется. Пока мы вырабатываем методологию и смотрим, какие есть инструменты. Но это что-то такое, что будет завтра.


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



На этом у меня все. В нижнем левом углу мои контакты. И я думаю, что мы сейчас еще немножко поговорим с Максимом и обсудим ваши вопросы.


Вопросы и ответы:


Вопрос: В твоем докладе сначала было больше про инфраструктуру, а потом немного промелькнуло про установку приложения на сервер. Это достаточно два крупных блока. И вопрос от Дмитрия: Для Ansible место где-то сохраняется?. Например, в infra или для деплоя приложений. Ты про деплой приложений упоминал. Ты говорил, что деплой приложений в Kubernetes может быть через Helm. А если облаков нет, не используется Kubernetes, для деплоя приложения Ansible это нормальное решение или тоже проблемы будут?


Ответ: Мы про это говорили. Надо исходить из контекста. Если в нашем контексте фигурирует оркестратор контейнеров, то он будет отвечать за доставку. Т. е. чтобы приложение оказалось на сервере, за это будет отвечать оркестратор. Когда мы делаем immutable-инфраструктуру, то у нас есть выбор. То есть мы можем положить приложение в образ и доставлять именно готовый образ с приложением. Каждая новая версия приложения это новый образ сервера или новый образ виртуалки. И мы таким образом перекатываем. Если у вас не такой возможности, то по старинке через Ansible. Это все зависит от контекста. Я не пытаюсь быть идеалистом. Исходите из того контекста, который у вас есть.


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


Вопрос: Я правильно понимаю, что для того, чтобы пойти в immutable-инфраструктуру, нужно преодолеть достаточно высокий порог входа? Т. е. эта история примерно повторяется, как было с микросервисами. Было так, что для того, чтобы пойти в микросервисы, тебе нужно было адекватно подготовить инфраструктуру, иначе ты рехнешься все это мониторить и за всем следить. И с immutable-инфраструктурой примерно та же история, потому что желательно, чтобы были облака, а также хорошо настроенный мониторинг, чтобы не было никакой необходимости ходить на сервера вручную и что-то там смотреть, а ты мог взять и порезать всем доступ. И без этого в immutable-инфраструктуру даже соваться не стоит?


Ответ: Я бы так не сказал. Хороший мониторинг тебе нужен всегда. Хороший мониторинг нужно всегда иметь, не важно, как ты инфраструктуру раскатываешь. Я могу примерно так же ответить на другие возражения. Если хочется получить максимум бенефита с минимум усилий, то можно идти по слайдам презентации, т. е. так, как это делали раньше люди. Просто убивайте свои сервера иногда. Сейчас вы Ansible запускаете на своем сервере, но когда был тот последний раз, что вы его запускали с нуля? Это хороший вопрос. И какая гарантия, что с нуля это сработает?


Т. е. если вы просто начнете перекатывать свои сервера изредка, хотя бы раз в месяц или раз в неделю, то ваш Ansible от этого улучшится, потому что вы будете раньше находить эти проблемы. И если у вас долгобегущие сервера, на которых накапливается конфигурационный дрифт, то ваш Ansible playbook начнет потихоньку подстраиваться под то, что у вас там есть, хотите ли вы этого или нет, потому что люди всегда режут углы. Поэтому не давайте людям резать углы, перекатывайте свои сервера с нуля. И таким образом вы тестируете свои playbooks всегда. Они становятся только лучше от этого.


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


Мы всегда советуем то, что имеет смысл в бизнес-контексте. Нет смысла в вакууме добиваться какой-то победы. Если вы уже получили 95 % бенефитов и вам нет смысла дальше это делать, потому что это будет дороже, и вы ничего не выиграете, то нет смысла этого делать. Вам нужно понять, где вы находитесь и понять, как это поможет вашему бизнесу.


Вопрос: Остается ли где-нибудь место для Ansible? В некоторых ситуациях оно, действительно, где-то остается. И при этом можно immutable-инфраструктуру создать вполне себе вменяемую.


Ответ: Да. Вы можете запускать Packer, взять свой playbook и просто в Packer запустить свой playbook, чтобы построить образ. И вот у вас есть образ со всем тем, что вам нужно. Некоторые люди еще делают золотой образ, что я не советую. Они берут сервер, делают с него снапшот. И потом настраивают его руками, делают еще один снапшот. Я не советую так делать.


Вопрос: У меня хитрый вопрос остался. Как быть с серверами баз данных? Т. е. с любой инфраструктурой, которая хранит состояния? Там бывает такая ситуация, когда ты обновляешь версию базы данных, а там какое-то мажорное обновление и в этих скриптах обновлений уже заложена конвертация данных. Например, появились транзакции в MySQL базе данных и это как-то повлияло на структуру хранения, и должны эти скрипты отработать. Как в этом случае с immutable быть?


Ответ: Ты же не будешь менять базу одновременно со схемой. Я не уверен, что понимаю вопрос.


Вопрос: Я не про пользовательские изменения. Т. е. не тогда, когда ты сам схемы меняешь. Предположим, у Mongo мажорная версия обновилась так, что у нее поменялась структура хранения данных. Например, они ввели файл и раньше они unlock хранили одним образом, а потом начали хранить другим. Такое бывает редко, но в некоторых инфраструктурах это бывает. И у них в скрипты обновлений встроены скрипты для обновления самих данных, т. е. то, как они их хранят.


Ответ: Т. е. здесь ты говоришь, что у тебя нет возможности пойти обратно? Т. е. если ты уже поднял новую Mongo, то возможности пойти обратно у тебя уже нет?


Вопрос: И ты не можешь просто убить сервер, перенести данные на новую версию Mongo, где она их подхватит. Надо, чтобы они все равно конвертнулись.


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


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

Подробнее..
Категории: Devops , Terraform , Ansible , Immutable 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