Skip to main content

How to provision AWS infrastructure with Ansible

Find out how to provision infrastructure and other resources in a public cloud.
Image
Sunset with tree and clouds over water

Image by Bessi from Pixabay

Infrastructure as Code (IaC) is a method to provision and manage infrastructure and other resources using declarative definition files or code. Instead of manually configuring the servers (physical or virtual) and network devices (and other resources), you can use IaC to manage the entire infrastructure lifecycle. Ansible is one of the best IaC tools, and this article explains how to use it to provision infrastructure and other resources in a public cloud.

Current vs. future modes of operation

In the current method, you manually do every task to create and build your infrastructure. You collect the cluster or region details to deploy your servers, network subnets, storage, and other items. Once you have the details, you create the virtual private cloud (VPC) project, security groups, network policies, and other items. Then you create servers (virtual machines, instances, droplets—whatever you call it) and configure them with additional disks as needed. Before you finish, you install and configure applications and packages, create users and groups, and do many other things.

In the future mode of operation, using Ansible as an IaC tool enables you to automate all those operations, and managing your infrastructure becomes more efficient. Instead of doing tasks manually, you create the resources using Ansible modules. 

Why Ansible for public cloud management?

The Ansible community is rapidly growing, and product vendors are contributing more and more Ansible content to the public community. This means you have ready-to-use modules and plugins available to manage the most well-known public cloud and private cloud platforms such as AWS, Azure, Google Cloud Platform, IBM, OpenShift, OpenStack, Oracle, VMware, and others.

I'll use AWS as the example in this article. You can find documentation on all cloud modules, and the cloud modules the vendors manage are available as Ansible Content Collections in Ansible Galaxy

How to manage AWS with Ansible

There are plenty of modules available from the community for managing AWS using Ansible. You can access the Community AWS Collection or Amazon AWS Collection from Ansible Galaxy. 

[ Find out what's new in Red Hat Ansible Automation Platform 2. ]

Create Elastic Compute Cloud (EC2) instances

Creating EC2 instances in AWS is a single task using the ec2_instance module module, but as a best practice, you can add more pretasks and validations as needed [editor's note: this article was updated on Nov. 11, 2021, to use the ec2_instance module rather than the deprecated ec2 module]:

- name: Launching EC2 instances
  community.aws.ec2_instance:
    #aws_access_key: "{{ec2_access_key}}"
    #aws_secret_key: "{{ec2_secret_key}}"
    profile: "{{ aws_boto_profile }}"
    key_name: "{{ aws_demo_key }}"
    security_group: "{{ aws_security_group }}"
    instance_type: "{{ item.value.instance_type }}"
    image_id: "{{ aws_ami_id }}" 
    state: present
    wait: yes
    wait_timeout: 300
    region: "{{ aws_region }}"
    tags:
       Name: "{{ item.value.name }}"
    detailed_monitoring: no
    vpc_subnet_id: "{{ vpc_subnet_list | random }}"
    network:
      assign_public_ip: yes
  loop: "{{ lookup('dict', ec2_new_list, wantlist=True) }}"

Create security groups

AWS security groups control the instance and other resource access. You can fine-tune the network access by source IP, network, port, and more:

- name: Create Security group
  amazon.aws.ec2_group:
    profile: "{{ aws_boto_profile }}"
    name: "{{ aws_security_group }}"
    description: 'Security Group with SSH and HTTP rules'
    vpc_id: "{{ aws_vpc_id }}"
    region: "{{ aws_region }}"
    rules:
      - proto: tcp
        ports:
        - 80
        cidr_ip: 0.0.0.0/0
        rule_desc: allow all on port 80
      - proto: tcp
        ports:
        - 22
        cidr_ip: 0.0.0.0/0
        rule_desc: allow all on port 22 

Create Elastic Load Balancers

The elb_application_lb module helps you create an Elastic Load Balancer (ELB) with a single module:

# create elb
- name: Create Amazon ELB
  amazon.aws.ec2_elb_lb:
    profile: "{{ aws_boto_profile }}"
    name: "{{ aws_elb_app_lb }}"
    region: "{{ aws_region }}"
    zones:
      - "{{ ap_zone1 }}"
      - "{{ ap_zone2 }}"
    listeners:
      - protocol: http
        load_balancer_port: 80
        instance_port: 80
        proxy_protocol: True
    state: present
  register: elbcreated

Install and configure an application

Once your infrastructure is ready and running, you need to deploy the application and configure it. Ansible is very good at this:

- name: Deploy Webserver to EC2 instances
  hosts: "{{ inventory_webgroup }}"
  remote_user: ec2-user
  become: true
  tasks:
    - name: Deploy Web service
      include_role: 
        name: deploy-web-server

An example: Build a web server infrastructure and application

Image
Web infrastructure diagram
(Gineesh Madapparambath, CC BY-SA 4.0)

In this demo, you deploy a full-stack infrastructure including:

  • Security groups
  • ELB target groups
  • Application load balancer
  • Dedicated key pair
  • 2x EC2 instance
  • Configured web server with default website content

The entire infrastructure code is available in my GitHub repository for reference.

Connect to AWS using credentials

Configure the AWS credentials that Ansible will use and automate the infrastructure management. This is a standard process, and you can refer to "How to install and configure AWS command-line interface (CLI)" to configure them.

If you have multiple credentials configured, use the correct profile inside your playbook as profile: "{{ aws_boto_profile }}" where aws_boto_profile is the variable you configured as the profile name.

Execute the Ansible playbook

Enter the following to tell Ansible to create all the resources and show the ELB's URL to access the website:

$ ansible-playbooks aws-infra-provisioning.yaml

Destroy the infrastructure

An IaC handles the infrastructure's entire lifecycle, so you can create a separate playbook for destroying the infrastructure. Once you finish testing, call the aws-infra-destroy.yaml playbook to destroy the entire infrastructure you created:

$ ansible-playbooks aws-infra-destroy.yaml

Wrap up

By using Ansible, you can manage AWS or any other public or private cloud platforms and resources. Make sure you follow all the best practices and validations to handle provisioning and destroying.

Image
Galaxy
Ansible Galaxy is a repository for Ansible Roles that are available to drop directly into your Playbooks to streamline your automation projects.
Topics:   Cloud   Ansible   Automation  
Author’s photo

Gineesh Madapparambath

Gineesh Madapparambath is a Platform & DevOps Consultant at Red Hat Singapore, specializing in automation and containerization with Ansible and OpenShift.  More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.