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

Iac

Перевод Построение конвейера IaC на AWS с полностью интегрированной безопасностью

02.12.2020 18:09:40 | Автор: admin

Перевод статьи подготовлен в преддверии старта курса "Infrastructure as a code in Ansible".


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


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

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

Теперь давайте разберем реальный пример того, как можно автоматически проконтролировать корректность методов разработки в конвейерах IaC для среды AWS посредством сотен проверок на соответствие правиламAWS Well-Architected Framework(безопасность, оптимизация затрат, производительность, высокие стандарты профессиональной деятельности и надежность) и другим стандартам.

Вот общее представление того, над чем мы будем работать:

Исходные требования

Для формирования нужной нам среды вам понадобятся следующие элементы:

Приступим к созданию вашего первого конвейера инфраструктура как код (IaC) с проверкой применения правильных методов разработки!

Этап1. Установка подключаемого модуля безопасности в среду программирования и получение токена API для сканирования шаблонов CloudFormation

После установки среды VSCode IDE не забудьте также установить подключаемый модуль Cloud Conformity Security, как показано здесь:

  • VSCode Marketplace подключаемый модуль Cloud ConformityССЛКА

Расширение для сканирования шаблонов Cloud One Conformity Template ScannerРасширение для сканирования шаблонов Cloud One Conformity Template Scanner

Создайте свою учетную запись в Cloud One Conformity, воспользовавшись приведенной здесь ссылкой (создать учетную запись), войдите в нее и сформируйте токен API.

В среде Cloud Conformity: щелкнитеимя пользователявверху справа и выберите User Settings (Настройки пользователя)API Keys (Ключи API)New API Key (Создать ключ API), чтобы создать ключ API, который будет использоваться в подключаемом модуле VSCode. Обязательно скопируйте ключ и сохраните его в надежном месте. Получить его еще раз невозможно.

Скопируйте ключ API и вернитесь в среду VSCode

1. Щелкните значок расширений (слева) и нажмитеExtension Settings (Настройки расширений) для записи сканера шаблонов Cloud Conformity Template Scanner.

2. В среде Cloud Conformity выберитеEdit in settings.json (Изменить файл settings.json). Перейдите к разделу ApiKey.

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

Теперь шаблоны CloudFormation можно сканировать с использованием сотен проверок на соответствие правилам AWS Well-Architected Framework и другим стандартам, гарантируя превосходное качество разрабатываемой облачной инфраструктуры.

Вот пример шаблона CloudFormation, не соответствующего передовым методам разработки, который вы можете протестировать:

Чтобы испытать расширение в работе, откройте указанный выше шаблон CloudFormation с помощью VSCode, после чего откройтепалитру команд, нажав:

  • macOS: + + P

  • Windows/Linux:Ctrl + Shift + P

Найдите элемент Cloud One Conformity: Scan the Current Open Template (Cloud One Conformity: сканировать открытый шаблон) и нажмите <Enter>, после чего автоматически начнется сканирование этого шаблона CloudFormation:

Результат сканирования появится на второй вкладке под названием Scan Result (Результат сканирования), как на приведенном ниже изображении. Также можно воспользоватьсяоблачной базой знаний, которая поможет лучше понять выявленные нарушения рекомендуемых методов, а также узнать способы их устранения в вашем шаблоне CloudFormation или в производственных средах:

Превосходно, первый этап автоматизации безопасности IaC завершен.

Этап2. Создание конвейера CI/CD средствами AWS с последующей интеграцией в него сканера шаблонов Conformity

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

С помощью такого шлюза можно отслеживать и выполнять аудит всех изменений в реальном времени и только затем производить развертывание в среду AWS.

В этом разделе мы покажем, как использовать сканер шаблонов в конвейере CI/CD сAWS CodeCommit,AWS CodeBuild иAWS CodePipeline. Приступим.

CodeCommit будет использоваться в качестве репозитория для размещения нашего кода. Многие люди и компании со всего мира используют для этого GitHub, GitLab и BitBucket. Чтобы ваша среда VSCode могла перемещать код в CodeCommit, нужно будет кое-что настроить.

Создание репозитория Git в AWS CodeCommit

  • Создайте пользователя IAM с разрешением использовать CodeCommit и доступом только с помощью ключа SSH. (Сведения о разрешении для Git и рекомендации приведены по этойссылкеот AWS.)

Перейдите в раздел Security credentials (Учетные данные безопасности) HTTPS Git credentials for AWS CodeCommit (Учетные данные Git HTTPS для AWS CodeCommit), чтобы сформировать учетные данные.

Загрузите учетные данные и сохраните их в надежное место.

Подробнее об этой процедуре на сайте AWS ССЛКА.

  • Создайте репозиторийAWS CodeCommit.

Можно выполнить команду git clone на своем компьютере и легко перенести на него git config.

git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/{ИМЯ ВАШЕГО РЕПОЗИТОРИЯ}

Теперь можете воспользоваться собственным шаблоном CloudFormation или взять плохой шаблон CloudFormation, который я предоставил ранее, для передачи в AWS CodeCommit.

git add .

git commit -m "First Commit"

git push

Итак, первое сохранение в AWS CodeCommit выполнено. Теперь давайте перейдем к AWS CodeBuild и AWS CodePipeline.

Создание CodeBuild для автоматического сканирования шаблонов CloudFormation

Решение AWS CodeBuild очень похоже на GitHub Actions, Azure DevOps и GitLab. Это технология CI/CD, с помощью которой можно создавать новые проекты, автоматизировать процессы и развертывать новые приложения или инфраструктуры.

Мы будем использовать CodeBuild с определенным образом контейнера для запуска сканера шаблонов Conformity с целью выявления возможных проблем перед развертыванием новой IaC в производственной среде.

  • Создание проекта построения в AWS CodeBuild

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

Вот конфигурация для приведенного ниже образа:

Environment image: Managed ImageOperationg System: Amazon Linux 2Runtime: StandardImage: aws/codebuild/amazonlinux2-x8664-standard:3.0Image version: Always use the latestEnvironment type: LinuxService Role: NewRole Name: <NEW ROLE NAME>

Вот конфигурация для приведенного ниже образа:

Environment VariablesCC_API_KEY = <YOUR API KEY FROM CLOUD ONE - CONFORMITY>CC_REGION = <REGION SELECTED TO CREATE YOUR CONFORMITY TENANT>CC_RISK_LEVEL = <RISK LEVEL NOT BE ACCEPT>CFN_TEMPLATE_FILE_LOCATION = <YOUR CLOUDFORMATION TEMPLATE PATH>STACK_NAME = <THE CLOUDFORMATION STACK NAME

Вот конфигурация для приведенного ниже образа:

Build specifications: Insert build commandsBuild Commands:version: 0.2phases:    install:        runtime-versions:            python: 3.7    pre_build:        commands:            - pip3 install awscli --upgrade --user    build:        commands:            - pip3 install -r https://raw.githubusercontent.com/OzNetNerd/Cloud-Conformity-Pipeline-Scanner/master/requirements.txt            - wget https://raw.githubusercontent.com/OzNetNerd/Cloud-Conformity-Pipeline-Scanner/master/src/scanner.py            - CC_API_KEY=`jq -r '.CC_API_KEY' <<< $CC_API_KEY`            - python3 scanner.py                post_build:        commands:            - aws cloudformation deploy --template-file $CFN_TEMPLATE_FILE_LOCATION --stack-name $STACK_NAME --no-fail-on-empty-changese

Ссылка на Buildspec.yml на GitHub https://raw.githubusercontent.com/fernandostc/IaC-Security-Automation/master/buildspec.yml

Примечание. Сканер шаблонов, который я использую в этом примере, был создан Уиллом Робисоном (Will Robison) архитектором решений из компании Trend Micro вот ссылка на этот проект на GitHub:https://github.com/OzNetNerd/Cloud-Conformity-Pipeline-Scanner

Теперь нажмите Create build project (Создать проект построения), чтобы завершить процесс.

Создание секретного ключа в диспетчере секретов для хранения ключа API Cloud One Conformity

Теперь нажмите Store (Сохранить), чтобы завершить процесс.

Важно!Не забудьте создать политику, чтобы назначить своей службе ролей в CodeBuild следующее разрешение, с которым CodeBuild сможет получать значение от SecretManager:

{    "Version": "2012-10-17",    "Statement": [        {            "Sid": "VisualEditor0",            "Effect": "Allow",            "Action": "secretsmanager:GetSecretValue",            "Resource": "arn:aws:secretsmanager:us-east-1:<AWS Account ID>:secret:<Secret Key ARN>"        }    ]}

Создание AWS CodePipeline для автоматизации триггера запуска сканирования шаблонов

AWS CodePipeline поможет автоматизировать процесс запуска сканера шаблонов после каждого обновления кода IaC. В CodePipeline можно создать несколько этапов, однако наш пример простой, для него достаточно одного этапа. Он очень прост для понимания.

Создадим новый конвейер в AWS CodePipeline

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

Теперь нужно задать следующие параметры с учетом созданного ранее CodeCommit:

Source Provider (Поставщик исходного кода): <AWS CodeCommit>Repository Name (Имя репозитория): <CloudOneConformity или заданное вами ранее имя репозитория>Branch Name (Имя ветви): <master>

Теперь нужно задать информацию о процессе построения:

Build provider (Поставщик построения): <AWS CodeBuild>Project Name (Имя проекта): <IaC-Security-Automation или заданное вами ранее имя репозитория>

В данном случае мы не планируем использовать команды развертывания, поскольку развертывание мы выполняем внутри CodeBuild в рамках одного из этапов.Можно нажать Skip the deploy stage (Пропустить этап развертывания).

Можно просмотреть конфигурацию и нажать Create pipeline (Создать конвейер).

Тестирование автоматизированного конвейера

1. Создайте собственный шаблон CloudFormation или воспользуйтесь вот этим:ссылка.

2. Просканируйте шаблон CloudFormation с помощью подключаемого модуля Cloud One Conformity и проверьте результат.

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

3. Шаблон можно отправить в репозиторий, чтобы проверить его работоспособность в конвейере. Это своеобразный тест перед исправлением всех проблем, найденных в шаблоне CloudFormation.

4. Сохраните новый код в CodeCommit:

git add .git commit -m "Test Automation"git push

5. Сохранение нового кода в CodeCommit приведет к запуску CodePipeline.

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

ПРИМЕЧАНИЕ.В случае возникновения каких-либо проблем проверьте процесс построения. Перейдите к последнему построению и просмотрите его журналы. Они очень полезны для отладки в случае возникновения затруднений.

Заключение

Итак, у вас есть полностью автоматизированный конвейер IaC с AWS CodeCommit, AWS CodeBuild, AWS CodePipeline и Cloud One Conformity, позволяющий анализировать всевозможные отклонения конфигурации в ходе процесса создания шаблонов CloudFormation.

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

Благодарности

Хочу сказать БОЛЬШОЕ спасибо некоторым людям, которые своими потрясающими отзывами помогли мне сделать эту статью лучше:

  • Raphael Bottino (Рафаэль Боттино)

  • Melissa Clow (Мелисса Клоу)

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


- Узнать подробнее о курсе"Infrastructure as a code in Ansible".


- Записаться на супер-интенсив IaC Ansible

Подробнее..

Перевод Автоматизация как вектор роста бизнеса

14.05.2021 10:12:48 | Автор: admin

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

Автоматизация рабочих процессов требует внимания на втором этапе цифровой трансформации с расширением цифрового присутствия бизнеса и накапливанием знаний и опыта.

Автоматизация играет центральную роль и в создании и реализации практических идей с использованием техник искусственного интеллекта для управления ИТ (AIOps). И далее, на последующих этапах, с использованием искусственного интеллекта.

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

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

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

Один из таких подходов: инфраструктура как код.

Инфраструктура как код

Инфраструктура как код (IaC) это практика, заимствованная из методологий DevOps и SRE, которые обрабатывают файлы (артефакты) инициализации и конфигурации так же, как разработчики взаимодействуют с кодом.

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

Из-за своего происхождения автоматизацию на базе IaC часто называют GitOps, потому что именно GitHub и GitLab обычно используются в качестве предпочтительных репозиториев, и оба они хорошо интегрированы в инструменты конвейерной автоматизации.

Сегодня компании, внедряющие IaC, видят преимущества с точки зрения вложения усилий в автоматизацию.

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

Преимущества IaC и автоматизации очевидны, но есть причины, по которым внедрение этих технологий идёт медленно.

Навыки и инструменты основные проблемы при автоматизации

Вы не можете автоматизировать что-либо без современных инструментов. Центральными фигурами пакета инструментов становятся мультиоблачные варианты, зачастую с открытым исходным кодом (например, Terraform и Ansible). Хотя API-интерфейсы облачных провайдеров используются всё так же часто, они чрезмерно зависят от провайдера. Это создаёт проблему для операций во всех областях ИТ (безопасность, инфраструктура и сеть) при работе приложений в облачной среде.

Отсюда большой рост популярности не зависящих от облака инструментов. Почти половина участвовавших в опросе (47%) используют Terraform, Ansible, GitHub, GitLab, Puppet и Chef. А заточенные под конкретного поставщика инструменты использует 29% опрошенных. Это говорит о необходимости комплексной автоматизации, не зависящей от облачных сред, поскольку портфели приложений и технологии, обеспечивающие их защиту, теперь распределены по множеству общедоступных и частных облаков, дата-центров и даже периферийных устройств.

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

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

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

Подробнее..

Путь разработчика в SRE зачем идти в инфраструктуру и что из этого выйдет

30.06.2020 20:09:15 | Автор: admin
Около года назад я переквалифицировался из .NET-разработчика в SRE. В этой статье делюсь историей о том, как группа опытных разработчиков отложила в сторону C# и пошла изучать Linux, Terraform, Packer, рисовать NALSD и строить IaC, как мы применяли практики экстремального программирования для управления инфраструктурой компании, и что из этого вышло.




В Додо Пицце больше 600 пиццерий в 13 странах мира, а большая часть процессов в пиццериях управляется с помощью информационной системы Dodo IS, которую мы сами пишем и поддерживаем. Поэтому надёжность и стабильность системы важны для выживания.

Сейчас стабильность и надёжность информационной системы в компании поддерживает команда SRE (Site Reliability Engineering), но так было не всегда.

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


Много лет я развивался как типичный fullstack-разработчик (и немного scrum-мастер), учился писать хороший код, применял практики из Extreme Programming и старательно уменьшал количество WTF в проектах, к которым прикасался. Но чем больше появлялось опыта в разработке ПО, тем больше я осознавал важность надёжных систем мониторинга и трейсинга приложений, качественных логов, тотального автоматического тестирования и механизмов, обеспечивающих высокую надёжность сервисов. И всё чаще стал заглядывать через забор к команде инфраструктуры.

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

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

Бермудский треугольник проблем


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

Проблемы разработчиков


Два года назад мы поняли, что большая сеть пиццерий не может жить без собственного мобильного приложения и решили его написать:

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



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

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

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

Сейчас это не сложно. В последние годы появилось огромное количество инструментов, которые позволяют программистам заглянуть в мир эксплуатации и ничего не сломать: Prometheus, Zipkin, Jaeger, ELK стек, Kusto.

Тем не менее у многих разработчиков до сих пор есть серьёзные проблемы с теми, кого называют инфраструктурой/DevOpsами/SRE. В итоге программисты:

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

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

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

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

Проблемы инфраструктуры


Сложности есть и на другой стороне.

Сложно управлять десятками сервисов и окружений без качественного кода. У нас в GitHub сейчас больше 450 репозиториев. Часть из них не требует операционной поддержки, часть мертва и сохраняется для истории, но значительная часть содержит сервисы, которые нужно поддерживать. Им нужно где-то хоститься, нужен мониторинг, сбор логов, единообразные CI/CD-пайплайны.

Чтобы всем этим управлять, мы ещё недавно активно использовали Ansible. В нашем Ansible-репозитории было:

  • 60 ролей;
  • 102 плейбука;
  • обвязка на Python и Bash;
  • тесты в Vagrant, запускаемые вручную.

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

Причина крылась в том, что этот код не использовал многие стандартные практики в мире разработки ПО. В нём не было CI/CD-пайплайна, а тесты были сложными и медленными, поэтому всем было лень или некогда запускать их вручную, а уж тем более писать новые. Такой код обречён, если над ним работает более одного человека.

Без знания кода сложно эффективно реагировать на инциденты. Когда в 3 часа ночи в PagerDuty приходит алерт, приходится искать программиста, который объяснит что и как. Например, что вот эти ошибки 500 аффектят пользователя, а другие связаны со вторичным сервисом, конечные клиенты его не видят и можно оставить всё так до утра. Но в три часа ночи программистов разбудить сложно, поэтому желательно самому понимать, как работает код, который ты поддерживаешь.

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

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

Проблемы бизнеса


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

Прямые потери от нестабильности системы, связанной с надёжностью и доступностью.
В 2018 году у нас произошёл 51 критический инцидент, а критичные элементы системы не работали в сумме больше 20 часов. В деньгах это 25 млн. рублей прямых потерь из-за несозданных и недоставленных заказов. А сколько мы потеряли на доверии сотрудников, клиентов и франчайзи, подсчитать невозможно, в деньгах это не оценивается.

Расходы на поддержку текущей инфраструктуры. При этом компания поставила перед нами цель на 2018 год: в 3 раза уменьшить стоимость инфраструктуры в пересчёте на одну пиццерию. Но ни программисты, ни DevOps-инженеры в рамках своих команд не могли даже приблизиться к решению этой задачи. Этому есть причины:

  • с одной стороны, для решения таких задач нужны программисты с глубокими знаниями инфраструктуры;
  • с другой стороны, нужны operations (назовём их баззвордом DevOps), которые умеют программировать на хорошем промышленном уровне;
  • с третьей стороны, бизнесу нужен баланс между надёжностью и доступностью этих систем и их стоимостью.

И что с этим делать?


Как решить все эти проблемы? Решение мы нашли в книге Site Reliability Engineering от Google. Когда прочли, поняли это то, что нам нужно.

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

Вся наша инфраструктура почти полностью живет в Microsoft Azure. Есть несколько независимых кластеров для прода, которые разнесены по разным континентам: Европа, Америка и Китай. Есть нагрузочные стенды, которые повторяют продакшн, но живут в изолированной среде, а также десятки DEV-окружений для команд разработчиков.

Из хороших практик SRE у нас уже были:

  • механизмы мониторинга приложений и инфраструктуры (спойлер: это мы в 2018 думали, что они хорошие, а сейчас уже всё переписали);
  • процессы для дежурств 24/7 on-call;
  • практика ведения постмортемов по инцидентам и их анализ;
  • нагрузочное тестирование;
  • CI/CD-пайплайны для прикладного софта;
  • хорошие программисты, которые пишут хороший код;
  • евангелист SRE в команде инфраструктуры.

Но были и проблемы, которые хотелось решить в первую очередь:

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

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

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

Онбординг SRE-команды


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

На проект мы выделили 4 месяца и поставили три цели:

  1. Обучить программистов тем знаниям и навыкам, которые необходимы для дежурств и операционной деятельности в команде инфраструктуры.
  2. Написать IaC описание всей инфраструктуры в коде. Причём это должен быть полноценный программный продукт с CI/CD, тестами.
  3. Пересоздать всю нашу инфраструктуру из этого кода и забыть про ручное накликивание виртуалок мышкой в Azure.

Состав участников: 9 человек, 6 из них из команды разработки, 3 из инфраструктуры. На 4 месяца они должны были уйти из обычной работы и погрузиться в обозначенные задачи. Чтобы поддерживать жизнь в бизнесе, ещё 3 человека из инфраструктуры остались дежурить, заниматься операционкой и прикрывать тылы. В итоге проект заметно растянулся и занял больше пяти месяцев (с мая по октябрь 2019-го года).

Две составляющие онбординга: обучение и практика


Онбординг состоял из двух частей: обучения и работы над инфраструктурой в коде.

Обучение. На обучение выделялось минимум 3 часа в день:

  • на чтение статей и книг из списка литературы: Linux, сети, SRE;
  • на лекции по конкретным инструментам и технологиям;
  • на клубы по технологиям, например, по Linux, где мы разбирали сложные случаи и кейсы.

Ещё один инструмент обучения внутреннее демо. Это еженедельная встреча, на которой каждый (кому есть, что сказать) за 10 минут рассказывал о технологии или концепции, которую он внедрил в нашем коде за неделю. Например, Вася поменял пайплайн работы с Terraform-модулями, а Петя переписал сборку образов на Packer.

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



Практика. Вторая часть онбординга создание/описание инфраструктуры в коде. Эту часть разделили на несколько этапов.



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

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

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

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

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

Наши инструменты для IaC
  • Terraform для описания текущей инфраструктуры.
  • Packer и Ansible для создания образов виртуальных машин.
  • Jsonnet и Python как основные языки разработки.
  • Облако Azure, потому что у нас там хостинг.
  • VS Code IDE, для которой создали единые настройки, расширенный набор плагинов, линтеров и прочего, чтобы писать унифицированный код и расшарили их между всеми разработчиками.
  • Практики разработки одна из основных вещей, ради которой затевался весь этот карнавал.


Практики Extreme Programming в инфраструктуре


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

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

О том, как мы адаптировали XP для инфраструктуры, есть отдельная статья. Но если вкратце: практики XP работают и для кода инфраструктуры, пусть с ограничениями, адаптациями, но работают. Если хотите их применять у себя, зовите людей с опытом применения этих практик. Большинство из этих практик так или иначе описаны в той самой книге о SRE.

Всё могло бы сложиться хорошо, но так не бывает.

Технические и антропогенные проблемы на пути


В рамках проекта было два вида проблем:

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

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

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

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

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

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

Если хотите собрать именно такую команду, не забудьте позвать сильного Agile- коуча, scrum-мастера, или психотерапевта что больше нравится. Возможно, они помогут.

Итоги онбординга


По итогам проекта онбординга (он завершился в октябре 2019 года) мы:

  • Создали полноценный программный продукт, который управляет нашей DEV-инфраструктурой, с собственным CI-пайплайном, с тестами и прочими атрибутами качественного программного продукта.
  • Удвоили количество людей, которые готовы дежурить и сняли нагрузку с текущей команды. Спустя ещё полгода эти люди стали полноценными SRE. Теперь они могут потушить пожар на проде, проконсультировать команду программистов по НФТ, или написать свою библиотеку для разработчиков.
  • Сместили майндсет в сторону идей SRE. Не только у участников проекта онбординга, но и у тех программистов из продуктовых команд, которые теперь могут разговаривать с нами на одном языке.
  • Сильно устали: и те, кто участвовал в онбординге, и те, кто участвовал в дежурствах.

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


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

Инфраструктура пока в прошлом. Когда я учился на первом курсе (15 лет назад) и начинал изучать JavaScript, у меня из инструментов были NotePad ++ и Firebug для отладки. C этими инструментами уже тогда нужно было делать какие-то сложные и красивые вещи.

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

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

Читайте документацию. Как программист, я относительно редко обращался к докам. Я достаточно глубоко знал свои инструменты: любимый язык программирования, любимый фреймворк и БД. Все дополнительные инструменты, например, библиотеки, обычно написаны на том же языке, а значит всегда можно посмотреть в исходники. IDE всегда подскажет, какие и где нужны параметры. Даже если я ошибусь, то быстро это пойму, запустив быстрые тесты.

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

Комментарии в коде инфраструктуры неизбежны. В мире разработки комментарии признак плохого кода. Они быстро устаревают и начинают врать. Это признак того, что разработчик не смог иначе выразить свои мысли. При работе с инфраструктурой комментарии так же признак плохого кода, но без них уже не обойтись. Для разрозненных инструментов, которые слабо связаны друг с другом и ничего не знают друг о друге, без комментариев не обойтись.

Часто под кодом скрываются обычные конфиги и DSL. При этом вся логика происходит где-то глубже, куда нет доступа. Это сильно меняет подход к коду, тестированию и работе с ним.

Не бойтесь пускать разработчиков в инфраструктуру. Они могут привнести полезные (и свежие) практики и подходы из мира разработки ПО. Пользуйтесь практиками и подходами от Google, описанными в книге про SRE, получайте пользу и будьте счастливы.

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

PPS: Эта статья написана по моему выступлению на DevOpsConf осенью 2019 года. С тех пор прошло довольно много времени, и теперь уже точно понятно, что всё было не зря: тойл теперь не съедает бОльшую часть времени инженеров, наша команда теперь может реализовывать крупные долгосрочные проекты по улучшению инфраструктуры в широком смысле, а программисты почти не жалуются на безумных DevOps-инженеров, которые только мешают жить.

PPPS: В этом году конференция, посвящённая DevOps-практикам, будет называться DevOps Live 2020. Изменения коснутся не только названия: в программе будет меньше докладов и больше интерактивных обсуждений, мастер-классов и воркшопов. Рецепты о том, как расти и перестраивать процессы с помощью DevOps-практик. Формат также изменится два блока по два дня и домашние задания между ними.

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

Что такое 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.

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

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

Подробнее..

GitOps очередной модный термин или прорыв в автоматизации?

06.10.2020 12:23:44 | Автор: admin

Большинство из нас, подмечая очередной новый термин в IT блогосфере или конференции, рано или поздно задается подобным вопросом: Что это? Очередное модное слово, buzzword или действительно что-то стоящее пристального внимания, изучения и обещающее новые горизонты? Точно также вышло у меня и с термином GitOps некоторое время назад. Вооружившись множеством уже существующих статей, а также знанием коллег из компании GitLab, я попытался разобраться, что же это за зверь, и как его применение может выглядеть на практике.

Кстати, о новизне термина GitOps также говорит недавно проведенный нами опрос: более половины опрошенных еще не начинали работы с его принципами.

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

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

Так в чем собственно отличие GitOps от IaC? Именно с этого вопроса я и начал свое расследование. Пообщавшись с коллегами, у меня получилось выработать следующее сравнение:

GitOps

IaC

Весь код хранится в git репозитории

Версионность кода необязательна

Декларативное описание кода / Идемпотентность

Допустимо как декларативное, так и императивное описание

Изменения вступают в силу с использованием механизмов Merge Request / Pull Request

Согласование, утверждение и коллаборация необязательны

Процесс выката обновлений автоматизирован

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

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

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

Любопытность GitOps, конечно, еще и в том, что это не продукт, плагин или платформа, связанная с каким бы то ни было вендором. Это скорее парадигма и набор принципов, аналогично с другим знакомым нам термином: DevOps.

В компании GitLab мы выработали два определения этого нового термина: теоретический и практически. Начнем с теоретического:

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

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

С практической же точки зрения мы описываем GitOps следующим образом:

GitOps = IaC + MRs + CI/CD

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

Merge Request (альтернативное название Pull Request). В плане процесса MR - это запрос на применение изменений кода и последующее слияние веток. Но в плане инструментов, которыми мы пользуемся - это скорее возможность для получения полной картины всех вносимых изменений: не только code diff, собранный из какого-то количества коммитов, но и контекст, результаты тестов, конечный ожидаемый результат. Если мы говорим про инфраструктурный код, то нам интересно, как именно изменится инфраструктура, сколько новых ресурсов будет добавлено или удалено, изменено. Желательно в каком-то более удобном и легко читаемом формате. В случае с облачными провайдерами неплохо было бы знать, какие финансовые последствия понесет это изменение.

Но MR - это еще и средство совместной работы, взаимодействия, общения. То место, где вступает в действие система сдержек и противовесов. От простых комментариев до формальных одобрений и утверждений.

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

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

А если вам вдруг станет интересно, как это все выглядит на практике, то приглашаю посмотреть наш мастер-класс, в котором я пошагово рассказываю, как при помощи GitLab:

  • Реализовать основные принципы GitOps

  • Создавать и вносить изменения в облачную инфраструктуру (на примере Yandex Cloud)

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

http://personeltest.ru/aways/bit.ly/34tRpwZhttps://bit.ly/34tRpwZ
Подробнее..

Agreements as Code как отрефакторить инфраструктуру и не сломаться

09.10.2020 12:10:51 | Автор: admin


Это расшифровка выступления на TechLeadConf 2020-06-09. Прежде чем начнем, попробуйте ответить для себя на вопрос какие у вас ожидания от взаимодействия с инфраструктурой? Например сколько времени займет:


  • Развернуть новое окружение для тестов.
  • Обновить версию java и/или ОС внутри контейнера.
  • Выдать права доступа на сервер.

Спойлер результатов опроса во время TechLeadConf


А теперь умножьте свои ожидания на двое, и вы получите суровую реальность. Не приятненько как-то, да?



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


Инфраструктура как она есть


Cлучайности + Договоренности + Процессы = Инфраструктура



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


  1. Случайность. Есть приложение. Но оно не появляется просто так, его разрабатывают вполне конкретные люди. Со временем или сразу появляется потребность развернуть/запустить приложение где-то(Спасибо Кэп!). В нашем случае лет 10-15 назад было отправлено письмо с просьбой смонтировать сервер в стойку. У кого-то это просьба в телеграмм чате настроить сервер. Суть в том, что инфраструктура это про то, что вас кто-то что-то попросил сделать, развернуть сервис. Изменения не происходят потому что вам так захотелось, за изменениями стоят люди.
  2. Договоренности. Со временем, случайные запросы на изменения через jira, email, slack могут перерасти в хаотичный поток запросов. В нашем случае необходимо было разворачивать множество окружений похожих на клиентские. Но бывает можно услышать "если хотите ускорить развёртывание, то не пишите нам в четверг, потому что мы ходим в серверную по средам". Появляются договоренности.
  3. Процессы. Апогеем становится преобразование договоренности в процесс. Появляется формальный процесс: заведите таску в jira, заполните необходимые поля и в течение 7 дней первый освободившийся инженер создаст вам новое окружение.

Инфраструктура стремится к хаосу



Как вы понимаете, монтаж серверов в стойку, процесс не быстрый, а разработка должна лететь. Но всё меняется, и приложение было контейнеризировано. Появилась возможность создавать динамически виртуалки на CoreOS и запустив compose файл получить окружение похожее боевое. Этакий k8s на минималках. И тут появился первый звоночек: а кто отвечает за YML файлике в git? Кто описывает инфру? Закономерно, код без присмотра начинает дурно пахнуть и привет групповая безответственность. Растет технический долг за счет быстрых и незаменимых подпорок из велосипедов. Меняется команда с одной стороны, потом с другой. И всё. Приплыли. Наступает ОПА момент когда инфраструктура работает, но никто не видит картинку целиком и не понимает почему она работает именно так. Это ни хорошо и ни плохо. Это данность: Инфраструктура стремится к хаосу, как и наша вселенная стремится к тепловой смерти.


Как бороться с Хаосом?


Бумажки и инструкции на защите от хаоса



Написать инструкции может прийти первым на ум, когда вы захотите бороться с хаосом. У меня тут есть, забавная история, как в одной ооооочень большой организации любили писать бумажки почти на каждый чих. Однажды, там для переезда сервиса согласовали временную схему сети на пару недель и выставили сервис в интернет. Соль в, том что я нашел это спустя пять лет. А на минутку это: нефтебаза в аэропорту с доступом в сеть ЦОД. Не хорошо как-то. Бумажка есть, а реальность показывает другое.


Agreements as Code



Аналогичная ситуация будет с задачами в Jira. Вас попросили, подготовить новое окружение. Вы что-то сделали и забыли как-оно там было настроено. Но если те же договорённости формализовать в виде кода. Пусть даже на своем DSL, или просто кодом на Ansible написали. Итогом у вас есть воспроизводимое решение и единая точка правды. Кто-то то поправил код в репозитории и вот обновленная версия приложения уже в проде. Но стоит ли это все эти договоренности автоматизировать? Стоит ли овчинка выделки?


Agreements as Code внедрять нельзя забить



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


  • *ОПА степень "проблемности" проблемы. Насколько вы/ваши коллеги/заказчики страдаете.
  • Стоимость решения сколько времени/денег стоит решить проблему.


Рассмотрим краевые случаи:


  • Проблема огромная, решается дешево надо делать. Инструкция по заведению пользователей из confluence который пользоваться каждый день, замечательно заменяется скриптом, который формализует договоренности.
  • Проблема маленькая, решается дешево спорно, делать по остаточному принципу. Разбираться с REST api редкого сервиса, чтобы раз в год обновить DNS может быть не лучшим выбором для инвестиции времени. Но на долгой дистанции может пригодиться.
  • Проблема маленькая, решается дорого игнорировать. Как часто вам приходится обновлять подпись к email? раз в год? в три?
  • Проблема огромная, решается дорого спорно, необходимо десять раз подумать, т.к. без опыта можно сделать только хуже. Например, скриптики которые автоматизировали процессы и договорённости вдруг стали стандартом, все пользуют и не знают как оно работает. Собственно, та самая *ОПА когда вам надо рефакторить IaC.

Ручной труд -> Механизация -> Автоматизация



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


  • Ручной труд нет автоматизации, вы руками проделываете всё, собираете шишки и понимаете, как выглядит процесс и какие в нем бутылочные горлышки.
  • Механизация первые попытки упростить себе жизнь. Статья в confluence с собранными шишками превращается в скрипт автоматизирующий отдельные проявления рутины. Но требующий человека для принятия решений.
  • Автоматизация "Слава роботам"(с) Бендер. Человек задействован минимально, появляются различные * as Service и позволяют другим людям автоматизировать их работу.


Когда эволюционировать и переходить на следующий уровень автоматизации, а когда нет?


  • Проблема огромная, автоматизируется легко надо делать. Заведение пользователей замечательно заменяется интеграцией, например, с LDAP и решает проблемы на корню. Инструкция -> скрипт -> LDAP.
  • Проблема маленькая, автоматизируется легко имеет смыл, т.к. на дальней дистанции можно переиспользовать наработки и не изобретать велосипед по новой, ваше знание сохранено и со временем может перерасти в сервис. Если посмотреть на AWS, то предоставляется множество * as Service на любой вкус, а ведь когда-то оно тоже могло начинаться с простого скрипта. Например, я завел приватный репозиторий, где хранятся такого рода скрипты.
  • Проблема маленькая, автоматизируется сложно скорее нет. Но для кого-то даже такое редкое действие как обновление подписи к email может быть актуально, у нас на дружественном проекте такое разрабатывают; говорят, что у одного крупного аутсорсера есть специальный web портал на котором можно получить свою подпись.
  • Проблема огромная, автоматизируется сложно скорее да, если ваши договоренности представлены в виде кода, то когда настанет *ОПА(а это неизбежно, т.к. всё стремится к хаосу!), у вас будет возможность отрефакторить код.

По мере развития инфраструктуры, договоренности формализуются в виде кода и стремятся стать * as Service.


Инфраструктуру можно и нужно рефакторить. Но не всегда


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


  • Разобраться как оно работает и удовлетворить собственное эго.
  • Ускорить внесение изменений.
  • Уменьшить количество падений сервисов
  • ...

Ansible: Миграция конфигурации 120 VM c Coreos на Centos за 18 месяцев



В моем случае, досталось в наследство самописное configuration management решение. Оно представляло инфраструктуру в виде кода, оно работало, но его поддержка было сложной, т.к. оно было хрупкой, никто не хотел его поддерживать. Планомерным итогом стала замена его на Ansible, подробности можно глянуть тут Ansible: Миграция конфигурации 120 VM c Coreos на Centos за 18 месяцев. Почему 1,5 года заняла миграция? Ответ прост 80% был reverse engineering как оно работает и только 20% непосредственно написание плэйбуков, ролей и миграция. Сам же процесс был прост:


CFM 2 Ansible


  1. Сформировать список серверов.
  2. Выбрать сервер из списка не перенесенных.
  3. Зафиксировать текущие договоренности.
  4. Разобраться как работает.
  5. Описать в виде кода.
  6. Вернуться на пункт 2.

Как начать тестировать Ansible, отрефакторить проект за год и не слететь с катушек


Ansible refactoring


На дружественном проекте занялись автоматизацией развертывания окружений у заказчиков и делали это через Ansible. Но спустя какое-то врем пришло понимание, что получившиеся плэйбуки страшно запускать на боевых серверах, т.к. нет уверенности что они не свалятся с ошибкой. Ситуацию еще усугубляло то, что до клиентов был air gap(инженеру могло потребоваться прийти на площадку к заказчику где нет интернета). Задача была стабилизировать плэйбуки и наладить процесс выпуска. Как решали можно почитать в Как начать тестировать Ansible, отрефакторить проект за год и не слететь с катушек, но если кратко:


  1. Составить список существующих ролей.
  2. Выбрать одну роль.
  3. Покрыть тестами и зафиксировать текущие договоренности.
  4. Внести правки в плэйбуки/роли, исправив причины падения.

