Как создавать моментальные снимки DigitalOcean с помощью Packer на CentOS 7

Вступление

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

В этом руководстве вы будете использовать Packer для настройки веб-сервера Nginx в CentOS 7. Затем вы будете использовать Packer для создания моментального снимка этой капли и немедленно сделать его доступным на панели инструментов DigitalOcean, чтобы вы могли использовать его для создания новых капель.

Предпосылки

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

  • Сервер CentOS 7, настроенный с пользователем без полномочий root с привилегиями sudo, вы можете настроить это, выполнивHow to Add and Delete Users on a CentOS 7 Server.

  • Токен API DigitalOcean с привилегиямиread иwrite. ПросмотритеHow to Use the DigitalOcean API v2, чтобы получить токен.

[[шаг-1 -—- загрузка-и-установка-упаковщика]] == Шаг 1. Загрузка и установка упаковщика

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

Самый простой способ запустить Packer в вашей системе - это загрузить последний двоичный пакет из официальных выпусков Hashicorpwebsite. На момент написания статьи последняя версия 0.12.2.

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

curl -O https://releases.hashicorp.com/packer/0.12.2/packer_0.12.2_linux_amd64.zip

После загрузки установите утилитуunzip и используйте ее для распаковки содержимого пакета в каталог/usr/local, рекомендуемое место, чтобы сделать Packer доступным для всех пользователей.

sudo yum install -y unzip
sudo unzip -d /usr/local packer_0.12.2_linux_amd64.zip

CentOS уже включает программу под названиемpacker, и хотя вы можете просто вводить полный путь каждый раз, когда запускаете команду, более эффективный метод решения этой проблемы - создать символическую ссылку, которая отображаетpacker.io в/usr/local/packer. Создайте символическую ссылку в папке/usr/local/bin с помощью следующей команды:

sudo ln -s /usr/local/packer /usr/local/bin/packer.io

Убедитесь, что установка прошла успешно, проверив, чтоpacker.io доступен в командной строке:

packer.io

Успешная установка выведет следующее:

Outputusage: packer [--version] [--help]  []

Available commands are:
    build       build image(s) from template
    fix         fixes templates from old versions of packer
    inspect     see components of a template
    push        push a template and supporting files to a Packer build service
    validate    check that a template is valid
    version     Prints the Packer version

Packer теперь установлен и работает на вашем компьютере. На следующем шаге вы создадите каталог проекта и настроите шаблон для создания базового снимка CentOS.

[[step-2 -—- configuring-the-digitalocean-builder]] == Шаг 2 - Настройка DigitalOcean Builder

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

На языке Packerbuilder - это объект JSON, который содержит схему изображения, которое вы хотите создать с помощью Packer. Используя конструкторdigitalocean, вы собираетесь проинструктировать Packer создать дроплет CentOS 7.3 объемом 512 МБ, который будет запущен в регионе NYC1.

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

mkdir ~/packerProject
cd ~/packerProject

Теперь, когда у вас есть каталог проекта, откройте новый файл с именемtemplate.json в текстовом редакторе:

vi ~/packerProject/template.json

Каждый строитель должен перейти в разделbuilderstemplate.json. Добавьте этот раздел сейчас и включите построительdigitalocean, поместив этот код в файл:

~/packerProject/template.json

{
  "builders": [
    {
      "type": "digitalocean"
    }]
}

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

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

Завершите настройку капли, добавив эти ключи и значения, чтобы получить снимок из капли CentOS 7 объемом 512 МБ, запущенной в регионе NYC1. Измените ваш файл так, чтобы он выглядел так:

~/packerProject/template.json

{
  "builders": [
    {
      "type": "digitalocean",
      "ssh_username": "root",
      "api_token": "YOUR_DIGITALOCEAN_API_TOKEN",
      "image": "centos-7-x64",
      "region": "nyc1",
      "size": "512mb"
    }]
}

Пакер подключается к каплям, используя значениеssh_username. Это значение должно быть установлено как «root» для правильной работы Packer.

Сохранитеtemplate.json и выйдите из текстового редактора.

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

Key Значение необходимые Описание

api_token

строка

Yes

Токен API для доступа к вашей учетной записи. Его также можно указать через переменную окруженияDIGITALOCEAN_API_TOKEN, если она установлена.

image

строка

Yes

Имя (или заголовок) используемого базового образа. Это изображение, которое будет использоваться для запуска новой капли и ее подготовки. См.https://developers.digitalocean.com/documentation/v2/#list-all-images для получения подробной информации о том, как получить список принятых имен / ярлыков изображений.

region

строка

Yes

Название (или название) региона, в котором запускается дроплет. Следовательно, это регион, где будет доступен снимок. См.https://developers.digitalocean.com/documentation/v2/#list-all-regions для допустимых названий / ярлыков регионов.

size

строка

Yes

Имя (или название) используемого размера капли. См.https://developers.digitalocean.com/documentation/v2/#list-all-sizes для допустимых имен / заголовков размеров.

api_url

строка

No

URL-адрес нестандартной конечной точки API. Установите это, если вы используете службу, совместимую с DigitalOcean API.

droplet_name

строка

No

Имя, присвоенное капле. DigitalOcean устанавливает это значение для имени хоста машины.

private_networking

логический

No

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

snapshot_name

строка

No

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

state_timeout

строка

No

Время ожидания в виде строки продолжительности, пока капля войдет в желаемое состояние (например, «активно») до истечения времени ожидания. Таймаут состояния по умолчанию - «6 минут».

user_data

строка

No

Пользовательские данные для запуска с помощью Droplet. См.An Introduction to Droplet Metadata для получения дополнительной информации.

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

[[step-3 -—- create-and-storing-user-variables]] == Шаг 3 - Создание и сохранение пользовательских переменных

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

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

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

Создайте и откройте новый файл JSON в каталогеpackerProject для хранения этой информации:

vi ~/packerProject/variables.json

Теперь добавьте переменнуюmy_token и установите ее значение в свой токен API DigitalOcean:

~/packerProject/variables.json

{
  "my_token": "YOUR_DIGITALOCEAN_API_TOKEN"
}

Сохранитеvariables.json и выйдите из редактора.

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

Откройтеtemplate.json в своем редакторе:

vi template.json

Добавьте новый разделvariables над ранее определенным разделомbuilders. В этом новом разделе объявите переменнуюmy_token и установите ее значение по умолчанию на пустую строку:

~/packerProject/template.json

