Продолжается подписка на наши издания! Вы не забыли подписаться?

Автоматизация для людей: Паттерны автоматизации развертывания

Автор: Paul Duvall
Опубликовано: 12.07.2010
Версия текста: 1.1

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

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

В более ранней статье, "Speed deployment with automation" (http://www.ibm.com/developerworks/java/library/j-ap01088/), вы ознакомились с методикой удаленного развертывания ПО в разных целевых окружениях. Эта статья, состоящая из двух частей, выводит обсуждение автоматизации развертывания на более высокий уровень. Так же, как и при разработке ПО, при его развертывании можно использовать паттерны, и за несколько последних лет я составил их каталог. В первой части статьи я приведу восемь таких паттернов с примерами.

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

На рисунке 1 показаны отношения между паттернами развертывания.


Рисунок 1. Паттерны автоматизации развертывания.

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

Помещение всех файлов в репозиторий системы контроля версий

Имя: Репозиторий.

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

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

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

Запись всех процессов развертывания в скрипт

Имя: Скрипты развертывания

Паттерн: Все процессы развертывания должны быть вписаны в скрипт

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

Листинг 1 демонстрирует использование паттерна Скрипты развертывания при автоматизации процесса (пере)запуска Web-контейнера Tomcat. Этот процесс описан с помощью скриптового языка Apache Ant.

Листинг 1. Пример запуска Web-контейнера Tomcat
<available file="@{tomcat.home}/server/@{tomcat.server.name}/bin" 
   property="tomcat.bin.exists"/>
<if>
  <isset property="tomcat.bin.exists"/>
<then>
  <echo 
    message="Starting tomcat instance at @{tomcat.home} with start_tomcat" />
  <exec 
    executable="@{tomcat.home}/server/@{tomcat.server.name}/bin/start_tomcat"
    osfamily="unix" />
</then>
<else>
  <echo 
    message="Starting tomcat instance at @{tomcat.home} with startup.sh" />
  <exec osfamily="unix" executable="chmod" spawn="true">
    <arg value="+x" />
    <arg file="@{tomcat.home}/bin/startup.sh" />
    <arg file="@{tomcat.home}/bin/shutdown.sh" />
  </exec>

  <exec executable="sh" osfamily="unix" dir="@{tomcat.home}/bin" spawn="true">
    <env key="NOPAUSE" value="true" />
    <arg line="startup.sh" />
  </exec>

    <exec osfamily="windows" executable="cmd" 
          dir="@{tomcat.home}/bin" spawn="true" >
      <env key="NOPAUSE" value="true" />
        <arg line="/c startup.bat" />
    </exec>
    <sleep seconds="15" />
    </else>
  </if>

Написав скрипт для этого процесса, вы исключите использование административной GUI-консоли, предоставляемой Tomcat. Более того, такой скрипт может использовать какая-либо программа в качестве части автоматизированного процесса развертывания.

Запуск развертывания одной командой

Имя: Одна команда (Single Command)

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

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

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

Пример запуска развертывания одной командой приведен в листинге 2.

Листинг 2. Развертывание одной командой с использованием Ant
ant -Dproperties.file=$USERHOME/projects/petstore/properties/dev-install.properties \
  deploy:remote:install

Команда из листинга 2 исполняет Ant-задачу deploy:remote:install, передавая ей файл .properties, чтобы удаленно развернуть ПО на других машинах. Эта задача выполняет такие действия как безопасное копирование файлов с использованием протокола Secure Copy (SCP); безопасно исполняет команды на удаленных машинах с помощью Secure Shell (SSH); устанавливает, конфигурирует и запускает Web-контейнеры; запускает другие процессы – без человеческого вмешательства. Очевидно, команду может ввести пользователь, но, благодаря ее краткости, это легко может сделать и какой-нибудь процесс, например, Continuous Integration или сервер управления сборкой.

Вставка переменной информации в конфигурационные файлы

Имя: Разметка конфигураций (Tokenize Configuration)

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

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

Листинг 3 – это XML-файл для управления конфигурацией Web-контейнера и сервера БД. В этом файле я разместил заглушки, обозначенные знаком @. В процессе автоматизированного развертывания скрипт заменит эти заглушки реальными значениями из внешних файлов.

Listing 3. Tokenized Web-container configuration file
<datasources>
  <local-tx-datasource>
    <jndi-name>@application.context.name@</jndi-name>
    <use-java-context>false</use-java-context>
    <connection-url>@database.url@</connection-url>
    <user-name>@database.user@</user-name>
    <password>@database.password@</password>
    <driver-class>@database.driver@</driver-class>
  </local-tx-datasource>
</datasources>

Вынос всех свойств, специфичных для окружения

Имя: Вынос конфигурации (Externalize Configuration)

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

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

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

Листинг 4. Пример свойств, внешних для файлов конфигурации приложения
authentication.type=db
application.url=http://${tomcat.server.hostname}:${tomcat.server.port}/brewery-webapp
database.type=mysql
database.server=localhost
database.port=3306
database.name=mydb
database.user=myuser!
database.password=mypa$$!
database.url=jdbc:mysql://${database.server}:${database.port}/${database.name}
tomcat.server.hostname=localhost
tomcat.server.name=default
tomcat.web.password=pa$$123!
tomcat.cobraorb.port=12748

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

Исполнение без человеческого участия

Имя: Исполнение без человеческого участия (Headless Execution)

Паттерн: безопасное взаимодействие со множественными машинами без ручного ввода команд.

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

Исполнение без человеческого участия – это вполне эффективное решение, если нужно удаленно обращаться к нескольким машинам. Используя инфраструктуру с открытым ключом (public key infrastructure, PKI), вы можете организовывать различные команды в автоматизированное решение. На рисунке 2 файл с закрытым ключом устанавливается на машине сборки и SSH. Специфичные значения указываются в файлах .properties. Эти значения, как правило, включают имя и путь к файлу с закрытым ключом, номер порта SSH и имя хоста. Целевые машины содержат открытый SSH-ключ для завершения SSH-рукопожатия (SSH handshake).


Рисунок 2. Использование SSH-ключей для реализации паттерна «Исполнение без человеческого участия».

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

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

Имя: Шаблонов-верификатор (Template Verifier)

Паттерн: Создание одного файла-шаблона, на котором основываются все свойства целевого окружения.

Антипаттерн: использование ручной проверки.

Проблема состоит в том, что вы должны убедиться в том, что в каждом целевом окружении получаете точно те же самые атрибуты. Но как проверить это при автоматизированном исполнении? Используя единый файл-шаблон .properties, с которым сравниваются все файлы целевых окружений, вы можете убедиться, что все атрибуты совпадают, независимо от того, с какой средой вы работаете. На рисунке 3 скрипт сборки исполняет Ant-задачу, котрая сравнивает атрибуты (а не их значения) в template.properties и .properties-файле окружения (dev.properties, qa.properties и т.д.). Если обнаруживаются различия, развертывание останавливается.

В листинге 5 показан пример файла template.properties. Заметьте, что он содержит только атрибуты, поскольку значения в данном случае несущественны.

Листинг 5. Файл-шаблон, содержащий атрибуты, но не значения.
db.database=
db.username=
db.password=
db.hostname=
db.driver=
db.port=
db.url=


Рисунок 3. Реализация паттерна Шаблон-верификатор.

В листинге 6 приведен отрывок из файла dev.properties (или qa.properties, или еще какого-то). Заметьте, что он включает и атрибуты, и значения. Эти значения специфичны для целевого окружения.

Листинг 6. Файл .properties целевого окружения
db.database=brewery
db.username=root
db.password=p@ssword
db.hostname=dev1.domain.com
db.driver=com.mysql.jdbc.Driver
db.port=3306
db.url=jdbc:mysql://${db.hostname}:${db.port}/${db.database}

Развертывание в разных целевых окружениях

Имя: Унифицированное развертывание (Unified Deployment)

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

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


Рисунок 4. Скрипт развертывания, работающий в разных окружениях.

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

Рисунок 4 описывает единый скрипт развертывания, способный работать в различных целевых окружениях.

Это еще не все!

Развертывание - это еще один аспект создания программного обеспечения, хорошо поддающийся автоматизации. Автоматизированному развертыванию присущи все достоинства надежного, повторяемого процесса: высокая точность, скорость и управляемость. В этой статье я рассмотрел восемь паттернов, которые могут быть эффективны при автоматизации развертывания ПО. Во второй части будут рассмотрены еще несколько паттернов, включая Удаленное развертывание (Remote Deployment), Одноразовые контейнеры (Disposable Containers), Тест развертывания (Deployment Test) и Откат среды (Environment Rollback).

Ресурсы


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

Copyright © 1994-2016 ООО "К-Пресс"