Ansible і ChatOps або як управляти 100+ серверами з чату

Ansible і ChatOps за допомогою StackStorm, Slack і Hubot
Що таке ChatOps?
ChatOps все ще свіже і рідкісне явище у світі DevOps, коли робота з інфраструктурою переноситься в загальний чат. Ви можете запускати команди прямо з чату, при цьому розробники/сисадміни бачать що відбувається в режимі реального часу, можуть переглядати історію змін, запускати свої команди, підтримувати комунікацію навколо роботи і навіть обмінюватися досвідом. Таким чином інформація і робочий процес належить усій команді — а це несе в собі багато переваг.

Можна придумати такі речі як деплой коду або розгортання серверів з чату, перегляд графіків моніторингу, відправку SMS, управління кластерами або просто запуск shell команд. ChatOps може бути високорівневим поданням вашої дійсно складною CI/CD системи, несучи простоту з допомогою команди в чаті кшталт:
!deploy <that thing>
. Такий підхід робить чудеса для поліпшення видимості і зниження складності навколо процесу розгортання.


Покращений ChatOps
StackStorm — OpenSource проект з особливою увагою до ChatOps. Платформа поєднує величезна кількість існуючих DevOps інструментів начебто управління конфігурацією, моніторингу, графіків, оповіщення ітд. разом, дозволяючи правити всім з єдиного контрольного пункту. І це ідеально з точки зору ChatOps, можна створювати і автоматизувати мислимі і немислимі робочі процеси, контролюючи будь-які набори інструментів прямо з чату.

Нещодавно StackStorm додали підтримку Ansible і додаткові ChatOps можливості, відкриваючи дорогу для реального застосування ChatOps, не просто постинг фотографій забавних котиків з допомогою бота. У цьому матеріалі ми розповімо як змусити працювати ChatOps і Ansible з допомогою StackStorm платформи.
до Речі, StackStorm як і Ansible декларативний, написаний на Python та використовує Yaml + Jinja, що дозволить вам легше у всьому розібратися.


План
Спочатку ми збираємося встановити контрольну машину, яка буде працювати під Ubuntu. Потім ми налаштуємо на ній StackStorm платформу, в тому числі пакети управління Ansible і ChatOps фреймворком Hubot. І нарешті, ми підключимо всю систему до Slack чату, і покажемо кілька простих, але реальних прикладів інтерактивного використання Ansible.

Давайте почнемо, а заодно перевіримо як далеко ми зайшли і настала технологічна сингулярність, даючи root доступ якимось чат ботам і дозволяючи їм керувати нашими 100+ серверами або навіть датацентрами (до речі RackSpace працюють з ChatOps).

Крок 0. Підготовка Slack
Як вже було сказано, ми будемо використовувати Slack.com чат платформу (хоча доступні інші інтеграції). Зареєструйте Slack аккаунт, якщо у вас його ще немає. Увімкніть інтеграцію Hubot в налаштуваннях.
Hubot — фреймворк бота від GitHub, створений спеціально для ChatOps
Увімкніть Hubot інтеграцію в Slack
У підсумку Slack видасть вам API токен кшталт:
HUBOT_SLACK_TOKEN=xoxb-5187818172-I7wLh4oqzhAScwXZtPcHyxCu

Далі ми налаштуємо StackStorm платформу, покажемо реальні приклади використання, і звичайно ж, розповімо як створити власні ChatOps команди.
Але зачекайте, є простий спосіб!

Для самих ледачих
Для тих хто ледачий (більшість DevOps розробників такі), є спеціально підготовлений репозиторій з Vagrant, який встановить все необхідне з допомогою найпростіших сценаріїв bash, доставивши вас з лінії старту прямо на фініш, даючи можливість після автоматичної установки відразу запускати ChatOps команди з Slack чату showcase-ansible-chatops:
# Замініть на токен
export HUBOT_SLACK_TOKEN=xoxb-5187818172-I7wLh4oqzhAScwXZtPcHyxCu
git clone https://github.com/armab/showcase-ansible-chatops.git
cd showcase-ansible-chatops
vagrant up

Для тих же кому цікаві подробиці — перемкнемося з автоматичного режиму на ручний і пройдемося по всіх кроків. Просто майте на увазі, якщо щось не виходить — звіртеся з прикладами з ansible & chatops демо репозиторію.

Крок 1. Установка StackStorm
Установка проста. Всього 1 команда:
curl-s https://downloads.stackstorm.net/releases/st2/scripts/st2_deploy.sh latest | sudo bash

Майте на увазі, це для демонстраційних цілей. При розгортанні продакшену використовуйте Ansible, звіряйте підпису і не довіряйте настановним командам в одну сходинку!
Після завершення установки (а StackStorm тягне купу пакетів Python, RabbitMQ, PostgreSQL, MongoDB, OpenStack), для простоти демонстрації вимкніть механізм StackStorm авторизації в файлі
/etc/st2/st2/conf
. Можна виставити в секції
[auth]
вручну
enable = False
, або скористатися магічним хаком:
sudo sed-i '/^\[auth\]$/,/^\[/ s/^enable = True/enable = False/' /etc/st2/st2.conf

Далі перезагрузим StackStorm:
sudo st2ctl restart


Крок 2. Установка StackStorm плагінів: Ansible і Hubot
Поставимо необхідні плагіни від StackStorm, що зв'язують Ansible і Hubot:
sudo st2 run packs.install packs=hubot,ansible register=all

Крім самих пакунків, буде встановлений ще і сам Ansible в Python virtualenv:
/opt/stackstorm/virtualenvs/ansible/bin


Крок 3. Установка Hubot
Встановимо Hubot і плагіни: Slack і StackStorm, що дозволяють запускати команди в Slack чаті і перенаправляти їх в st2. Ланцюжок виглядає так:
Slack -> Hubot -> StackStorm -> Ansible

Redis — місце, де Hubot тримає свої мізки. Розумійте як хочете, але мізки нам потрібні:
sudo apt-get install build-essential redis-server

Hubot зроблений на Nodejs, необхідна залежність:
curl-sL https://deb.nodesource.com/setup_0.12 | sudo bash -
sudo apt-get install nodejs

Установка самого Hubot:
sudo npm install-g hubot coffee-script yo generator-hubot

Створимо персональну hubot збірку з-під
stanley
linux юзера (він раніше був створений StackStorm). В майбутньому ми будемо запускати бота з правами
stanley
:
sudo mkdir-p /opt/hubot
sudo chown stanley:stanley /opt/hubot
sudo-H-u stanley bash-c 'cd /opt/hubot && echo "n" | yo hubot --name=stanley --description="Stanley StackStorm bot" --defaults'

Встановимо npm плагіни hubot-stackstorm і hubot-slack:
sudo-H-u stanley bash-c 'cd /opt/hubot && npm install hubot-slack hubot-stackstorm --save'

Для того щоб
hubot-stackstorm
підвантажуються при старті бота, додайте запис
hubot-stackstorm
файл:
/opt/hubot/external-scripts.json
:
sed-i 's/.*\[.*/&\n "hubot-stackstorm",/' /opt/hubot/external-scripts.json

І нарешті, можна запустити бота (не забудьте замінити API токен на свій):
cd /opt/hubot && HUBOT_SLACK_TOKEN=xoxb-5187818172-I7wLh4oqzhAScwXZtPcHyxCu ST2_WEBUI_URL=http://chatops:8080 PORT=8181 bin/hubot --name "stanley" --adapter slack --alias !


Крок 4. Перший ChatOps досвід
На даному етапі Stanley бот повинен бути онлайн в чаті. Щоб запросити його в певну Slack кімнату:
/invite @stanley

Отримати список доступних команд:
!help

Напевно вам сподобається:
!ship it

Вдосталь награвшись з існуючими командами, займемося дійсно серйозними речами.

Крок 5. Створення власних ChatOps команд
Одна з можливостей StackStorm — це здатність створювати прості аліаси/обгортки навколо команд, спрощуючи роботу з ChatOps. Замість того щоб набирати довгу команду, ви можете просто забиндить її на щось більш дружнє і легке, синтаксичний цукор.