{
  "variables": {
    "my_token":""
  },
  "builders": [
  ...

}

Переменные, определенные в разделеvariables, доступны глобально.

Затем замените свой токен API в разделеbuilders на вызовmy_token:

~/packerProject/template.json

{
  ...
  "builders": [
    {
      "type": "digitalocean",
      "api_token": "{{ user `my_token` }}",
      ...
    }]
}

Как видите, вызовы пользовательских переменных должны использовать определенный формат:+"{{ user \`variable_name\}} + `. Требуются кавычки и обратные кавычки, а также двойные фигурные скобки.

Сохраните файл и выйдите из редактора.

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

[[step-4 -—- configuring-provisioners]] == Шаг 4. Настройка Provisioners

Разделprovisioners - это место, где Packer устанавливает и настраивает программное обеспечение на работающей Droplet, прежде чем превратить его в образ машины. Как и компоновщики, существуют разные типы провайдеров, которые вы можете использовать для настройки дроплета.

Чтобы настроить Nginx, вы собираетесь использовать инициатор Packerfile для загрузки файлов конфигурации на сервер, а затем использовать инициаторshell для выполнения сценария установки, который использует эти файлы. Инициаторfile позволяет перемещать файлы и каталоги на работающую машину и обратно до того, как она будет преобразована в образ. С помощью инициатораshell вы можете удаленно выполнять сценарии оболочки на этом компьютере.

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

Добавьте разделprovisioners сразу после разделаbuilders вtemplate.json и установите два провайдера, которые вы будете использовать:

~/packerProject/template.json

{
  ...
  "builders": [
    {
      ...
  }],
  "provisioners": [
    {
      "type": "file"
    },
    {
      "type": "shell"
    }]
}

Провайдеруfile требуетсяsource, указывающий на локальный путь к файлу, иdestination, указывающий на существующий путь к файлу на работающей машине. Упаковщик может перемещать файлы только в те места назначения, которые уже существуют. По этой причине мы обычно загружаем файлы в каталог/tmp.

Настройте инициаторfile, добавив выделенные строки вtemplate.json:

~/packerProject/template.json

{
  ...
  "provisioners": [
    {
      "type": "file",
      "source": "configs/",
      "destination": "/tmp"
    },
    ...
}

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

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

Теперь настройте инициаторshell, указав полный путь к вашему скрипту:

~/packerProject/template.json

{
  ...
  "provisioners": [
    {
      "type": "file",
      "source": "configs/",
      "destination": "/tmp"
    },
    {
      "type": "shell",
      "scripts": [
        "scripts/configureNginx.sh"
      ]
    }]
}

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

Разделprovisioners вашего шаблона завершен. Сохраните файл и выйдите из Vim.

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

[[step-5 -—- add-configuration-files-and-installation-scripts]] == Шаг 5 - Добавление файлов конфигурации и сценариев установки

Мы хотим, чтобы наш образ поставлялся с полностью настроенной установкой Nginx, с соответствующими файлами конфигурации и веб-страницей по умолчанию. В этом разделе вы создадите эти файлы из некоторой предопределенной конфигурации на основе руководстваHow To Set Up Nginx Server Blocks (Virtual Hosts) on Ubuntu 16.04, поскольку конфигурация Nginx выходит за рамки этого руководства.

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

Сначала создайте новый каталог в папке проекта для хранения файлов конфигурации.

mkdir ~/packerProject/configs

Измените на/configs, чтобы создать файлы конфигурации Nginx:

cd ~/packerProject/configs

Во-первых, вам нужна веб-страница по умолчанию для обслуживания с вашего нового домена. Создайте файлindex.html.new:

vi index.html.new

В этот новый файл вставьте следующее:

~/packerProject/configs/index.html.new

HELLO FROM YOUR TEST PAGE

Затем вам нужен файл конфигурации Nginx, который определяет блок сервера для вашего домена, который определяет порт прослушивания и расположение ваших веб-страниц для домена. Создайте файл с именемnewDomain.conf:

vi newDomain.conf

Поместите следующую конфигурацию в этот файл:

~/packerProject/configs/newDomain.conf

server {
        listen 80;
        listen [::]:80;

        server_name example.com;

        location / {
                root /var/www/html/newDomain;
                index index.html index.htm;
        }
}

[.note] # В этом примере мы используемexample.com в качестве значения-заполнителя. Когда вы создаете новую машину из своего образа, вам нужно будет войти в систему на новой машине и изменить этот файл, чтобы отразить фактический домен или IP-адрес, указывающий на машину.
#

Наконец, вы хотите, чтобы Nginx загружал конфигурацию вашего домена из нового каталога/etc/nginx/vhost.d/. Это означает редактирование основного файла конфигурации Nginx.

Создайтеnginx.conf.new:

vi nginx.conf.new

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

~/packerProject/configs/nginx.conf.new

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/vhost.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

}

Сохраните и выйдите из файла.

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

mkdir ~/packerProject/scripts

Теперь перейдите в этот новый каталог и создайте сценарий установкиconfigureNginx.sh, который устанавливает, настраивает, включает и запускает веб-сервер Nginx:

cd ~/packerProject/scripts
vi configureNginx.sh

Вставьте следующее в файл, который устанавливает, настраивает и запускает Nginx, используя только что созданные вами файлы конфигурации:

~/packerProject/scripts/configureNginx.sh

#!/bin/bash
# Script to install Nginx and enable on boot.

# Update your system:
yum update -y

# Install EPEL Repository, update EPEL, and install Nginx:
yum install -y epel-release
yum update -y
yum install -y nginx

#Start Nginx service and enable to start on boot:
systemctl enable nginx
systemctl start nginx

# Create new 'vhost' directory for domain configuration:
mkdir /etc/nginx/vhost.d

# Create a new directory to serve new content.
mkdir -p /var/www/html/newDomain

# Create a copy of original configuration files and import configuration:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.original
cp /tmp/nginx.conf.new /etc/nginx/nginx.conf

# Copy over the server block configuration:
cp /tmp/newDomain.conf /etc/nginx/vhost.d/newDomain.conf

# Copy over the html test page:
cp /tmp/index.html.new /var/www/html/newDomain/index.html

# Restart Nginx:
systemctl restart nginx

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

Шаг 6 - Проверка и построение капли

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

Перейдите в корень вашего проекта:

cd ~/packerProject

Подкомандаvalidate проверяет ваш шаблон на наличие допустимого синтаксиса и параметров конфигурации:

packer.io validate -var-file=variables.json template.json

Флаг-var-file считываетvariables.json и устанавливает значение дляmy_token в пределахtemplate.json.

Вы увидите следующий вывод:

OutputTemplate validated successfully.

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

Подкомандаbuild запускает сборку, которую вы определили в разделеbuilders вашего шаблона. Другими словами, он сообщает Packer, что нужно создать свою каплю, а затем создать снимок этой капли на панели инструментов DigitalOcean.

Вызовитеpacker.io build для построения капли и создания снимка:

packer.io build -var-file=variables.json template.json

Обратите внимание, что флаг-var-file действует одинаково для подкомандbuild иvalidate.

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

Outputdigitalocean output will be in this color.

==> digitalocean: Creating temporary ssh key for Droplet...
==> digitalocean: Creating Droplet...
==> digitalocean: Waiting for Droplet to become active...
==> digitalocean: Waiting for SSH to become available...
==> digitalocean: Connected to SSH!
==> digitalocean: Gracefully shutting down Droplet...
==> digitalocean: Creating snapshot: packer-1467580504
==> digitalocean: Waiting for snapshot to complete...
==> digitalocean: Destroying Droplet...
==> digitalocean: Deleting temporary ssh key...
Build 'digitalocean' finished.

==> Builds finished. The artifacts of successful builds are:
--> digitalocean: A snapshot was created: 'packer-1487878703' (ID: 18252043) in region 'nyc1'

После успешной сборки вы найдете новый снимок в вашем хранилище снимков DigitalOcean. Вы можете найти имя снимка в выводе. В этом примере этоpacker-1487878703.

Отсюда перейдите на панель управления DigitalOcean, выберитеImages, и новый снимок появится в вашем списке:

Docker snapshot in DigitalOcean dashboard

Теперь вы можете использовать этот новый снимок для создания новых капель. ВыберитеMore и выберитеCreate Droplet. Затем заполните форму, чтобы создать новую машину.

Когда компьютер подключен к сети, определите его IP-адрес на панели инструментов и войдите на свой новый компьютер:

ssh root@your_new_server_ip_address

Затем отредактируйте файл конфигурации сервера Nginx:

vi /etc/nginx/vhost.d/newDomain.conf

И заменитеexample.com либо IP-адресом машины, либо именем домена, которое вы будете использовать:

~/packerProject/configs/newDomain.conf

server {
        listen 80;
        listen [::]:80;

        server_name your_new_server_ip_address;

        location / {
                root /var/www/html/newDomain;
                index index.html index.htm;
        }
}

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

sudo sed -i 's/^.*server_name example.com/server_name your_new_server_ip_address/' /etc/nginx/vhost.d/newDomain.conf

Вы можете узнать больше оsed вthis tutorial.

Поиск проблемы

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

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

Вы можете войти в режим отладки, передав флаг-debug параметруpacker.io build в командной строке:

packer.io build -debug --var-file=variables.json template.json

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

Чтобы включить журналы Packer, установите для переменной средыPACKER_LOG любое значение, кроме «0» или пустой строки:

PACKER_LOG=1 packer build --var-file=variables.json template.json

Журналы будут выводиться на консоль, если вы также не установите переменную окруженияPACKER_LOG_PATH.

Если у вас по-прежнему возникают проблемы, вы можете попробовать связаться с кем-нибудь изPacker community.

Заключение

Теперь, когда вы знакомы с основами Packer, вы можете быть заинтересованы в создании этого фундамента.

Попробуйте добавить второго компоновщика в шаблон, чтобы создать локальную среду тестирования вместе со снимком DigitalOcean. Компоновщикvirtualbox-iso, например, создает образы дляVirtualBox, бесплатного продукта виртуализации с открытым исходным кодом, используемого как предприятиями, так и любителями. Вы можете определитьpost-processor для образа VirtualBox и создавать бродячие среды, которые отражают ваши снимки DigitalOcean. Это позволит вам проверить изменения веб-сайта локально, прежде чем отправлять их в активную каплю. Вы можете узнать больше вVagrant post-processor documentation.

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

Если вам удобнее использовать инструменты управления конфигурацией, Packer поставляется с готовой поддержкой дляAnsible,Puppet,Chef и других. Попробуйте использовать одного из этих провайдеров для дальнейшей настройки Droplet в соответствии с вашим вариантом использования. Если вы никогда раньше не пробовали управлять конфигурацией, взгляните наHow To Create Ansible Playbooks to Automate System Configuration on Ubuntu.

Related