В этой статье я хотел бы рассказать про то, как мы используем Puppet и Hiera для конфигурирования железных и виртуальных серверов. В основном, в ней будет идти речь об архитектуре и придуманной нами иерархии, облегчающей и систематизирующей конфигурацию серверов.
Написать эту статью меня побудило то, что в интернете я особо не находил хороших, реально рабочих примеров того, как можно работать с hiera и для чего она нужна. В основном, это туториалы с примерами для того, чтобы въехать в тему. Но реальное практическое применение hiera там не написано. Возможно, я плохо искал, но вот вам реальный пример, который, возможно, вам поможет расставить все точки над i, как и мне когда-то.
Для кого была бы полезна данная статья
Если:
- Вы знаете, что такое Puppet и Hiera, но особо не использует их в связке, потому что непонятно, как это делать и зачем
- У вас в компании есть множество команд и вам надо как-то разграничивать конфигурацию серверов на уровне команд
- Вы используете паппет, и нодные файлы у вас разрослись до неимоверных размеров
- Вам нравится читать конфигурацию серверов в божественном yaml формате :)
- Вы в принципе интересуетесь темой Configuration Management и системным администрированием
Эта статья для вас.
Прежде, чем начать
Предупрежу сразу, статья получилась длинной, но, я надеюсь, полезной. Кроме того, подразумевается, что у вас уже подключена hiera в puppet, и вы хоть как-то, но знакомы с puppet. Если hiera не подключена, это не сложно сделать.
- Подробнее о том, что такое Puppet, можно почитать тут: Puppet for beginners.
- Как работает Hiera — Introducing in Hiera.
Вводные данные
- У нас в SEMrush есть около 30 команд разработки, каждая из которых имеет свои сервера
- Каждая команда работает со своим набором технологий (ЯП, СУБД и т.д.)
- Команды могут и должны (в идеале) использовать общую конфигурацию для каких-то конкретных проектов (code reuse)
- Команды сами управляют деплоем приложений на свои сервера (это делается не через паппет)
Немного истории
Изначально у нас все было в паппете версии 3, потом решили внедрить 4-й паппет, и все новые сервера начали размещать в нем, а старые потихоньку портировать в 4й.
В третьем паппете у нас раньше использовалась классическая система нодных файлов и модулей. Модули создавали в специальной группе проектов в Gitlab, клонировали их на паппет-сервер (с помощью r10k), дальше паппет агенты приходили к мастеру и получали каталог, чтобы применить его на сервере.
Потом начали стараться так не делать и не использовать локальные модули, а помещать ссылки на нужные модули и их репозитории в Puppetfile. Почему? Потому что те модули постоянно поддерживаются и улучшаются (ну, в идеале) сообществом и разработчиками, а наши локальные — нет. Позже внедрили hiera и перешли полностью на нее, а нодные файлы (типа nodes.pp) канули в лету.
В четвертом паппете мы постарались полностью отказаться от локальных модулей и использовать только remote модули. К сожалению, тут снова следует вставить оговорку, так как “полностью” не получилось, иногда все равно приходится что-то склонировать и доделать самим. Конечно, здесь только hiera и никаких нодных файлов.
Когда у вас 30 команд с зоопарком технологий, проблема того, как содержать этот зверинец с >1000 серверов становится особенно остро. Дальше я расскажу, как в этом нам помогает hiera.
Иерархия
У hiera (собственно, от чего она и получила свое название) настраивается иерархия. У нас она выглядит следующим образом:
---
:hierarchy:
- "nodes/%{::fqdn}"
- "teams/%{::team}_team/nodes/%{::fqdn}"
- "teams/%{::team}_team/projects/%{::project}/tiers/%{::tier}"
- "teams/%{::team}_team/projects/%{::project}/%{::role}"
- "teams/%{::team}_team/projects/%{::project}"
- "teams/%{::team}_team/roles/%{::role}"
- "teams/%{::team}_team/%{::team}"
- "projects/%{::project}/tiers/%{::tier}/%{::role}"
- "projects/%{::project}/tiers/%{::tier}"
- "projects/%{::project}/%{::role}"
- "projects/%{::project}"
- "tiers/%{::tier}"
- "virtual/%{::virtual}"
- "os/%{::operatingsystem}/%{::operatingsystemmajrelease}"
- "os/%{::operatingsystem}"
- users
- common
Сначала разберемся с непонятными переменными (фактами).
Каждый сервер в SEMrush в идеале должен иметь 4 выставленных, специальных факта, описывающих его принадлежность:
- факт
team
— к какой команде он относится - факт
project
— к какому проекту он относится - факт
role
— какую роль в этом проекте имеет - факт
tier
— какой у него стейджинг (prod, test, dev)
Как это работает? Паппет агент приходит к паппет мастеру и на основе данных фактов ищет файлы для себя, проходясь по папкам в соответствии с нашей иерархией. Не нужно указывать принадлежность конфигурационых файлов к серверам. Вместо этого сервера сами знают, какие файлы относятся к ним, смотря только лишь на их путь и свои факты.
При сетапе сервера админы связываются с разработчиками и уточняют данные параметры (часто даже наоборот, знающие люди сами связываются с админами), чтобы в дальнейшем построить иерархию в hiera, на основе которой потом описать конфигурацию сервера. Такая система помогает повторно использовать код и быть более гибким в плане конфигурации серверов.
Например, есть у нас проект special. В этом проекте может быть какой-то фронтенд-сервер с nginx, backend-сервер с python, db-кластер с mysql, redis-сервера для кэширования. Все эти сервера следует поместить в один проект под названием special, а дальше назначать серверам роли.
В проектном файле мы описываем общие для всего проекта параметры. Первое, что приходит на ум, это создание на всех серверах пользователя для деплоя с выдачей ему нужных прав и раскаткой его ssh-ключей.
В роли для каждого сервера обычно описывается и кастомизируется конкретно сервис — для чего данный сервер предназначен (nginx, python, mysql и т.д.) Tier в данном случае нам обязательно понадобится, если нам также нужно разворачивать копию продакшн окружения на dev-площадке, но что-то в ней изменить (пароли, например). В таком случае, dev-сервера и prod-сервера будут лишь отличаться выставленным фактом tier в нужное “положение” (prod или dev). А дальше немного магии и hiera сделает свое дело.
Если же нам нужно развернуть два идентичных сервера в одинаковой роли, но что-то в них должно отличаться, например, какие-то строки в конфигурации, то на помощь придет другая часть иерархии. Помещаем файлы с названием формата {fqdn сервера}.yaml
в нужное место (например, nodes/myserver.domain.net
), выставляем нужные значения переменных на уровне конкретного сервера, и паппет применит на оба сервера одинаковую конфигурацию для роли, и уникальную для каждого из серверов.
Пример: два бэкэнда с php-кодом находятся в одной роли и полностью идентичные. Понятно, что мы не хотим бэкапить оба сервера — нет смысла. Мы можем создать роль, в которой описать одинаковую конфигурацию для обоих серверов, а потом создать еще файл nodes/backend1.semrush.net
, в который поместить конфигурацию для бэкапа.
В командном файле teams/team-name.yaml
указывается конфигурация для всех серверов, принадлежащих команде. Чаще всего там описываются пользователи, которые могут взаимодействовать с этими серверами, а также их права доступа.
На основе этих переменных у нас построена данная иерархия. Чем выше найденный файл по иерархии, тем выше приоритет конфигурации, указанной в нем.
Отсюда следует, что переменные могут оверрайдиться исходя из данной иерархии. То есть переменная в файле роли "projects/%{::project}/%{::role}
" имеет больший приоритет, чем переменная в файле проекта "projects/%{::project}
". Также переменные могут мерджиться на всех уровнях иерархии, если у вас модуль и/или профиль/роль написаны так, что позволяют это делать. Указав общую часть конфига mysql для всех серверов проекта, можно добавить в ту же переменную на других уровнях иерархии специальные части, имеющие вес для данной роли (для слейва будет дополнительная секция в конфиге).
Получается, самый высокий приоритет имеет файл конкретной ноды, расположенный по пути — "hieradata/nodes/%{::fqdn}
". Дальше следует файл ноды, но уже на уровне команды. Ниже всего находится блок, описывающий другие, более общие факты:
- "virtual/%{::virtual}"
- "os/%{::operatingsystem}/%{::operatingsystemmajrelease}"
- "os/%{::operatingsystem}"
- users
- common
Соответственно, в файле common.yaml
у нас содержится конфигурация, которая точно должна приезжать на все сервера, в файле users.yaml
описаны все юзеры (но не все они создаются на серверах, конечно же), в os/%{::operatingsystem}
общая конфигурация, свойственная серверам с определенной ОС (используется факт ::operatingsystem
) и так далее.
Думаю, взглянув на данную иерархию, становится все понятно. Ниже я рассмотрю пример использования такой иерархии. Но сначала следует рассказать о профилях.
Профили
Важным моментом в конфигурировании серверов с помощью модулей является использование профилей. Они располагаются по пути site/profiles
и являются точками входа в модули. Благодаря им можно более тонко настраивать навешиваемые модули на сервера и создавать нужные ресурсы.
Рассмотрим простой пример. Есть модуль, устанавливающий и настраивающий redis. И мы хотим также при подключении данного модуля установить sysctl параметр vm.overcommit_memory
в значение 1, потому что вот. Тогда пишем небольшой профиль, обеспечивающий этот функционал:
# standalone redis server
class profiles::db::redis (
Hash $config = {},
String $output_buffer_limit_slave = '256mb 64mb 60',
) {
# https://redis.io/topics/faq#background-saving-fails-with-a-fork-error-under-linux-even-if-i-have-a-lot-of-free-ram
sysctl { 'vm.overcommit_memory':
ensure => present,
value => '1',
}
class { '::redis':
* => $config,
}
}
Как было сказано выше, профили являются инструментом, позволяющим менять/улучшать поведение модуля, а также уменьшать количество конфигурации в hiera. Если вы используете удаленные модули, то часто можете столкнуться с проблемой, что "одобренные" модули часто не обладают нужным вам функционалом, или имеют какие-то баги/недоработки. Тогда в принципе можно склонировать этот модуль и поправить/добавить функционал. Но правильным решением будет, если это возможно, написать хороший профиль, который способен “приготовить” модуль нужным вам образом. Ниже будут представлены несколько примеров профилей, и можно будет лучше понять, для чего они нужны.
Сокрытие секретов в hiera
Одним из важных преимуществ hiera по сравнению с “голым” паппетом является ее способность хранить sensitive data в конфигурационных файлах в зашифрованном виде в репозитории. Ваши пароли будут в безопасности.
Вкратце, вы с помощью публичного ключа шифруете нужную информацию и помещаете ее такой строкой в файл hiera. На паппет мастере хранится приватная часть ключа, которая позволяет эти данные дешифровать. Более подробно с этим можно ознакомиться на странице проекта.
На клиенте (рабочем компьютере) тулза ставится просто, можно через gem install hiera-eyaml
. Дальше с помощью команды вида eyaml encrypt --pkcs7-public-key=/path/to/public_key.pkcs7.pem -s 'hello'
можно шифровать данные и вставлять в файл с расширением eyaml или просто yaml в зависимости от того, как вы настроите, а дальше паппет сам разберется. Получится что-то вроде:
roles::postrgresql::password: 'ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAbIz1ihQlThMWa9T+Lq194Y6QdElMD1XTev5y+VPSHtkPTu6Al6TJaSrXF+7phJIjue+NF4ZVtJCLkHxUR6nJJqks0fcGS1vF2+6mmM9cy69sIU1A3HqpOHZLuqHAc7jUqljYxpwWSIGOK6I2FygdAp5FfOTewqfcVVmXj97EJdcv3DKrbAlSrIMO2iZRYwQvyv+qnptnZ7pilR2veOCPW2UMm6zagDLutX9Ft5vERbdaiCiEfTOpVa9Qx0GqveNRVJLV/5lfcL5ajdNBJXkvKqDbx8d3ZBtEVAAqeKlw0LqzScgmCbWQx2kUzukX5LSxbTpT0Th984Vp1sl7iPk7UTA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCp5GcwidcEMA+0wjAMblkKgBCR/f9KGXUgLh3/Ok60OIT5]'
Или многострочной строкой:
roles::postgresql::password: >
ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQEw
DQYJKoZIhvcNAQEBBQAEggEAbIz1ihQlThMWa9T+Lq194Y6QdElMD1XTev5y
+VPSHtkPTu6Al6TJaSrXF+7phJIjue+NF4ZVtJCLkHxUR6nJJqks0fcGS1vF
2+6mmM9cy69sIU1A3HqpOHZLuqHAc7jUqljYxpwWSIGOK6I2FygdAp5FfOTe
wqfcVVmXj97EJdcv3DKrbAlSrIMO2iZRYwQvyv+qnptnZ7pilR2veOCPW2UM
m6zagDLutX9Ft5vERbdaiCiEfTOpVa9Qx0GqveNRVJLV/5lfcL5ajdNBJXkv
KqDbx8d3ZBtEVAAqeKlw0LqzScgmCbWQx2kUzukX5LSxbTpT0Th984Vp1sl7
iPk7UTA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCp5GcwidcEMA+0wjAM
blkKgBCR/f9KGXUgLh3/Ok60OIT5]
Кажется, с подготовкой закончили, теперь можно рассмотреть пример.
Пример на пальцах
Спойлер: дальше будет много конфигураций, так что тем, кому эта статья представляла чисто теоретический интерес, можно пропускать этот раздел и переходить в конец.
Давайте теперь рассмотрим пример, как можно конфигурировать сервера с помощью hiera в puppet4. Я не буду публиковать код всех профилей, потому что иначе пост получится довольно больших размеров. Основной акцент я сделаю на иерархии и конфигурации hiera.
Задача такая: нам нужно развернуть:
- Два идентичных бд-сервера, на которых развернут postgresql
- Еще два сервера — frontend с nginx
- Пятый и шестой сервера — бэкэнды на python в докере
- Все то же самое и на dev-окружении, за исключением некоторой конфигурации серверов
Будем создавать нашу иерархию по порядку и начнем мы с проектного файла.
Проект
Создаем файл проекта projects/kicker.yaml
. Поместим в него то, что общее у всех серверов: нам нужны некоторые репозитории и папки для деплоя, а также сам пользователь deploy.
---
classes:
- apt::debian::semrush
files:
"/srv/data":
ensure: 'directory'
owner: 'deploy'
group: 'www-data'
mode: '0755'
'/srv/data/shared_temp':
ensure: 'directory'
owner: 'deploy'
group: 'www-data'
mode: '0775'
user_management::present:
- deploy
Роль db
Создаем файл роли для БД-серверов projects/kicker/db.yaml
. Пока что обойдемся без разделения серверов на окружения:
---
classes:
- profiles::db::postgresql
profiles::db::postgresql::globals:
manage_package_repo: true
version: '10'
profiles::db::postgresql::db_configs:
'listen_addresses':
value: '*'
profiles::db::postgresql::databases:
kicker: {}
profiles::db::postgresql::hba_rules:
'local connect to kicker':
type: 'local'
database: 'kicker'
user: 'kicker'
auth_method: 'md5'
order: '001'
'allow connect from 192.168.1.100':
type: 'host'
database: 'kicker'
user: 'kicker'
auth_method: 'md5'
address: '192.168.1.100/32'
order: '002'
Здесь мы подключаем один профиль, написанный для общего использования всеми, кто захочет установить postgres себе на сервера. Профиль конфигурируем и позволяет гибко настроить модуль перед его применением.
Для самых любопытных ниже под катом код этого профиля:
class profiles::db::postgresql (
Hash $globals = {},
Hash $params = {},
Hash $recovery = {},
Hash[String, Hash[String, Variant[String, Boolean, Integer]]] $roles = {},
Hash[String, Hash[String, Variant[String, Boolean]]] $db_configs = {},
Hash[String, Hash[String, Variant[String, Boolean]]] $databases = {},
Hash[String, String] $db_grants = {},
Hash[String, Hash[String, String]] $extensions = {},
Hash[String, String] $table_grants = {},
Hash[String, Hash[String, String]] $hba_rules = {},
Hash[String, String] $indent_rules = {},
Optional[String] $role = undef, # 'master', 'slave'
Optional[String] $master_host = undef,
Optional[String] $replication_password = undef,
Integer $master_port = 5432,
String $replication_user = 'repl',
String $trigger_file = '/tmp/pg_trigger.file',
){
case $role {
'slave': {
$_params = {
manage_recovery_conf => true,
}
if $globals['datadir'] {
file { "${globals['datadir']}/recovery.done":
ensure => absent,
}
}
$_recovery = {
'recovery config' => {
standby_mode => 'on',
primary_conninfo => "host=${master_host} port=${master_port} user=${replication_user} password=${replication_password}",
trigger_file => $trigger_file,
}
}
$_conf = {
'hot_standby' => {
value => 'on',
},
}
file { $trigger_file:
ensure => absent,
}
}
'master': {
$_conf = {
'wal_level' => {
value => 'replica',
},
'max_wal_senders' => {
value => 5,
},
'wal_keep_segments' => {
value => 32,
},
}
file { $trigger_file:
ensure => present,
}
}
default: {
$_params = {}
$_recovery = {}
$_conf = {}
}
}
class { '::postgresql::globals':
* => $globals,
}
class { '::postgresql::server':
* => deep_merge($_params, $params),
}
create_resources('::postgresql::server::config_entry', deep_merge($_conf, $db_configs))
create_resources('::postgresql::server::role', $roles)
create_resources('::postgresql::server::database', $databases)
create_resources('::postgresql::server::database_grant', $db_grants)
create_resources('::postgresql::server::extension', $extensions)
create_resources('::postgresql::server::table_grant', $table_grants)
create_resources('::postgresql::server::pg_hba_rule', $hba_rules)
create_resources('::postgresql::server::pg_indent_rule', $indent_rules)
create_resources('::postgresql::server::recovery', deep_merge($_recovery, $recovery))
}
Таким образом, мы одним махом устанавливаем Postgresql 10
, настраиваем конфиг (listen
), создаем БД kicker
, а также записываем в pg_hba.conf
два правила для доступа к этой базе. Круто!
Роль frontend
Беремся за frontend
. Создаем файл projects/kicker/frontend.yaml
следующего содержания:
---
classes:
- profiles::webserver::nginx
profiles::webserver::nginx::servers:
'kicker.semrush.com':
use_default_location: false
listen_port: 80
server_name:
- 'kicker.semrush.com'
profiles::webserver::nginx::locations:
'kicker-root':
location: '/'
server: 'kicker.semrush.com'
proxy: 'http://kicker-backend.semrush.com:8080'
proxy_set_header:
- 'X-Real-IP $remote_addr'
- 'X-Forwarded-for $remote_addr'
- 'Host kicker.semrush.com'
location_cfg_append:
'proxy_next_upstream': 'error timeout invalid_header http_500 http_502 http_503 http_504'
proxy_connect_timeout: '5'
Здесь все просто. Мы подключаем профиль profiles::webserver::nginx
, который подготавливает вход в модуль nginx, а также определяем переменные, а конкретно server
и location
для этого сайта.
Внимательный читатель заметит, что правильнее будет поместить описание сайта выше по иерархии, ведь у нас будет еще dev-окружение, и там будут использоваться другие переменные (server_name
, proxy
), но это не слишком важно. Описывая роль таким образом, мы сможем увидеть, как переопределяются эти переменные только лишь иерархией.
Роль docker
Осталась роль docker
projects/kicker/docker.yaml
:
---
classes:
- profiles::docker
profiles::docker::params:
version: '17.05.0~ce-0~debian-stretch'
packages:
'python3-pip':
provider: apt
'Fabric3':
provider: pip3
ensure: 1.12.post1
user_management::users:
deploy:
groups:
- docker
Профиль profiles/docker.pp
очень прост и изящен. Приведу его код:
class profiles::docker (
Hash $params = {},
Boolean $install_kernel = false,
){
class { 'docker':
* => $params,
}
if ($install_kernel) {
include profiles::docker::kernel
}
}
Все готово. Этого уже достаточно, чтобы развернуть нужный нам продукт на множестве серверов, просто назначив им определенные проект и роль (например, положив файлик в нужном формате в директорию facts.d, местоположение которой зависит от способа установки puppet).
Сейчас мы имеем следующую структуру файлов:
.
├── kicker
│ ├── db.yaml
│ ├── docker.yaml
│ └── frontend.yaml
└── kicker.yaml
1 directory, 4 files
Разберемся теперь с окружениями и определением конфигурации, уникальной для роли на конкретной площадке.
Окружения и override
Создадим общую конфигурацию для всего прода. Файл projects/kicker/tiers/prod.yaml
содержит указание, что нам нужно подключить класс с файрволом на это окружение (ну, прод же все-таки), а также некий класс, обеспечивающий повышенный уровень безопасности:
---
classes:
- semrush_firewall
- strict_security_level
Для dev-окружения, если нам нужно описать что-то специфичное, создается такой же файл, и в него вносится нужная конфигурация.
Далее нужно все-таки переопределить переменные для nginx-конфига роли frontend
в dev-окружении. Для этого понадобится создать файл projects/kicker/tiers/dev/frontend.yaml
. Обратите внимание на новый уровень иерархии.
---
profiles::webserver::nginx::servers:
'kicker-dev.semrush.com':
use_default_location: false
listen_port: 80
server_name:
- 'kicker-dev.semrush.com'
profiles::webserver::nginx::locations:
'kicker-root':
location: '/'
server: ‘kicker-dev.semrush.com'
proxy: 'http://kicker-backend-dev.semrush.com:8080'
proxy_set_header:
- 'X-Real-IP $remote_addr'
- 'X-Forwarded-for $remote_addr'
- 'Host kicker-dev.semrush.com'
location_cfg_append:
'proxy_next_upstream': 'error timeout invalid_header http_500 http_502 http_503 http_504'
proxy_connect_timeout: '5'
Класс указывать уже не надо, он наследуется с предыдущих уровней иерархии. Здесь мы изменили server_name
и proxy_pass
. Сервер, у которого будут факты role=frontend и tier=dev, сначала найдет для себя файл projects/kicker/frontend.yaml
, но потом переменные из этого файла будут переопределены файлом с бОльшим приоритетом projects/kicker/tiers/dev/frontend.yaml
.
Сокрытие пароля для PostgreSQL
И таким образом у нас остается последний пункт на повестке дня — это задать пароли для PostgreSQL.
Пароли должны различаться в окружениях. Будем использовать eyaml для безопасного хранения паролей. Создадим пароли:
eyaml encrypt -s 'verysecretpassword'
eyaml encrypt -s 'testpassword'
Вставляем полученные строки в файлы **projects/kicker/tiers/prod/db.yaml**
и **projects/kicker/tiers/dev/db.yaml**
(или можно использовать расширение eyaml, это настраиваемо) соответственно. Вот пример:
---
profiles::db::postgresql::roles:
'kicker':
password_hash: > 'ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAsdpb2P0axUJzyWr2duRKAjh0WooGYUmoQ5gw0nO9Ym5ftv6uZXv25DRMKh7vsbzrrOR5/lLesx/pAVmcs2qbhd/y0Vr1oc2ohHlZBBKtCSEYwem5VN+kTMhWPvlt93x/S9ERoBp8LrrsIvicSYZByNfpS2DXCFbogSXCfEPxTTmCOtlOnxdjidIc9Q1vfAXv7FRQanYIspr2UytScm56H/ueeAc/8RYK51/nXDMtdPOiAP5VARioUKyTDSk8FqNvdUZRqA3cl+hA+xD5PiBHn5T09pnH8HyE/39q09gE0pXRe5+mOnU/4qfqFPc/EvAgAq5mVawlCR6c/cCKln5wJTA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBDNKijGHBLPCth0sfwAjfl/gBAaPsfvzZQ/Umgjy1n+im0s]'
Далее пароль для роли kicker
приедет, расшифруется и применится на БД-сервере в PostgreSQL.
На этом, собственно, и все. Да, пример получился массивным, но, надеюсь, функциональным, не оставляющим вопросов, понятным и полезным. Итоговая иерархия в hiera получилась такая:
.
├── db.yaml
├── docker.yaml
├── frontend.yaml
└── tiers
├── dev
│ ├── db.yaml
│ └── frontend.yaml
├── prod
│ └── db.yaml
└── prod.yaml
3 directories, 7 files
Вы можете посмотреть эти файлы "вживую", склонировав специально созданный репозиторий
Заключение
Puppet хорош и удобен в связке с hiera. Я бы не назвал его идеальным инструментом конфигурации в современном мире, вовсе нет, но он заслуживает внимания. С некоторыми задачами он справляется очень хорошо, а его “философия” поддержки постоянно одинакового состояния ресурсов и конфигурации может играть немаловажную роль в обеспечении безопасности и единообразия конфигураций.
Современный мир постепенно синергирует и развивается. Мало кто сейчас использует только одну систему конфигурации, часто в арсенале девопсов и админов сразу несколько систем. И это хорошо, так как есть из чего выбрать. Главное, чтобы все было логично и понятно, как и где это можно сконфигурировать.
Наша цель как админов в итоге — ничего не конфигурировать самим. Все это в идеале должны делать сами команды. А мы им должны дать инструмент или продукт, позволяющий это делать безопасно, легко и, главное, с точным результатом. Ну, и помогать решать архитектурные и более серьезные задачи, чем "Нужно установить PostgreSQL на сервер и создать пользователя". Камон, 2018-й год на дворе! Поэтому выкидывайте puppet и ansible и двигайтесь в serverless future.
C развитием облаков, контейнеризации и систем оркестраций контейнеров, системы управления конфигураций потихоньку отступают и отходят на задний план для пользователей и клиентов. Можно же в облаке поднять отказоустойчивый кластер контейнеров и держать свои приложения в контейнерах с авто-скелингом, бэкапированием, реплицированием, авто-дискавери и т.д, не написав ни строчки для ansible, puppet, chef etc. Ни о чем заботиться не надо (ну почти). С другой стороны, железных серверов из-за облаков меньше не стало. Просто вам их больше не нужно конфигурировать, это действие находится в ответственности облачного провайдера. Но вряд ли они пользуются теми же системами, что и простые смертные.
Credits
Спасибо:
- Дмитрию Тупицину, Дмитрию Логинову, Степану Федорову и всей команде системных администраторов за помощь в подготовке этой статьи
- Владимиру Легкоступову за картинку
- Яне Табаковой за организацию этого всего и помощь в прохождении всех pre-publishing этапов
- Никите Захарову за помощь в делах лицензирования
Автор: nikitashalnov