Отже, створимо свій власний StackStorm пак який буде містити потрібні нам команди. Форкните StackStorm template pack на GitHub. Наш перший action alias
/aliases/ansible.yaml
:
---
name: "chatops.ansible_local"
action_ref: "ansible.command_local"
description: "Run ansible command on local machine"
formats:
- "ansible {{args}}"

Для довідки: вищевказаний аліас використовує ansible st2 integration pack
Відправляємо зміни в нещодавно створений GitHub репозиторій і можна встановлювати наш пак. Для цього вже є ChatOps аліас:
!pack deploy st2-ansible-aliases repo_url=armab/st2-ansible-aliases

де
repo_url
— ваш github репозиторій.

Тепер можна запускати прості Ansible ad-hoc команди прямо з Slack чату:
!ansible "uname-a"

Запуск ansible команд - ChatOps
На низькому рівні це теж саме що:
/opt/stackstorm/virtualenvs/ansible/bin/ansible all --connection=local --args='uname-a' --inventory-file='127.0.0.1,'

Але давайте розглянемо більш корисні приклади інтерактивного ChatOps.

Приклад 1. Отримуємо статус серверів
У Ansible є ping модуль, який підключається до хостам і повертає
pong
в разі успіху. Простий, але потужний приклад, що дозволяє зрозуміти стан серверів прямо з чату за лічені секунди без необхідності заходити в термінал.

Для цього створимо в нашому паці
action
, що запускає реальну команду і
action alias
, який є синтаксичним цукром для екшна і дозволяє створити таку ChatOps конструкцію:
!status 'web'

Action
actions/server-status.yaml
:
---
name: server_status
description: Show server status by running ansible ping ad-hoc command
runner_type: local-shell-cmd
entry_point: ""
enabled: true
parameters:
sudo:
description: "Run command with sudo"
type: boolean
immutable: true
default: true
kwarg_op:
immutable: true
cmd:
description: "Command to run"
type: string
immutable: true
default: "/opt/stackstorm/virtualenvs/ansible/bin/ansible {{hosts}} --module-name=ping"
hosts:
description: "Ansible hosts to ping"
type: string
required: true

Action alias
aliases/server_status.yaml
:
---
name: chatops.ansible_server_status
action_ref: st2-chatops-aliases.server_status
description: Show status for hosts (ansible ping module)
formats:
- "status {{hosts}}"

Переконайтеся, що ви додали потрібні хости в Ansible inventory файл:
/etc/ansible/hosts


Після відправки коду в репозиторій, не забудьте перезавантажити ваш пак з чату:
!pack deploy st2-chatops-aliases repo_url=armab/st2-chatops-aliases

Дуже зручно що ми можемо зберігати всі наші ChatOps налаштування у вигляді st2 пака і підхоплювати зміни з репозиторію, — інфраструктура як код. Результат щойно створеної команди в Slack:
Показати статус серверів - ChatOps

Це дійсно зручно, навіть ваш CEO може подивитися статус не маючи доступу до серверів! З таким підходом спілкування, розгортання і робота навколо інфраструктури може відбуватися прямо в чаті: перебуваєте ви в офісі або працюєте віддалено (деякі з нас можуть працювати прямо з пляжу).

Приклад 2. Перезавантаження сервісів
З вами колись траплялося так, що проста перезавантаження сервісу допомагала? Не ідеальний спосіб, але найчастіше швидке рішення просто необхідно. Давайте створимо ChatOps команду яка б перевантажувала зазначений сервіс на певних серверах.
Завдання отримати таку конструкцію:
!service restart "gearmand" on "MQ-server"

Для цього у вже існуючому st2 паці створіть
actions/service_restart.yaml
:
---
name: service_restart
description: Restart service on remote hosts
runner_type: local-shell-cmd
entry_point: ""
enabled: true
parameters:
sudo:
description: "Run command with sudo"
type: boolean
immutable: true
default: true
kwarg_op:
immutable: true
cmd:
description: "Command to run"
type: string
immutable: true
default: "/opt/stackstorm/virtualenvs/ansible/bin/ansible {{hosts}} --become --module-name=service --args='name={{service_name}} state=restarted'"
hosts:
description: "Ansible hosts"
type: string
required: true
service_name:
description: "Service to restart"
type: string
required: true

