Thank you for reading this post, don't forget to subscribe!
Ansible — бесплатное ПО для конфигурирования и управления компьютерами, сочетает в себе развертывание многоузлового программного обеспечения, выполнения различных задач и управление конфигурациями. Он управляет нодами (которые должны иметь поддержку Python 2.4 или более поздней версии) через SSH. Модули работают над JSON и стандартный вывод может быть написан на любом языке программирования. Система использует YAML для написании функций (задач выполнения). Главная цель Ansible — это с одного (можно сделать и пару) серверов с ансиблом можно было управлять всеми другими нодами. С такого сервера можно отправлять различные команды (набор некоторых инструкций, так называемых playbooks) на любую из подключенных нод на сервере. Выполнение команд выполняется путем подключения сервера к ноде через публичный ключ по SSH.
В файле «Host inventory» содержится информация о обслуживаемых нодах ( где собственно все команды будут исполнены). Конфигурационный файл с Ansible может быть использован для настройки переменного окружения.
В ansible, используются playbooks — это набор инструкций и они состоят из задач. Плейбуки описываются с помощью функциональности модуля ядра самого Ansible ( так же, могут использовать сторонние модули). Playbooks — последовательность или набор команд в которых так же, может использоваться различные проверки: если условие не выполняется, то определенные команды могут пропускаться. Данные кукбуки, описываются в формате YAML.
Установка Ansible в CentOS/RedHat
Чтобы установить ansible для начала, стоит подключить репозиторий EPEL
Устанавливаем ansible из пакета:
yum -y install ansible
Проверка версии ansible
Проверяем версию ansible:
[root@centos64 ~]# ansible --version
ansible 2.5.5
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Настройка Ansible в Unix/Linux
Сам конфигурационный файл описывается в формате INI. Так же, имеется возможность переопределения части конфигурации( можно даже всего конфига) в параметрах playbook или в переменных окружения.
При выполнении команд, Ansible выполняет проверку и ищет наличия файла с конфигурациями в следующих расположениях:
Параметр ANSIBLE_CONFIG проверяется переменная окружения, который может быть указывать на файл конфигурации.
- ./ansible.cfg – в текущей папке.
- ~/.ansible.cfg — в домашней директории пользователя.
- /etc/ansible/ansible.cfg — в папке, смого ansible.
Настройка через переменные окружения
Много опций, можно задать с помощью переменного окружения, для этого стоит использовать префикс ANSIBLE_ перед названием самого параметра с конфигурацией (большими буквами). Например:
export ANSIBLE_SUDO_USER=root
После чего переменная ANSIBLE_SUDO_USER может быть использована в playbook.
Настройка в ansible.cfg
Самих параметров в Ansible конфигурации много, но основные я перечислю:
- hostfile: Данная опция указывает на путь к inventory file. В нем хранится список ваших хостов, к которым Ansible сможет выполнить подключение.
Например: hostfile = /etc/ansible/hosts - library: Путь к папке. В ней сохранены все модули Ansible.
Например: library = /usr/share/ansible - forks: Задается количество процессов, которые может породить Ansible. По-умолчанию параметр установлен в 5.
Например: forks = 5 - sudo_user: Пользователь который будет использоватся по умолчанию и от которого Ansible собственно будет выполнять запуск команд на удаленных нодах.
Например: sudo_user = root - remote_port: Порт для соединения по SSH к нодам (по умолчанию использует стандартный 22-й порт).
Например: remote_port = 22 - host_key_checking: Данная опция дает возможность выключить проверку SSH–ключа на хосте, но по-умолчанию даная проверка включена.
Например: host_key_checking = False - timeout: Данная опция задает таймаут ( время попытки подключения по SSH).
Например: timeout = 60 - log_path: Путь для сохранения лог-файлов. По-умолчанию Ansible не сохранит их вообще.
Например: log_path = /var/log/ansible.log
Первый файл конфигурации Ansible
Для этого нужно выполнить подключение по SSH к серверу где установлен Ansible. Я создам папку для всех моих проектов и после чего, перейду в нее
mkdir ~/ansible
cd ~/ansible
Также создаем директорию для сохранения всех модулей для Ansible и так же, директорию для сохранения всех логов
mkdir ~/ansible/modules
mkdir ~/ansible/logs
Создадим конфиг файл
nano ~/ansible/ansible.cfg
В него прописываем:
[defaults]
become_user = root
log_path = ~/ansible/logs/ansible.log
inventory = /etc/ansible/hosts
##hostfile = ~/ansible/inventory
В новой версии ansible поля «hostfile» нет, за место его, есть другое:
inventory = /etc/ansible/hosts
Указываем обслуживаемые сервера в host inventory
Как я описывал раньше, данный файл, служит для внесения IP адресов всех имеющихся нод ( те, которые будут обслуживаться) и так же, сгруппирую их, добавляем в /etc/ansible/hosts
[test1]
192.168.1.16
Генерация ключа для ansible
ansible использует подключение SSH по ключу (для доступа к настраиваемым серверам), по этому, нужно сгенерировать его:
ssh-keygen -t rsa -b 4096 -C "admin@centos"
Создаем простой ключ, все пропускаем (нажимаем enter на все вопросы). После того как ключ сгенерировали, нужно его передать на все имеющийся ноды, для этого есть команда:
ssh-copy-id root@ip_адрес_настраиваемого_сервера
у меня это:
ssh-copy-id root@192.168.1.16
И так для каждой управляемой ноды!
Можно попинговать обслуживаемые сервера:
ansible test1 -m ping
192.168.1.16 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Можно пингануть и проверить все сервера
# ansible -m ping all
Модуль «shell, command» позволяет нам послать команду на удаленный хост и получить результаты. Например, чтобы узнать использование памяти на нашей машине some_your_host_1, мы могли бы использовать:
ansible -m command -a 'df -h' test1
192.168.1.16 | SUCCESS | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
6.5G 2.3G 3.9G 37% /
tmpfs 250M 0 250M 0% /dev/shm
/dev/sda1 477M 26M 427M 6% /boot
Управление ansible конфигурациями
Работа с playbook-ами
На playbook-ах основан собственно весь ansible, так как они служат ( содержат) для выполнения разных задач. Каждая написанная задача внутри самого Ansible использует кусок кода-модуля. Плейбуки, используют формат YAML, но собственно, любые другие ваши модули могут быть написаны на любом языке программирования.
Хочу заметить, что очень важно, чтобы формат сообщений от модулей был в JSON.
YAML
Каждый плейбук пишется на языке YAML и для ансибл, почти каждый YAML файл начинается с некоторого списка, а этот элемент данного списка — список пар «ключ-значение»(иногда зовут словарем).
Данные файлы обязаны начинаться с «—» (такой формат присущий YAML )и означает начало вашего документа.
Так же, все ваши списки должны находится с одинаковым отступом от начала каждой строки, и должны начинаться с пробела или «-«. Чтобы закомментировать, используйте «#».
Например:
#Message
- Administration
– Install
Словарь представлен в виде «ключ:» (двоеточие и пробел) «значение»:
#Message
site: sid.com1
blog: blog.linux-notes
При необходимости словари могут быть представлены в сокращенной форме:
#Comment
{site: linux-notes, blog: blog.linux-notes}
Можно указать логические значение (истина/ложь) так:
need_access: no
use_service: yes
file_conf: TRUE
read_value: True
kill_process: false
Целиком наш пример YAML–файла будет выглядеть так:
#About blog
site: sid.com1
blog: blog
must_read: True
themes:
- hosting
- cloud
- it
- geeks
brands:
- infobox
- infoboxcloud
Для переменных Ansible использует «{{ var }}». Если значение после двоеточия начинается с «{«, то YAML будет думать, что это словать.
Для использования переменных нужно заключить скобки в кавычки:
word: "{{ variable }}"
первый playbook
Playbooks может состоять из списка обслуживаемых серверов, переменных пользователя, задач, обработчиков (хендлеров) и т.д. Большинство настроек конфигурации можно переопределить в playbook. Каждый playbook состоит из одного или более действия (игры) в списке.
Цель игры — связать группу хостов с предопределенными ролями, представленными как вызов задач Ansible.
В качестве примера давайте рассмотрим процесс установки nginx.
Создадим директорию, где будут хранится playbooks:
mkdir ~/ansible/playbooks
Создадим файл setup_nginx.yml в директории playbooks:
vim ~/ansible/playbooks/setup_nginx.yml
со следующим содержанием:
- hosts: test1
tasks:
- name: Install nginx package
apt: name=nginx update_cache=yes
sudo: yes
- name: Starting nginx service
service: name=nginx state=started
sudo: yes
Давайте рассмотрим содержимое:
- hosts: Список хостов или группа, на которой вы запускаете задачу. Это поле обязательное и каждый playbook должен иметь его, за исключением ролей. Если указана хост-группа, сначала Ansible ее ищет в playbook, а затем в файле inventory. Узнать, на каких хостах будет происходить работа, можно командой: ansible-playbook —list-host, где – путь к вашему playbook (playbooks/setup_nginx.yml).
- tasks: Задачи. Все playbooks содержат задачи. Задача — это список действий, которые вы хотите выполнить. Поле задачи содержит имя задачи (справочная информация о задаче для пользователя playbook), модуль, который должен быть выполнен и аргументы, требуемые для модуля. Параметр «name» опциональный, но рекомендуемый.
Команды
playbook для ansible
Выполнение плейбука с названием test_job.yml для определенного хоста или группы хостов (прописано в файле):
ansible-playbook --check -i my_custom_hosts_file test_job.yml
Опция «-i» говорит ансиблу использовать произвольные хосты с файла. Иногда вы можете захотеть выполнить данный playbook (или часть его), только на определенных хостах. Вместо того, чтобы делать различные хосты в разные файлы, можно попробовать эти методы:
Используйте опцию «—limit» чтобы указать на каком хосте запустить указанный плейбук (например на host1):
ansible-playbook -i all_hosts.inventory some_playbook.yml --limit "your_host_1"
Используйте опцию «—limit» чтобы указать несколько хостов (розделенные запятыми), например для host1,host2,host3:
ansible-playbook -i all_hosts.inventory some_playbook.yml --limit "your_host_1,your_host_2,your_host_3"
Используйте опцию «—limit» чтобы указать диапазон подобных хостов, например host10-host20 или host5-15:
# ansible-playbook -i all_hosts.inventory some_playbook.yml --limit your_host[10-20]
# ansible-playbook -i all_hosts.inventory some_playbook.yml --limit your_host[5-15]
Используйте опцию «—limit» чтобы указать файл с которого будет браться хосты (должны идти в столбик):
# ansible-playbook -i all_hosts.inventory some_playbook.yml --limit @/path_to_file
Если вы не уверены в том, что опция «—limit» будет работать, вы можете использовать опцию «—list-hosts» и вы получите список хостов, на которых будет выполняться playbook.
Можно задавать так званые метки для некоторых задач и потом выполнять их по этим заданным меткам. Можно сделать задачу чтобы она выполнялась в любых условиях, независимо от меток. Это может быть сделано путем добавления:
always_run: yes
Примеры
Пример использования «—tags» и «—skip-tags», открываем main.yml файл и прописываем:
tasks:
- name: Copy MY_FILE_HERE_1
copy: src=/root/work/MY_FILE_HERE_1 dest=/root/work/MY_FILE_HERE_1
tags:
- MY_FILE_HERE_1
- name: Copy MY_FILE_HERE_2
copy: src=/root/work/MY_FILE_HERE_2 dest=/root/work/MY_FILE_HERE_2
tags:
- MY_FILE_HERE_2
- name: Copy MY_FILE_HERE_2
copy: src=/root/work/MY_FILE_HERE_3 dest=/root/work/MY_FILE_HERE_3
tags:
- MY_FILE_HERE_3
Теперь, если хотите скопирывать ТОЛЬКО MY_FILE_HERE_1, выполните:
# ansible-playbook main.yml --tags "MY_FILE_HERE_1"
Если хотите наоборот, скопировать все, НО КРОМЕ MY_FILE_HERE_1, запустите:
# ansible-playbook main.yml --skip-tags "MY_FILE_HERE_1"
Проверьте, какие задачи будут выполнены из данного плейбука «—tags или —skip-tags»:
# ansible-playbook main.yml --skip-tags "MY_FILE_HERE_1" --list-tags
# ansible-playbook main.yml --tags "MY_FILE_HERE_1" --list-tags
Пример хэш-цикла:
- name: vim files
synchronize:
src=/absolute/repo/path/roles/common/files/{{ item.src }}
dest={{ item.dst }}
with_items:
- {src: vim/bundle, dst: /home/jefdaj/.vim }
- {src: vim/vimrc , dst: /home/jefdaj/.vimrc}
- {src: vim/bundle, dst: /root/.vim }
- {src: vim/vimrc , dst: /root/.vimrc }
- name: vim permissions
file: path={{ item.pth }} owner={{ item.own }} group={{ item.grp }} recurse=yes
with_items:
- {pth: /root/.vim , own: root , grp: root }
- {pth: /root/.vimrc , own: root , grp: root }
- {pth: /home/jefdaj/.vim , own: jefdaj, grp: jefdaj}
- {pth: /home/jefdaj/.vimrc, own: jefdaj, grp: jefdaj}
Выполнить любую команду:
# ansible -i my_inventory all -a "/bin/uptime" -f 10
Запускаем команду «-a «/bin/uptime»» на всех хостах ( опция «all») с определенного файла (опция «-i») с установленным паралельным использованием в 10.
Запускаем команды с использованием модуля «shell»:
# ansible -i my_inventory some_host -m shell -a 'echo $TERM'
Где, some_host — Хост, на котором будет выполняться команда.
Копируем файл на удаленный сервер
$ ansible -i my_hosts -m copy -a "src=/my_local_path_file dest=my_destination_path_file"
Мы же создадим чистую роль:
# ansible-galaxy init jenkins-installation -p roles
PS: У меня запускается с текущей директории ( где находится проект с ансиблом).
Замена строк/слов в файле через ansible
При работе с ansible и файлами (конфигурационные файлы — как пример), очень просто найти и заменить нужную строку или слово чем скопировать файл на компьютер и редактировать его. В ансибле, имеется модуль lineinfile, который предоставляет функциональные возможности наподобие «sed». Конечно, можно использовать и утилиту sed, но если нужно заменить на разных серверах одну и туже строку во многих файлах — то для этой задачи хорошо подойдет ansible.
Это можно это сделать с помощью playbook-а:
- name: uncomment a line
lineinfile: dest=/etc/lighttpd/lighttpd.conf
regexp='^ include "mod_fastc gi.conf"'
insertafter='^# include "mod_fastc gi.conf"'
line=' include "mod_fastc gi.conf"'
state=present
Ниже представляет собой простой набор различных вариантов использования модуля lineinfile.
Создадим тестовый файл через ансибль для тестирования работы lineinfile модуля:
- name: create a complete empty file
command: /usr/bin/touch /home/vagrant/tmp.txt
Чтобы создать новую, пустую строку — используем:
- name: create a new file with lineinfile
lineinfile: dest=/home/vagrant/tmp.txt
regexp='^' line=''
state=present
create=True
Данный плейбук, создаст пустую строку. Сейчас, я покажу как можно ее заменить на что-то другое:
- name: add a string to the new file
lineinfile: dest=/home/vagrant/tmp.txt
regexp='^'
line='This works'
state=present
Добавим 5 строк в файл:
- name: add a multiline string to the file and delete the string from before
lineinfile: dest=/home/vagrant/tmp.txt
regexp='^'
line='#This is a 1st comment\n#The 2d comment\n#The 3d comment\n#The 4th a comment\n#The last comment'
state=present
Получаем:
$ cat tmp.txt
#This is a 1st comment
#The 2d comment
#The 3d comment
#The 4th a comment
#The last comment
Вставить строку, после заданной ( например после 1-й):
- name: add a single line, in this case the same as the comment but uncommented
lineinfile: dest=/home/vagrant/tmp.txt
regexp='^This'
insertafter='^#This'
line='This is a 1st comment'
state=present
Получаем:
$ cat tmp.txt
#This is a 1st comment
This is a 1st comment
#The 2d comment
#The 3d comment
#The 4th a comment
#The last comment
Удаляем определенную строку:
- name: remove the line '#This is a 1st comment'
lineinfile: dest=/home/vagrant/tmp.txt
regexp='^#This is a 1st comment'
state=absent
Вывод:
$ cat tmp.txt
This is a 1st comment
#The 2d comment
#The 3d comment
#The 4th a comment
#The last comment
Заменить строку ( в моем случае — это первая):
- name: change a str
lineinfile: dest=/home/vagrant/tmp.txt
regexp='^This'
insertbefore=BOF
line='This is no longer a comment'
Вот что вышло:
$ cat tmp.txt
This is no longer a comment
#The 2d comment
#The 3d comment
#The 4th a comment
#The last comment
Вставить строку перед указанной:
- name: add a new string before the match
lineinfile: dest=/home/vagrant/tmp.txt
regexp='^The 3d comment'
insertbefore='^#The 3d comment'
line='Another The 3d comment'
вывод
$ cat tmp.txt
This is no longer a comment
#The 2d comment
Another The 3d comment
#The 3d comment
#The 4th a comment
#The last comment
Вставляем строку в самый конец файла:
- name: add a new string at the end of the file
lineinfile: dest=/home/vagrant/tmp.txt
regexp=''
insertafter=EOF
line='The latest entry'
получаем:
$ cat tmp.txt
This is no longer a comment
#The 2d comment
Another The 3d comment
#The 3d comment
#The 4th a comment
The latest entry