(domain-specific language, DSL) для проверки развернутой вами инфраструктуры на соответствие какого-то рода спецификации. Например, если вы тестируете модуль Terraform, который развертывает сервер EC2, можно использовать следующий код для inspec, чтобы проверить, имеет ли этот сервер подходящие права для доступа к определенным файлам, установлены ли у него конкретные зависимости и прослушивает ли он заданный порт:
describe file('/etc/myapp.conf') do
it { should exist }
its('mode') { should cmp 0644 }
end
describe apache_conf do
its('Listen') { should cmp 8080 }
end
describe port(8080) do
it { should be_listening }
end
Преимущество этих инструментов в том, что языки DSL, помимо своей лаконичности и простоты в использовании, предлагают эффективный декларативный способ проверки большого количества свойств инфраструктуры. Это отлично подходит для соблюдения списка требований, в особенности тех, которые касаются стандартов и правовых норм (вроде стандарта PCI или закона HIPAA). Недостатком этих инструментов является то, что даже после успешной проверки всех свойств ваша инфраструктура может не работать! Для сравнения, чтобы протестировать эти же свойства с помощью Terratest, вам пришлось бы выполнять HTTP-запросы к серверу и проверять, возвращает ли тот ожидаемые ответы.
Резюме
В мире инфраструктуры все постоянно меняется. Не стоят на месте и такие инструменты, как Terraform, Packer, Docker, Kubernetes, AWS, Google Cloud, Azure и др. Это означает, что инфраструктурный код очень быстро теряет свою актуальность. Или, говоря другими словами: инфраструктурный код без автоматических тестов можно считать неисправным.
Это одновременно и афоризм, и буквальное утверждение. Каждый раз, когда я берусь за написание инфраструктурного кода, при переходе к автоматическим тестам неминуемо всплывает множество неочевидных проблем. И неважно, сколько усилий я перед этим потратил на рефакторинг, ручное тестирование и разбор кода. Когда вы находите время для автоматизации процесса тестирования, почти всегда происходит какая-то магия и вам удается выявить проблемы, которые вы бы сами никогда не нашли (а вот ваши клиенты — легко). Причем они находятся не только при первом добавлении автоматических тестов, но и с каждой последующей фиксацией кода, особенно по мере изменения мира DevOps вокруг вас.
Автоматические тесты, которыми я оснастил свой инфраструктурный код, нашли ошибки не только в моей инфраструктуре, но и в используемых мной инструментах, включая нетривиальные проблемы в Terraform, Packer, Elasticsearch, Kafka, AWS и т. д. Как показывает эта глава, написание автоматических тестов — занятие непростое, требующее значительных усилий. Еще больше усилий уходит на их поддержку и обеспечение надежности за счет достаточного количества повторных попыток. А самое сложное — поддерживать в порядке тестовую среду, чтобы контролировать свои расходы. Но оно того стоит.
Например, когда я работаю над модулем для развертывания хранилища данных, после каждой фиксации кода в репозитории мои тесты создают десяток копий этого хранилища с разными конфигурациями, записывают и считывают данные, после чего удаляют все это. Каждое успешное прохождение этих тестов дает мне железную уверенность в том, что мой код по-прежнему работает. По меньшей мере они позволяют мне лучше спать. Те часы, которые я потратил на логику повторных попыток и отложенную согласованность, компенсируются тем, что мне не приходится подниматься посреди ночи из-за перебоев в работе.
У этой книги тоже есть тесты!
Для всех примеров кода в этой книге тоже предусмотрены тесты. Весь представленный здесь код и тесты к нему можно найти по адресу github.com/brikis98/terraform-up-and-running-code.
В этой главе вы познакомились с основными принципами тестирования кода Terraform, включая ключевые моменты.
•Тестирование кода Terraform не может проходить локально. В связи с этим для ручного тестирования приходится развертывать настоящие ресурсы в одной или нескольких изолированных средах.
• Чтобы держать расходы под контролем, регулярно чистите свои изолированные среды. В противном случае ваши ресурсы станут неуправляемыми и расходы выйдут из-под контроля.
• Вы не можете проводить чистое тестирование кода Terraform. Поэтому все автоматическое тестирование должно происходить с помощью кода, который развертывает реальные ресурсы в одной или нескольких изолированных средах.
• Все ваши ресурсы должны быть разделены по пространствам имен. Это гарантирует отсутствие конфликтов между несколькими тестами, запущенными параллельно.
•Чем меньше модули, тем легче и быстрее их тестировать. Это один из ключевых выводов главы 6, но он стоит того, чтобы повторить его еще раз: чем меньше модуль, тем легче его создавать, поддерживать, использовать и тестировать.
В главе 8 вы узнаете, как внедрить код Terraform и автоматические тесты в рабочий процесс вашей команды. Среди прочего мы рассмотрим управление окружениями, конфигурацию процессов непрерывной интеграции и непрерывного развертывания и т. д.
55 AWS не взимает плату за дополнительные учетные записи, и, если вы используете AWS Organizations, у вас есть возможность создавать «дочерние» учетные записи, все расходы которых записываются на единый «главный» счет.
56 В отдельных случаях точки входа, которые использует Terraform, можно переопределить. Например, вы можете переопределить точку входа, с помощью которой Terraform взаимодействует с Amazon S3, и заменить ее mock-объектом, реализующим API S3. Это нормальное решение для небольшого количества точек входа, но код Terraform обычно выполняет сотни разных API-вызовов к исходному провайдеру и создавать mock-объекты для каждого из них было бы непрактично. Более того, если вы пошли на создание этих mock-объектов, это вовсе не означает, что итоговый модульный тест даст вам достаточно уверенности в корректной работе вашего кода. Если вы создадите mock-объекты для точек входа ASG и ALB, команда terraform apply может завершиться успешно. Но говорит ли это о том, что наш код способен развернуть рабочее приложение поверх этой инфраструктуры?
57 В будущих версиях Terratest, скорее всего, начнет использовать go mod для управления зависимостями. На момент написания этих строк go mod имеет лишь предварительную поддержку, но с выходом Go 1.13 этот компонент должен быть включен по умолчанию, поэтому он, вероятно, станет стандартным инструментом для работы с зависимостями в Go и заодно устранит необходимость в GOPATH. Подробнее об этом читайте по адресу blog.golang.org/using-go-modules.
8. Как использовать Terraform в команде
Чтение книги и разбор примеров кода — это то, чем обычно занимаются в одиночку. Но в реальности вы будете работать в команде, что создает целый ряд новых проблем. Возможно, придется убеждать свою команду в переходе на Terraform и другие инструменты IaC. Вы, вероятно, будете иметь дело с множеством людей, которые одновременно пытаются понять, использовать и модифицировать написанный вами код Terraform. Вам также нужно придумать, как интегрировать Terraform в ваш стек технологий и в рабочий процесс вашей компании.
В этой главе мы подробно рассмотрим ключевые процессы, которые вы должны наладить, чтобы ваша команда смогла использовать Terraform и IaC.
• Внедрение концепции «инфраструктура как код» внутри команды.
• Процесс развертывания кода приложений.
• Процесс развертывания инфраструктурного кода.
• Объединение отдельных элементов.
Последовательно пройдемся по каждой из этих тем.
Примеры кода
Напоминаю: все примеры кода для этой книги можно найти по адресу github.com/brikis98/terraform-up-and-running-code.
Внедрение концепции IaC внутри команды
Если ваша команда привыкла управлять всей инфраструктурой вручную, переход на концепцию IaC не ограничится простым знакомством с новым инструментом или технологией. Вам придется изменить культуру и рабочие процессы в вашей команде. Это задача не из простых, особенно в больших компаниях. Поскольку культура и процессы внутри каждой команды немного различаются, универсальных инструкций попросту не существует. Однако следующие советы будут полезны в большинстве ситуаций:
• убедите свое начальство;
• сделайте переход постепенным;
• дайте своей команде время на обучение.
Убедите свое начальство
Я часто наблюдал эту ситуацию во многих компаниях: разработчик открывает для себя Terraform, вдохновляется возможностями этой технологии, приходит на работу взволнованный, полный энтузиазма, рассказывает о Terraform всем вокруг… а начальник говорит «нет». Конечно, это разочаровывает и обескураживает разработчика. Почему эти преимущества видны не всем? Мы могли бы все автоматизировать! Мы могли бы избежать стольких ошибок! Как еще выплатить весь этот технический долг? Как все вокруг могут быть настолько слепыми?
Проблема в том, что за всеми преимуществами от внедрения средств IaC, таких как Terraform, этот разработчик не видит цену, которую придется заплатить. Приведем несколько примеров.
•Разный уровень навыков. Переход на IaC будет означать, что вашим системным администраторам придется тратить большую часть своего времени на написание больших объемов кода: модулей Terraform, тестов на Go, рецептов для Chef и т. д. Некоторые из них вполне счастливы программировать днями напролет и с радостью воспримут изменения, но для других этот переход будет тяжелым. Многие операционные инженеры и сисадмины привыкли вносить изменения вручную, возможно, с периодическим использованием небольших скриптов; вместо этого им придется переквалифицироваться в полноценных разработчиков, что потребует изучения целого ряда новых навыков (или поиска новых работников).
• Новые инструменты. Разработчики программного обеспечения могут прикипеть к инструментам, которые они используют. Иногда такая приверженность становится почти религиозной. Каждый раз, когда вы вводите в обиход новый инструмент, одни разработчики будут в восторге от в