15 речей, які ви повинні знати про Ansible

Пропоную читачам «Хабрахабра» переклад опублікованій на codeheaven.io статті «15 Things You Should Know About Ansible» за авторством Marlon Bernardes.

Останнім часом я багато працював з Ansible і вирішив поділитися деякими речами, які вивчив по дорозі. Нижче ви знайдете список з 15 речей, які, як я думаю, ви повинні знати про Ansible. Щось пропустив? Просто залиште коментар і поділіться вашими особистими порадами.

1 — Ви можете передавати параметри для ролей

Хорошою практикою є створення ролей для організації ваших плейбуков. Скажімо, ми хочемо створити роль для встановлення Jenkins. Структура каталогів для цієї ролі буде виглядати так:

jenkins/
files/
templates/
tasks/
handlers/
defaults/

Каталог defaults використовується для зберігання змінних за замовчуванням ролі. Всередині нього може знаходитися файл main.yml:

jenkins_port: 8080
jenkins_context_path: /jenkins
jenkins_home: /jenkins

Ви можете змінити змінні за замовчуванням, передачею різних параметрів для ролі, ось так:

roles:
- { role: jenkins, jenkins_port: 8181, jenkins_home: '/jenkins1' }
- { role: jenkins, jenkins_port: 8080, jenkins_home: '/jenkins2' }

2 — Як зробити модуль command идемпотентным

Идемпотентность — властивість певних операцій, які можуть бути виконані багаторазово, не змінюючи результат первісного застосування. Ця концепція є у більшості модулів Ansible: ви вказуєте бажаний кінцевий стан і Ansible вирішує, чи має бути виконано завдання. За замовчуванням цей принцип не поширюється на модуль command. Якщо у вас в плейбуке є завдання, вона завжди буде виконана:

- command: /usr/bin/create-database.sh

Для досягнення ідемпотентності ви можете використовувати атрибут creates. Коли він присутній, Ansible виконає завдання command, тільки якщо вказаний у файлі шаблону не існує. В якості альтернативи можна використовувати removes, який буде виконувати завдання, тільки якщо зазначений файл.

- command: /usr/bin/create-database.sh creates=/path/to/database

Завжди майте на увазі, що у Ansible багато модулів і найбільш поширені операції не вимагають використання модуля command. Наприклад, є модулі для створення файлових систем, зміни правил iptables і управління завданнями cron. За замовчуванням, всі ці модулі идемпотентны, так що ви завжди повинні віддавати перевагу їм.

3 — Використання Ansible модуля setup для збору інформації про ваших хостах

Ймовірно, ви бачили, що перше, що Ansible робить, коли виконує плейбук — це щось типу цього:

TASK [setup] *******************************************************************
ok: [servername]

Це відбувається тому що Ansible викликає спеціальний модуль setup перед виконанням першого завдання. Модуль setup коннектітся на хост і збирає факти усіх видів: IP адреса, дисковий простір, архітектура процесора, доступна пам'ять та багато іншого. Може бути корисним виклик цього модуля вручну, як швидкий спосіб збору інформації про ваших машин. Щоб зробити це, просто виконайте команду:

$ ansible localhost -m setup
localhost | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"10.27.12.77",
"192.168.33.1"
],
(безліч інших фактів)
}

4 — Ви можете відобразити всі завдання плейбука

Хочете згадати, що робить плейбук? Виконайте ansible-playbook використовуючи прапор --list-tasks і Ansible відобразить всі имещиеся завдання:

$ ansible-playbook install-jenkins.yml --list-tasks
PLAY: #1
завдання:
TASK: meta
TASK: open-jdk : Install open jdk 1.8
TASK: mount-partition : Creating the filesystem for the device {{ device }} (if needed)
TASK: mount-partition : Mounting the device {{ device }} on path {{ path }}
TASK: jenkins : Ensure Jenkins repo is installed.
TASK: jenkins : Add Jenkins repo GPG key.
TASK: jenkins : Ensure Jenkins is present.
TASK: jenkins : Ensures that the home directory exists
TASK: jenkins : include
TASK: jenkins : Ensure Jenkins is started and runs on startup.
TASK: jenkins : Wait for Jenkins to start up before proceeding.
TASK: jenkins : Get the jenkins-cli jarfile from the Jenkins server.

5 — Використовуйте ansible-vault, якщо ви хочете зберігати конфіденційну інформацію

Якщо одна з ваших завдань вимагає конфіденційної інформації (скажімо, доступи в базу даних), хорошою практикою є зберігання цієї інформації в зашифрованому вигляді, замість того, щоб зберігати її відкритим текстом.

Ansible поставляється з утилітою командного рядка ansible-vault, яка дозволяє створювати і управляти шифрованими файлами. Таким чином, ви можете «коммитить» зашифрований файл у вашу систему керування версіями і тільки користувачі з паролем дешифрування зможуть прочитати його.

