Как использовать переменные Ansible в файлах для управления конфигурацией

AnsibleAnsibleBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Introduction

This tutorial will guide you through using Ansible vars_files for efficient configuration management. Ansible is a powerful automation tool that helps manage infrastructure through simple, human-readable YAML files. The vars_files feature allows you to keep your configuration data separate from your automation logic, making your Ansible projects more organized and maintainable.

By the end of this tutorial, you will learn how to create and organize vars_files, incorporate them into playbooks, and leverage them to manage different environments effectively. This knowledge will help you build more scalable and maintainable infrastructure automation.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ansible(("Ansible")) -.-> ansible/ModuleOperationsGroup(["Module Operations"]) ansible(("Ansible")) -.-> ansible/InventoryManagementGroup(["Inventory Management"]) ansible(("Ansible")) -.-> ansible/PlaybookEssentialsGroup(["Playbook Essentials"]) ansible(("Ansible")) -.-> ansible/AnsibleSetupandConfigurationGroup(["Ansible Setup and Configuration"]) ansible/AnsibleSetupandConfigurationGroup -.-> ansible/install("Ansible Setup") ansible/ModuleOperationsGroup -.-> ansible/apt("Package Manager") ansible/ModuleOperationsGroup -.-> ansible/copy("Transfer Files") ansible/ModuleOperationsGroup -.-> ansible/debug("Test Output") ansible/ModuleOperationsGroup -.-> ansible/file("Manage Files/Directories") ansible/InventoryManagementGroup -.-> ansible/group_variables("Set Group Variables") ansible/InventoryManagementGroup -.-> ansible/host_variables("Set Host Variables") ansible/PlaybookEssentialsGroup -.-> ansible/playbook("Execute Playbook") subgraph Lab Skills ansible/install -.-> lab-411647{{"Как использовать переменные Ansible в файлах для управления конфигурацией"}} ansible/apt -.-> lab-411647{{"Как использовать переменные Ansible в файлах для управления конфигурацией"}} ansible/copy -.-> lab-411647{{"Как использовать переменные Ansible в файлах для управления конфигурацией"}} ansible/debug -.-> lab-411647{{"Как использовать переменные Ansible в файлах для управления конфигурацией"}} ansible/file -.-> lab-411647{{"Как использовать переменные Ansible в файлах для управления конфигурацией"}} ansible/group_variables -.-> lab-411647{{"Как использовать переменные Ansible в файлах для управления конфигурацией"}} ansible/host_variables -.-> lab-411647{{"Как использовать переменные Ansible в файлах для управления конфигурацией"}} ansible/playbook -.-> lab-411647{{"Как использовать переменные Ansible в файлах для управления конфигурацией"}} end

Installing Ansible and Creating Your First vars_file

In this first step, we will install Ansible on our system and create our first vars_file to store configuration data.

Installing Ansible

Let's start by installing Ansible on our Ubuntu system:

sudo apt update
sudo apt install -y ansible

After installation completes, verify that Ansible is installed correctly:

ansible --version

You should see output similar to this, showing the Ansible version and configuration:

