Configuring Haproxy to balance the load between two webservers using Ansible

Configuring Haproxy to balance the load between two webservers using Ansible

Today Modern High traffic websites serves millions of requests concurrently and return images, videos ,files or data in a efficient, fast and reliable manner .To cost-effectively scale and meet this increasing demands the best practice is to generally increase the number the servers. If the number of servers increases the problem is how we can distribute the incoming user traffic to different servers in a effective and secure manner.

This is where the role of load balancer/haproxy comes in, it will act as a reverse proxy and will take the request of the client to the server(webserver in our case) and will return its response to the client. Let me explain this with the help of an example:

No alt text provided for this image

Here we have multiple users that are connected to the multiple servers via a Load Balancer(Haproxy). In this scenario we have given only one IP(of the Load Balancer) to the client. The client will send a request to this IP thinking that he is directly connected to the server but in fact he will send this request to the load balancer. Now the load balancer will further take the request from the client to a server. The server will then process this request and send the output to the load balancer IP which will further take the output to the client.

Now for creating the above architecture I have created ansible playbook which will create the entire setup on the running of the command. All the servers launched using the playbook are launched on AWS, the IP is then fetched using the concept of dynamic inventory and is used to configure the Haproxy server.

If you want to learn how launch and configure instances on AWS using ansible and its dynamic inventory concept refer my previous article.

First making sure that the configuration file of ansible has been configured for the use of dynamic inventory:

No alt text provided for this image

Now onto the playbook. I will explain the playbook in two parts. The first part is launching the instances on AWS and the second part will be how to configure the launched instances.

- hosts: localhost
  vars_files:
  - passwd.yml
  tasks:
  - name: start an instance and Add EBS
    amazon.aws.ec2:
     exact_count: 2
     count_tag:
             Type: Webserver
     region: ap-south-1
     vpc_subnet_id: subnet-202e446c
     instance_type: t2.micro
     image: ami-0a9d27a9f4f5c0efc
     key_name: "mykey"
     group_id: sg-02491ed86d2c7184c
     aws_access_key: "{{ access_key }}"
     aws_secret_key: "{{ secret_key }}"
     instance_tags:
             Type: Webserver


  - name: start an instance and Add EBS
    amazon.aws.ec2:
     exact_count: 1
     count_tag:
             Type: Haproxy
     region: ap-south-1
     vpc_subnet_id: subnet-202e446c
     instance_type: t2.micro
     image: ami-0a9d27a9f4f5c0efc
     key_name: "mykey"
     group_id: sg-07970abf3ac6fbc39
     aws_access_key: "{{ access_key }}"
     aws_secret_key: "{{ secret_key }}"
     instance_tags:
             Type: Haproxy


  - name: Refresh inventory to ensure new instances exist in inventory
    meta: refresh_inventory

The code used here is pretty self explanatory but the thing to be noted here is that, the tags that are given while launching the instance will be used by dynamic inventory to create groups like here the tag: Type: Webserver will create a group : tag_Type_Webserver. The group so created can be used in the playbook to refer to the IPs.

I have also used the 'refresh_inventory' to update the inventory with the newly launched instances.

Now for the second half of the playbook, Here I have used the concept of Roles in ansible to configure the target nodes. Roles are basically what a package is in python here it is a directory that contains another set of directory, in those directories we can write what we want ansible to do. The directory structure is something like:

No alt text provided for this image

Here for each property of the playbook there is a different directory like for tasks there is a separate directory, for vars a separate one and so on. To create a role use the following commands:

ansible-galaxy init 'role name'

These roles can also be uploaded to Ansible Galaxy which is a public repository for ansible roles. These roles can be downloaded and are ready to be used.

The rest of the playbook code:

- hosts: tag_Type_Webserver
  become: yes
  remote_user: ec2-user
  roles:
  - webserver
                                                                                                                                                                    
- hosts: tag_Type_Haproxy
  become: yes
  remote_user: ec2-user
  roles:
  - haproxy

Here each role will work on different groups which have been created by the dynamic inventory code as explained above.

Here two roles have been used webserver and haproxy. The tasks of each are as follows:

No alt text provided for this image
No alt text provided for this image

The code of each is self explanatory but these are the changes which are to be made in the config file of haproxy:

No alt text provided for this image

Here the thing to be noted is to access the haproxy server we will send the request on the 5000 port and a 'for' loop has been added to the file. The use of this for loop is to update the haproxy file with the IPs of the webservers. The following is syntax of jinja2 which is a templating language and is used to created dynamic content.

Execute the playbook using the following command:

ansible-playbook --ask-vault-password haproxy.yml

Output as seen on the terminal:

No alt text provided for this image
No alt text provided for this image

Output as seen on the AWS console:

No alt text provided for this image

Accessing the webserver via the haproxy server's IP:

No alt text provided for this image
No alt text provided for this image

As it can be seen there are two different private IPs of the servers launched which confirms that the haproxy server has launched successfully.

Github link for the code: https://github.com/ArjunRekhi/ansible-aws

To view or add a comment, sign in

More articles by Arjun Rekhi

Others also viewed

Explore content categories