ChatOps аліас
aliases/service_restart.yaml
:
---
name: chatops.ansible_service_restart
action_ref: st2-chatops-aliases.service_restart
description: Restart service on remote hosts
formats:
- "service restart {{service_name}} on {{hosts}}"

Результат:
Перезавантаження MySQL сервісу на віддалених серверах - ChatOps
І знаєте що? Завдяки мобільному додатком Slack ви можете перезавантажувати сервіси прямо з вашого телефону!

Приклад 3. MySQL processlist
Ми хочемо створити просту Slack команду, яка б відображала список виконуваних SQL запитів на MySQL сервері:
!show mysql processlist

Action
actions/mysql_processlist.yaml
:
---
name: mysql_processlist
description: Show MySQL processlist
runner_type: local-shell-cmd
entry_point: ""
enabled: true
parameters:
sudo:
immutable: true
default: true
kwarg_op:
immutable: true
cmd:
description: "Command to run"
type: string
immutable: true
default: "/opt/stackstorm/virtualenvs/ansible/bin/ansible {{ hosts }} --become --become-user=root-m shell-a \"mysql --execute='SHOW PROCESSLIST;' | expand-t 10\""
hosts:
description: "Ansible hosts"
type: string
default: db

Action alias для ChatOps:
aliases/mysql_processlist.yaml
:
---
name: chatops.mysql_processlist
action_ref: st2-chatops-aliases.mysql_processlist
description: Show MySQL processlist
formats:
- "show mysql processlist {{hosts=db}}"

Зауважте, що ми зробили
hosts
параметр опціональним (
db
за замовчуванням), так що ці дві команди еквівалентні:
!show mysql processlist
!show mysql processlist 'db'

Показати список виконуваних SQL запитів - ChatOps
Ваш DBA буде щасливий!

Приклад 4. Отримуємо HTTP статистику з nginx
Ми хочемо отримати масив HTTP статус кодів з nginx лода, відсортувати їх у залежності від кількості і красиво відобразити в чаті, щоб зрозуміти як багато
200
або
50x
помилок на веб серверах, вони знаходяться в межах норми чи ні:
!show nginx stats on 'web'

Для цього створимо action, який запускає bash команду,
actions/http_status_codes.yaml
:
---
name: http_status_codes
description: Show sorted http status codes from nginx logs
runner_type: local-shell-cmd
entry_point: ""
enabled: true
parameters:
sudo:
immutable: true
default: true
kwarg_op:
immutable: true
cmd:
description: "Command to run"
type: string
immutable: true
default: "/opt/stackstorm/virtualenvs/ansible/bin/ansible {{ hosts }} --become-m shell-a \"awk '{print \\$9}' /var/log/nginx/access.log|sort |uniq-c |sort-k1,1nr 2>/dev/null|column-t\""
hosts:
description: "Ansible hosts"
type: string
required: true

Alias
aliases/http_status_codes.yaml
:
---
name: chatops.http_status_codes
action_ref: st2-chatops-aliases.http_status_codes
description: Show sorted http status codes from nginx on hosts
formats:
- "show nginx stats on {{hosts}}"

Спасибі Brian Coca, Ansible core розробнику за чудову ідею!
Показати список nginx статус кодів на серверах - ChatOps
Все більше і більше це виглядає як контрольний центр управління польотами. Ви можете запускати цілі ланцюжки команд на серверах прямо з чату і кожен може бачити результат в режимі реального часу. Відмінно!

Приклад 5. Security patching
Уявіть, що вам необхідно терміново усунути чергову критичну вразливість зразок Shellshock. Для цього треба оновити
bash
на всіх серверах. Ansible мабуть ідеальний інструмент для таких операцій. Але замість запуску однорядкової ansible команди, давайте створимо добротний playbook:
playbooks/update_package.yaml
:
---
- name: Update package on remote hosts, run on 25% of servers at a time
hosts: "{{ hosts }}"
serial: "20%"
sudo: yes
завдання:
- name: Check if Package is installed
command: dpkg-query-l {{ package }}
register: is_installed
failed_when: is_installed.rc > 1
changed_when: no

