Правильно используйте инфраструктуру и конфигурацию как код

Для большинства профессионалов DevOps создание виртуальной машины обычно состоит из ее развертывания в облаке с помощью Terraform, а затем использования инструмента управления конфигурацией (например, Ansible или Puppet) или сценария начальной загрузки (например, cloud-init) для преобразования исходной виртуальной машины. на целевой сервер.

Мы все делаем это в течение длительного времени, и в большинстве случаев это работает, но имеет некоторые недостатки.

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

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

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

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

Хотя эта концепция не нова, с подходом были проблемы, потому что тогда не было доступных инструментов. К счастью, с современными практиками DevOps и CI / CD мы можем легко создать новый образ и выпустить его, когда нам нужно. Вы также можете запустить тесты на новом образе, прежде чем решите его выпустить. Это помогает уменьшить боль, которую вы можете понести при производстве. Откатить изменение тоже легко. Просто разверните старый образ. Вы можете выполнить канареечное развертывание с этим подходом, если вам нужно, и с легкостью провести A / B-тестирование.

HashiCorp имеет впечатляющий стек DevOps, который относится как к управлению инфраструктурой, так и к настройке серверов. В то время как Terraform от HashiCorp является ведущим мультиоблачным решением Инфраструктура как код, HashiCorp Packer предоставляет вам возможность создавать неизменяемую инфраструктуру.

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

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

Предварительные условия

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

Обратитесь к разделу Настройка облачной среды в статье Как терраформировать с помощью Jenkins и Slack на облачной платформе Google для получения дополнительных сведений о создании учетной записи службы.

Клонируйте этот репозиторий, скопируйте загруженный ключ JSON в место репозитория и переименуйте его как credentials.json. Вы можете выполнить шаги, описанные ниже:

Установка Packer и Terraform

Установить Packer и Terraform очень просто. Загрузите двоичный файл для своей среды и переместите его в свой PATH.

Вы можете следовать официальным инструкциям по установке для Packer и Terraform для получения дополнительной информации.

Запуск сборки упаковщика

Теперь, когда мы загрузили и Packer, и Terraform CLI, давайте приступим к настройке Packer.

Мы собираемся развернуть собственный образ веб-сервера NGINX с помощью Packer.

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

В файле есть два раздела: Builders и Provisioners.

В разделе «Строители» мы предлагаем следующее:

  • type - Тип изображения, которое мы пытаемся создать (googlecompute здесь, так как это изображение GCP).
  • account_file - файл учетных данных, который мы будем использовать для аутентификации и авторизации с помощью облачных API с использованием созданной нами учетной записи службы.
  • project_id - идентификатор проекта GCP, в котором вы хотите создать и сохранить это изображение. Замените <GCP_PROJECT_ID> идентификатором вашего проекта.
  • zone - зона, в которой вы хотите запустить виртуальную машину сборки. Packer создает виртуальную машину для создания образа, поэтому убедитесь, что у учетной записи службы есть разрешения на запуск виртуальной машины.
  • source_image_family - это семейство изображений, из которого вы хотите получить исходное изображение. Вы также можете использовать source_image, если собираетесь использовать конкретный базовый образ для создания своей виртуальной машины, но если вы хотите использовать последний стабильный образ определенного семейства в качестве базового, вы можете указать source_image_family. Это также гарантирует, что вы не устареете. В этом случае мы будем использовать ubuntu-1604-lts.
  • ssh_username — Это имя пользователя, которое Packer будет использовать для входа в вашу виртуальную машину сборки.
  • image_name - имя образа, который вы хотите создать после завершения подготовки. В этом случае мы используем nginx-{{timestamp}}. Поэтому, когда Packer завершит построение образа, он заменит {{timestamp}} фактической меткой времени сборки. Это гарантирует, что у вас будут новые образы каждый раз при сборке, и ваш старый образ не будет перезаписан.
  • image_family - Семейство изображений, в котором вы хотите сохранить свое изображение. Хотя это необязательно, это помогает, потому что, когда вы создаете несколько изображений одного семейства, вы можете указать семейство изображений в самом шаблоне экземпляра. В следующий раз, когда вы создадите свою инфраструктуру, у вас будет развернут последний стабильный образ. В этом случае мы используем webserver в качестве семейства изображений.

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

  • Средство подготовки файлов для копирования файла index.html из локального каталога в каталог /tmp виртуальной машины сборки.
  • Средство подготовки оболочки для настройки NGINX на машине. Мы также могли бы использовать для этого провайдер Ansible, но пока давайте не будем усложнять.

Давайте сначала посмотрим на файл index.html:

Сценарий setup.sh устанавливает NGINX, перемещает файл index.html в каталог NGINX HTML по умолчанию, а затем включает и запускает службу NGINX.

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

$ packer build packer.json

И когда мы его запускаем, Packer выполняет следующие действия:

  • Разворачивает Build VM, используя Ubuntu 16.04LTS в качестве базового образа на GCP, используя зону, указанную в файле Packer.
  • Копирует файл index.html в каталог /tmp сервера сборки.
  • Устанавливает поверх него NGINX с помощью сценария setup.sh.
  • Создает изображение из полученной конфигурации.
  • Отправляет изображение в репозиторий изображений вашего проекта.

Если вы перейдете в свой облачный проект Google - ›Compute Engine -› Хранилище - ›Изображения в облачной консоли, вы увидите изображение NGINX с меткой времени в конце.

Создание экземпляра GCE из образа упаковщика

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

Файл main.tf определяет экземпляр GCE с использованием настраиваемого изображения из семейства webserver. Вам необходимо скопировать файл terraform.tfvars.example в terraform.tfvars и отредактировать файл в соответствии с вашей конфигурацией.

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

$ terraform init
$ terraform apply

После завершения terraform apply давайте посмотрим на облачную консоль и получим внешний IP-адрес экземпляра:

Поскольку NGINX прослушивает порт HTTP по умолчанию (80), мы можем использовать IP-адрес для доступа к настраиваемому веб-сайту.

И, как мы видим, вместо страницы NGINX по умолчанию мы получаем в результате пользовательскую index.html.

Поздравляю! Вы успешно создали и запустили пользовательский образ с помощью Packer и Terraform.

Заключение

Использование Packer с Terraform помогает переопределить методы управления конфигурациями и позволило использовать неизменяемую инфраструктуру в основной индустрии высоких технологий.

Спасибо за прочтение! Надеюсь, вам понравилась статья.