Автоматизируем и ускоряем процесс настройки облачных серверов с Ansible. Часть 3: Переменные и файл inventory

    В первой части мы начали изучение Ansible, популярного инструмента для автоматизации настройки и развертывания ИТ-инфраструктуры. Ansible был успешно установлен, описаны принципы работы, базовая настройка. В завершении статьи мы показали как быстро установить nginx на несколько серверов.

    Во второй части мы разобрались в выводе playbook, научились отлаживать и повторно использовать скрипты Ansible.



    В этой части вы узнаете, как писать единый Ansible playbook для разных ОС (например с rpm и deb), как обслуживать множество хостов и не писать их все в inventory, как сгруппировать сервера по регионам InfoboxCloud и многое другое.

    Переменные в Ansible


    Переменные используются для хранения значений, которые могут применяться в playbook. В процессе использования переменные можно переопределять множество раз. Информация о серверах из inventory также может использоваться как переменные.

    Есть несколько способов определения переменных в Ansible:
    • передача файла переменных
    • определение переменных в playbook
    • передача в ansible-playbook, используя команду -e / --extra-vars
    • определение переменных в файле inventory

    Необходимость использования переменных отлично демонстрирует пример с установкой Apache. Дело в том, что в разных дистрибутивах пакет с apache называется по-разному. Разница в конфигурациях разных ОС встречается достаточно часто.
    Например:
    - set_fact package_name=httpd
      when: ansible_os_family == "Redhat"
    - set_fact package_name=apache2
      when: ansible_os_family == "Debian"
    

    Задача установит в переменную package_name значение httpd или apache2 в зависимости от семейства ОС на сервере.

    Переменные можно использовать для установки значений пользователя в процессе исполнения playbook:
    - name: Package to install
      pause: prompt="Provide the package name which you want to install "
      register: package_name
    

    В переменные удобно сохранить список значений для его многократного использования. Если одна и та же переменная используется во множестве playbook – их использование уменьшит сложность скриптов.

    Все переменные в Ansible должны начинаться с буквы. В имени можно использовать буквы, цифры и подчеркивания.
    Переменные, определенные в include файлах будут перегружать (заменять) переменные, определенные на других уровнях иерархии, кроме переменных, переданных через --extra-vars.

    Переменные в импортированных файлах

    Давайте рассмотрим, как можно использовать переменные из импортированных в playbook файлов.
    Сделаем отдельный файл задачи по установке Apache (~/ansible/playbooks/tasks/pkg_apache_install.yml):
      - 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=httpd state=latest
        sudo: yes
        when: ansible_os_family == "Redhat"
    
      - name: Install apache2 package
        apt: name=apache2 state=latest
        sudo: yes
        when: ansible_os_family == "Debian"
    

    Включим его в файл установки Apache и проверки, что сервис запущен (~/ansible/setup_apache.yml):
    ---
    - hosts: experiments
      remote_user: root
      tasks:
      - include: tasks/pkg_apache_install.yml
    
      - name: Check apache service
        service: name={{ package_name }} state=started
        sudo: yes
    

    Как мы видим, в файле setup_apache.yml мы успешно используем переменную, определенную во включенном файле. Данный playbook будет правильно устанавливать apache и на rpm дистрибутивы и на deb, используя правильное имя пакета с apache.



    Переменные в playbook

    Переменные в playbook устанавливаются с помощью ключевого слова vars:. Переменные устанавливаются в виде имя_переменной: значение. Переменные перегрузят другие переменные, которые установлены в глобальном файле или в inventory.

    Пример описания переменной в playbook:
    vars:
      - package_name: "httpd"
    


    Переменные в глобальном файле

    Переменные в Ansible можно задавать в отдельном файле, что позволяет отделить данные от playbook. Можно создавать столько файлов переменных, сколько необходимо, нужно только сказать playbook где их искать. Формат определения переменных в файле похож на формат определения переменных в Playbook.
    ~/ansible/common/vars/global.yml
    ---
    package_name: "httpd" #Apache
    
    #Enviroment variables
    proxy_env:
      INFOBOXCLOUD_API_KEY: "{{ lookup('env', 'INFOBOXCLOUD_API_KEY') }}"
      INFOBOXCLOUD_LOGIN: "{{ ('env', 'INFOBOXCLOUD_LOGIN') }}"
    

    В данном примере мы задаем переменную package_name напрямую (после # можно написать комментарий), а ключи доступа для InfoboxCloud API ищем в переменных окружения с помощью плагина lookup.

    В playbook путь к файлам переменных задается через vars_files:
    vars_files:
      - var1.yml
      - var2.yml
    


    Использование фактов как переменных

    Вы можете использовать любой факт как переменную, который собирается при gather_facts. Для получения списка всех фактов для конкретной группы машин используйте команду:
    ansible experiments -i inventory -m setup
    

    , где experiments – название группы машин в inventory.

    Погружаемся в inventory–файл


    В первой части мы кратко рассматривали простой inventory–файл. Давайте посмотрим на него внимательнее.

    Простой inventory (~/ansible/inventory):
    ansible.trukhin.com
    77.221.144.179
    

    Можно просто записать имена хостов и ip адреса и будут использоваться все сервера при исполнении playbook с этим файлом inventory.

    Группы в inventory

    Использование групп мы также уже видели ранее:
    [my]
    ansible.trukhin.com
    ansible2.trukhin.com
    [corp]
    ansible.sandbox.infoboxcloud.ru
    ansible2.sandbox.infoboxcloud.ru
    


    Группа для исполнения playbook указывается в разделе «hosts:» playbook
    hosts: my
    

    Если вы хотите использовать конкретный хост — можно в раздел hosts передать его.
    hosts: ansible.trukhin.com
    

    Если вы хотите использовать все хосты всех групп — можно использовать
    hosts: all
    


    Группы групп в inventory

    Очень полезная функция, позволяющая, например, сгруппировать хосты не только по назначению, но и по региону размещения, что очень актуально для InfoboxCloud (Москва, Амстердам). Нередко бывают и другие задачи, где нужно использовать группы групп.
    [msk]
    webMSK.trukhin.com
    dbMSK.trukhin.com
    [ams]
    webAMS.trukhin.com
    dbAMS.trukhin.com
    [web:children]
    msk
    ams
    

    В этом примере в группу web my входят сервера в Москве и Амстердаме. Можно из playbook обращаться как к группе web, так и к группам серверов в конкретном регионе.

    Регулярные выражения в inventory

    Если у вас есть большое количество серверов, использование соглашений о наименовании (например web001, web002… web00N) позволит проще указывать их в inventory. Можно использовать регулярные выражения в inventory файле:
    [web]
    web[001:200]
    [db]
    db[001:020]
    [balancer]
    192.168.2.[1:3]
    

    , где web[001:200] будет соответствовать web 001, web002, web003, web004, ..., web199, web200 для группы web;
    db[001:020] будет соответствовать db001, db002, db003 ..., db019, db020 для группы db.
    192.168.2.[1:30] будет соответствовать 192.168.2.1, 192.168.2.2, 192.168.2.3 для группы balancer.

    Переменные в inventory–файле

    Рассмотренные ранее способы установки переменных применяли их сразу ко всем хостам в inventory. Иногда может потребоваться использование специфических переменных для конкретной группы хостов или конкретного хоста.

    Установка переменных для конкретных хостов:
    ansible.trukhin.com
    web001
    db001 db_name=mysql
    192.168.2.1 db_name=redis db_port=6380
    

    Установка переменных для группы хостов (web):
    [web]
    web[001:010]
    [db]
    db[001:002]
    [web:vars]
    web_port=443
    


    Вынос переменных в отдельные файлы для inventory

    Можно создавать файлы переменных для хостов и для групп. Папки с этими файлами должны быть в одной директории с файлом inventory. Файлы переменных, относящиеся к конкретным хостам, нужно сохранять в папку host_vars, относящиеся к конкретным группам — в папку group_vars.

    Пример файла переменных для хоста web001 (~/ansible/host_vars/web001):
    web_port_ssl=443
    web_port=80
    

    Пример файла переменных для группы db (~/ansible/group_vars/db):
    db_port=6380
    db_name=redis
    

    Переменные inventory следуют иерархии: переменные в глобальном файле перегружают любые хост-переменные, групповые переменные и переменные в файле inventory. Хост-переменные перегружают групповые переменные, а в свою очередь групповые переменные перегружают переменные файла inventory.

    Через ansible.cfg можно переопределить параметры конфигурации Ansible.

    Заключение


    В написании статьи очень помогла книга "Learning Ansible" и конечно официальная документация.

    Все эксперименты с Ansible удобно проводить в InfoboxCloud, так как имеется возможность для каждого виртуального сервера установить именно то количество ресурсов, которое необходимо для задачи (CPU/Ram/диск независимо друг от друга) или использовать автомасштабирование, а не выбирать VM из готовых шаблонов. Когда эксперименты не проводятся — можно просто выключить VM и оплачивать только стоимость диска.

    Если вы обнаружили ошибку в статье, автор ее с удовольствием исправит. Пожалуйста напишите в ЛС или на почту о ней. Туда же можно задавать вопросы по Ansible для освещения в последующих статьях.

    Часть 4: работаем с модулями
    Часть 5: local_action, условия, циклы и роли

    Успешной работы!
    • +19
    • 19.3k
    • 2
    Infobox
    34.63
    Company
    Share post

    Comments 2

      0
      Основная проблема с переменными в ansible — что их можно много где описывать — и потом огрести проблемы с поддержкой. Поэтому необходимо с момента начала реальной эксплуатации вырабатывать некие правила работы с переменными.

      Поделюсь своими наработками:
      Максимум переменных выносим в роли, из них большинство должно находится в role/defaults/main.yml, то-есть быть переменными по-умолчанию.

      Если у вас много переменных, завязанных на конкретный проект|сервис, а роль используется для многих проектов|сервисов, то пока лучшее решение, что я нашел — это напротив хоста или в группе хостов ставить переменную project=bla, а внутри роли импортировать в переменных массив такого вида:
      role_foo_vars:
        - { project: 'bla', var1: '/var', var2: 'user', var3: 'group', var4: '42', var5: 'httpd' }
        - { project: 'bar', var1: '/var', var2: 'user2', var3: 'group2', var4: '42', var5: 'apache2' }
      

      в плейбуке строить шаги следующим образом:
          file: path={{ item[0].var1 }} owner={{ item[0].var2 }} group={{ item[0].var3 }} state=directory
          with_nested:
            - role_foo_vars
            - project
          when: "item[0].project == item[1]"
      

      этот шаг будет использовать переменные var1, var2 и var3 из массива, где в переменной project стоит необходимое значение (в нашем случае — bla).
      • UFO just landed and posted this here

      Only users with full accounts can post comments. Log in, please.