В итоге обе команды, Dev и Ops, в основном занимаются работой с ПО, и граница между ними постепенно размывается. Возможно, наличие отдельных команд, отвечающих за прикладной и инфраструктурный код, все еще имеет смысл, но уже сейчас очевидно, что обе они должны работать вместе более тесно. Вот где берет начало движение DevOps.
DevOps не название команды, должности или какой-то определенной технологии. Это набор процессов, идей и методик. Каждый понимает под DevOps что-то свое, но в этой книге я буду использовать следующее определение: цель DevOps — значительно повысить эффективность доставки ПО.
Вместо многодневного кошмара со слиянием веток вы постоянно интегрируете свой код, поддерживая его в развертываемом состоянии. Вместо ежемесячных развертываний вы можете доставлять свой код десятки раз в день или даже после каждой фиксации. Вместо того чтобы иметь дело с постоянными простоями и перебоями в работе, вы сможете создавать устойчивые системы с автоматическим восстановлением, используя мониторинг и оповещения для обнаружения проблем, которые требуют ручного вмешательства.
Компании, прошедшие через подобные трансформации, показывают изумительные результаты. Например, после применения в своей организации методик DevOps компания Nordstrom сумела удвоить количество выпускаемых ежемесячно функций, уменьшить число дефектов на 50 %, сократить сроки реализации идей в промышленных условиях на 60 % и снизить частоту сбоев в процессе эксплуатации ПО на 60–90 %. После того как в подразделении LaserJet Firmware компании HP стали использовать методики DevOps, доля времени, затрачиваемого на разработку новых возможностей, увеличилась с 5 до 40 %, а общая стоимость разработки была снижена на 40 %. До внедрения DevOps доставка кода в компании Etsy была нечастым процессом, сопряженным со стрессом и многочисленными перебоями в работе. Теперь развертывания выполняются по 25–50 раз в день с куда меньшим количеством проблем3.
Движение DevOps основано на четырех принципах: культуре, автоматизации, измерении и разделении (в англ. языке иногда используется аббревиатура CASM (http://bit.ly/2GS3CR3) — culture, automation, sharing, measurement). Эта книга не задумывалась как комплексный обзор DevOps (рекомендуемая литература приводится в приложении), поэтому сосредоточусь лишь на одном из указанных принципов: автоматизации.
Наша задача — автоматизировать как можно больше аспектов процесса доставки программного обеспечения. Это означает, что вы будете управлять своей инфраструктурой через код, а не с помощью веб-страницы или путем ввода консольных команд. Такую концепцию обычно называют «инфраструктура как код» (infrastructure as code, или IaC).
Что такое инфраструктура как код
Идея, стоящая за IaC, заключается в том, что для определения, развертывания, обновления и удаления инфраструктуры нужно писать и выполнять код. Это важный сдвиг в образе мышления, когда все аспекты системного администрирования воспринимаются как программное обеспечение — даже те, которые представляют оборудование (например, настройка физических серверов). Ключевым аспектом DevOps является то, что почти всем можно управлять внутри кода, включая серверы, базы данных, сети, журнальные файлы, программную конфигурацию, документацию, автоматические тесты, процессы развертывания и т. д.
Инструменты IaC можно разделить на пять общих категорий:
• специализированные скрипты;
• средства управления конфигурацией;
• средства шаблонизации серверов;
• средства оркестрации;
• средства инициализации ресурсов.
Рассмотрим каждую из них.
Специализированные скрипты
Самый простой и понятный способ что-либо автоматизировать — написать для этого специальный скрипт. Вы берете задачу, которая выполняется вручную, разбиваете ее на отдельные шаги, описываете каждый шаг в виде кода, используя любимый скриптовый язык, и выполняете получившийся скрипт на своем сервере, как показано на рис. 1.1.
Рис. 1.1. Выполнение специализированного скрипта на сервере
Например, ниже показан bash-скрипт setup-webserver.sh, который конфигурирует веб-сервер, устанавливая зависимости, загружая код из Git-репозитория и запуская Apache:
# Обновляем кэш apt-get
sudo apt-get update
# Устанавливаем PHP и Apache
sudo apt-get install -y php apache2
# Копируем код из репозитория
sudo git clone https://github.com/brikis98/php-app.git /var/www/html/app
# Запускаем Apache
sudo service apache2 start
Крайне удобной особенностью специализированных скриптов (и их огромным недостатком) является то, что код можно писать как угодно и с использованием популярных языков программирования общего назначения.
Если инструменты, специально созданные для IaC, предоставляют лаконичный API для выполнения сложных задач, языки программирования общего назначения подразумевают написание своего кода в каждом отдельно взятом случае. Более того, средства IaC обычно навязывают определенную структуру кода, тогда как в специализированных скриптах каждый разработчик использует собственный стиль и делает вещи по-своему. Если речь идет о скрипте из восьми строк, который устанавливает Apache, обе проблемы можно считать незначительными, но, если вы попытаетесь применить тот же подход к управлению десятками серверов, базами данных, балансировщиками нагрузки и сетевой конфигурацией, все пойдет наперекосяк.
Если вам когда-либо приходилось поддерживать большой репозиторий bash-скриптов, вы знаете, что это почти всегда превращается в «кашу» из плохо структурированного кода. Специализированные скрипты отлично подходят для небольших одноразовых задач, но, если вы собираетесь управлять всей своей инфраструктурой в виде кода, следует использовать специально предназначенный для этого инструмент IaC.
Средства управления конфигурацией
Chef, Puppet, Ansible и SaltStack являются средствами управления конфигурацией. Это означает, что они предназначены для установки и администрирования программного обеспечения на существующих серверах. Например, ниже показана роль Ansible под названием web-server.yml, которая настраивает тот же веб-сервер Apache, что и скрипт setup-webserver.sh:
- name: Update the apt-get cache
apt:
update_cache: yes
- name: Install PHP
apt:
name: php
- name: Install Apache
apt:
name: apache2
- name: Copy the code from the repository
git: repo=https://github.com/brikis98/php-app.git dest=/var/www/html/app
- name: Start Apache
service: name=apache2 state=started enabled=yes
Этот код похож на bash-скрипт, но использование такого инструмента, как Ansible, дает ряд преимуществ.
•Стандартизированное оформление кода. Ansible требует, чтобы код имел предсказуемую структуру. Это касается документации, структуры файлов и каталогов, параметров с понятными именами, управления конфиденциальными данными и т. д. Если каждый разработчик организует свои специализированные скрипты по-разному, то большинство средств управления конфигурацией имеют набор правил и соглашений, которые упрощают навигацию по коду.
• Идемпотентность4. Написать рабочий специализированный скрипт не так уж и трудно. Намного сложнее написать скрипт, который будет работать корректно вне зависимости от того, сколько раз вы его запустите. Каждый раз, когда вы создаете в своем скрипте папку, нужно убедиться, что ее еще не существует. Всякий раз, когда вы добавляете строчку в конфигурационный файл, необходимо проверить, существует ли эта строчка. И всегда, когда вы хотите запустить программу, надо определить, выполняется ли она в данный момент.
Код, который работает корректно независимо от того, сколько раз вы его запускаете, называется идемпотентным. Чтобы сделать идемпотентным bash-скрипт из предыдущего раздела, придется добавить много строчек кода, включая уйму условных выражений. Для сравнения: большинство функций Ansible идемпотентно по умолчанию. Например, роль Ansible web-server.yaml установит сервер Apache только в случае, если он еще не установлен, и попытается его запустить лишь при условии, что он еще не выполняется.
• Распределенность. Специализированные скрипты предназначены для выполнения на одном локальном компьютере. Ansible и другие средства управления конфигурацией специально «заточены» под работу с большим количеством удаленных серверов, как показано на рис. 1.2.
Рис. 1.2. Такие средства управления конфигурацией, как Ansible, способны выполнять ваш код на большом количестве серверов
Например, чтобы применить роль web-server.yml к пяти серверам, нужно сначала создать файл под названием hosts, который содержит IP-адреса этих серверов:
[webservers]
11.11.11.11
11.11.11.12
11.11.11.13
11.11.11.14
11.11.11.15
Далее следует определить такой плейбук (playbook) Ansible:
- hosts: webservers
roles:
- webserver
И в конце этот плейбук выполняется:
ansible-playbook playbook.yml
Это заставит Ansible параллельно сконфигурировать все пять серверов. В качестве альтернативы в плейбуке можно указать параметр под названием serial. Это позволит выполнить скользящее развертывание, которое обновит серверы пакетным образом. Например, если присвоить serial значение 2, Ansible будет обновлять сразу по два сервера, пока не будут обновлены все пять. Дублирование любой части этой логики в специализированных скриптах потребовало бы написания десятков или даже сотен строчек кода.
Средства шаблонизации серверов
Альтернативой управлению конфигурацией, набирающей популярность в последнее время, являются средства шаблонизации серверов, такие как Docker, Packer и Vagrant. Вместо того чтобы вводить кучу серверов и настраивать их, запуская на каждом один и тот же код, средства шаблонизации создают