ansible [core 2.12.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (default, Mar 14 2023, 14:21:35) [GCC 11.3.0]
  jinja version = 3.0.3
  libyaml = True

Creating a Project Directory Structure

Let's create a directory structure for our Ansible project:

mkdir -p ~/project/ansible-vars-demo/vars
cd ~/project/ansible-vars-demo

Understanding Ansible vars_files

Ansible vars_files are YAML files that store variable definitions which can be imported into playbooks. These files allow you to:

  1. Separate configuration data from automation logic
  2. Reuse the same variables across multiple playbooks
  3. Maintain different configurations for different environments

Creating Your First vars_file

Let's create our first vars_file to store web server configuration settings. Using the WebIDE, create a new file at ~/project/ansible-vars-demo/vars/webserver.yml with the following content:

---
## Web Server Configuration
http_port: 80
server_name: example.com
document_root: /var/www/html
max_clients: 200

This vars_file defines four variables that might be used in configuring a web server:

  • http_port: The port the web server will listen on
  • server_name: The domain name for the web server
  • document_root: The directory where website files will be stored
  • max_clients: The maximum number of simultaneous client connections

To help understand what this looks like in the WebIDE, navigate to the file explorer on the left side, expand the project folder, then ansible-vars-demo, then vars, and you should see your webserver.yml file. Click on it to view or edit its contents.

Creating an Inventory File

Next, we need to create an inventory file to tell Ansible which hosts to manage. In a real environment, this would contain actual server addresses, but for this tutorial, we'll use localhost.

Create a new file at ~/project/ansible-vars-demo/inventory.ini with the following content:

[webservers]
localhost ansible_connection=local

This simple inventory defines a group called webservers that includes only our local machine.

Understanding the Project Structure

At this point, your project structure should look like this:

ansible-vars-demo/
├── inventory.ini
└── vars/
    └── webserver.yml

This basic structure separates our inventory (which hosts to manage) from our variable definitions (how to configure those hosts).

Creating a Basic Playbook with vars_files

Now that we have our vars_file created, let's build a simple Ansible playbook that uses these variables. This will demonstrate how to import and use configuration data from vars_files.

Understanding Ansible Playbooks

Ansible playbooks are YAML files that define a set of tasks to be executed on managed hosts. Playbooks are the core of Ansible's functionality, allowing you to automate complex configuration processes.

Creating a Simple Playbook

Let's create a playbook that will simulate configuring a web server using the variables we defined in our vars_file. Create a new file at ~/project/ansible-vars-demo/webserver_setup.yml with the following content:

---
- name: Configure Web Server
  hosts: webservers
  vars_files:
    - vars/webserver.yml

  tasks:
    - name: Display web server configuration
      debug:
        msg: "Web server will be configured with: Port={{ http_port }}, ServerName={{ server_name }}, DocumentRoot={{ document_root }}"

    - name: Create a directory for document root
      file:
        path: "/tmp/{{ document_root }}"
        state: directory
        mode: "0755"

    - name: Create a sample index.html file
      copy:
        content: |
          <html>
            <head>
              <title>Welcome to {{ server_name }}</title>
            </head>
            <body>
              <h1>Welcome to {{ server_name }}</h1>
              <p>This server is configured to handle {{ max_clients }} simultaneous connections.</p>
            </body>
          </html>
        dest: "/tmp/{{ document_root }}/index.html"
        mode: "0644"

Let's understand what this playbook does:

  1. hosts: webservers - Specifies that this playbook should run on all hosts in the "webservers" group from our inventory.
  2. vars_files: - vars/webserver.yml - Imports variables from our vars_file.
  3. The first task uses the debug module to display a message showing the variables.
  4. The second task creates a directory structure that would be used for the web server document root.
  5. The third task creates a sample HTML file that includes the variables from our vars_file.

Running the Playbook

Now, let's run the playbook to see it in action:

cd ~/project/ansible-vars-demo
ansible-playbook -i inventory.ini webserver_setup.yml

You should see output similar to this:

PLAY [Configure Web Server] ****************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Display web server configuration] ****************************************
ok: [localhost] => {
    "msg": "Web server will be configured with: Port=80, ServerName=example.com, DocumentRoot=/var/www/html"
}

TASK [Create a directory for document root] ************************************
changed: [localhost]

TASK [Create a sample index.html file] *****************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Verifying the Results

Let's verify that our playbook has created the expected files:

ls -la /tmp/var/www/html/
cat /tmp/var/www/html/index.html

You should see the directory structure and the contents of the index.html file, which should include the values from our vars_file:

<html>
  <head>
    <title>Welcome to example.com</title>
  </head>
  <body>
    <h1>Welcome to example.com</h1>
    <p>This server is configured to handle 200 simultaneous connections.</p>
  </body>
</html>

Understanding the Workflow

Let's recap what we've accomplished:

  1. We stored configuration data in a separate vars_file (vars/webserver.yml).
  2. We created a playbook that imports and uses this configuration data.
  3. We ran the playbook to execute tasks that use the variables.

This separation of configuration data (vars_files) from automation logic (playbooks) makes our Ansible code more maintainable and reusable. We can now update the configuration by editing just the vars_file, without changing the playbook itself.

Working with Multiple vars_files

Now that we understand the basics of vars_files, let's explore how to use multiple vars_files to manage different environments. This is a common practice in real-world scenarios where you might have different configurations for development, staging, and production environments.

Creating Environment-Specific vars_files

Let's create vars_files for different environments. First, let's create a development environment configuration:

Create a new file at ~/project/ansible-vars-demo/vars/dev_environment.yml with the following content:

---
## Development Environment Configuration
environment_name: development
debug_mode: true
log_level: debug
backup_frequency: weekly
max_memory: 512MB

Next, let's create a production environment configuration:

Create a new file at ~/project/ansible-vars-demo/vars/prod_environment.yml with the following content:

---
## Production Environment Configuration
environment_name: production
debug_mode: false
log_level: error
backup_frequency: daily
max_memory: 2048MB

Creating a Playbook with Multiple vars_files

Now, let's create a playbook that uses both our webserver configuration and environment-specific configurations. Create a new file at ~/project/ansible-vars-demo/environment_setup.yml with the following content:

---
- name: Configure Environment
  hosts: webservers
  vars:
    env: dev
  vars_files:
    - vars/webserver.yml
    - "vars/{{ env }}_environment.yml"

  tasks:
    - name: Display environment details
      debug:
        msg: >
          Setting up {{ environment_name }} environment with the following parameters:
          - Web Server: {{ server_name }} on port {{ http_port }}
          - Debug Mode: {{ debug_mode }}
          - Log Level: {{ log_level }}
          - Backup Frequency: {{ backup_frequency }}
          - Max Memory: {{ max_memory }}
          - Max Clients: {{ max_clients }}

    - name: Create environment config file
      copy:
        content: |
          ## Environment Configuration for {{ server_name }}
          ENVIRONMENT={{ environment_name }}
          DEBUG={{ debug_mode }}
          LOG_LEVEL={{ log_level }}
          BACKUP_FREQUENCY={{ backup_frequency }}
          MAX_MEMORY={{ max_memory }}
          HTTP_PORT={{ http_port }}
          MAX_CLIENTS={{ max_clients }}
        dest: "/tmp/{{ environment_name }}_config.env"
        mode: "0644"

This playbook introduces several new concepts:

  1. We set a variable env: dev within the playbook itself.
  2. We include both our webserver vars_file and an environment-specific vars_file.
  3. The environment vars_file path includes a variable: "vars/{{ env }}_environment.yml", which evaluates to vars/dev_environment.yml.
  4. The tasks use variables from both vars_files.

Running the Playbook with Different Environments

Let's run the playbook first with the development environment (which is already the default):

cd ~/project/ansible-vars-demo
ansible-playbook -i inventory.ini environment_setup.yml

You should see output that includes the development environment settings:

TASK [Display environment details] ********************************************
ok: [localhost] => {
    "msg": "Setting up development environment with the following parameters:\n- Web Server: example.com on port 80\n- Debug Mode: True\n- Log Level: debug\n- Backup Frequency: weekly\n- Max Memory: 512MB\n- Max Clients: 200"
}

Now, let's run the same playbook but override the env variable to use the production environment:

ansible-playbook -i inventory.ini environment_setup.yml -e "env=prod"

You should see output that includes the production environment settings:

TASK [Display environment details] ********************************************
ok: [localhost] => {
    "msg": "Setting up production environment with the following parameters:\n- Web Server: example.com on port 80\n- Debug Mode: False\n- Log Level: error\n- Backup Frequency: daily\n- Max Memory: 2048MB\n- Max Clients: 200"
}