- name: Update Package only if installed
apt: name={{ package }}
state=latest
update_cache=yes
when: is_installed.rc == 0

Playbook
оновить пакет тільки якщо він вже встановлений, операція проводиться на 20% хостів за раз, ті в 5 кроків. Корисно, коли треба оновити щось більш серйозне зразок
nginx
на дійсно великій кількості серверів. Таким чином ми не відправляємо весь веб кластер в даун. Додатково можна додати відключення від балансувальника навантаження групами. Приклад з реального життя.

Видно, що playbook змінні
{{hosts}}
та
{{package}}
приходять звідкись ззовні, а саме екшену в нашому StackStorm паці
actions/update_package.yaml
:
---
name: update_package
description: Update package on remote hosts
runner_type: local-shell-cmd
entry_point: ""
enabled: true
parameters:
sudo:
immutable: true
default: true
kwarg_op:
immutable: true
timeout:
default: 6000
cmd:
description: "Command to run"
immutable: true
# ця строчка
default: "/opt/stackstorm/virtualenvs/ansible/bin/ansible-playbook /opt/stackstorm/packs/${ST2_ACTION_PACK_NAME}/playbooks/update_package.yaml --extra-vars='hosts={{ hosts }} package={{ package }}'"
hosts:
description: "Ansible hosts"
type: string
required: true
package:
description: "Package to upgrade"
type: string
required: true

Action alias, що дає можливість запускати playbook у вигляді простої ChatOps команди,
aliases/update_package.yaml
:
---
name: chatops.ansible_package_update
action_ref: st2-chatops-aliases.update_package
description: Update package on remote hosts
formats:
- "update {{package}} on {{hosts}}"

Ось вона:
!update 'bash' on 'all'


Важлива частина роботи DevOps інженера — це поліпшення процесів, роблячи роботу розробників простіше, спілкування в команді краще, діагностику проблем швидше за рахунок автоматизації та використання правильних інструментів, — все для того, щоб зробити компанію успішніше.
ChatOps допомагає вирішити ці проблеми абсолютно новим, ефективним способом!

На завершення. Священна корова
Як ви знаєте, у Ansible відома любов до утиліті
cowsay
. Давайте перенесемо її в ChatOps!

Встановимо для початку саму утиліту:
sudo apt-get install cowsay

Екшн
actions/cowsay.yaml
:
---
name: cowsay
description: Draws a cow that says what you want
runner_type: local-shell-cmd
entry_point: ""
enabled: true
parameters:
sudo:
immutable: true
kwarg_op:
immutable: true
cmd:
description: "Command to run"
type: string
immutable: true
default: "/usr/games/cowsay {{message}}"
message:
description: "Message to say"
type: string
required: true

Alias
aliases/cowsay.yaml
:
---
name: chatops.cowsay
action_ref: st2-chatops-aliases.cowsay
description: Draws a cow that says what you want
formats:
- "cowsay {{message}}"

Виклик священної ChatOps корови:
!cowsay 'Holy ChatOps Cow!'

Священна ChatOps корова
Для довідки: Всі результати виконання команд можна подивитися в панелі управління StackStorm
http://www.chatops:8080/ логін:
testu
пароль:
testp

(замініть hostname на IP якщо не скористалися Vagrant демо):


Не зупиняйтеся на досягнутому!
Це були прості, але бойові приклади використання. Більш складні речі коли кілька DevOps інструментів з'єднані в динамічний робочий процес буде показано в наступних статтях. Тут StackStorm демонструє всю свою міць, приймаючи рішення в залежності від ситуації: це називається подійно-орієнтованою архітектурою кшталт самовідновлюються після інциденту систем.
Якщо ви не знайшли потрібного функціоналу в StackStorm, запропонуйте ідею або додайте Pull Request на GitHub (Python наш основний мова). Так само є коммьюніті де можна задати питання або поділитися своїм досвідом, IRC:
#StackStorm
на freenode.net
і публічний Slack канал, а ще ми любимо GitHub ✮ зірочки.


Спасибі за увагу, сподіваюся вийшло висвітлити особливості цього досить нового підходу в світі DevOps.
А для яких випадків ви б використовували ChatOps? Прошу ділитися ідеями в коментарях.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.