Container Deployment on AWS with Ansible Playbook and RHEL 9

Madhuvardhan
8 min readSep 17, 2023

--

Introduction:

In the rapidly evolving world of cloud computing, AWS (Amazon Web Services) has become a dominant force, offering a wide array of services to cater to diverse business needs. Running containerized applications on AWS can boost scalability, flexibility, and cost-effectiveness. Red Hat Enterprise Linux 9 (RHEL 9) has emerged as a robust platform known for its stability and performance to facilitate this seamless integration. To harness the full potential of AWS and RHEL 9, automation plays a pivotal role, in streamlining complex deployment tasks.

In this article, we present an empowering solution that combines the power of Ansible Playbook with AWS and RHEL 9. We will demonstrate how to effortlessly configure Docker, pull and run an HTTPD server image from Docker Hub, and deploy a web server with custom HTML code, all orchestrated through Ansible. With this comprehensive playbook, DevOps engineers can confidently orchestrate containerized applications on AWS using RHEL 9, revolutionizing their deployment workflows and ensuring unparalleled success in the cloud-native era.

Let’s embark on this journey of automation excellence and explore the seamless world of container deployment with Ansible, AWS, and RHEL 9.

The Complete Process From Very Zero Level

A. Creating AWS Instances and Configuring Security Groups

Step 1: Log in to the AWS Management Console and navigate to the EC2 Dashboard.

EC2 Dashboard

Step 2: Launch two instances with RHEL 9 as the chosen AMI, ensuring they are in the same VPC.

Client and Server Instance

Step 3: Configure the security groups to allow all types of inbound and outbound traffic for development purposes.

SG to allow all inbound traffic for dev purposes.

Step 4: Create a new key pair and download the private key file (.pem) for SSH access.

B. SSH Access to Client & Server Node via Windows PowerShell

Step 1: Open Windows PowerShell and navigate to the folder containing the downloaded private key (.pem) file.

Step 2: Connect to the server node using SSH with the following command:

ssh -i "ansible.pem" ec2-user@ec2-3-110-176-189.ap-south-1.compute.amazonaws.com

On a successful connection, you will see something like this:

Server connected via SSH

Step 3: Perform the same steps to connect with the client, again on a successful connection you will see this:

Client connected via SSH

C. Preparing the Server Node

Step 1: Install sshpass using yum to enable password-based SSH authentication:

sudo yum install -y sshpass

Step 2: Install pip3 using yum for package management:

sudo yum install -y python3-pip

Step 3: Install Ansible Core using pip:

sudo pip3 install ansible-core

Step 4: Verify the Ansible version before proceeding, use:

ansible --version

If installed properly, you would be able to get the version information.

Ansible core 2.15.2

Step 5: Add a new user named ‘ansadmin’ using the useradd command:

sudo useradd ansadmin

Provide the password, and keep it safe

User added Successfully

Step 6: Grant ansadmin sudo powers by editing the sudoers file:

Use the following command to open the file

sudo visudo

Then, add the following line, to elevate the permissions

ansadmin ALL=(ALL) NOPASSWD: ALL

In the File it should look something like this:

The visudo file

Step 7: Allow password-based authentication by editing the sshd_config file:

Use the following command to open the file

sudo vim /etc/ssh/sshd_config

Then, uncomment the line “PasswordAuthentication yes”

In the file it should look like this:

D. Preparing the Client Node

From the preceding section, repeat Steps 5, 6 & 7 to set up the client node.

E. Establish SSH Connectivity between Server and Client Nodes

Step 1: Connect to ‘ansadmin’ user over SSH for both client and server.

Connecting to AnsAdmin over SSH for Server node

Step 2: From the server node, generate a public-private key pair using ssh-keygen.

public-private key pair

Step 3: Copy the server node’s public key to the client node using the following command:

ssh-copy-id ansadmin@client_node_ip

In this case, it is:

copying keys & testing connectivity!

Step 4: Test SSH connectivity from the server node to the client node:

ssh ansadmin@client_node_ip

Refer to the above picture for output.

F. Configuring Ansible and Creating HTML File

Step 1: Add the client node’s IP address to the Ansible inventory file:

sudo vim /etc/ansible/hosts

Add the client node’s IP address under a group called [client]. Then the file should look like this:

Hosts Added!

Step 2: Install Ansible Core on the client node if required, otherwise skip this step.

