Про Ansible и про Salt

2024/03/01

Моя давняя идея – это заиметь открытую инфрструктуру. Т.е. я хочу открыть всякие 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 в монорепы.

Схема деплоя на DroneCI

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

Вновь созданный сервер автоматически регистрируется в 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 просто превосходная документация, только посмотрите на это!

Этот пост в дзене.