Verifying the Configuration Files

Let's verify that our playbook created the environment configuration files:

cat /tmp/development_config.env
cat /tmp/production_config.env

You should see two different configuration files, each with settings from the respective environment vars_file.

Understanding Variable Precedence

It's important to understand that when using multiple vars_files, Ansible follows a specific order of precedence for variables. If the same variable name appears in multiple places, the value defined later will override earlier definitions.

In our example, if we had defined http_port in both the webserver.yml and dev_environment.yml files, the value from dev_environment.yml would take precedence because it's included later in the vars_files list.

This behavior allows you to define common defaults in one file and then override specific values for different environments.

Advanced vars_files Techniques

In this final step, we'll explore some advanced techniques for working with vars_files in Ansible, including organizing variables hierarchically and implementing role-based variable organization.

Organizing Variables Hierarchically

In complex projects, it's often helpful to organize variables hierarchically. Let's create a structure where we have:

  1. Common variables that apply to all environments
  2. Environment-specific variables
  3. Application-specific variables

First, let's create a common variables file:

Create a new file at ~/project/ansible-vars-demo/vars/common.yml with the following content:

---
## Common variables for all environments
organization: "Example Corp"
admin_email: "admin@example.com"
timezone: "UTC"

Next, let's create application-specific variables:

Create a new file at ~/project/ansible-vars-demo/vars/database.yml with the following content:

---
## Database application variables
db_port: 3306
db_user: "dbuser"
db_name: "appdb"
db_max_connections: 100

Creating a Hierarchical Playbook

Now, let's create a playbook that demonstrates using these hierarchical variables. Create a new file at ~/project/ansible-vars-demo/hierarchical_setup.yml with the following content:

---
- name: Hierarchical Variable Demo
  hosts: webservers
  vars:
    env: dev
    app: database
  vars_files:
    - "vars/common.yml"
    - "vars/{{ env }}_environment.yml"
    - "vars/{{ app }}.yml"

  tasks:
    - name: Display hierarchical configuration
      debug:
        msg: >
          Configuration for {{ app }} in {{ environment_name }} environment:
          - Organization: {{ organization }}
          - Admin Email: {{ admin_email }}
          - Timezone: {{ timezone }}
          - Debug Mode: {{ debug_mode }}
          - Log Level: {{ log_level }}
          - DB Port: {{ db_port }}
          - DB User: {{ db_user }}
          - DB Max Connections: {{ db_max_connections }}

    - name: Create hierarchical config file
      copy:
        content: |
          ## {{ organization }} Configuration
          ## {{ environment_name }} Environment

          ## Common Settings
          ADMIN_EMAIL={{ admin_email }}
          TIMEZONE={{ timezone }}

          ## Environment Settings
          DEBUG={{ debug_mode }}
          LOG_LEVEL={{ log_level }}
          BACKUP_FREQUENCY={{ backup_frequency }}

          ## {{ app | capitalize }} Settings
          DB_PORT={{ db_port }}
          DB_USER={{ db_user }}
          DB_NAME={{ db_name }}
          DB_MAX_CONNECTIONS={{ db_max_connections }}
        dest: "/tmp/{{ environment_name }}_{{ app }}_config.conf"
        mode: "0644"

Understanding Group and Host Variables

In addition to vars_files, Ansible also supports storing variables in special directories called group_vars and host_vars. Let's see how these work:

Create a directory structure for group and host variables:

mkdir -p ~/project/ansible-vars-demo/group_vars
mkdir -p ~/project/ansible-vars-demo/host_vars

Now, create a group variables file for the 'webservers' group:

Create a new file at ~/project/ansible-vars-demo/group_vars/webservers.yml with the following content:

---
## Variables for all webservers
firewall_enabled: true
ssh_port: 22
monitoring_enabled: true

And create a host variables file for 'localhost':

Create a new file at ~/project/ansible-vars-demo/host_vars/localhost.yml with the following content:

---
## Variables specific to localhost
local_backup_path: "/tmp/backups"
is_development_machine: true