Step 3: Check the connectivity between the client and server nodes using Ansible’s ping module:

ansible all -m ping

On a successful connection, you will see:

Connection Success!

Step 4: Create a file named hello.html on the server node using cat command, and add some HTML code to it.

Step 5: Copy the hello.html file from the server node to the client node using Ansible’s copy module:

ansible all -m copy -a "src=/home/ansadmin/hello.html dest=/home/ansadmin"

Output for Step 4 & 5:

Success Received in copying

G. [Optional] Preparing the Client Node for Docker Installation

Step 1: Install pip on the client node for package management.

Step 2: Check if Docker is already available on the client node.

Docker not found.

F. The Final Steps 💥💥

Step 1: On the server, logged in as ansadmin, install the Required Ansible Modules as

sudo pip install dnsimple
ansible-galaxy collection install community.docker
ansible-galaxy collection install community.general

Step 2: Creating the Ansible Playbook (in my case named docker1.yml)

- name: "Configuring HTTPD on Docker"
hosts: all
tasks:
- name: "Yum configuration of Docker"
yum_repository:
name: docker
description: "docker repository"
baseurl: https://download.docker.com/linux/centos/9/x86_64/stable/
gpgcheck: no
    - name: "Installing Docker"
command: "yum install docker-ce --nobest -y"
- name: "Docker service start and enable"
service:
name: docker
state: started
enabled: yes
- name: "Install Python SDK for Docker"
pip:
name: "docker"
state: present
- name: "Pulling HTTPD image from Docker Hub"
docker_image:
name: httpd
source: pull
state: present
- name: "Creation of a directory"
file:
path: "/var/www/html"
state: directory
- name: "Copying HTML file"
copy:
src: "index.html"
dest: "/var/www/html/index.html"
- name: "Launching Docker container"
docker_container:
name: webserver
image: httpd
state: started
ports: "8081:80"
volumes: /var/www/html/index.html:/usr/local/apache2/htdocs/index.html
detach: true

Step 3: Executing the Ansible Playbook

To run the playbook, execute the following command from the terminal on the server node:

ansible-playbook docker1.yml -b --flush-cache

Explanation of the Playbook:

  1. The playbook starts by configuring the Docker repository, installing Docker, and enabling and starting the Docker service on the server node.
  2. The playbook pulls the HTTPD image from Docker Hub using the docker_image module.
  3. It then creates a directory /var/www/html using the file module on the server node.
  4. The index.html file, which contains custom HTML code, is copied to the /var/www/html directory on the server node.
  5. Finally, the playbook launches a Docker container named “webserver” with the pulled HTTPD image, mapping port 8081 on the server node to port 80 on the container, and binding the /var/www/html/index.html file from the server node to the container’s /usr/local/apache2/htdocs/index.html.

By executing this Ansible Playbook, we have achieved a fully automated container deployment of the HTTPD server on our RHEL 9 instances running on AWS. This approach streamlines the deployment process and ensures consistent and efficient container management. Congratulations on successfully automating the deployment of your containerized application!

Outputs:

On the client node, we can see docker is configured and running

Docker Up!

Also, if we curl localhost, we can see the webpage being returned

Finally, if we hit the public IP of the client instance, we can see the web page live

Simple Yet Powerful!

Conclusion

In this guide, we have demonstrated the effectiveness of automation using Ansible, RHEL 9, and Docker to facilitate containerized application deployment on AWS. By following the step-by-step process, we achieved a smooth setup of RHEL 9 instances on AWS with Ansible, effortlessly configuring security groups, establishing SSH access, and installing required packages. Leveraging Ansible’s capabilities, we seamlessly managed communication between the instances and prepared them for Docker-based containerization.

With Ansible’s playbook, we simplified the configuration of Docker, ensuring the effortless deployment of an HTTPD server as a Docker container. By pulling the HTTPD image from Docker Hub and copying the custom HTML code, we efficiently launched the container on the server node. Throughout this automation journey, we experienced the transformative power of Ansible, dramatically reducing manual tasks and minimizing potential errors, thus enhancing the reliability and scalability of our containerized web application.

Through the successful orchestration of containerized applications on AWS, we have demonstrated the significance of automation in today’s dynamic IT landscape. By embracing automation with Ansible, RHEL 9, and Docker, organizations can optimize their cloud-native deployments, achieve consistent performance, and unlock new levels of efficiency and agility in their cloud-based operations.

--

--

No responses yet