Как реализовано тестирование Ansible ролей?


Ansible testing


Так исторически сложилось, что использовался репозиторий в котором лежали все роли. Был создан Jenkins Pipeline, который:


  1. Вычитвает конфиг из репозитория что тестировать.
  2. Генерирует динамически стадии для Jenkins.
  3. Запускает lint для всех ролей и плэйбуков.
  4. Запускает molecule для всех ролей

Реафаторинг IaC


IaC refactoring


Мы то с вами помним, что инфраструктура эволюционирует и формализуется в скрипты и/или множество * as Service. А с этим можно работать как с кодом и переиспользовать практики по рефакторингу кода. Из предыдущих сценариев выбивается нечто общее:


  1. Определяем измеримую цель.
  2. Проверяем наличие нужных знаний и времени на изменения.
  3. Выбираем маленький кусочек инфраструктуры.
  4. Разбираем что он делает.
  5. Формализуем договоренности и покрываем их тестами.
  6. Отдыхаем(это важно! иначе сгоришь оставив недоделанным работу).
  7. Повторяем.

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


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

Ускоряем ускорение



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


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

По графику можно увидеть, что:


  • Количество кода растет линейно и прогнозируемо.
  • Количество тестов отложенное коррелирует с количеством кода и растет по экспоненте.
  • Количество инженеров константно.

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


Используй IaC testing pyramid. Не откладывай не потом!


IaC testing pyramid


Годом ранее на DevopConf рассказывал Что я узнал, протестировав 200 000 строк инфраструктурного кода и подробно рассмотрел пирамиду тестирования инфраструктуры. Ровно таже идея, что в разработке, но для инфраструктуры: идем от дешевых быстрых тестов, которые проверяют простые вещи, например отступы, к дорогим полноценным тестами разворачивающих цельную инфраструктуру.


  • Static Analysis Статистический анализ кода, без запуска. Линтеры, например.
  • Unit IaC должна состоять из простых кирпичиков и вот их тестируем. В случае Ansible это роли тестируемые при помощи Molecule.
  • Integration Очень похожи на unit, но представляют комбинацию ролей описывающих целевую конфигурацию сервера.
  • E2E Цельная инфраструктура, состоящая из множества серверов.

Когда начинать писать тесты?


Ок, договоренности в инфраструктуре можно представить как код. А потом можно рефакторить. А если есть тесты то еще и не закопаться в рефакторинге. Но вот вопрос, когда начинать писать тесты? Рассмотрю пару проектов.


Проект 1



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


Проект 2



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


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


  • 2000 линтинг должен быть.
  • 4000 пора делать юнит тесты
  • 6000 время интеграционных тестов.
  • 8000 E2E тесты мерещат на горизонте.

Lessons learned


  1. Инфраструктура стремится с хаосу.
  2. Agreements as Сode внедрять нельзя забить.
  3. Ручной труд -> Механизация -> Автоматизация.
  4. Инфраструктуру можно и нужно рефакторить. Но не всегда.
  5. Тесты на инфраструктуру удешевляют/ускоряют ее изменения.
  6. Используй IaC testing pyramid. Не откладывай не потом!


Подробнее..

Стоит ли переходить с Powershell DSC на Ansible и как это сделать

03.03.2021 14:04:54 | Автор: admin
Об IaC под Windows пишут мало, потому что DevOps/SRE ассоциируется в основном c Linux и Kubernetes. Мы решили исправить эту ситуацию и сравнить инструменты, которыми можно управлять IaC на базе Windows. Статья будет полезна разработчикам, которые работают с Windows-инфраструктурой и выбирают способы управления, и тем, кто уже внедрил Powershell DSC или Ansible, но сомневается в своем решении. Ниже поделимся опытом и расскажем:
  • как устроен Powershell DSC и чем он отличается от Ansible при управлении инфраструктурой на Windows;
  • почему мы перешли на Ansible;
  • с какими проблемами столкнулись и как их решали;
  • как соотносятся ожидания и реальность после перехода на Ansible;
  • кому стоит выбрать Powershell DSC, а кому Ansible.

Почему изначально выбрали PowerShell DSC


В Mindbox развита культура DevOps/SRE, несмотря на преимущественно Windows-инфраструктуру: Hyper-V, IIS, MS SQL Server. И хотя компания постепенно переходит на Linux и Open Source, Windows пока превалирует.

Чтобы управлять этой инфраструктурой, планировали использовать инфраструктурный код: писать его, сохранять в репозиторий, а затем с помощью какого-то инструмента превращать код в реальную инфраструктуру. В то время как Ansible самый популярный инструмент управления инфраструктурой через код, он все-таки традиционно ассоциируется с Linux-миром. Нам хотелось что-то нативное и заточенное под Windows, поэтому выбрали PowerShell DSC.

Как работает Powershell DSC


PowerShell Desired State Configuration (DSC) это сервис, который уже есть в Windows из коробки и помогает управлять инфраструктурой через конфигурационные файлы. На вход он принимает инфраструктурный код на PowerShell, а внутри преобразует его в команды, которые конфигурируют систему. Кроме тривиальных операций, например установки Windows-компонентов, изменения ключей реестра, создания файлов или конфигурирования служб, он умеет многое из того, что обычно выполняется PowerShell-скриптами. Например, полный цикл настройки DNS или высокодоступный инстанс MS SQL Server.



Полезные ссылки к схеме:
Пример простой конфигурации для документов по DSC
Как использовать датафайлы
Как использовать SQL Server-базу в качестве бэкэнда для Windows Server 2019
Как настроить DSC pull server для работы с базой данных SQL для версий раньше Windows Server 2019

Чем DSC отличается от Ansible


Критерий DSC Ansible
Архитектура Служба на каждом управляемом хосте. В случае pull-модели, отдельный управляющий хост и база данных, пререквизиты в виде .NET Framework 4.0 и WMF 5.1 Несколько исполняемых файлов, например ansible, ansible-playbook и ansible-inventory. Запускается с любого Linux-хоста, пререквизит у управляемых хостов один python
Хранение состояния хостов Можно хранить в базе данных Нет
Кроссплатформенность Да Да, включая управление сетевыми устройствами
Pull/push-режимы Pull и push Только push
Устранение дрифта конфигурации Есть в pull-режиме Нет
Декларативность Декларативно-процедурный: важна последовательность выполнения тасков, можно писать недекларативные конструкции в любом месте, а значит, больше шансов написать запутанный код Декларативно-процедурный: важна последовательность выполнения тасков, при этом невозможно написать скриптовый код, не обернув в таск
Аудитория ~1300 ресурсов в Gallery ~20000 ролей в Ansible Galaxy
Используемый язык PowerShell YAML
Инвентаризация Да, по удобству проигрывает Ansible Да
Единица распространения Ресурс (модуль) Роль

Проблемы, которые возникли с DSC


Ожидания от DSC оправдались не во всём. Кроме этого, во время работы возникли новые потребности, которые не могли удовлетворить с помощью DSC.

Разработчики не могут использовать инструмент самостоятельно без помощи SRE. Хотя почти в каждой команде есть SRE, инструмент IaC должен быть достаточно простым, чтобы разработчик мог им пользоваться и тратить на это не больше получаса. DSC позволяет использовать не только декларативный код, но и любые конструкции на Powershell. Это значит, что высок шанс сделать код, который будет сложно сопровождать или который приведет к инфраструктурной аварии. Например, развертывание приложения с некорректными параметрами не в той среде.

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

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

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

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

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

Как планировали перейти с DSC на Ansible


Сначала задача казалась простой, приблизительно на месяц. Мы выделили три этапа работ:
  • научиться подключаться к Windows-хостам с помощью Ansible;
  • переписать конфигурации DSC с помощью Ansible-модулей;
  • удалить DSC pull server, его базу данных и прочие артефакты.

Вот какой рабочий процесс был на DSC, и как планировали организовать в Ansible:




Стандартная структура ролей в Ansible

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

С какими сложностями столкнулись при переходе на Ansible и как их решали


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

WinRM или SSH


Первый сюрприз состоял в выборе типа подключения. В случае Windows их два WinRM и SSH. Оказалось, что Ansible медленно работает через WinRM. При этом Ansible не рекомендует использовать OpenSSH из коробки для Windows Server 2019. И мы нашли новое решение:
  1. Форкнули и переделали под себя роль из Galaxy.
  2. Написали плейбук, в котором есть только вызов этой роли. Это единственный плейбук, при котором идет подключение к хостам по WinRM.
  3. Стандартными средствами Prometheus Blackbox Exporter сделали мониторинг порта 22/tcp и версии OpenSSH:

    - alert: SSHPortDown
    expr: probe_success{job=~".*-servers-ssh",instance!~".*domain..ru"} == 0
    for: 1d
    annotations:
    summary: "Cannot reach {{`{{ $labels.instance }}`}} with SSH"
  4. Выбрали и настроили LDAP-плагин для инвентаризации, чтобы не вписывать вручную все Windows-серверы из домена в статическую инвентаризацию:

    plugin: ldap_inventory
    domain: 'ldaps://domain:636'
    search_ou: "DC=domain,DC=ru"
    ldap_filter: "(&(objectCategory=computer)(operatingSystem=*server*)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
    validate_certs: False
    exclude_hosts:
    - db-
    account_age: 15
    fqdn_format: True
  5. Развернули везде OpenSSH с нужными ключами и убедились, что ни одного алерта о недоступности Windows-серверов по SSH больше нет.
  6. Чуть позже интегрировали установку OpenSSH в стандартный образ. Наши образы готовятся с помощью Packer, который также умеет вызывать Ansible:

    "type": "shell-local",
    "tempfile_extension": ".ps1",
    "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"],
    "env_var_format": "$env:%s=\"%s\"; ",
    "environment_vars": [
    "packer_directory={{ pwd }}",
    "ldap_machine_name={{user `ldap_machine_name`}}",
    "ldap_username={{user `ldap_username`}}",
    "ldap_password={{user `ldap_password`}}",
    "ansible_playbooks={{user `ansible_playbooks`}}",
    "github_token={{user `github_token`}}"
    ],
    "script": "./scripts/run-ansiblewithdocker.ps1"


Рефакторинг


Когда мы переписывали код под Ansible, то периодически натыкались на дублирование кода. Например, почти все конфигурации DSC содержали установку windows_exporter. Единственное, что отличалось это коллекторы, которые экспортер должен был использовать:



Чтобы избавиться от дублированного кода, вынесли windows_exporter в отдельную Ansible-роль, а параметры этой установки в переменные групп хостов.

Second hop authentication


Наверное, second hop authentication самая распространенная проблема, с которой сталкиваются те, кто начал использовать Ansible под Windows:

- name: Custom modules loaded into module directory
win_copy:
src: '\\share\dsc\modules'
dest: 'C:\Program Files\WindowsPowerShell\Modules'
remote_src: yes


Такая конструкция вызывает ошибку Access Denied из-за того, что по умолчанию делегировать учетные данные для авторизации на удаленном ресурсе невозможно без дополнительных настроек. Обойти ошибку помогает, например, new_credentials. Но мы предпочли воспользоваться тем, что Ansible умеет вызывать ресурсы DSC через модуль win_dsc. Вызываем DSC-ресурс File, который по умолчанию выполняется под учетной записью компьютера. Делегация Kerberos в этом случае не нужна:

- name: Custom modules loaded into module directory
win_dsc:
resource_name: File
SourcePath: '\\share\dsc\modules'
DestinationPath: 'C:\Program Files\WindowsPowerShell\Modules'
Type: Directory
Recurse: true
Force: true
MatchSource: true


При этом нет противоречия в том, чтобы отказываться от DSC, но использовать его ресурсы, если они лучше решают задачу, чем модуль Ansible. Главная цель прекратить использовать DSC-конфигурации, потому что нас не устраивала именно экосистема DSC, а не сами ресурсы. Например, если нужно создать виртуальный свитч Hyper-V, то придется использовать ресурс DSC в Ansible пока нет средств по управлению конфигурацией Hyper-V.

Сетевой дисконнект


