Terraform: инфраструктура на уровне кода — страница 58 из 65

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

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


Дайте своей команде время на обучение

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

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

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

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

3. Случается неизбежное: перебой в работе системы.

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

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

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

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

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


Процесс развертывания кода приложений

В этом разделе вы познакомитесь с типичным рабочим процессом доставки прикладного кода (такого как приложение на Ruby on Rails или Java/Spring), начиная с этапа разработки и заканчивая промышленной средой. В области DevOps этот рабочий процесс известен достаточно хорошо, поэтому вы уже должны быть знакомы с некоторыми его аспектами. Позже в этой главе мы поговорим о доставке инфраструктурного кода (вроде модулей Terraform). Этот процесс куда менее распространен в нашей индустрии, поэтому будет полезно сравнить его с доставкой прикладного кода и провести параллели между их аналогичными этапами.

Рассмотрим рабочий процесс для кода приложений.

1. Используем систему управления версиями.

2. Выполняем код локально.

3. Вносим изменения в код.

4. Подаем изменения на рассмотрение.

5. Выполняем автоматические тесты.

6. Проводим слияние и выпускаем новую версию.

7. Развертываем.

По очереди пройдемся по каждому из этих этапов.


Использование системы управления версиями

Весь ваш код должен находиться в системе управления версиями. Без исключений. Это первый пункт классического теста Джоэла (http://bit.ly/2meqAb7), который Джоэл Спольски создал примерно 20 лет назад. С тех пор изменилось лишь то, что: а) благодаря таким инструментам, как GitHub, использовать системы управления версиями теперь проще, чем когда-либо: б) в виде кода можно описывать все больше и больше вещей. Это относится к документации (как файл README в формате Markdown), конфигурации приложений (вроде файла настроек на YAML), спецификациям (скажем, тестовый код, написанный на RSpec), тестам (например, автоматические тесты с применением JUnit), базам данных (типа схемы миграции, написанной на Active Record) и, конечно, к инфраструктуре.

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

$ git clone https://github.com/brikis98/terraform-up-and-running-code.git

Эта команда по умолчанию загружает из репозитория ветку master, но вы, скорее всего, занимаетесь разработкой в отдельной ветке. Вот как с помощью команды gitcheckout можно создать ветку под названием example-feature и переключиться на нее:

$ cd terraform-up-and-running-code

$ git checkout -b example-feature

Switched to a new branch 'example-feature'


Локальное выполнение кода

Теперь, когда код находится на вашем компьютере, можно выполнить его локально. Помните пример с веб-сервером на Ruby из главы 7? Так он запускается:

$ cd code/ruby/08-terraform/team

$ ruby web-server.rb

[2019-06-15 15:43:17] INFO  WEBrick 1.3.1

[2019-06-15 15:43:17] INFO  ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin17]

[2019-06-15 15:43:17] INFO  WEBrick::HTTPServer#start: pid=28618 port=8000

Теперь его можно протестировать вручную с помощью curl:

$ curl http://localhost:8000

Hello, World

При желании можно также выполнить автоматические тесты:

$ ruby web-server-test.rb

(...)

Finished in 0.633175 seconds.

--------------------------------------------

8 tests, 24 assertions, 0 failures, 0 errors

100% passed

--------------------------------------------

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


Внесение изменений в код

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

Например, вы можете заменить вывод web-server.rb на Hello,Worldv2, перезапустить сервер и проверить результат:

$ curl http://localhost:8000

Hello, World v2

Еще раз выполните тесты и посмотрите, будут ли они пройдены:

$ ruby web-server-test.rb

(...)

Failure: test_integration_hello(TestWebServer)

web-server-test.rb:53:in `block in test_integration_hello'

     50:     do_integration_test('/', lambda { |response|

     51:       assert_equal(200, response.code.to_i)

     52:       assert_equal('text/plain', response['Content-Type'])

  => 53:       assert_equal('Hello, World', response.body)

     54:     })

     55:   end

     56:

web-server-test.rb:100:in `do_integration_test'

web-server-test.rb:50:in `test_integration_hello'

<"Hello, World"> expected but was

<"Hello, World v2">

(...)

Finished in 0.236401 seconds.

--------------------------------------------

8 tests, 24 assertions, 2 failures, 0 errors

75% passed

--------------------------------------------

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