9maf4you
9maf4you
9maf4you's blog
69 posts
Don't wanna be here? Send us removal request.
9maf4you · 6 years ago
Text
Как правильно готовить SaltStack
SaltStack - очень мощный и гибкий инструмент управления конфигурациями. К большому сожалению из-за отсутствия договоренности ( политики / RFC , как это ни называй )  мало кто задумывается о "чистой конфигурации".
Под чистой конфигурацией я понимаю легкость чтения стейтов и их поддержку в будущем. Для себя я выбрал несколько принципов, которые позволят сделать ту самую "чистую конфигурацию".
В первую очередь подход заключается в том, чтобы готовить стейты как это принято в debain репозиториях и пакетах, плюс некоторые нюансы, которые взяты из моей практики.
Стейт, как deb-пакет - является самостоятельно и отчуждаемой сущностью
Каждый стейт должен находится в директории, сущности который он принадлежит.
Не стоит брезговать копипастой во избежании программирования на Jinja. Простые и примитивные вещи не ломаются.
Важно разделять стейты на слои. То что можно поставить на все хосты стоит унести в base. Все остальное - нужно уносить в другие environment ( production / stage / service ). Overwritting.
Pillars - это настройки ( конфиги ), Grains - это методанные ( информация о миньоне, например кол-во жестких дисков.
А теперь более детально по каждому пункту.
Стейт, как deb-пакет - является самостоятельной и отчуждаемой сущностью.
В первую очередь - это важно потому оно становится переносимым и самостоятельным. Как пример, можно смотреть на fat-binary в языке Go  или на APP- приложений в MacOSX.
Идя другим путем можно наткнутся на типичную проблему с зависимостей.
Пример
Вы хотите принести какой-то экспортет на свой хост, чтобы собирать метрики или python-script написанный python3.6.
Разберем оба примера.
node_exporter - бинарь, а для его запуска нам нужно service-unit, возможно какой-то конфиг, если мы не запускаем его через аргументы командной строки.
Итого, наш стейт-пакет будет выглядеть так.
/path/to/node-exporter-service-unit:  file.managed:    - source: salt://node-exporter-service-unit packages:  pkg.installed:    - pkgs:      - node_exporter node-exporter-service-unit:  service.running:    - enable: True    - reload: True
/path/to/my-powerfull-script.py: # Приностим сам скрипт  file.managed:    - source: salt://my-powerfull-script.py packages:  pkg.installed:    - pkgs:      - python3.6 # Да приносим python, даже если вы уверены, что он на хосте есть.  - python3-pip      - systemd python-click-pkg:  pip.installed:    - name: click    - require:      - pkg: python3-pip /path/to/my-powerfull-script.py:  cron.present:    - user: root    - minute: random    - hour: 2
Этот стейт приносит с собой необходимые зависимости. python, pip3 и даже systemd. Это на сто процентов гарантирует, что скрипт заработает.
Также он легко читаем, потому что все находится перед глазами в одном файле.
Его легко перенести куда угодно по дереву директорий или просто передать кому-то на переиспользование.
Каждый стейт должен находится в директории, сущности который он принадлежит.
Для упрощения понимания структуры / чтения. Стоит помещать каждый из стейтов в директорию, сущности, которой он принадлежит.
По аналогии с репозиториями deb-пакетов. Там это не так явно выражено, но есть метаданные пакета Group , которая указывает пакет какой категории вы устанавливаете.
Такой подходит позволит четко понимать какой стейт�� привязаны к миньону при просмотре state.show_top
Пример    
Допустим, мы хотим настроить наш rsyslog для отправки логов в разные точки назначения - ELK и  rsyslog-server.
А также хотим собирать метрики через node_exporter, а логи ротировать.  
Дерево будет выглядеть так
. └── base    ├── logs    │   ├── logrotate.sls    │   ├── rsyslog.sls    │   └── rsyslog-elk.sls    ├── monitoring    │   ├── node_exporter.sls    │   └── redis.sls    └── system
Для elk нам понадобится отдельный модуль из репозитория + шаблон, для второго - только шаблон. И все они требуют установленный rsyslogd.
Как показано в пункте 1 каждый стейт должен приносить зависимости для себя.
Ответ: "ДА" - в каждом стейте мы дублируем rsyslog как зависимость.  
P.S. Возможны случаи, когда не ясно как классифицировать тот или иной стейт. В таких случая я уношу их  в system. Но всячески стараюсь этого избегать.
Плохой пример - называть директории backend / frontend - это не класс, а роль.
Не стоит брезговать копипастой.
Многие не согласны с таким высказыванием, но как я уже упоминал - это упросит отчуждаемость стейтов для переноса и переиспользования.
В примере выше нам нужно настроить rsyslog и они оба имеют одну зависимость - rsyslog пакет.
Казалось бы, можно вынести в отдельный стейт и назвать его packages.sls, но тем самым есть риск сломать стейт, кто-то другой решит о не надобности rsyslog, потому что он приезжает с базовой системой и по своему будет прав.
packages:  pkg.installed:    - pkgs:      - rsyslog /etc/rsyslog.d/10-main.conf:  file.managed:    - source: salt://10-main.conf
packages:  pkg.installed:    - pkgs:      - rsyslog      - rsyslog-elasticsearch /etc/rsyslog.d/30-elasticsearch.conf:  file.managed:    - source: salt://30-elasticsearch.conf
Важно разделять стейты на слои. Environments: base / production / stage / service  и overwritting.
Слои лучше рассматривать как: base - это то что одинаково для всех, например, список установленных пакетов. production / stage / servicename - это сервсис-зависимый слой.
В большинстве случаев ( в основном в небольших проектах ) нет необходимости в использование среды кроме base.
Как быть, если node_exporter нужен всем, а запускается он различными аргументами ( например, порт на котором он слушает или debug-флаг ) у каждого сервиса или в разной среде ( production / stage )?
Куда положить такой стейт в base или  сервсисо-зависимый слой? Ответ: "в оба".
В случае когда есть единая команда ответственная за инфраструктуру ( нижний слой - предоставление виртуалок / железа и проч ) она должна предоставить готовое решение - железку/виртуалку с минимально рабочей конфигурацией - некоторыми дефолами.
А команды сервисов - сами вольны решать как именно им перенастроить дефолты - overwritting
Пример
. ├── base │   ├── logs │   │   ├── logrotate.sls │   │   ├── rsyslog │   │   └── rsyslog-elk.sls │   ├── monitoring │   │   ├── node_exporter.sls # Базовая настройка node_exoprter слушает порт 9117 │   │   └── redis.sls │   └── system └── service-name    └── monitoring        └── node_exporter.sls # Перезаписанная настройка node_exoprter слушает порт 8080 и запускается c debug-флагом
Pillars - это настройки, Grains - это методанные.
Если очень примитивно: Pillars - это настройки, Grains - это методанные. В принципе все что нужно о них знать.
К Pillars можно отнести: переменные для конфигов, секреты - пароли / сертификаты.
Grains - это то, что описывает миньон - метаданные: кол-во жестких дисков,  модель процессора. У нас в компании - это еще и принадлежность хоста к группе ( они же hostgroups ).
Самая худшее что можно придумать с этиму сущностями - это делать на них таргетинг непосредствено в стейтах.
Плохой пример
base:  '*':    - node_exporter
packages:  pkg.installed:    - pkgs:      - node_exporter run-exporter:  cmd.run {% if grains['hostgroup'] != 'production-server' %}    - 'node_exporter --arg1 foo' {% else %}    - 'node_exporter --arg1 foo --arg2 bar' {% endif %}
Не стоит использовать их для таргетирования - это увеличивает энтропию. Для таргетирования -  top.sls
Хороший пример
base:  'G:production-server':    - path.to.node_exporter    'G:dev-server':    - other.path.to.node_exporter
packages:  pkg.installed:    - pkgs:      - node_exporter run-exporter:  cmd.run    - 'node_exporter --arg1 foo'
packages:  pkg.installed:    - pkgs:      - node_exporter run-exporter:  cmd.run    - 'node_exporter --arg1 foo --arg2 bar'
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
почти уникальная штука. одна копия из 1000
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
загран готов! 😏
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
хозяин сказал копать - значит надо копать 😂😂
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
теперь у меня есть собственный порш :)
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
поговорили...😂😂😂
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
домашний том-ян - хорош :)
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
дай пять!:)
0 notes
9maf4you · 11 years ago
Audio
1 note · View note
9maf4you · 11 years ago
Photo
Tumblr media
#8secondspub
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
#jenga @p1pachkaaaaaa
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
If @kellyslater likes my photo, this year will be amazing!!! :)) 
0 notes
9maf4you · 11 years ago
Video
вхахха!! вот это игрушка :)
0 notes
9maf4you · 11 years ago
Photo
Tumblr media
нг начинается :))
0 notes