Creating a Playbook with All Variable Types

Let's create a final playbook that demonstrates using all the variable types together. Create a new file at ~/project/ansible-vars-demo/complete_setup.yml with the following content:

---
- name: Complete Variable Demo
  hosts: webservers
  vars:
    env: prod
    app: database
  vars_files:
    - "vars/common.yml"
    - "vars/{{ env }}_environment.yml"
    - "vars/{{ app }}.yml"

  tasks:
    - name: Display complete configuration
      debug:
        msg: >
          Complete configuration for {{ inventory_hostname }}:
          - Organization: {{ organization }}
          - Environment: {{ environment_name }}
          - Debug Mode: {{ debug_mode }}
          - Firewall Enabled: {{ firewall_enabled }}
          - SSH Port: {{ ssh_port }}
          - Monitoring Enabled: {{ monitoring_enabled }}
          - Local Backup Path: {{ local_backup_path }}
          - Is Development Machine: {{ is_development_machine }}

    - name: Create complete config file
      copy:
        content: |
          ## {{ organization }} - {{ environment_name }} Environment
          ## Host: {{ inventory_hostname }}

          ## Common Settings
          ADMIN_EMAIL={{ admin_email }}
          TIMEZONE={{ timezone }}

          ## Environment Settings
          DEBUG={{ debug_mode }}
          LOG_LEVEL={{ log_level }}

          ## Server Settings
          FIREWALL_ENABLED={{ firewall_enabled }}
          SSH_PORT={{ ssh_port }}
          MONITORING_ENABLED={{ monitoring_enabled }}

          ## Host-specific Settings
          LOCAL_BACKUP_PATH={{ local_backup_path }}
          IS_DEVELOPMENT_MACHINE={{ is_development_machine }}

          ## {{ app | capitalize }} Settings
          DB_PORT={{ db_port }}
          DB_USER={{ db_user }}
          DB_NAME={{ db_name }}
        dest: "/tmp/complete_config.conf"
        mode: "0644"

Running the Advanced Playbooks

Let's run our hierarchical playbook:

cd ~/project/ansible-vars-demo
ansible-playbook -i inventory.ini hierarchical_setup.yml

You should see output that includes variables from all three vars_files.

Now, let's run our complete playbook:

ansible-playbook -i inventory.ini complete_setup.yml

This time, you should see output that includes variables from vars_files, group_vars, and host_vars.

Verifying the Configuration Files

Let's check the configuration files created by our advanced playbooks:

cat /tmp/dev_database_config.conf
cat /tmp/complete_config.conf

Understanding Variable Precedence in Ansible

When using multiple variable sources, Ansible follows a specific order of precedence:

  1. Command line variables (-e or --extra-vars)
  2. Variables defined in the play
  3. Variables from included files and roles
  4. Host facts
  5. Host vars
  6. Group vars
  7. Inventory vars
  8. Role default vars

This means that variables defined in host_vars will override the same variables defined in group_vars, which will override the same variables defined in vars_files.

This hierarchical structure gives you a powerful way to manage configuration across different environments, hosts, and applications.

Summary

In this tutorial, you have learned how to effectively use Ansible vars_files for configuration management. You have:

  1. Installed Ansible and created your first vars_file to store configuration data
  2. Created and run a basic playbook that uses vars_files to separate configuration from automation logic
  3. Worked with multiple vars_files to manage different environments
  4. Explored advanced techniques including hierarchical variable organization and using group_vars and host_vars

These skills provide a solid foundation for building scalable and maintainable Ansible automation. By separating your configuration data from your automation logic, you can:

  • Make your playbooks more reusable across different environments
  • Simplify the process of updating configuration values
  • Manage complex configurations in a structured way
  • Improve collaboration by clearly organizing configuration data

As you continue working with Ansible, remember that effective variable management is key to building maintainable automation. The techniques you've learned in this tutorial will help you organize your Ansible projects as they grow in complexity.