Multi-Environment Deployments with Ansible

By Raman Kumar

Updated on Aug 27, 2024

In this tutorial, we'll explain the multi-environment deployments with Ansible. 

Ansible is a powerful automation tool that can help you manage and deploy applications across multiple environments - such as development, staging, and production - efficiently. In this tutorial, we'll walk through the steps needed to configure Ansible for multi-environment deployments.

Prerequisites

Before we start, make sure you have the following:

  • A control node with Ansible installed.
  • Target nodes (servers) with SSH access from the control node.
  • Basic knowledge of Ansible playbooks and inventory.

Step 1: Set Up Your Directory Structure

The first step is to set up a directory structure that reflects your environments. This will help you manage different configurations and settings for each environment.

mkdir -p ansible/{group_vars,host_vars,roles,playbooks,inventory}
cd ansible

Your directory structure should look something like this:

ansible/
├── group_vars/
├── host_vars/
├── inventory/
├── playbooks/
└── roles/

Step 2: Define Your Inventory

Ansible's inventory file defines the hosts and groups of hosts you will manage. We will create an inventory file for each environment (development, staging, and production).

Note: Replace all the following IP addresses with your server's IP addresses.

Create an inventory file for each environment:

nano inventory/development

Add following content:

# inventory/development
[webservers]
dev-web1 ansible_host=192.168.1.101

[dbservers]
dev-db1 ansible_host=192.168.1.102

Save and exit.

nano inventory/staging

Add following content:

# inventory/staging
[webservers]
stg-web1 ansible_host=192.168.1.111

[dbservers]
stg-db1 ansible_host=192.168.1.112

Save and exit.

nano inventory/production

Add following content:

# inventory/production
[webservers]
prod-web1 ansible_host=192.168.1.121

[dbservers]
prod-db1 ansible_host=192.168.1.122

Save and exit.

Step 3: Set Up Group Variables

Group variables allow you to define environment-specific settings. These can include things like database credentials, API keys, and other configurations that vary between environments.

Create group variable files for each environment:

nano group_vars/development.yml

Add following content:

# group_vars/development.yml
db_host: dev-db1
db_user: dev_user
db_password: dev_password

Save and exit the file.

nano group_vars/staging.yml

Add following content:

# group_vars/staging.yml
db_host: stg-db1
db_user: stg_user
db_password: stg_password

Save and exit the file.

nano group_vars/production.yml

Add following content:

# group_vars/production.yml
db_host: prod-db1
db_user: prod_user
db_password: prod_password

Save and exit the file.

Step 4: Create Playbooks for Each Environment

Now, create a playbook for each environment that uses the corresponding inventory and group variables.

# playbooks/deploy.yml
- hosts: webservers
  roles:
    - roles/deploy-web

- hosts: dbservers
  roles:
    - roles/deploy-db

This playbook is generic and can be used across all environments. The specific variables for each environment will be picked up from the group variables files.

Step 5: Create Roles

Roles are reusable units of Ansible content. They allow you to organize tasks, handlers, variables, and files in a structured way.

Create roles for deploying web and database servers:

ansible-galaxy init roles/deploy-web
ansible-galaxy init roles/deploy-db

Within each role, you can define tasks that will be executed for each environment:

nano roles/deploy-web/tasks/main.yml
Add following content:
                                                                                                 
---
# tasks file for roles/deploy-web
- name: Install Nginx
  apt:
    name: nginx
    state: present

- name: Start nginx service
  service:
    name: nginx
    state: started

- name: Allow HTTP traffic on port 80
  ufw:
    rule: allow
    port: 80
    proto: tcp

- name: Ensure UFW is enabled
  ufw:
    state: enabled

Save and exit the file.

nano roles/deploy-db/tasks/main.yml

Add following content:

---
# tasks file for roles/deploy-db
- name: Update Ubuntu Server
  apt:
    update_cache: yes
    cache_valid_time: 3600

- name: Install PostgreSQL
  apt:
    name: postgresql
    state: present

- name: Start PostgreSQL Service
  service:
    name: postgresql
    state: started

Save and exit the file.

Note: If you find any error with above code, check the indentation of the variables.

Step 6: Deploy to Different Environments

To deploy to a specific environment, you simply specify the inventory file corresponding to that environment when running the playbook.

For development:

ansible-playbook -i inventory/development playbooks/deploy.yml

For staging:

ansible-playbook -i inventory/staging playbooks/deploy.yml

For production:

ansible-playbook -i inventory/production playbooks/deploy.yml

Step 7: Test and Verify

After running the playbooks, verify that your configurations have been applied correctly in each environment. Check the application, web server, and database server to ensure everything is running as expected.

Conclusion

By following this guide, you should now be able to configure Ansible for multi-environment deployments. This setup allows you to maintain consistent deployments across different environments, making it easier to manage your infrastructure and application configurations. As your project grows, you can expand on this setup by adding more environments, roles, and tasks to meet your specific needs.