Некоторые задачи вызывают отключение сети (дисконнект) на конфигурируемых серверах. Например, создание виртуального свитча Hyper-V из примера выше:

- name: External switch present
win_dsc:
resource_name: xVMSwitch
Ensure: 'Present'
Name: 'Virtual Network'
Type: 'External'
NetAdapterName: 'TEAM_LAN'
AllowManagementOS: True


Проблема в том, что в DSC такой вызов работает, а в Ansible завершается с ошибкой, так как управляемый хост дисконнектнул. Это происходит потому, что Windows всегда дисконнектит при создании виртуального экстернал-свитча. Решение добавить к таску аргумент async:

async: 10

Так Ansible отправляет таск на хост, ждет заданное время и только потом запрашивает состояние.

Дрифт инфраструктуры


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

Чтобы облегчить работу с IaC, мы собрали все скрипты и документы и сделали единые однозначные инструкции. Кроме этого, организовали процесс так, чтобы никто не внес случайные изменения в Ansible. Мы храним весь инфраструктурный код в GitHub, а задачи инженерам ставим через GitHub Projects, поэтому у нас есть возможность связывать изменения инфраструктурного кода (pull requests) с задачами. Так мы можем посмотреть изменения по каждой выполненной задаче. Если у задачи не будет изменений, то её не примут и вернут на доработку.

Баги сбора фактов


В отличие от DSC, Ansible при запуске собирает факты об управляемых хостах, чтобы у разработчика была возможность определить поведение тасков в зависимости от состояния хоста. При сборе фактов с Windows-хостов Ansible может выдавать ошибку, из-за некорректного кода модуля. Чтобы её исправить, нужно подключить коллекцию ansible.windows.

[WARNING]: Error when collecting bios facts: New-Object : Exception calling ".ctor" with "0" argument(s): "Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index" At line:2
char:21 + ... $bios = New-Object -TypeName


Пайплайн для Ansible перед запуском каждого плейбука проверяет наличие файлов requirements.yml со списком необходимых ролей и коллекций, а затем устанавливает их. Туда мы и добавили коллекцию ansible.windows.

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

Тесты


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

Для тестирования Ansible обычно используют инструмент molecule как обертку для запуска тестов. Это удобный инструмент для Linux-ролей, но в случае с Windows есть проблема. Раньше molecule умела поднимать инфраструктуру сама, но сейчас разработчики убрали такую возможность. Теперь инфраструктура поднимается либо с помощью molecule в Docker, либо вне molecule. Протестировать Windows-роли в Docker чаще всего невозможно: Hyper-V и большинство других Windows-фич в Docker-контейнере не установятся. Придется разворачивать инфраструктуру под тесты вне molecule и использовать delegated driver в molecule.

Эту задачу мы еще не решили, но нашли инструменты, которые обнаружат самые очевидные ошибки:

Проверка Функционал Комментарий
Синтаксическая проверка Проверяет синтаксис и возможность запуска кода Используем синтаксическую проверку и линтинг локально и в репозитории. Например, встраиваем в pre-commit check и настраиваем GitHub Action, который будет запускаться при каждом pull request
Линтинг Проверяет код на логические ошибки
Dry run Позволяет до запуска плейбука узнать, что он сделает Используем в пайплайне раскатки кода: запускаем ansible-playbook с флагами check и diff, затем оцениваем изменения и подтверждаем раскатку. Когда пишем роли, учитываем, что для некоторых тасков необходимо явно указывать, что именно они должны поменять. Например, win_command и win_shell

Как устроена работа с Ansible


После того как мы внедрили Ansible и преодолели все сложности, сформировался процесс действий инженеров и автоматических запусков:
  1. Инженер пишет код роли и тесты к ней, если это роль для Linux-серверов. Как только инженер решит, что роль готова, он делает pull request в отдельный бранч в GitHub-репозитории, созданном специально для роли.
  2. При создании pull request автоматически запускается воркфлоу GitHub Actions, который выполняет синтаксическую проверку и линтинг роли. Если это Linux-роль, то запускаются еще и тесты. Инженер проверяет, что всё хорошо, и при необходимости исправляет.
  3. Другой инженер делает ревью кода из pull request. После того как автор роли исправляет все замечания, код вливается в мастер-бранч, а версия роли автоматически повышается.
  4. Теперь нужно развернуть новую версию роли. Версии перечислены в специальных файлах requirements.yml, которые лежат в GitHub-репозитории с плейбуками. Для каждого плейбука отдельный такой файл. Автор роли изменяет версию в таком файле. Если нужно развернуть роль на серверы, которых нет в инвентаризации Ansible, автор дополняет инвентаризацию. Потом автор снова создает pull request, но уже в репозиторий с плейбуками.
  5. После подтверждения pull request снова запускается GitHub Actions, который создает новый релиз в Octopus Deploy. Роль готова к развертыванию.
  6. Инженер заходит в Octopus Deploy и запускает развертывание. Процесс развертывания позволяет инженеру ограничить теги и хосты, а также переопределить переменные аналогично опциям команды ansible-playbook: --tags, --limit и --extra-vars.
  7. Процесс развертывания сначала запускает режим проверки, который показывает, какие изменения будут сделаны. Инженер оценивает результат проверки и либо подтверждает развертывание кода на целевую инфраструктуру, либо сначала устраняет обнаруженные недостатки.

Организация работы с Ansible




Что выбрать: DSC или Ansible


Перейти с DSC на Ansible Если важно:
  • отслеживать состояние тасков;
  • иметь возможность пропустить конфигурацию в режиме dry run перед прокаткой;
  • модифицировать инфраструктурный код;
  • делать синтаксические и логические проверки.


Если Linux-хосты или сетевое оборудование уже управляются с помощью Ansible.

Если не боитесь работать с Linux, потому что Ansible нужно централизованно запускать на Linux, будь то агент CI/CD системы или Docker-контейнер.
Внедрить с нуля или остаться на DSC Если инфраструктура только на Windows и вы не хотите работать с Linux.

Если готовы дописывать свои ресурсы для DSC.

Нужно хранить состояние инфраструктуры, а также исправлять её дрифт.
Внедрить с нуля Ansible Если управляете смешанной Windows/Linux средой и хотите переделать существующие скрипты в инфраструктурный код и разворачивать его с помощью CI/CD систем.


Евгений Берендяев, SRE-инженер
Подробнее..

Перевод Как создать инфраструктуру в разных окружениях с помощью 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

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

Подробнее..

Идеальная избирательная система

02.05.2021 16:16:26 | Автор: admin

На днях мне пришло сообщение от портала Госуслуги с предложением поучаствовать в тестировании дистанционного электронного голосования (ДЭГ). Стало интересно, начал гуглить и поисковик сразу же выдал ссылку на хабровскую статью Обзор системы дистанционного электронного голосования ЦИК РФ. Ознакомилсяипосле прочтения, испытал противоречивые чувства, которые вылились в эту статью, созданную на базе идеи, описанной мной еще в 2018 году на сайте change.org.

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

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

  • власть имущими, не желающими уступать дорогу другим

  • теми, кто власти пока не имеет, но желает её получить

  • теми, кто хорошо устроился при действующей власти и ничего менять не хочет.

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

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

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

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

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

И лично у меня создается ощущение, что циковская система специально для этого и создана :)

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

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

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

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

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

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

  1. Внесение фиктивных имен в списки избирателей или Мертвые души (F)

  2. Фальсификация итоговых цифр голосования. Это когда глава избирательной комиссии УИК No 666, приезжает с итоговым протоколом в ТИК No 777, там его встречают, отводят в сторонку, и перед внесением протокола в систему ГАС-выборы немного правят протокол (T)

  3. Вбросы (в урну закидывают пачку бюллетеней) (F)

  4. Хитрый палец - порча бюллетеней, заполненных в пользу нежелательного кандидата (M)

  5. Перестановка результатов голосования, - это когда кандидата, занявшего последнее место, меняют с первым (T)

  6. Неправильный подсчет бюллетеней сотрудниками избирательной комиссии (M-T)

  7. Подмена сейф пакетов и избирательных урн темной безлунной ночью (M)

  8. Приезд пожарных, с последующим досрочным закрытием участка (T)

  9. Забор сейф пакетов сотрудниками МВД на ночное хранение. С целью препятствования подмене бюллетеней и фальсификации выборного процесса. Наша доблестная всегда на страже наших интересов (M-T)

  10. Голосование по паспортным данным. Если избирательным комиссиям будут известны не только ФИО и адреса избирателей, но и их паспортные данные, то не исключено, что недобросовестные члены комиссий смогут внести в журнал за непрошедших на участок избирателей их данные, взять бюллетень и проголосовать (F)

  11. Изъятие или признание недействительными бюллетеней, заполненных в пользу нежелательного кандидата (M)

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

  13. Волшебная урна или выездное голосование на дому (F)

  14. Пустышка - члены избирательных комиссий могут специально выдавать недействительные бюллетени, не имеющие подписей двух членов избирательной комиссии или печати (M)

Все эти проблемы можно разбить по трем классам:

  1. Изменение существующего бюллетеня (M)

  2. Вброс фантомных бюллетеней (F)

  3. Фальсификация итоговых цифр (T)

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

  • Immutability. Неизменяемость голоса сразу после того как человек проголосовал. Защита от проблемы (1)(M)

  • Accuracy. Точное соответствие проголосовавших людей количеству бюллетеней в базе данных. Защита от проблемы (2)(F)

  • Countability. Возможность избирателя, самостоятельно подсчитать итоговые цифры. Защита от проблемы (3)(T)

Итого, если избирательная система удовлетворяет требованиям IAC то это значит, что можно её обсуждать в сообществе. Ну а так как система предложенная ЦИК, удовлетворяет только первому требованию IAC (Immutability)*, то и тратить время на её дальнейшее полоскание смысла не вижу.

Теперь настало время привести пример избирательной системы, удовлетворяющей требованиям IAC.

Сценарии взаимодействия с iac-системой

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

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

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

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

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

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

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

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

Когда голосование по всей стране завершилось, на центральном сервере, единый агрегирующий механизм, собирает всю информацию вместе и после проводит ряд операций:

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

  2. Подсчитывает и публикует итоговые результаты выборов

  3. Выкладывает в открытый доступ базу данных агрегирующую публичные данные всех избирательных участков по всей стране. Как упоминал ранее эта база, не содержит конфиденциальных данных, ибо в ней обезличенная информация о бюллетенях без привязки к людям. Каждый может скачать эту базу данных и пописать запросы, чтоб проверить правильность итоговых цифр. Также предоставляется программа-интерфейс, доступа к БД, на случай, если человек не знаком с языком запросов к базам данных. Таким образом у каждого гражданина появляется возможность проверить свой голос и голоса своих родных, по квитку, который распечатал для них терминал в момент голосования (тут мы достигаем выполнения принципа Countability)

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

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

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

Немного о защите программного кода

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

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

Также, поправьте меня если я ошибаюсь, можно взять хэш от секции кода собранных библиотек. А также секций импорта/экспорта. Тут идея в том, чтобы любой программист мог скачать исходники, собрать бинарные файлы, и проверить полученный хэш на соответствие. Этот шаг необходим для того, чтобы можно было провести соответствие между версией исходного кода, скачанного программистом, и хэшами эталонных бинарных файлов, опубликованными ЦИК-ом. Если в изначальных исходниках был вредоносные код, рано или поздно это вскроется. Соответственно атака на избирательную систему с этой стороны становится бессмысленной.

В итоге мы имеем систему, удовлетворяющую требования IAC, для которой характерны:

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

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

  3. Количество людей, необходимых для сопровождения системы, сведено к минимуму. Следовательно, получаем удешевление обслуживания системы. А также имеем повышенную надежность системы, ввиду уменьшения роли человека.

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

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

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

Примечания:

* - непосредственное доказательство этого утверждения выходит за рамки данной статьи. Если в комментариях 200 раз попросят разобраться этот момент подробней, то ждите вторую статью)

Материалы использованные для написания статьи:

1) Статья Способы фальсификаций на выборах

Подробнее..

Мир без DevOps. Каким бы он был?

28.07.2020 16:18:22 | Автор: admin

Вспомним классику.


Разработчики с трудом выкатывают фичи раз в год. Зато админы довольны и радостны им больше не нужно уходить с работы, они теперь работают круглосуточно, и руководство их ласково называет нянечки для разрабов. Технологии начинают откатываться. Отладка требует сотни передач из отдела в отдел все с огромным энтузиазмом перекидывают друг другу дохлую свинью через забор. Даже свинья улыбается. Долгое ожидание сервера под проект запросил сервер, получил посмертно, за заслуги перед компанией. Баги в продакшене с полной уверенностью рассчитывают увидеть XXII век. SLA 50% и седые до прозрачной белизны владельцы бизнеса. Упал сервис не проблема, подождём часок или два, пока поднимется. Универсальные инженеры на грани психоза на столе у каждого по две полупустых баночки бензодиазепиновых транквилизаторов и пачка SSRI-антидепрессантов.


Вздрогнули? И с лёгким сердцем обратно в нормальный мир, где есть DevOps-философия и DevOps-инструменты, как часть неё.


19-21 августа пройдёт онлайн-интенсив Слёрм DevOps: Tools&Cheats. Мы покажем IDDQD из мира DevOps.



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


Слёрм DevOps: Tools&Cheats:


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

С программой курса и спикерами вы можете ознакомиться и познакомиться на странице интенсива.



Поговорим откровенно? Почему мы создали этот курс? Потому что нас тоже бесит:


  • что курсы для практиков ведут теоретики;
  • что решением проблем считают не подход, а должность;
  • что 80% курсов по девопсу рассказывают о концепции и философии. А инструменты где? Чем гвозди забивать, микроскопом или лучше Macbook Pro?
  • бесит, когда к концу обучения забыл, что было в начале, а результатов надо ждать от 6 до 8 месяцев.

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


За эти три дня вы научитесь основным DevOps-практикам, которые позволят:


  • организовать командную работу с Git;
  • автоматизировать рутинные операции;
  • настроить мониторинг и интегрировать его с мессенджерами;
  • развернуть серверы, используя подход Infrastructure as Code;
  • обеспечить процесс CI;
  • И ещё немного практических читов из реальной работы.

Слёрм DevOps пройдет с 19 по 21 августа 2020. Каждый день начинаем в 10:00 и заканчиваем в 19:00, с перерывами на чай и обед.


Инструменты DevOps + IDDQD + IDKFA и за работу. И пусть кто-то только попробует помешать.

Подробнее..

Инфраструктура как код в Авито уроки, которые мы извлекли

18.08.2020 14:15:47 | Автор: admin

Привет, Хабр! Меня зовут Саша Козлов, я занимаюсь разработкой инфраструктуры и системным администрированием вАвито последние три споловиной года. Я расскажу, как мы масштабировали и модернизировали современем нашу работу синфраструктурным кодом и вывели её накачественно новый уровень.


Мы отвечаем заполный цикл управления оборудованием: отзакупки и монтажа вДЦ додоставки доконечного потребителя. Речь пойдёт обуроках, которые мы вынесли запоследние несколько лет, работая стысячей единиц оборудования и несколькими тысячами единиц конфигурирования.



Речь пойдёт обинструментах первого поколения IaC, таких как Ansible, Chef, Salt, Puppet. Если вы имеете дело сon-premises инфраструктурой, и увас нет своего облака навиртуализации, то, скорее всего, вы уже используете один изэтих инструментов.


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


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


Напервый взгляд, инструменты управления инфраструктурой очень разные. Некоторые требуют, чтобы нанодах был запущен специальный агент. Где-то используется push-модель, где-то pull, но впринципе ничего не мешает запускать ansible накаждой машине покрону и получить pull-конфигурации. Содной стороны Python, Jinja-шаблоны и YAML-программирование, сдругой DSL и Ruby. Многие инструменты включают всвою экосистему дополнительные компоненты: дашборды, хранилище конфигурации вроде PuppetDB, централизованный компонент, который хранит и распространяет навсе ноды ваш инфраструктурный код.


Слюбым инструментом подобного рода не получится работать синфраструктурным кодом ровно так же, как работает скодом разработчик сервиса. Далеко не все изменения откатываются через git revert, сама выкатка этих изменений не происходит одновременно навсей инфраструктуре, а применяется постепенно. Конфигурация влюбом случае остаётся мутабельной, а это значит, что всё равно придётся держать вголове текущее состояние машины. А А не то же самое, что 0 А. Многие такие особенности приходится учитывать.


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


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

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


Определите границы применимости инструмента


Любой инструмент имеет свои сильные и слабые стороны. Поэтому важно понимать границы его применимости: где его следует использовать и, что не менее важно, где не следует.


Puppet очень гибок, местами даже слишком. Он впостоянном цикле приводит состояние инфраструктуры кописанному в коде виду, т.к. использует pull-модель. Как следствие этого недостаточно хорошую обратную связь и задержку при применении изменений. По умолчанию конфигурация применяется раз в 30минут, поэтому длязадач, требующих более динамичного управления, Puppet не подходит. Кроме этого, внём нет event-driven автоматизации, как вSalt, что также ограничивает область его применения.


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


Для себя мы определили границы так: применяем Puppet дляконфигурирования железных нод и stateful-контейнеров, но не используем его длядеплоя сервисов, конфигурации рантайма инфраструктурных сервисов и других быстро меняющихся вещей. Например, мы постепенно отходим отуправления DNS-записями через Puppet, который сложился унас исторически. Мы хотим, чтобы управление было более динамическим, поэтому этим занимается инфраструктурный сервис, предоставляющий свой API.


Правильный выбор структуры кода и уменьшение связанности кода


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


Поэтому мы выделили основные сущности: control repo и модули. Каждая находится вотдельном git-репозитории. Сами тут ничего особенно не придумали, просто обратились клучшим практикам дляPuppet-кода, которые описаны встатье "The roles and profiles method".


Control repo это репозиторий синфраструктурным кодом. Внём находится тот код, который выкатывается через CI-систему напаппет-сервер и применяется намашинах. Роль это некоторая типовая конфигурация, способ сгруппировать машины содинаковыми настройками. Это самый высокоуровневый слой абстракции условно, ответ навопрос чем занимается эта машина?. Примеры ролей: k8s-нода кластера Х, нода Kafka встейджинг окружении дляшины данных, ClickHouse-нода и т.п.


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


Роли и профили описываются вcontrol repo, а модули подключаются внеё как внешние зависимости и применяются внутри профилей или ролей.


Модуль это подключаемая библиотека, код, который занимается настройкой определённого инфраструктурного компонента, как правило переиспользуемый. Модули релизятся отдельно отcontrol repo, версионируются поsemver и подключаются как зависимости. Унас сейчас порядка 50 модулей: модуль дляработы ссекретами, настройки различных БД, конфигурирования кластеров Kubernetes и другие.


Вопрос, как структурировать код, насамом деле не очень прост в случае сPuppet. Единственно правильного ответа нанего нет. Далеко не всегда ясно, что должно считаться одной ролью, а вкаких случаях профиль нужно пилить нанесколько. Нужно ли сразу делить код намодули, или можно допоры довремени складывать всё вcontrol repo?


Здесь всё зависит отразмера инфраструктуры, её разнородности и количества инженеров, которые занимаются разработкой инфракода. Дляначала вполне подойдёт просто иметь control repo и весь код писать вней, организуя его впрофили. Унас вАвито инфраструктурой занимается несколько команд, длякаждой важны разные вещи. Одним важнее стабильность, а не скорость внесения изменений, поэтому они обложили код кучей тестов. Другим не подошла стандартная схема тестирования вDocker, и пришлось настроить свою. Поэтому унас несколько control repo, поодной натакую команду. А чтобы можно было переиспользовать решения и не дублировать код, мы пишем модули.


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



А ещё на своём Гитхаб-аккаунте мы поделились шаблоном модуля и control repo, который используем усебя. Вшаблонах можно посмотреть пример того, как организовать код, а ещё там есть инструменты, которые нужны длязапуска всех видов тестов:



Используйте External Node Classifier вместо регулярных выражений


Ну хорошо, есть роли, профили и модули но как именно определяется то, какой код накакой машине выполнять?


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


node /^avi-ceph(2[1-9]|3[0-9]|4[0-9]|5[0-9]|6[0-9]|7[0-9]|8[0-9]|9[0-9])/ {...}

Одна неправильно закрытая скобка тут может привести кполному краху. Поиск потакому коду не работает невозможно быстро разобраться, какой код выполняется наотдельно взятой машине. Вобщем, такой подход казался разумным вначале, но современем оказался неудачным. Дляпривязки машин кнаписанным ролям Puppetlabs предлагает использовать External Node Classifier.


External Node Classifier это компонент, который хранит всебе то, какую роль следует применить ккаждой ноде. Он даёт возможность винфракоде описывать только роли, а логику привязки ролей кконкретным машинам вынести вовнешнюю систему. Навход ENC принимает имя ноды и отдаёт некий набор параметров, которые вкоде становятся доступны как top-scope variables. Вкаждой control repo есть примерно такой код, который обеспечивает привязку ноды кроли, и это единственное место, где используется node definition:


node default {  include base # применяем базовый слой конфигурации, общий для всех control repo  if $::role != '' {    notify{ "Node ${::fqdn} has role ${::role}": loglevel => info }    include "role::${role}"  } else {    notify{ "Node ${::fqdn} has no role": loglevel => warning }  }}

Вкачестве ENC может выступать любая система, ведь логику получения и формирования ответа вы пишете сами. Такой системой внашем случае стала CMDB, внутренняя система учёта оборудования и его комплектующих. Наш CMDB основан наnetbox отDigital Ocean, сильно доработанном поднаши нужды. Он плотно интегрирован сrazor, системой провижнинга железа, и умеет собирать всевозможные данные ожелезе, которое установлено вдата-центре.


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


Упростите процесс предварительной настройки серверов


Почему так важно иметь простой способ получить чистую конфигурацию? Длятого, чтобы уменьшить влияние Configuration Drift, который современем будет неизбежно накапливаться. Configuration Drift это неконсистентность конфигурации машины, описанной вкоде, поотношению кеё фактическому состоянию. Его источники это ручные изменения намашинах, тестирование гипотез, ресурсы, которые приизменении вышли из-подуправления Puppet.


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


В идеале нужно иметь возможность получить чистое состояние, отправив машину впереналивку простым API-вызовом. Мы делаем это через netboxAPI, который расширили подсвои нужды. Подкапотом там загрузка поPXE и netboot-образ Debian, шаблонизация preseed'ов наоснове параметров, переданных вAPI, много низкоуровневой настройки и взаимодействия поIPMI черезRedfish API. И, конечно же, болей, связанных сразной его реализацией уразных вендоров.


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


Настройте инструменты тестирования инфраструктурного кода


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


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


Когда мы перешли с3.7 на6 версию Puppet, то поняли, что появилась куча крутых инструментов длятестирования. Последовательность тестирования инфраструктурного кода выглядит так:


  1. Запуск линтера.
  2. Юнит-тесты.
  3. Приёмочные тесты

Наэтих трёх шагах мы делаем следующее:


  1. Проверяем валидность синтаксиса, соответствие стайлгайдам и т.п.
  2. Проверяем, что код компилируется вкаталог, отлавливаем ошибки duplicate resource declaration. Вэтих тестах можем зафиксировать определённый контракт: например, код должен содержать ресурс сервис, который должен рестартовать приизменениях вопределённых файлах.
  3. На стадии приёмочных тестов применяем код вDocker-контейнере, проверяем, что сервис работает припомощи inspec.

Приёмочное тестирование длямодуля Kubernetes

Кластеры Kubernetes мы разворачиваем припомощи Puppet и делаем это встиле "Kubernetes The Hard Way", то есть контролируем настройку компонентов кластера досамых мелочей.


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


Приёмочные тесты, написанные наBeaker поднимают три виртуальные машины изподготовленных образов, доставляют туда секреты, применяют внутри паппет-код, который готовит кластер изтрех нод. Вконце мы ~~запускаем smoke-тест: ~~ применяем деплоймент снджинксом, сервис и проверяем его доступность черезингресс.


Код тестов, которые выполняют эту проверку, выглядят так:


  context 'application deployment' do    it 'can deploy an application into a namespace and expose it' do      shell('systemctl restart kubelet')      shell('count=0;        while [[ $(kubectl get pods -n tiller -l name=tiller -o \'jsonpath={..status.conditions[?(@.type=="Ready")].status}\') != "True" ]];          do            if [[ count -gt 180 ]]; then              break;            fi;            sleep 1 && ((count++));          done')      shell('kubectl create -f /tmp/nginx.yaml', acceptable_exit_codes: [0]) do |r|        expect(r.stdout).to match(%r{namespace/nginx created\nconfigmap/my-nginx-config created\ndeployment.apps/my-nginx created\nservice/my-nginx created\n})      end    end    it 'can access the deployed service' do      shell('count=0;        while [[ $(kubectl get pods -n nginx -l run=my-nginx -o \'jsonpath={..status.conditions[?(@.type=="Ready")].status}\') != "True" ]];          do            if [[ count -gt 180 ]]; then              break;            fi;            sleep 1 && ((count++));          done')      shell('curl --connect-timeout 1 --retry-delay 1 --retry-max-time 300 --retry 150 -s --retry-connrefused 10.100.10.5', acceptable_exit_codes: [0]) do |r|        expect(r.stdout).to match %r{Welcome to nginx!}      end    end end

Если все шаги прошли безошибок, тест считается успешным. Приёмочные тесты мы запускаем наCI накаждое изменение.


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


Вот список инструментов, которые помогут помочь настроить тестирование инфракода:



И неплохая статья про юнит-тестирование:



Development kit для инфраструктурного кода


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


В паппет-экосистеме есть отличный инструмент PDK, который активно используется всообществе. Но его мы использовать не стали, потому что он был несовместим снашим инструментарием, и пришлось бы многое дорабатывать. ВPDK впервую очередь не хватило возможности работать сcontrol repo и тестирования сиспользованием Kitchen и Docker. Длятестирования PDK использует Beaker, укоторого довольно высокий порог входа.


Поэтому мы написали свой инструмент, который позволяет:


  • Создать изшаблона пустой проект, готовый кработе: тесты, CI пайплайны и прочее.
  • Сгенерировать заготовки дляманифестов, тестов, паппет-функций.
  • Запускать статические валидаторы кода, юнит-тесты, приёмочные тесты.
  • Разрешить зависимости вcontrol repo, показать, есть ли более новые версии зависимостей.
  • Сгенерировать документацию вмаркдауне издокстрингов.
  • Собрать модуль и запушить вовнутренний репозиторий.


Когда разработчик инфракода создаёт новый модуль припомощи development tool, он сразу получает репозиторий снастроенными сборками наCI длястатического анализа, запуска тестов и релиза модуля.


После бутстрапа проекта врепозитории уже будет настроен инструментарий дляработы скодом (puppet-rspec, puppet-linter, test-kitchen) и настроены гит хуки, которые запускают нужный инструмент накоммит или пуш. Всозданном репозитории поумолчанию применяются политики, запрещающие пуш вмастер и мердж ветки, если тесты упали или код не прошел ревью.


IDE для Puppet

Кстати, вкачестве IDE дляразработки паппет-кода неплохо подходит VSCode, внём есть замечательный плагин схорошей поддержкой DSL, автодополнением и сниппетами.


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


Об управлении зависимостями в инфраструктурном коде


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


В управлении зависимостями вPuppet есть много странных и неочевидных вещей. Например, зависимости вмодулях можно указывать двумя разными способами: metadata.json и Puppetfile. Они немного отличаются посвоим возможностям, и разные инструменты по-разному их обрабатывают. Официально поддерживаемого инструмента поразрешению зависимостей нет. Есть librarian-puppet, который, вотличие отофициального r10k, умеет резолвить зависимости второго и высших порядков. Но проект давно не развивается и не имеет нормальной документации, хотя задачу свою вцелом выполняет. За неимением лучшего инструмента взяли его он применяется везде, где требуется резолв зависимостей: вacceptance-тестах и придеплое кода напаппет-сервер.


Достаточно долго мы искали подходящий путь. Сначала подключали модули как гит репу, а версионировали git-тегами, вот так:


mod 'dba-clickhouse',  :git => 'ssh://git@github.com/iac/dba-clickhouse.git',  :ref => '1.2.2'mod 'dba-kafka',  :git => 'ssh://git@github.com/iac/dba-kafka.git',  :ref => '1.2.0'

Такой способ работает, но требует явно указывать версию модуля, и не даёт завязаться намажорную или минорную версию. Дляболее гибкого версионирования придётся поднять собственный локальный Puppet Forge, загружать модули внего, а зависимости резолвить черезlibrarian-puppet.


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


# Puppetfilemod 'arch-puppetserver', '0.20.5' # подключаем строго указанную версию модуляmod 'arch-vault', '~> 2.1' # подключаем модуль в пределах мажорной версииmod 'si-lxc' # используем самую последниюю версию

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


[22:39:43] in dba-control on  production via  ruby-2.5.1 at   unstable $ iack dep show[] Collecting modules metadataFULL NAME            | CURRENT VERSION | LATEST VERSION | OUT OF DATE?  ---------------------|-----------------|----------------|---------------si-lxc               | latest          | 0.3.2          | N/A           si-base              | latest          | 1.3.1          | N/A           petems-hiera_vault   | v0.4.1          |                | Majorarch-vault           | 2.1.0           | 2.1.0          | No   dba-postgresql       | 0.1.2           | 0.1.3          | Tiny dba-pgbouncer        | 0.4.0           | 0.5.1          | Minorsi-grub              | 0.1.0           | 0.1.0          | No   si-collectd          | 0.2.3           | 0.2.4          | Tiny si-confluent         | 0.3.0           | 0.3.0          | No   dba-redis            | 0.2.3           | 0.2.3          | No   dba-collectd_plugins | latest          | 0.2.0          | N/A           dba-mongodb          | 0.2.1           | 0.2.1          | No   dba-patroni          | 0.1.4           | 0.2.4          | Minordba-cruise_control   | 0.1.1           | 0.1.2          | Tiny dba-lxd              | 0.7.0           | 0.7.0          | No   dba-clickhouse       | 1.2.1           | 1.2.2          | Tiny dba-zookeeper        | 2.0.0           | 2.0.0          | No   si-td_agent          | 0.1.0           | 0.1.0          | No   dba-kafka            | 1.1.6           | 1.2.1          | Minorarch-puppetserver    | 0.20.1          | 0.20.2         | Tiny pcfens-filebeat      | 4.1.0           | 4.4.1          | MinorKyleAnderson-consul  | 5.0.3           | 6.0.1          | Majorpuppetlabs-apt       | 6.3.0           | 7.4.2          | Majorpuppetlabs-stdlib    | 5.2.0           | 6.3.0          | Major

Вот несколько полезных ссылок потеме:



О важности code style и документации дляинфраструктурного кода


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


В Puppet сэтим всё отлично. The puppet language style guide содержит все основные рекомендации понаписанию кода. Puppet-lint, который мы запускаем наCI, проверяет соблюдение этих рекомендаций и позволяет добавлять внего собственные проверки.


Внутри Авито мы его немного расширили и дополнили его своими, более высокоуровневыми правилами и рекомендациями. Их мы выложили вместе с шаблонами модулей и control repo:



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


  • иметь единую точку входа вовнутреннюю документацию дляинженера инфраструктуры;
  • описать процесс работы отпростого к сложному: отhow to поразработке простейшего модуля доболее справочных материалов. Часть этой документации была переработана и превратилась встатью наХабре;
  • предоставить канал поддержки, где можно задать любой вопрос потеме.

Удобное управление секретами это важно


Управление секретами дляинфракода должно быть удобным и простым, иначе секреты начинают коммитить вкод. ВPuppet управление секретами удобно делать черезинтеграцию Hiera и Vault. На Гитхабе есть hiera-backend, который позволяет получать их значения прямо изvault черезhiera_lookup.


Для работы ссекретами вАвито есть модуль-обёртка, который позволяет либо получить секрет впеременную, либо положить файл-секрет вопределённое место всистеме. Первый способ работает через функцию, которая вызывается вкоде вот так:


$token_data = vault::secret_field('tokens.csv', 'data')

В этом примере впеременную token_data получаем значение поля 'data' изсекрета tokens.csv, который находится вVault. Всамом Vault секреты хранятся иерархически, также, как вHiera:


$ vault-util ls puppet/arch/      common/nodes/roles/

Таким образом, если мы хотим иметь общее значение секрета длявсех машин, достаточно положить его вcommon. Если оно разное длякаждой роли или ноды вroles/ или nodes/.

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


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



Canary релизы инфраструктурного кода


В Puppet есть интересный механизм, который позволяет выкатить код изветки control repo. Все ветки репозитория control repo отображаются наокружении, а каждая нода принадлежит кодному из них. Информация обэтом отдаётся изENC вместе сименем роли.


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


Это ещё один, финальный, способ протестировать свои изменения, и не уронить систему.


О достоинствах и недостатках Puppet


Если говорить одостоинствах Puppet, я бы назвал отличную документацию, развитый тулинг вокруг, очень большую гибкость и расширяемость инструмента. Если не хватает возможностей DSL его можно расширять наRuby. Hiera отличное решение дляхранения параметров, которые передаются вроли. Можно обеспечить максимальную стандартизацию инфраструктуры, приэтом сохранить возможность внести изменения сгранулярностью доконкретной машины. Данные вHiera можно выносить вразличные бэкенды, а если не хватает подходящего, можно написать свой.


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


Puppet наследовал у Ruby подход, когда узадачи имеется несколько решений. Это может быть интересно, если ты водиночку пилишь небольшой pet project. Но если ты работаешь синфраструктурой, где крайне важна стабильность и простота, вкоманде изнескольких десятков инженеров это очень вредит. Обычно получается так: если инструмент позволяет решать одну задачу несколькими способами, то будет выбран самый простой и, скорее всего, неправильный.


Ещё один недостаток плохая обратная связь привнесении изменений. Он впринципе присущ всем инструментам, работающим поpull-модели. Неизвестно, вкакой момент времени применятся изменения, которые попали вмастер. Длянекоторых задач это становится критичным, и приходится изобретать велосипеды, чтобы pull превратить вpush. Bolt, который Puppetlabs предлагает дляподобных задач, выглядит странно, сложно интегрируется сPuppetDB, и отего использования мы пока отказались.


Суммируя


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


  1. Вместо безупречного инструмента концентрируемся наулучшении тулинга и практик, которые применяем приразработке.
  2. Определяем границы применимости каждого инструмента и фиксируем их.
  3. Стараемся уменьшать связанность инфраструктурного кода и более контролируемое применение изменений засчёт версионирования его частей.
  4. Тестируем код и обеспечиваем быструю обратную связь привнесении изменений.
  5. Обеспечиваем запуск тестов наCI и вывод их результатов приревью кода.
  6. Используем пайплайны и инструменты, которые поддерживают необходимый workflow дляинфраструктурного кода.
  7. Используем External Node Classifier вместо регулярок.
  8. Упрощаем процессы предварительной настройки серверов.
  9. Обеспечиваем безопасное и удобное получение секретов винфраструктуру.
Подробнее..

Перевод Достоинства и недостатки стратегии Infra-as-Code Repo

25.08.2020 14:18:31 | Автор: admin

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



Если говорить о репозиториях инфраструктуры есть два устоявшихся варианта:


  • Monorepo. Один репозиторий для управления всем. Содержит всю вашу IaC, модули и любую вспомогательную автоматизацию;
  • Распределенные, автономные репозитории. Содержат компоненты, необходимые для решения, которое вы предоставляете. Они могут ссылаться на другие репозитории для повторно используемых компонентов или переменных данных.

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


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


Jaana Dogan лучше всего отразила проблему в этой цитате. Простое решение чаще всего является сложным и дорогим (такой вот каламбур получается), а также требует обработки огромного числа информации, прежде чем будет реализовано. Это требования, процессы, ограничения и потребности людей, но список можно сильно расширить. Понимая это, давайте разберем требования, обычно предъявляемые к репозиториям infra-as-code (этот список не претендует на роль абсолютно исчерпывающего, либо строго упорядоченного, но в него включены те вещи, которые я обычно встречаю в моих рабочих процессах):


  • Возможность ссылаться на общий стек или базовые настройки. Обычно такое получается, если у вас есть рабочее пространство terraform или отдельный файл состояния для вашего основного VPC или сети, обеспечивающих вашим подсетям основное подключение. Обычно они идут в виде выходных данных, вместо использования ресурсов позже в других частях кода.
  • Простота продвижения изменений из окружения А в окружение А + 1. Нужно наличие возможности быстрого сравнения окружений и безопасного продвижения изменений, сохранив при этом читаемость кодовой базы. В растущем окружении вы возможно захотите быстро найти что изменилось или в чем разница.
  • Гармония программных продуктов. Никто не использует отдельно Terraform, точно так же как не используется Ansible, Puppet или Kubernetes для запуска всего в вашей компании. Структура репозитория должна включать в себя различные, используемые вами инструменты, и предлагать инженерам интуитивное или, по крайней мере, хорошо задокументированное руководство по использованию или внесению изменений.
  • Оставаться простым, но не слишком простым. Согласно твиту от Jaana, простота не всегда легка, или достижима в большинстве случаев. Чрезмерное упрощение или оптимизация приведут к положению, препятствующему любой значимой скорости. Проектируйте, обеспечивая скорость изменений и простоту тестирования изменений. Сохраняйте гибкость, поскольку новые требования и запросы всегда а я в этом уже уверен придут оттуда, где их не ждешь.
  • Гладкая кривая обучения. Не все будут с одинаковым опытом и уровнем навыков. Нужно проектировать и документировать для интуитивного использования и простого вовлечения новых инженеров. Чрезмерно сложное решение, красивое на первый взгляд, потребует много времени вашей команды по вовлечению, обучению и устранению неполадок.

Простое решение.


Начиналось вроде как просто X vs Y, но теперь выглядит примерно так:



Какой лепесток не дернете придете к компромиссу, поскольку в его основе инженерное дело.


Чего не надо делать


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


Избегайте (слишком большой) вложенности модулей


Сложить матрешкой git submodules или модули terraform заманчиво, но можно легко попасть впросак, пытаясь найти комбинацию репозитория\ветки\каталога, где размещен модуль, а также молиться, чтобы не было другого модуля где-нибудь еще, на который этот ссылается. Модуль вне кодовой базы редко обновляется. А когда все-таки обновится в лучшем случае вы потратите время, а в худшем что-то отломается.


Избегайте симлинков


Я как-то видел реализацию, модули которой были в виде каталогов символических ссылок в окружении, где они запускались. Если от такого заранее не трясутся поджилки попытка найти модуль по ссылке может стать ужасом, особенно зная, что ваши изменения обязательно к этому приведут. В конце концов эта реализация была прошита файлами provider-module.tf, связанными с многими экземплярами модулей\окружений. Если не хотите слететь с катушек просто используйте инструменты Terragrunt и подобные.


Займите полосу


Выберите стратегию контроля версий и держитесь ее.


Желаете использовать ветки, чтобы разделять стабильные модули и находящиеся в разработке? Действуйте! Хотите применять метки git для проверки, что версии модуля уже пригодна к тестированию и предварительному внедрению? Шикарно! Захотелось использовать папки в репозитории, чтобы собрать все модули в одном репозитории вместо того, чтобы каждый модуль держать в отдельном репозитории? Так тому и быть, раз оно работает в вашем конкретном случае, если оно соотвествует вашей операционной модели.

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


Что же делать?


Работайте командой, с вашими пользователями, для ваших заказчиков


Неважно, руководите вы платформой в ветке\канале\организационном подразделении или отделом DevOps\SRE\платформы\инфраструктуры\сети\<подставьте свое имя здесь>, обслуживающим боооольшое предприятие, ваши пользователи (читай разработчики, тестировщики, бизнес-аналитики, ...) это те, кто будет использовать вашу платформу для обеспечения ценности ваших клиентов. И то, что они запрашивают будет прямо или косвенно способствовать счастью ваших клиентов. Слушайте их, собирайте требования (Я хочу легко и непринужденно настраивать этот неломаемый параметр в среде для проверки производительности, не проходя каждый раз эти десять шагов) и адаптироваться к ним или вместе с ними. Счастливые пользователи, соотвественно, будут лучше работать и делать ваших клиентов счастливее.


Помечайте со смыслом


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


Не раздавайте бездумно права на ветки и PR


Добавьте контроль там, где он будет наиболее уместен. Не забывайте, что люди с инженерным складом ума всегда будут искать более простой и удобный способ выполнения своей работы. А если вы поставите слишком много препятствий перед ними они найдут способы обхода. Защитите ключевые части вашей инфраструктуры, добавьте мосты в виде review и approval там, где, по вашему мнению, расположены точки принятия решений по продвижению.


Оптимизируйте репозитории


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


Не раздувайте модули сверх нужного


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


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

Что мне нравится делать


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


Решение 1: Инфраструктурный репозиторий + репозитории модулей на каждое организационное подразделение



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


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


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


module "ecr_<repo_name>" {   source      = "git::ssh://<repository/terraform-modules.git//ecr?ref=stable"   environment = var.environment   name        = "<repo_name>"}

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


Решение 2: Monorepo с логическими компонентами


Для мелких подразделений\компаний\проектов мне больше нравится подход с ветками master и develop, которыми разделены prod и non-prod окружения. При таком подходе, совмещенном с рядом расположенными модулями, права на ветки и автоматические применения предоставляют более быстрое внесение изменений и упрощение работы за счет некоторого разделения обязанностей.



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


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


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

Подробнее..

Перевод Применение паттернов Netflix DevOps к Windows

11.01.2021 12:12:41 | Автор: admin

Когда говорят про DevOps обычно всегда подразумевают работу с Linux. Но есть большое количество решений под Windows. Как осуществлять сборку Windows c помощью Packer в своем блоге поделился Netflix (Джастин Фелпс и Мануэль Корреа - Applying Netflix DevOps Patterns to Windows). Предлагаю перевод статьи.

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

Artisan Crafted Images

В культуре DevOps в Netflix группа, ответственная за создание сервиса, также отвечает за развертывание, тестирование, инфраструктуру и работу этой службы. Основная обязанность инженеров Netflix - выявление пробелов и болевых точек при разработке и эксплуатации сервисов. Хотя большинство наших сервисов работают на Linux Amazon Machine Images (AMI), все еще существует множество сервисов, критически важных для Netflix Playback Experience, работающих на инстансах Windows Elastic Compute Cloud (EC2).

Мы изучили наш процесс создания образов Windows AMI и обнаружили, что он подвержен ошибкам и полон утомительных усилий. Сначала инженер запускал инстанс EC2 и ждал, пока он перейдет в режим онлайн. Как только экземпляр оказывался доступен, инженер использовал инструмент удаленного администрирования, такой как RDP, для входа в экземпляр для установки программного обеспечения и настройки параметров. Затем этот образ сохранялся как AMI и использовался в Auto Scale Group для развертывания кластера инстансов. Поскольку этот процесс занимал много времени и был долгим, в наших экземплярах Windows обычно отсутствовали последние обновления безопасности от Microsoft.

В прошлом году мы решили улучшить этот процесс.

Были следующие проблемы:

  • устаревшая документация.

  • обновления ОС.

  • высокие когнитивные издержки.

  • отсутствие непрерывного тестирования.

Масштабирование создания образов.

Наш существующий инструмент создания AMI - Aminator - не поддерживает Windows, поэтому нам пришлось использовать другие инструменты.

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

Конфигурация как код

Первая часть нашего нового решения для создания образов Windows - Packer. Packer позволяет описать процесс настройки образов в виде файла JSON. Мы используем конструктор amazon-ebs Packer для запуска инстанса EC2. После подключения Packer использует WinRM для копирования файлов и выполнения сценариев PowerShell для экземпляра. Если все шаги настройки выполнены успешно, Packer сохраняет новый AMI. Файл конфигурации, сценарии, на которые имеются ссылки, и описание зависимостей артефактов находятся во внутреннем репозитории git. Теперь у нас есть конфигурация инстанса и программного обеспечения в виде кода. Это означает, что эти изменения можно отслеживать и просматривать, как и любые другие изменения кода.

Packer требуется специфическая информация для вашей среды создания образов и расширенные разрешения AWS IAM. Чтобы упростить использование Packer для наших разработчиков программного обеспечения, мы объединили специфичную для Netflix информацию о среде AWS и вспомогательные сценарии. Изначально мы сделали это с репозиторием git и файлами переменных Packer. Также был специальный экземпляр EC2, где Packer выполнялся как задания Jenkins. Эта установка была лучше, чем создание образов вручную, но у нас все же были некоторые проблемы с эргономикой. Например, стало сложно гарантировать, что пользователи Packer получают обновления.

Последняя часть нашего решения - найти способ упаковать наше программное обеспечение для установки в Windows. Это позволит повторно использовать вспомогательные сценарии и инструменты инфраструктуры, не требуя от каждого пользователя копировать это решение в свои сценарии Packer. В идеале это должно работать аналогично тому, как приложения упаковываются в процессах Animator. Мы решили эту проблему, используя Chocolatey, менеджер пакетов для Windows. Пакеты Chocolatey создаются и затем сохраняются во внутреннем репозитории артефактов. Этот репозиторий добавлен в качестве источника для команды choco install. Это означает, что мы можем создавать и повторно использовать пакеты, которые помогают интегрировать Windows в экосистему Netflix.

Использование Spinnaker для непрерывной доставки

Базовый Dockerfile позволяет обновлениям Packer, вспомогательным скриптам и конфигурациям среды распространяться через весь процесс создания образов Windows.Базовый Dockerfile позволяет обновлениям Packer, вспомогательным скриптам и конфигурациям среды распространяться через весь процесс создания образов Windows.

Чтобы сделать процесс создания образов более надежным, мы решили использовать образ Docker, содержащий Packer, конфигурацию нашей среды и вспомогательные скрипты. В дальнейшем пользователи создают свои собственные образы Docker на основе этого базового образа. Это означает, что мы можем обновить базовый образ, добавив в него новую информацию о среде и вспомогательные сценарии, и пользователи будут получать эти обновления автоматически. Со своим новым образом Docker пользователи запускают свои задания по созданию образов Packer с помощью Titus, нашей системы управления контейнерами. Задание Titus создает файл свойств как часть пайплайна Spinnaker. Полученный файл содержит AMI ID и используется на более поздних этапах пайплайна для деплоя. Создание образа в Titus сняло ограничение на использование одного экземпляра EC2, что позволило выполнять задания. Теперь каждое изменение в инфраструктуре тестируется, обрабатывается и развертывается, как и любое другое изменение кода. Этот процесс автоматизирован с помощью пайплайна Spinaker:

пример пайплайна Spinaker, показывающий этапы создания, сборки и развертывания образов.пример пайплайна Spinaker, показывающий этапы создания, сборки и развертывания образов.

На этапе сборки Kayenta используется для сравнения показателей между базовым образом (текущий AMI) и тем что собирается (новый AMI). На сборочном этапе оценка будет определяться на основе таких показателей, как CPU, threads, latency и GC pause. Если эта оценка находится в пределах допустимого порога, AMI развертывается в каждой среде. Запуск сборки для каждого изменения и тестирование AMI в производственной среде позволяет нам получить представление о влиянии обновлений Windows, изменений скриптов, настройки конфигурации веб-сервера и т. д.

Избавление от тяжелого труда(Eliminate Toil)

Автоматизация этих утомительных рабочих задач позволяет командам работать быстрее. Нашим инженерам больше не нужно вручную обновлять Windows, Java, Tomcat, IIS и другие службы. Мы можем легко протестировать изменения настройки сервера, обновления программного обеспечения и другие модификации среды выполнения. Каждое изменение кода и инфраструктуры проходит через один и тот же конвейер тестирования и развертывания.

Получение преимуществ

Изменения, которые раньше требовали нескольких часов ручной работы, теперь легко модифицировать, тестировать и развертывать. Другие группы могут быстро развернуть безопасные и воспроизводимые инстансы в автоматическом режиме. Услуги более надежны, тестируемы и документированы. Изменения в инфраструктуре теперь рассматриваются, как и любые другие изменения кода. Это снимает ненужную когнитивную нагрузку и документирует наши знания. Исключение тяжелого труда позволило команде сосредоточиться на других функциях и исправлениях ошибок. Все эти преимущества снижают риск сбоя, который может повлиять на клиента. Принятие шаблона Immutable Server для Windows с использованием Packer и Chocolatey принесло большие преимущества.

Подробнее..
Категории: Devops , Netflix , Packer , Iac

Категории

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

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