Моя давняя идея – это заиметь открытую инфрструктуру. Т.е. я хочу открыть всякие ansible, ci, скрипты и.т.д. Я даже к этому приблизился, но никак не находил времени, чтобы отрефакторить свою монорепу. По-этому идея так и осталась идеей. Но пост на самом деле не об этом.
Свою монорепу с инфраструктурным кодом, а именно роли Ansible и скрипты я начал лет так 10 назад. Потом в ней еще появился Terraform, а затем еще и Nomad. Короче, оно все не очень красивое было (и еще есть пока) и открыть все это я никак не мог. А тут очень удачно Hetzner сказал, что у меня паспорт не той страны и он убьет все мои серверы 29.02.2024. Сейчас уже, на момент написания поста, я перенес все данные в Selectel. Вчера были удалены все виртуалки, сети, балансеры, а железный сервер отправлен в ресетап с удалением всех данных. Понятно, что если надо, то данные достать будет можно, но мне кажется, что я не настолько кому-то нужен, чтобы таким заморачиваться. По пути были потяряны некоторые сервисы, вроде, ноды idec, но данные все живы, по-этому запуск их это всего лишь вопрос времени. Я на самом деле рад, что так все вышло с хетцнером, это был как раз тот стимул для того, чтобы задуматься о том, как я управляю инфраструктурой. А на тот момент инфраструктурой управлял во всю Nomad. Новый кластер Nomad в новом месте я не планировал вот совсем. Хотелось проще, чтобы меньше оверхеда по ресурсам было. И я выбрал Salt для того, чтобы перенести туда всё, кроме (скорее всего) terraform.
Salt подкупил тем, что он может управляться, как с контроллера (как в ansible), так и запускаться на самом агенте по таймеру. Похоже на то, как в Puppet. Но в Salt в отличии от Puppet – yaml и Jinja2, как в ansible, что подкупает. Ещё Salt написан на python3, очень сильно расширяем, умеет в Hashicorp Vault из коробки, имеет аналог hiera и кучу всего остального. Inventory в таком виде, как в Ansible, отсутствует. Но зато имеется Pillar, где можно хранить все необходимые данные. Salt Master кэширует это все дело и автоматически обновляет. Да, кстати, мастер так же следит и за основным кодом. Т.е. вместо одной монорепы, где лежит вообще всё, у меня появляется 3:
репа | описание |
---|---|
lessmore-salt | Код salt, можно воспринимать, как роль/плейбуку |
lessmore-pillar | Данные, похоже на groupvars/hostvars |
lessmore-tf | Код Terraform |
От CI было решено отказаться полностью. Раньше у меня был DroneCI, который дергал ansible по коммиту в master в монорепы.
Gitea отправляла вебхук в drone master, где тот пускал job на drone agent. Где уже тот в свою очередь поднимал контейнер с Ansible/Nomad и на основе сообщения коммита пускал либо
ansible-playbook --inventory inventory.yaml $PLAYBOOK
либо
nomad plan $JOB_PATH && nomad apply $JOB_PATH
Ничего необычного, в общем.
Вместо двух серверов Drone теперь есть один (HA буду делать позже и напишу про это) Salt master, который сам следит за актуальностью кода, а миньёны сами на себя применяют конфигурацию. Плюс к тому, т.к. я уехал из хетцнера на железо, куда поставил Proxmox, то я могу творить что угодно. Например, у меня собран шаблон с уже установленным salt minion, который смотрит на salt master. Виртуалка после создания сразу получает ip от dhcp сервера, который заодно обновляет зону в DNS сервере, который обслуживает локальную зону lessmore.local.
Вновь созданный сервер автоматически регистрируется в salt master и применяет на себя стейт. В top.sls есть формулы, которые применяются сразу на все сервера. Это common, который настраивает системные компоненты, устанавливает необходимые пакеты и тому подобное.
---
base:
'*':
- base.common
- base.logging
'web-service*':
- base.services
- base.firewall
В результате после создания виртуальной машины, через 10 минут уже получается полностью готовый сервер – очень удобно. Далее остается только коммитить нужную конфигурацию в git и она будет применяться автоматически. Например, этот блог тоже выкатывается salt. Вот так это выглядит.
blog repo:
git.latest:
- name: {{ pillar["git_clone_uri"] }}
- submodules: true
- target: /var/local/blog
- identity: /root/.ssh/id_ed25519
- require:
- file: /root/.ssh/id_ed25519
generate blog content:
cmd.wait:
- name: hugo --config config.yaml
- cwd: /var/local/blog
- watch:
- git: blog repo
- require:
- pkg: hugo package
copy content:
cmd.wait:
- name: "cp -r /var/local/blog/public/* /var/www/blog/"
- watch:
- cmd: generate blog content
- require:
- file: /var/www/blog
/etc/nginx/sites-enabled/blog.conf:
file.managed:
- contents: |
server {
listen 8080;
server_name difrex.ru;
location / {
root /var/www/blog;
}
}
- user: root
- group: root
- mode: 0644
- require:
- pkg: web server
ensure nginx service:
service.running:
- name: nginx
- enable: true
- watch:
- file: /etc/nginx/sites-enabled/blog.conf
Вместо последовательного указания тасков, как в ансибле, тут используется система зависимостей. Все блоки исполняются асинхронно. Причем сначала происходит генерация стейта на мастере, который уже сформированным графом попадает на миньёна.
Что я могу сказать после 2 недель переезда про это всё? Мне нравится. Почти всё уже раскатывается salt. Из того, что пока управляется Ansible – это dhcp сервер и главный Nginx. Роль DroneCI для Ansible сейчас исполняю я, т.е. пускаю руками с ноутбука. Переписывание займет не так много времени, особенно учитывая, то что шаблоны из-под Ansible требуют минимальной правки. Потом буду поднимать оставшиеся сервисы. После чего можно будет сделать финальный рефакторинг и выложить в открытый доступ. Думаю, пару месяцев это займет, хотя может и меньше. Про Salt, наверное, будет много постов.
А еще у Salt просто превосходная документация, только посмотрите на это!
Этот пост в дзене.