вторник, 23 февраля 2016 г.

Ansible: playbook установки nginx

Тут я рассказывал, как я первый раз устанавливал ansible: http://blog.amet13.name/2016/02/ansible.html

В этой части я создам свой первый полезный playbook.

В предыдущей части я использовал так называемый Ad-Hoc режим.
Для Ad-Hoc режима используется команда /usr/bin/ansible.
Для плейбуков используется команда /usr/bin/ansible-playbook. Плейбуки - это файлы в формате YAML (.yml) которые содержат описание необходимых для выполнения операций.

Примеры плейбуков:
https://github.com/ansible/ansible-examples

Каждый playbook состоит из одного или нескольких plays. В свою очередь каждый play состоит из списка заданий (tasks).
Хендлеры (handlers) - списки задач, которые выполняются в блоке notify, выполняются они после выполнения всех tasks, используются в основном для перезагрузки сервисов.
Роли (roles) позволяют структурированно организовать плейбуки и отделять "мух от котлет" упрощая работу с хостами.

Пример структуры ролей common и webservers:
site.yml
webservers.yml
fooservers.yml
roles/
   common/
     files/
     templates/
     tasks/
     handlers/
     vars/
     defaults/
     meta/
   webservers/
     files/
     templates/
     tasks/
     handlers/
     vars/
     defaults/
     meta/
   
Запускается плейбук командой:
# ansible-playbook playbook.yml -f 10
где -f 10 опционально запускается команда в 10 потоков.

Команда ansible-pull может пригодиться для чекаута репозитория ansible.

Примеры ролей можно посмотреть тут: https://galaxy.ansible.com/

Создадим первый плейбук, этот плейбук будет устанавливать httpd на все хосты группы centos:
[root@ansible ~]# grep "\[centos\]" -A1 /etc/ansible/hosts
[centos]
centos7.host.tld
[root@ansible ~]# vim /etc/ansible/install_httpd.yml
---
- hosts: centos
  tasks:
  - name: Install httpd
    yum: name=httpd state=present

  - name: Starting httpd
    service: name=httpd state=started

Параметр --list-host позволяет перед запуском вывести список хостов, для который будет запущен плейбук:
[root@ansible ~]# cd /etc/ansible/
[root@ansible ansible]# ansible-playbook install_httpd.yml --list-host
playbook: install_httpd.yml
  play #1 (centos): host count=1
    centos7.host.tld
[root@ansible ansible]# ansible-playbook install_httpd.yml
...
PLAY RECAP ******************************************************************** 
centos7.host.tld           : ok=3    changed=2    unreachable=0    failed=0   

Удалить httpd можно по аналогии:
[root@ansible ansible]# vim remove_httpd.yml
---
- hosts: centos
  tasks:
  - name: Install httpd
    yum: name=httpd state=absent

Если мы имеем дело не только с CentOS, а например еще и с Debian/Ubuntu, то установить apache просто так не выйдет.

Установим apache для всех хостов:
[root@ansible ansible]# vim install_apache2.yml
---
- hosts: all
  tasks:
  - name: Debug
    debug: msg={{ ansible_os_family }}

  - set_fact: package_name=httpd
    when: ansible_os_family == "RedHat"

  - set_fact: package_name=apache2
    when: ansible_os_family == "Debian"

  - name: Install httpd package
    yum: name={{ package_name }} state=latest
    when: ansible_os_family == "RedHat"

  - name: Install apache2 package
    apt: name={{ package_name }} state=latest
    when: ansible_os_family == "Debian"

[root@ansible ansible]# ansible-playbook install_apache2.yml --list-hosts
playbook: install_apache2.yml
  play #1 (all): host count=3
    centos7.host.tld
    ubuntu14.host.tld
    debian8.host.tld

[root@ansible ansible]# ansible-playbook install_apache2.yml
...
PLAY RECAP ******************************************************************** 
centos7.host.tld           : ok=5    changed=1    unreachable=0    failed=0   
debian8.host.tld           : ok=5    changed=1    unreachable=0    failed=0   
ubuntu14.host.tld          : ok=5    changed=1    unreachable=0    failed=0   

