Deploying to AWS with Ansible

Hands-On Lab

 

Photo of Stosh Oldham

Stosh Oldham

Course Development Director in Content

Length

01:00:00

Difficulty

Advanced

This exercise provides a simple yet realistic task of deploying a basic website to dynamically provisioned AWS infrastructure. We will work with multiple AWS components through Ansible, and also perform basic web server configuration against a Linux host with Ansible. This exercise will help demonstrate a portion of the power provided by rolling cloud provisioning into deployment automation.

What are Hands-On Labs?

Hands-On Labs are scenario-based learning environments where learners can practice without consequences. Don't compromise a system or waste money on expensive downloads. Practice real-world skills without the real-world risk, no assembly required.

Deploying to AWS with Ansible

Introduction

This exercise provides a simple yet realistic task of deploying a basic website to dynamically provisioned AWS infrastructure. We will work with multiple AWS components through Ansible, and also perform basic web server configuration against a Linux host with Ansible. This exercise will help demonstrate a portion of the power provided by rolling cloud provisioning into deployment automation.

Instructions

In an effort to get senior management on board with using AWS for web content, we have been asked to produce a quick proof of concept. We need to demonstrate how quickly we can stand up a new website using EC2 for compute and S3 for content. A colleague has started the work but taken ill. We can pick up where they left off.

We have been provided an Ansible Control node and a sandbox AWS environment.

We'll start our work on the Ansible Control node:

  • Run the provided playbook /home/ansible/get-environment-details.yml to complete another provided file, /home/ansible/env_vars.yml with environment specific configuration information.
  • Edit /home/ansible/env_vars.yml and update the placeholder value for the BUCKET variable. It should be a unique S3 bucket name that meets the S3 naming restrictions (See https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html for details).
  • Create the playbook /home/ansible/deploy.yml to perform the following tasks:
    • Using the provided SSH key for the ansible system user in /home/ansible/.ssh/id_rsa.pub, create a new AWS Keypair named ansible_keypair
    • Create a new EC2 instance that meets the following requirements:
      • Use the Subnet, Security Group, and AMI defined in /home/ansible/env_vars.yml.
      • Use ansible_keypair, created in the initial task as the instance login key pair.
      • Set the instance type to t2.micro.
      • The instance should be deployed with a public IP.
      • The instance should have a tag with the key type and value web.
      • We only need a single instance for the purpose of the proof of concept.
    • Create a new S3 Bucket meeting the following requirements:
      • The bucket should be named after the BUCKET variable in /home/ansible/env_vars.yml.
      • The bucket should have public read permissions.
    • Upload the provided image /home/ansible/webimage.png to the new S3 bucket with an object name of /webimage.png
    • The playbook will need to configure the new EC2 instance as a webserver in another play in the same playbook.
    • The following tasks must be performed on the EC2 instance after it is provisioned:
      • Install the httpd package using yum.
      • Start and enable the httpd package.
      • Deploy the provided template /home/ansible/index.html.j2 to /var/www/html/index.html. We will need to include the variable file /home/ansible/env_vars.yml in the play to successfully deploy the template.
  • Run the playbook /home/ansible/deploy.yml to bulid the environment.
  • Verify the work by loading http://<public-ip-of-new-ec2-instance>/index.html in a web browser. If we did everything correctly, we should see a statement and an image in a browser.

    The Ansible control node has been configured, and Ansible is installed. The control node also has a system user named ansible configured with SSH access keys and necessary system privileges.

    An IAM user called ansible has been created on the provided AWS sandbox account. The access keys for the ansible IAM user are stored in /home/ansible/keys.sh and /home/ansible/keys.yml for whichever authentication method we prefer. The ansible IAM user has appropriate permissions to perform the required task.

    The default Ansible inventory has been configured to include a the Ansible control host as localhost.

    Logging In

    Use the hands-on lab page to get the public IP of the cloud server we need to log into (making sure to use cloud_user as a username), then switch to the ansible user. The password for the two users is the same.

Run the Provided Playbook to Collect Necessary Environment Details

  • Run the following command:
    • ansible-playbook /home/ansible/get-environment-details.yml

Replace the placeholder in /home/ansible/env_vars.yml

Create a Playbook and Add a Play

  • Create the playbook and edit it such that it resembles the following:
  • hosts: localhost gather_facts: no vars_files:

    • /home/ansible/env_vars.yml tasks:

    • name: Create AWS key pair using Ansible's key. local_action: ec2_key args: name: ansible_keypair key_material: "{{ lookup('file', '/home/ansible/.ssh/id_rsa.pub') }}"

    • name: Provision instances local_action: ec2 args: instance_type: t2.micro group: "{{ SEC_GROUP_NAME }}" keypair: ansible_keypair image: "{{ AMI_ID }}" assign_public_ip: yes vpc_subnet_id: "{{ DEFAULT_VPC_SUBNET }}" wait: yes instance_tags: type: web count: 1 register: ec2

    • name: Add host to inventory add_host: hostname: "{{ item.public_ip }}" groupname: webservers ansible_ssh_common_args: "-o StrictHostKeyChecking=no" ansible_ssh_private_key_file: /home/ansible/.ssh/id_rsa loop: "{{ ec2.instances }}"

    • name: Create S3 Bucket local_action: aws_s3 args: bucket: "{{ BUCKET_NAME }}" mode: create permission: public-read

    • name: Add file to bucket local_action: aws_s3 args: bucket: "{{ BUCKET_NAME }}" mode: put object: /webimage.png src: /home/ansible/webimage.png permission: public-read

Add Another Play to Further Configure the New EC2 Instance

  • Add another play to /home/ansible/deploy.yml that resembles the following:
  • hosts: webservers gather_facts: no vars_files:

    • /home/ansible/env_vars.yml remote_user: ec2-user tasks:

    • name: Wait for SSH to come up wait_for_connection: delay: 5 timeout: 90

    • name: Collect instance facts ec2_metadata_facts:

    • name: Install HTTPD become: yes yum: name: httpd state: present

    • name: Start HTTPD become: yes service: name: httpd state: started enabled: yes

    • name: Deploy content become: yes template: src: /home/ansible/index.html.j2 dest: /var/www/html/index.html

Run the Playbook

  • Source our Bash profile:
    • source .bash_profile
  • Run the following command:
    • ansible-playbook /home/ansible/deploy.yml

Conclusion

If the playbook ran with no errors, then we can fetch our instance's web content, using its public IP, with:

curl <PUBLIC_IP_ADDRESS>/index.html

If all goes well, we've got a running web page. Congratulations!