We automate and speed up the process of setting up cloud servers with Ansible. Part 3: Variables and inventory file

    In the first part, we started exploring Ansible, a popular tool for automating the configuration and deployment of IT infrastructure. Ansible has been successfully installed, the principles of operation, basic configuration are described. At the end of the article, we showed how to quickly install nginx on several servers.

    In the second part, we figured out the output of a playbook, learned how to debug and reuse Ansible scripts.



    In this part, you will learn how to write a single Ansible playbook for different operating systems (for example, with rpm and deb), how to serve many hosts and not write all of them in inventory, how to group servers by InfoboxCloud regions and much more.

    Variables in Ansible


    Variables are used to store values ​​that can be used in a playbook. During use, variables can be redefined many times. Server information from inventory can also be used as variables.

    There are several ways to define variables in Ansible:
    • variable file transfer
    • defining variables in a playbook
    • transfer to ansible-playbook using the -e / --extra-vars command
    • definition of variables in inventory file

    The need to use variables is excellently demonstrated by the Apache installation example. The fact is that in different distributions, the package with apache is called differently. The difference in the configurations of different operating systems is quite common.
    For instance:
    - set_fact package_name=httpd
      when: ansible_os_family == "Redhat"
    - set_fact package_name=apache2
      when: ansible_os_family == "Debian"
    

    The task sets the package_name variable to httpd or apache2 depending on the OS family on the server.

    Variables can be used to set user values ​​during the execution of a playbook:
    - name: Package to install
      pause: prompt="Provide the package name which you want to install "
      register: package_name
    

    It is convenient to save a list of values ​​into variables for reuse. If the same variable is used in many playbooks, using them will reduce the complexity of the scripts.

    All variables in Ansible must begin with a letter. You can use letters, numbers, and underscores in the name.
    Variables defined in include files will overload (replace) variables defined at other levels of the hierarchy, except for variables passed through --extra-vars .

    Variables in Imported Files

    Let's look at how you can use variables from files imported into a playbook.
    Let's create a separate Apache installation task file (~ / 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"
    

    We include it in the Apache installation file and verify that the service is running (~ / 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
    

    As we can see, in the setup_apache.yml file we successfully use the variable defined in the included file. This playbook will correctly install apache on both rpm distributions and deb using the correct package name with apache.



    Variables in a playbook

    Variables in the playbook are set using the vars: keyword . Variables are set as variable_name: value. Variables will overload other variables that are set in the global file or in inventory.

    An example of a variable description in a playbook:
    vars:
      - package_name: "httpd"
    


    Variables in a Global File

    Variables in Ansible can be set in a separate file, which allows you to separate data from the playbook. You can create as many variable files as necessary, you just need to tell the playbook where to look for them. The format for defining variables in a file is similar to the format for defining variables in a 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') }}"
    

    In this example, we set the package_name variable directly (after # you can write a comment), and we look for access keys for the InfoboxCloud API in the environment variables using the lookup plugin.

    In the playbook, the path to the variable files is set via vars_files:
    vars_files:
      - var1.yml
      - var2.yml
    


    Using facts as variables

    You can use any fact as a variable that is collected at gather_facts. To get a list of all the facts for a specific group of machines, use the command:
    ansible experiments -i inventory -m setup
    

    , where experiments is the name of a group of machines in inventory.

    Diving into the inventory file


    In the first part, we briefly looked at a simple inventory file. Let's look at it more closely.

    Simple inventory (~ / ansible / inventory ):
    ansible.trukhin.com
    77.221.144.179
    

    You can simply record the hostnames and ip addresses and all servers will be used when playing the playbook with this inventory file.

    Groups in inventory

    We also saw the use of groups earlier:
    [my]
    ansible.trukhin.com
    ansible2.trukhin.com
    [corp]
    ansible.sandbox.infoboxcloud.ru
    ansible2.sandbox.infoboxcloud.ru
    


    The group for execution of the playbook is indicated in the "hosts:" section of the playbook
    hosts: my
    

    If you want to use a specific host, you can transfer it to the hosts section.
    hosts: ansible.trukhin.com
    

    If you want to use all the hosts of all groups - you can use
    hosts: all
    


    Group Groups in inventory

    A very useful feature that allows, for example, to group hosts not only by purpose, but also by region, which is very important for InfoboxCloud (Moscow, Amsterdam). Often there are other tasks where you need to use group groups.
    [msk]
    webMSK.trukhin.com
    dbMSK.trukhin.com
    [ams]
    webAMS.trukhin.com
    dbAMS.trukhin.com
    [web:children]
    msk
    ams
    

    In this example, the web my group includes servers in Moscow and Amsterdam. From the playbook, you can access both the web group and server groups in a specific region.

    Regular expressions in inventory

    If you have a large number of servers, using naming conventions (eg web001, web002 ... web00N) will make it easier to specify them in inventory. You can use regular expressions in the inventory file:
    [web]
    web[001:200]
    [db]
    db[001:020]
    [balancer]
    192.168.2.[1:3]
    

    where web [001: 200] will correspond to web 001, web002, web003, web004, ..., web199, web200 for the web group;
    db [001: 020] will correspond to db001, db002, db003 ..., db019, db020 for the db group.
    192.168.2. [1:30] will correspond to 192.168.2.1, 192.168.2.2, 192.168.2.3 for the balancer group.

    Variables in inventory file

    The methods for setting variables discussed earlier applied them immediately to all hosts in inventory. Sometimes it may be necessary to use specific variables for a specific group of hosts or a specific host.

    Setting variables for specific hosts:
    ansible.trukhin.com
    web001
    db001 db_name=mysql
    192.168.2.1 db_name=redis db_port=6380
    

    Setting variables for a group of hosts (web):
    [web]
    web[001:010]
    [db]
    db[001:002]
    [web:vars]
    web_port=443
    


    Removing variables into separate files for inventory

    You can create variable files for hosts and for groups. Folders with these files should be in the same directory as the inventory file. Files of variables related to specific hosts must be saved in the host_vars folder related to specific groups - to the group_vars folder.

    An example variable file for the web001 host (~ / ansible / host_vars / web001):
    web_port_ssl=443
    web_port=80
    

    Example variable file for a db group (~ / ansible / group_vars / db):
    db_port=6380
    db_name=redis
    

    Inventory variables follow a hierarchy: the variables in the global file overload any host variables, group variables, and variables in the inventory file. Host variables overload group variables, and in turn group variables overload inventory file variables.

    Through ansible.cfg can override Ansible configuration.

    Conclusion


    The writing of the article was greatly helped by the book Learning Ansible and of course the official documentation .

    All experiments with Ansible are conveniently carried out in InfoboxCloud , since it is possible for each virtual server to set exactly the amount of resources that is necessary for the task (CPU / Ram / disk independently of each other) or use autoscaling, rather than choosing a VM from ready-made templates. When experiments are not carried out - you can just turn off the VM and pay only the cost of the disk.

    If you find a mistake in the article, the author will gladly correct it. Please write to the PM or e-mail about it. There you can ask questions about Ansible for coverage in subsequent articles.

    Part 4: working with modules
    Part 5: local_action, conditions, loops and roles

    Success!

    Also popular now: