Первое мое знакомство с ansible, крутая штука.
В этой заметке оставлю основные выдержки из вводной документации: http://docs.ansible.com/ansible/intro.html
В VirtualBox развернул Virtuozzo 7, а в нем окружение, в котором я буду тестировать ansible.
Выглядит это так, ansible.host.tld - мастер-сервер ансибла, остальные три виртуалки подопытые кролики:
[root@virtuozzo ~]# prlctl list -o name,ip,ostemplate,hostname
NAME IP_ADDR OSTEMPLATE HOSTNAME
ansible-c7 192.168.0.151 .centos-7-x86_64 ansible.host.tld
centos7 192.168.0.154 .centos-7-x86_64 centos7.host.tld
debian8 192.168.0.153 .debian-8.0-x86_64 debian8.host.tld
ubuntu14 192.168.0.152 .ubuntu-14.04-x86_64 ubuntu14.host.tld
Ansible удобен в первую очередь тем, что на агентах ему не нужно ничего ставить, т.к. общение между мастером и агентами происходит по SSH, никаких тебе демонов, сервисов, кучи зависимостей в виде ruby и прочих Java.
Установка ansible на мастере в CentOS 7:
[root@ansible ~]# yum install epel-release git
[root@ansible ~]# yum install ansible
[root@ansible ~]# ansible --version
ansible 1.9.4
configured module search path = None
В EPEL для RHEL7 до сих пор версия 1.9.4, хотя уже давно 2.0.0 есть для той же Ubuntu.
Пробовал я и с помощью исходников ставить на CentOS 7, но у меня при компиляции просил какой-то пакет asciidoc, который тянет за собой половину иксов, поэтому я поставил с EPEL'а.
Для инвентаризации хостов ansible использует так называемы инвентори-файл /etc/ansible/hosts.
Приведем его к такому виду:
[root@ansible ~]# vim /etc/ansible/hosts
centos7.host.tld
debian8.host.tld
ubuntu14.host.tld
Я внес туда список хостнеймов моих подопытных виртуалок, но т.к. у меня локальная сеть и DNS-сервер я не настраивал, то дополнительно я еще и добавлю такие записи в /etc/hosts:
[root@ansible ~]# vim /etc/hosts
192.168.0.152 ubuntu14.host.tld
192.168.0.153 debian8.host.tld
192.168.0.154 centos7.host.tld
Далее сгенерируем SSH-ключ и раскидаем его по виртуалкам, чтобы постоянно не вводить пароль:
[root@ansible ~]# ssh-keygen
[root@ansible ~]# ls /root/.ssh/
authorized_keys id_rsa id_rsa.pub
[root@ansible ~]# cat /etc/ansible/hosts | xargs -i ssh-copy-id {}
После того как ключи раскиданы, можно проверить коннект:
[root@ansible ~]# ansible all -m ping
ubuntu14.host.tld | success >> {
"changed": false,
"ping": "pong"
}
debian8.host.tld | success >> {
"changed": false,
"ping": "pong"
}
centos7.host.tld | success >> {
"changed": false,
"ping": "pong"
}
Все работает.
Приведем инвентори к такому виду:
[root@ansible ~]# vim /etc/ansible/hosts
[frontend]
centos7.host.tld:2222
[backend]
debian8.host.tld
[backend:vars]
frontend_server=centos7
database_server=ubuntu14
[database]
ubuntu14.host.tld backend_server=debian8
Здесь в инвентори в.ini формате можно объединять хосты в группы и создавать переменные.
Например я тут создал группы frontend, backend и database, понятно, какие хосты к каким группам относятся.
Для группы backend установлены две переменные frontend_server и backend_server, которые впоследствии мы сможем использовать.
Для хоста ubuntu15.host.tld установили переменную backend_server=debian8.
Строка centos7.host.tld:2222 указывает подключение к порту 2222 по SSH.
Хранение переменных нежелательно в инвентори файле, предпочтительно хранить их отдельно. Пример:
[root@ansible ~]# mkdir /etc/ansible/{host,group}_vars
[root@ansible ~]# vim /etc/ansible/group_vars/backend
---
frontend_server: centos7
database_server: ubuntu14
[root@ansible ~]# vim /etc/ansible/host_vars/ubuntu14.host.tld
---
backend_server: debian8
[root@ansible ~]# vim group_vars/frontend
---
ansible_ssh_port: 2222
# Тут стоит обратить внимание на то, что с версии ansible 2.0
# имена переменных меняются, например на ansible_port
# http://docs.ansible.com/ansible/intro_inventory.html#list-of-behavioral-inventory-parameters
Таким образом я аккуратно разнес переменные для хостов и групп по файлам. А также указал, что для хостов группы frontend порт для подключения SSH 2222.
Теперь можно привести инвентори снова к такому виду:
[root@ansible ~]# cat /etc/ansible/hosts
[frontend]
centos7.host.tld
[backend]
debian8.host.tld
[database]
ubuntu14.host.tld
Я в самом начале устанавливал git не зря, ведь удобно хранить все конфиги ansible в репозитории:
[root@ansible ~]# cd /etc/ansible/
[root@ansible ansible]# git init
Initialized empty Git repository in /etc/ansible/.git/
[root@ansible ansible]# git config --global user.name "Amet13"
[root@ansible ansible]# git config --global user.email [email protected]
[root@ansible ansible]# git commit -m "First commited ansible configuration"
Пример использования ansible, отключаем httpd на frontend-серверах:
[root@centos7 ~]# systemctl is-active httpd
active
[root@ansible ~]# ansible frontend -m service -a "name=httpd state=stopped"
centos7.host.tld | success >> {
"changed": true,
"name": "httpd",
"state": "stopped"
}
[root@centos7 ~]# systemctl is-active httpd
inactive
Вместо группы frontend можно указать all или *, тогда httpd отключится на всех хостах, можно указать только хостнейм, например debian8.host.tld.
Отправить ping только группам backend и frontend:
[root@ansible ~]# ansible backend:frontend -m ping
Для примера добавим centos7.host.tld в секцию frontend и backend:
[root@ansible ~]# vim /etc/ansible/hosts
[frontend]
centos7.host.tld
[backend]
debian8.host.tld
centos7.host.tld
...
И пропингуем все хосты, которые находятся в группе backend, но не находятся в группе frontend:
[root@ansible ~]# ansible backend:\!frontend -m ping
debian8.host.tld | success >> {
"changed": false,
"ping": "pong"
}
Как видим пинг отправился только для debian8.host.tld, который находится только в группе backend.
Можно использовать подстановки для хостнеймов и IP:
[root@ansible ~]# ansible *.host.tld -m ping
С этими возможностями можно делать множество различиных подстановок.
Более подробно тут: http://docs.ansible.com/ansible/intro_patterns.html#patterns
По умолчанию модуль command не поддерживает пайпы, кавычки, переменные, например при выполнении такой команды:
[root@ansible ~]# ansible frontend -a 'cat /etc/passwd | wc -l'
centos7.host.tld | FAILED | rc=1 >>
cat: invalid option -- 'l'
Try 'cat --help' for more information.
Для этого нужно использовать модуль shell:
[root@ansible ~]# ansible frontend -m shell -a 'cat /etc/passwd | wc -l'
centos7.host.tld | success | rc=0 >>
26
Либо второй вариант, в /etc/ansible/ansible.cfg изменить:
module_name = command
на
module_name = shell
Модуль copy позволяет посредством scp копировать файлы на хосты:
[root@ansible ~]# ansible backend -m copy -a 'src=/etc/hosts dest=/tmp/hosts'
Модуль file позволяет менять владельца файла и права на него.
root@debian8:~# ls -l /tmp/hosts
-rw-r--r-- 1 root root 353 Feb 20 13:09 /tmp/hosts
[root@ansible ~]# ansible backend -m file -a 'dest=/tmp/hosts mode=600 owner=mail group=mail'
root@debian8:~# ls -l /tmp/hosts
-rw------- 1 mail mail 353 Feb 20 13:09 /tmp/hosts
Создать директорию:
[root@ansible ~]# ansible backend -m file -a 'dest=/tmp/dir/test state=directory'
root@debian8:~# ls /tmp/dir/ -l
total 0
drwxr-xr-x 2 root root 40 Feb 20 13:15 test
Рекурсивно удалить директорию:
[root@ansible ~]# ansible backend -m file -a 'dest=/tmp/dir/ state=absent'
root@debian8:~# ls /tmp/dir/ -l
ls: cannot access /tmp/dir/: No such file or directory
Управление пакетами.
Создадим в инвентори группы centos и debian-ubuntu для удобства управления пакетами:
[root@ansible ~]# cat /etc/ansible/hosts
...
[centos]
centos7.host.tld
[debian-ubuntu]
debian8.host.tld
ubuntu14.host.tld
Установим httpd на все хосты с CentOS:
[root@ansible ~]# ansible centos -m yum -a 'name=httpd state=present'
И удалим его сразу:
[root@ansible ~]# ansible centos -m yum -a 'name=httpd state=absent'
Аналогично с apache2 для Debian/Ubuntu:
[root@ansible ~]# ansible debian-ubuntu -m apt -a 'name=apache2 state=present'
root@debian8:~# systemctl is-active apache2
active
[root@ansible ~]# ansible debian-ubuntu -m apt -a 'name=apache2 state=absent'
root@debian8:~# systemctl is-active apache2
inactive
Создание и удаление пользователей:
[root@ansible ~]# ansible debian-ubuntu -m user -a 'name=ansible-user password=$6$IT91ljNr$vfLfnBi4ntlyqsmCa8feNLCwmruv5iZLxW6ZOwcCZ1dOFHrOdithHRbqWdLnTueLi5nf0bDiI3TSYpa51Z/QW/'
[root@ansible ~]# ssh [email protected]
[email protected]'s password: 123456
[root@ansible ~]# ansible debian-ubuntu -m user -a 'name=ansible-user state=absent'
Пример пароля можно сгенерить так:
[root@ansible ~]# mkpasswd --method=sha-512
Password:
$6$yX3fe4eqN6C4lqFO$q86.JTDz3ShkPnErY8HdiOf9HYaGzKHw79TBD6SUnOOWpdN0.raq8ZIBAdOpDd5LYnzpV.yfnsfZlj04ZvfiI.
Модуль git используется для деплоймента приложений например:
[root@ansible ~]# ansible frontend -m yum -a 'name=git state=present'
[root@ansible ~]# ansible frontend -m git -a 'repo=https://github.com/Amet13/icinga2-plugins-extra.git dest=/srv version=HEAD'
[root@centos7 ~]# cat /srv/.git/config | grep url
url = https://github.com/Amet13/icinga2-plugins-extra.git
Управление сервисами, тут все понятно:
[root@ansible ~]# ansible debian-ubuntu -m service -a 'name=postfix state=started'
[root@ansible ~]# ansible debian-ubuntu -m service -a 'name=postfix state=restarted'
[root@ansible ~]# ansible debian-ubuntu -m service -a 'name=postfix state=stopped'
Запуск задачи в фоновом режиме:
[root@ansible ~]# ansible all -B 60 -P 0 -a 'ping ya.ru'
background launch...
[root@ansible ~]# ansible ubuntu14.host.tld -m async_status -a "jid=254659849531.1643"
ubuntu14.host.tld | success >> {
"ansible_job_id": "254659849531.1643",
"changed": false,
"finished": 0,
"results_file": "/root/.ansible_async/254659849531.1643",
"started": 1
}
Порядок чтения конфигов ansible'ом:
1. Переменная ANSIBLE_CONFIG
2. ansible.cfg в текущей директории
3. .ansible.cfg в домашней директории
4. /etc/ansible/ansible.cfg
В этой заметке оставлю основные выдержки из вводной документации: http://docs.ansible.com/ansible/intro.html
В VirtualBox развернул Virtuozzo 7, а в нем окружение, в котором я буду тестировать ansible.
Выглядит это так, ansible.host.tld - мастер-сервер ансибла, остальные три виртуалки подопытые кролики:
[root@virtuozzo ~]# prlctl list -o name,ip,ostemplate,hostname
NAME IP_ADDR OSTEMPLATE HOSTNAME
ansible-c7 192.168.0.151 .centos-7-x86_64 ansible.host.tld
centos7 192.168.0.154 .centos-7-x86_64 centos7.host.tld
debian8 192.168.0.153 .debian-8.0-x86_64 debian8.host.tld
ubuntu14 192.168.0.152 .ubuntu-14.04-x86_64 ubuntu14.host.tld
Ansible удобен в первую очередь тем, что на агентах ему не нужно ничего ставить, т.к. общение между мастером и агентами происходит по SSH, никаких тебе демонов, сервисов, кучи зависимостей в виде ruby и прочих Java.
Установка ansible на мастере в CentOS 7:
[root@ansible ~]# yum install epel-release git
[root@ansible ~]# yum install ansible
[root@ansible ~]# ansible --version
ansible 1.9.4
configured module search path = None
В EPEL для RHEL7 до сих пор версия 1.9.4, хотя уже давно 2.0.0 есть для той же Ubuntu.
Пробовал я и с помощью исходников ставить на CentOS 7, но у меня при компиляции просил какой-то пакет asciidoc, который тянет за собой половину иксов, поэтому я поставил с EPEL'а.
Для инвентаризации хостов ansible использует так называемы инвентори-файл /etc/ansible/hosts.
Приведем его к такому виду:
[root@ansible ~]# vim /etc/ansible/hosts
centos7.host.tld
debian8.host.tld
ubuntu14.host.tld
Я внес туда список хостнеймов моих подопытных виртуалок, но т.к. у меня локальная сеть и DNS-сервер я не настраивал, то дополнительно я еще и добавлю такие записи в /etc/hosts:
[root@ansible ~]# vim /etc/hosts
192.168.0.152 ubuntu14.host.tld
192.168.0.153 debian8.host.tld
192.168.0.154 centos7.host.tld
Далее сгенерируем SSH-ключ и раскидаем его по виртуалкам, чтобы постоянно не вводить пароль:
[root@ansible ~]# ssh-keygen
[root@ansible ~]# ls /root/.ssh/
authorized_keys id_rsa id_rsa.pub
[root@ansible ~]# cat /etc/ansible/hosts | xargs -i ssh-copy-id {}
После того как ключи раскиданы, можно проверить коннект:
[root@ansible ~]# ansible all -m ping
ubuntu14.host.tld | success >> {
"changed": false,
"ping": "pong"
}
debian8.host.tld | success >> {
"changed": false,
"ping": "pong"
}
centos7.host.tld | success >> {
"changed": false,
"ping": "pong"
}
Все работает.
Приведем инвентори к такому виду:
[root@ansible ~]# vim /etc/ansible/hosts
[frontend]
centos7.host.tld:2222
[backend]
debian8.host.tld
[backend:vars]
frontend_server=centos7
database_server=ubuntu14
[database]
ubuntu14.host.tld backend_server=debian8
Здесь в инвентори в.ini формате можно объединять хосты в группы и создавать переменные.
Например я тут создал группы frontend, backend и database, понятно, какие хосты к каким группам относятся.
Для группы backend установлены две переменные frontend_server и backend_server, которые впоследствии мы сможем использовать.
Для хоста ubuntu15.host.tld установили переменную backend_server=debian8.
Строка centos7.host.tld:2222 указывает подключение к порту 2222 по SSH.
Хранение переменных нежелательно в инвентори файле, предпочтительно хранить их отдельно. Пример:
[root@ansible ~]# mkdir /etc/ansible/{host,group}_vars
[root@ansible ~]# vim /etc/ansible/group_vars/backend
---
frontend_server: centos7
database_server: ubuntu14
[root@ansible ~]# vim /etc/ansible/host_vars/ubuntu14.host.tld
---
backend_server: debian8
[root@ansible ~]# vim group_vars/frontend
---
ansible_ssh_port: 2222
# Тут стоит обратить внимание на то, что с версии ansible 2.0
# имена переменных меняются, например на ansible_port
# http://docs.ansible.com/ansible/intro_inventory.html#list-of-behavioral-inventory-parameters
Таким образом я аккуратно разнес переменные для хостов и групп по файлам. А также указал, что для хостов группы frontend порт для подключения SSH 2222.
Теперь можно привести инвентори снова к такому виду:
[root@ansible ~]# cat /etc/ansible/hosts
[frontend]
centos7.host.tld
[backend]
debian8.host.tld
[database]
ubuntu14.host.tld
[root@ansible ~]# cd /etc/ansible/
[root@ansible ansible]# git init
Initialized empty Git repository in /etc/ansible/.git/
[root@ansible ansible]# git config --global user.name "Amet13"
[root@ansible ansible]# git config --global user.email [email protected]
[root@ansible ansible]# git commit -m "First commited ansible configuration"
Пример использования ansible, отключаем httpd на frontend-серверах:
[root@centos7 ~]# systemctl is-active httpd
active
[root@ansible ~]# ansible frontend -m service -a "name=httpd state=stopped"
centos7.host.tld | success >> {
"changed": true,
"name": "httpd",
"state": "stopped"
}
[root@centos7 ~]# systemctl is-active httpd
inactive
Вместо группы frontend можно указать all или *, тогда httpd отключится на всех хостах, можно указать только хостнейм, например debian8.host.tld.
Отправить ping только группам backend и frontend:
[root@ansible ~]# ansible backend:frontend -m ping
Для примера добавим centos7.host.tld в секцию frontend и backend:
[root@ansible ~]# vim /etc/ansible/hosts
[frontend]
centos7.host.tld
[backend]
debian8.host.tld
centos7.host.tld
...
И пропингуем все хосты, которые находятся в группе backend, но не находятся в группе frontend:
[root@ansible ~]# ansible backend:\!frontend -m ping
debian8.host.tld | success >> {
"changed": false,
"ping": "pong"
}
Как видим пинг отправился только для debian8.host.tld, который находится только в группе backend.
Можно использовать подстановки для хостнеймов и IP:
[root@ansible ~]# ansible *.host.tld -m ping
С этими возможностями можно делать множество различиных подстановок.
Более подробно тут: http://docs.ansible.com/ansible/intro_patterns.html#patterns
По умолчанию модуль command не поддерживает пайпы, кавычки, переменные, например при выполнении такой команды:
[root@ansible ~]# ansible frontend -a 'cat /etc/passwd | wc -l'
centos7.host.tld | FAILED | rc=1 >>
cat: invalid option -- 'l'
Try 'cat --help' for more information.
[root@ansible ~]# ansible frontend -m shell -a 'cat /etc/passwd | wc -l'
centos7.host.tld | success | rc=0 >>
26
Либо второй вариант, в /etc/ansible/ansible.cfg изменить:
module_name = command
на
module_name = shell
Модуль copy позволяет посредством scp копировать файлы на хосты:
[root@ansible ~]# ansible backend -m copy -a 'src=/etc/hosts dest=/tmp/hosts'
Модуль file позволяет менять владельца файла и права на него.
root@debian8:~# ls -l /tmp/hosts
-rw-r--r-- 1 root root 353 Feb 20 13:09 /tmp/hosts
[root@ansible ~]# ansible backend -m file -a 'dest=/tmp/hosts mode=600 owner=mail group=mail'
root@debian8:~# ls -l /tmp/hosts
-rw------- 1 mail mail 353 Feb 20 13:09 /tmp/hosts
Создать директорию:
[root@ansible ~]# ansible backend -m file -a 'dest=/tmp/dir/test state=directory'
root@debian8:~# ls /tmp/dir/ -l
total 0
drwxr-xr-x 2 root root 40 Feb 20 13:15 test
Рекурсивно удалить директорию:
[root@ansible ~]# ansible backend -m file -a 'dest=/tmp/dir/ state=absent'
root@debian8:~# ls /tmp/dir/ -l
ls: cannot access /tmp/dir/: No such file or directory
Управление пакетами.
Создадим в инвентори группы centos и debian-ubuntu для удобства управления пакетами:
[root@ansible ~]# cat /etc/ansible/hosts
...
[centos]
centos7.host.tld
[debian-ubuntu]
debian8.host.tld
ubuntu14.host.tld
Установим httpd на все хосты с CentOS:
[root@ansible ~]# ansible centos -m yum -a 'name=httpd state=present'
И удалим его сразу:
[root@ansible ~]# ansible centos -m yum -a 'name=httpd state=absent'
Аналогично с apache2 для Debian/Ubuntu:
[root@ansible ~]# ansible debian-ubuntu -m apt -a 'name=apache2 state=present'
root@debian8:~# systemctl is-active apache2
active
[root@ansible ~]# ansible debian-ubuntu -m apt -a 'name=apache2 state=absent'
root@debian8:~# systemctl is-active apache2
inactive
Создание и удаление пользователей:
[root@ansible ~]# ansible debian-ubuntu -m user -a 'name=ansible-user password=$6$IT91ljNr$vfLfnBi4ntlyqsmCa8feNLCwmruv5iZLxW6ZOwcCZ1dOFHrOdithHRbqWdLnTueLi5nf0bDiI3TSYpa51Z/QW/'
[root@ansible ~]# ssh [email protected]
[email protected]'s password: 123456
[root@ansible ~]# ansible debian-ubuntu -m user -a 'name=ansible-user state=absent'
Пример пароля можно сгенерить так:
[root@ansible ~]# mkpasswd --method=sha-512
Password:
$6$yX3fe4eqN6C4lqFO$q86.JTDz3ShkPnErY8HdiOf9HYaGzKHw79TBD6SUnOOWpdN0.raq8ZIBAdOpDd5LYnzpV.yfnsfZlj04ZvfiI.
Модуль git используется для деплоймента приложений например:
[root@ansible ~]# ansible frontend -m yum -a 'name=git state=present'
[root@ansible ~]# ansible frontend -m git -a 'repo=https://github.com/Amet13/icinga2-plugins-extra.git dest=/srv version=HEAD'
[root@centos7 ~]# cat /srv/.git/config | grep url
url = https://github.com/Amet13/icinga2-plugins-extra.git
Управление сервисами, тут все понятно:
[root@ansible ~]# ansible debian-ubuntu -m service -a 'name=postfix state=started'
[root@ansible ~]# ansible debian-ubuntu -m service -a 'name=postfix state=restarted'
[root@ansible ~]# ansible debian-ubuntu -m service -a 'name=postfix state=stopped'
Запуск задачи в фоновом режиме:
[root@ansible ~]# ansible all -B 60 -P 0 -a 'ping ya.ru'
background launch...
[root@ansible ~]# ansible ubuntu14.host.tld -m async_status -a "jid=254659849531.1643"
ubuntu14.host.tld | success >> {
"ansible_job_id": "254659849531.1643",
"changed": false,
"finished": 0,
"results_file": "/root/.ansible_async/254659849531.1643",
"started": 1
}
Порядок чтения конфигов ansible'ом:
1. Переменная ANSIBLE_CONFIG
2. ansible.cfg в текущей директории
3. .ansible.cfg в домашней директории
4. /etc/ansible/ansible.cfg
По конфигу можно почитать тут, информация периодически меняется:
http://docs.ansible.com/ansible/intro_configuration.html
Тут я познакомился с плейбуками в nginx (рекомендую к ознакомлению): http://blog.amet13.name/2016/02/ansible-playbook-nginx.html
Ссылки пригодятся:
Книга Ansible for DevOps: https://www.dropbox.com/sh/m9z66tysri8l53f/AADa3vMrwjb8XyUXMXqxZpGga/pub/eng/administration/Ansible%20for%20DevOps.pdf
Получасовое видео о Ansible, где четко поясняют основы: https://www.ansible.com/get-started
Получасовое видео о Ansible, где четко поясняют основы: https://www.ansible.com/get-started
Очень хороший пост. Все понятно и есть примеры для практического использования.
ОтветитьУдалитьХотя я для того же в основном работаю через pssh, он конечно не на столько удобный в описании нужных хостов (нельзя там убрать хосты что повторяются в другом списке), и для выполнения нужной команда нужно описать как она выглядит в shell.
О вспомнил.. один вопрос возник.
ОтветитьУдалитьДля того, чтобы всё-таки вводить пароль, если не делать проброс ключа, то как команда должна выглядеть, хотя бы того же пинга?
http://docs.ansible.com/ansible/intro_getting_started.html
ОтветитьУдалить>When speaking with remote machines, Ansible by default assumes you are using SSH keys. SSH keys are encouraged but password authentication can also be used where needed by supplying the option --ask-pass. If using sudo features and when sudo requires a password, also supply --ask-become-pass (previously --ask-sudo-pass which has been deprecated).