# Зашифрувати існуючий файл. Вам необхідно створити пароль шифрування.
ansible-vault encrypt secrets.yml

# Створити новий зашифрований файл. Вам необхідно створити пароль шифрування.
ansible-vault create secrets.yml

# Розшифрувати файл. Вам необхідно ввести пароль, який використовується для шифрування.
# Використовуйте з обережністю! Не залишайте ваші файли не зашифрованими.
ansible-vault decrypt secrets.yml

# Редагувати зашифрований файл
# (за замовчуванням використовується vim, змінюється змінної оточення $EDITOR)
ansible-vault edit secrets.yml

# Відобразити вміст зашифрованого файлу
ansible-vault edit secrets.yml

Якщо ви імпортуєте файл secrets.yml в ваш плейбук, Ansible «зафейлится», так як не буде знати як прочитати зашифрований файл. Вам необхідно вказати аргумент командного рядка --ask-vault-pass, який змусить Ansible запропонувати ввести пароль для зашифрованого файлу.

ansible-playbook playbook.yml -i hosts --ask-vault-password

Інший спосіб полягає у зберіганні пароль у файлі (він не повинен бути «закоммичен») і вказати шлях до файлу, використовуючи аргумент --vault-password-file. Якщо цей файл виконується, Ansible буде запускати його і використовувати висновок в якості пароля.

Дізнатися більше про ansible-vault можна тут.

6 — Використання with_items може бути гарною ідеєю

При використанні with_items, Ansible створить змінну {{item}}, що містить значення поточної ітерації. Деякі модулі обробляють колекції дуже добре, та набагато швидше, ніж при запуску тієї ж самої задачі декілька раз з різними параметрами.

# Установка всіх пакетів (швидше)
- name: install required packages using the apt module
apt: package={{ item }} update_cache=yes
sudo: True
with_items:
- git
- memcached
- nginx

# Установка пакетів окремо (повільніше)
- name: install git
apt: package=git update_cache=yes
sudo: True

- name: install memcached
apt: package=memcached update_cache=yes
sudo: True

- name: install nginx
apt: package=nginx update_cache=yes
sudo: True

7 — Як працюють Local Actions

Іноді вам може знадобитися виконати завдання на вашому локальному хості, замість запуску її на віддаленому хості. Це може бути корисно, якщо ми хочемо почекати, поки сервер завантажиться (якщо він тільки що запущений), або коли ми хочемо додати деякі вузли в пул балансувальника (або видалити):

tasks:
- name: take out of load balancer pool
local_action: >
command /usr/bin/take_out_of_pool {{ inventory_hostname }}

- name: update application
yum: name=acme-web-stack state=latest

- name: add back to load balancer pool
local_action: >
command /usr/bin/take_out_of_pool {{ inventory_hostname }}

Приклад нижче показує як запустити EC2 інстанси і дочекатися, коли він стане доступний:

- name: Launching EC2 Instance
# instance options here
register: ec2


- name: Waiting for ec2 instances to listen on port 22
wait_for:
state=started
host={{ item.public_dns_name }}
port=22
with_items: ec2.instances

8 — Ви можете вказати Ansible виконувати завдання тільки один раз

Іноді вам може знадобитися виконати завдання тільки один раз, навіть при наявності кількох хостів. В якості прикладу, скажімо, у вас є кілька серверів з додатками, які конектяться до тій же базі даних і у вас є задача, яка виробляє міграцію бази. У цьому випадку вам необхідно виконати це завдання лише один раз.

Що б добитися цього, ви можете використовувати параметр run_once, що вказує Ansible виконувати команду лише один раз:

- name: run the database migrations
command: bundle exec rake db:migrate
run_once: true

9 — Обробники (handlers) це спеціальні типи завдань

Обробники (handlers) це завдання з унікальними іменами, які будуть виконуватися тільки у разі повідомлення від іншого завдання. Вони дуже зручні для перезапуску сервісів або перезавантаження системи.

Обробники, які були повідомлені, будуть виконуватися один раз в кінці плейбука незважаючи на те, як багато разів вони були повідомлені. Ви можете оголосити їх використовуючи handler і викликати з допомогою notify.

Ось приклад того, як перезапустити 2 сервісу, коли вміст файлу змінюється, але тільки в тому випадку, якщо файл змінюється (приклад взято з Ansible docs).

- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache

Обробники повинні бути оголошені де-небудь у вашому плейбуке:

handlers:
- name: restart memcached
# Використовується модуль service, але ви можете використовувати будь-який інший модуль
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted

10 — Прискорення з допомогою конвеєризації (pipelining)

Кілька порад, про те як змусити Ansible виконуватися ще швидше:

  • Включення конвеєризації
Включення конвеєрної обробки (pipelining) скорочує кількість операцій SSH, необхідних для виконання модуля на віддаленому сервері, передаючи сценарії по каналу (pipe) в SSH сесію замість того, щоб копіювати їх. В результаті це може призвести до значного підвищення продуктивності.

Однак, ви повинні бути обережні. Конвеєризація буде працювати тільки якщо опція requiretty відключена на всіх віддалених хостах у файлі sudoers (/etc/sudoers).

[ssh_connection]
pipelining = True

  • Відключення збору фактів або увімкнути кешування фактів
Якщо ви не використовуєте Ansible факти у ваших завданнях, ви можете вимкнути крок збору фактів для збільшення швидкості. Що б це зробити, просто додайте в ваш плейбук опцію gather_facts: False:

- hosts: servername
gather_facts: False
завдання:
- name: ...
# ...

З іншого боку, якщо вам необхідно використовувати Ansible факти (автоматично зібрані модулем setup) ви можете закешувати їх, що б подальші виконання були швидше. Якщо ви хочете дізнатися більше, документація Ansible докладно охоплює це тут.

11 — У Ansible є кілька модулів для повідомлень

Використовуєте Ansible для автоматизації ваших blue-green деплоев (blue-green deployment)? Запускаєте плейбуки для «провіженінга» нових инстансов AWS? Дайте знати про це вашій команді, з допомогою одного з модулів для повідомлень. В якості прикладу, завдання нижче відправить повідомлення у Slack:

- hosts: servername
завдання:
- name: Send notification message via Slack
local_action:
module: slack
# To retrieve your slack token, open your team settings and look for the
# Incoming Webhooks plugin
token: <your>/<token>/<goes here>
msg: "Hello team! I just out updating our production environment."
джерело: "#general"
username: "ansible-bot"

Також доступні модулі для повідомлення в irc, twillio, hipchat, jabber і багато інших.

12 — EC2 инстансы автоматично групуються за їх тегами

При використанні Amazon Web Services і Ansible EC2 скрипта динамічної інвентаризації, всі инстансы будуть згруповані спираючись на їх характеристиках, таких як тип, кейпары і теги. EC2 теги це просто ключ=значення асоційоване з вашими инстансами, які ви можете використовувати як вам завгодно. Деякі використовують мітки, щоб згрупувати production/staging сервера, для позначення web-серверів або «активних» серверів під час blue-green деплоев.

EC2 Dynamic Inventory скрипт використовує наступний шаблон (без дужок) при групуванні хостів по тегу:
tag_[TAG_NAME]_[TAG_VALUE]

Так що, якщо ви хочете виконати завдання на всіх вузлах з тегом env=staging, просто додайте його в ваш плейбук:
hosts: tag_env_staging
завдання:
- name: This task will be run on all servers with env == staging
# ...

Щоб зробити це ще більш цікавим, ви можете використовувати шаблони Ansible, конкретизувавши, які хости повинні бути порушені. Наприклад, якщо ви хочете виконати певне завдання на ваших production db серверах (за умови, що вони позначені належним чином), ви можете використовувати перехресний шаблон :& ), як тут:

hosts: tag_env_production&:tag_type_db
завдання:
- name: This task will be run on all servers with tags 'env=production' and 'type=db'
# ...

13 — Ви можете виконувати завдання в режимі «Dry Run»

Ansible підтримує запуск плейбука в режимі dry run (також званий Check Mode).
У цьому режимі Ansible не вносити ніяких змін на вашому хості, а просто повідомить, які зміни будуть зроблені, якби плейбук був запущений без цього прапора.

Хоч це й корисно в деяких ситуаціях, але може не працювати належним чином, якщо ваші завдання використовуються умови.

14 — Завдання можуть виконуватися крок за кроком

Іноді, ви не хочете виконувати всі завдання вашого плейбука.
Це поширене рішення, коли ви пишете новий плейбук і хочете перевірити його.
Ansible надає спосіб, який дозволить вам вирішити завдання, які ви хочете запустити, використовуючи прапор --step.
Це дозволить вам вибирати, чи ви хочете виконати завдання ( y ), пропустити її ( n ) або ( c ) продовжити не питаючи.

15 — Можна виконувати завдання грунтуючись на їх тегах

Ви можете додати один або кілька тегів до задачі або плейбуку.
Щоб зробити це, просто відмітьте, що ви хочете «тегировать» з допомогою атрибута tags:

Пізніше ви можете вирішити які теги виконати або пропустити використовуючи прапор
--tags tagname (або -t) і --skip-tags tagnames:

# виконати тільки завдання з тегом 'dependencies'
$ ansible-playbook --tags=dependencies playbook.yml

# виконає всі завдання, крім тих, що містять тег 'додаткова'
$ ansible-playbook --skip-tags=optional playbook.yml

Можна вказати більше одного тега, розділяючи їх комами.

Рекомендації

Ansible Docs
Ansible Up & Running Book by Lorin Hochstein
Джерело: Хабрахабр

0 коментарів

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