Значения переменных посмотреть например так:
# ansible -m setup centos7.host.tld

Фильтровать значения можно так:
# ansible all -m setup -a "filter=ansible_distribution*"

Тут мы научились ставить apache на разные дистрибутивы с использованием переменных.

Далее задачка чуть посложнее.
На всех трех хостах нужно установить nginx и на каждой виртуалке создать виртуальный хост, при котором будет открываться index.html из шаблона.
Создаем структуру каталогов для плейбука:
[root@ansible ansible]# mkdir -p /etc/ansible/roles/nginx/{handlers,tasks,templates,vars}

Наш хендлер, просто ребутает nginx:
[root@ansible ansible]# vim /etc/ansible/roles/nginx/handlers/main.yml
---
- name: restart nginx
  service: name=nginx state=restarted enabled=yes

Собственно говоря сами таски.
Для CentOS нужно установить EPEL, т.к. в базовых репах CentOS 7 nginx'а нет.
После установки nginx создается директория /srv/имя_хоста, где имя_хоста берется из инвентори ansible.
Затем создается виртуальный хост для nginx из шаблона default.conf, а также копируется файл index.html из шаблона в root виртхоста. После этого запускается хендлер, который ребутает nginx:
[root@ansible ansible]# vim /etc/ansible/roles/nginx/tasks/main.yml
---
- name: Install epel
  yum: name=epel-release state=present
  when: ansible_os_family == "RedHat"

- name: Install nginx CentOS
  yum: name=nginx state=present
  when: ansible_os_family == "RedHat"

- name: Install nginx Debian/Ubuntu
  apt: name=nginx state=present
  when: ansible_os_family == "Debian"

- name: Create directory for virtualhost
  file: dest=/srv/{{ server_name }} state=directory

- name: Copy virtualhost config
  template: src=default.conf dest=/etc/nginx/conf.d/{{ server_name }}.conf

- name: Copy index.html
  template: src=index.html dest=/srv/{{ server_name}}/index.html
  notify: restart nginx

Вот как выглядит шаблон виртхоста:
[root@ansible ansible]# vim /etc/ansible/roles/nginx/templates/default.conf
server {
        listen       80;
        server_name  {{ server_name }};
        root /srv/{{ server_name }};

        location / {
                index index.html index.htm;
        }
}

А это шаблон index.html:
[root@ansible ansible]# vim /etc/ansible/roles/nginx/templates/index.html
Hello! My name is {{ server_name }}

Та самая переменная server_name, которая использует значение переменной ansible_fqdn:
[root@ansible ansible]# vim /etc/ansible/roles/nginx/vars/main.yml
---
server_name: "{{ ansible_fqdn }}"

И собственно сам плейбук, запускает нужные роли на нужных хостах:
[root@ansible ansible]# vim /etc/ansible/nginx.yml
---
- name: Install nginx on different VM's
  hosts: all
  roles:
    - nginx

Запускаем плейбук:
[root@ansible ansible]# ansible-playbook nginx.yml
...
PLAY RECAP ******************************************************************** 
centos7.host.tld           : ok=7    changed=6    unreachable=0    failed=0   
debian8.host.tld           : ok=6    changed=5    unreachable=0    failed=0   
ubuntu14.host.tld          : ok=6    changed=5    unreachable=0    failed=0  

Проверка:
[root@ansible ~]# curl ubuntu14.host.tld
Hello! My name is ubuntu14.host.tld
[root@ansible ~]# curl debian8.host.tld
Hello! My name is debian8.host.tld
[root@ansible ~]# curl centos7.host.tld
Hello! My name is centos7.host.tld

Целью заметки было попробовать установить окружение на разных дистрибутивах, попробовать использовать переменные, разобраться в костяке ролей и разобраться в условии when.

Комментариев нет: