Webserver configuration on AWS EC2 using Ansible

Webserver configuration on AWS EC2 using Ansible

Moving towards industry 4.0 the drastic change we will see or we have to get ready to face will be automation on an industrial scale. So the basic needs of IT Infrastructure we see are resources and the hosting platform we use to make our idea public. One such is webserver which we commonly use. Today we will see how to configure apache webserver on AWS EC2 instance using ansible.

Ansible is not meant for provisioning operating systems, it's meant to configure systems. Tho ansible has a capability to provision it, this concept we have seen in terraform also. Terraform is not meant for configuring services, it's meant for managing cloud services. Tho it can configure services.

Moving towards building the code, let's understand the use case for it. For instance, let's say we have around 10 different servers running in different parts of the world. We need to deploy our web server and website on these servers so that the people in the near locality can get low latency in accessing the website. So, we need an intelligent script that goes to all the servers and on top of AWS it will provision EC2 and inside it, it will configure apache webserver and give us the unique URL which will be a public DNS name through which we can access our website. The main thing here will be we won't be doing anything manual even while writing code and won't go to AWS portal even once for doing anything.

We will create our workspace first, I have created this particular file system for this project to manage the things.

No alt text provided for this image

Here we see two files vars.yml and webserver.yml, vars.yml contains our AWS secret, and access key in encrypted form using ansible-vault and webserver.yml is the one which contains our main code. So, let's see how to write the Infrastructure as a Code.

vars.yml

To save passwords in clear text is not a good practice, hence we will save it in an encrypted format. To do so we will create a vault.

No alt text provided for this image

Using vim we can create a normal text file and save our password in a particular format as it's a YAML file.

No alt text provided for this image

Here awsaccess and awssecret are variables and their corresponding value. Here, the values which I have provided are not correct, obviously?? for security reasons. So, it will somewhat look like this.

Now we will encrypt it and save it in the vault.

No alt text provided for this image

Here, ansible-vault is the command, encrypt will tell vault to encrypt the file, --vault-id is to tell some user will be specified to use it shubham@prompt, shubham is the user, note: it's not compulsory to physically have shubham as a user it's just a name and prompt here means, it will prompt the user to insert password. Finally, we have to give the file name, for our case it's vars.yml.

Now if you check the content of the vars.yml file by cat or vim command, you will see encrypted data.

No alt text provided for this image

webserver.yml

The main code file where we tell the managed nodes and what all configuration we need to do on them. In our case, we are configuring our own system, hence we will give host as localhost. This means we are going to configure our own system or say controller node, if we have multiple nodes to be configured we can use the inventory file. To know more about these files and how to setup ansible visit my previous article and read about it here.

- name: Webserver on aws instance
  hosts: localhost
  vars_files:
  
        - vars.yml

This is the start of the code where we mention the managed nodes as hosts. Then we have vars_files: this module helps us to import variables from other files.

tasks:
          - name: getting vpc subnet info
            ec2_vpc_subnet_info:
                    aws_secret_key: "{{ awssecret }}"
                    aws_access_key: "{{ awsaccess }}"
            register: vpc
          - debug:
                  var: vpc.subnets[0].subnet_id  

Here we are using ec2_vpc_subnet_info: module because later we have to launch ec2 instance with public IP. To assign public IP we need a specific vpc subnet or else there we will face error and have to manually give subnet id. Using register we have saved the output and we retrieve and print it using the debug module. We have randomly picked the initial subnet of the three by default using vpc.subnets[0].subnet_id. We have used the aws_secret_key and aws_access_key using our vault.

          - name: creating security group for webserver
            ec2_group:
                    name: "webosansible"
                    description: sg with ssh and http
                    region: ap-south-1
                    aws_secret_key: "{{ awssecret }}"
                    aws_access_key: "{{ awsaccess }}"
                    rules:
                            - proto: tcp
                              from_port: 80
                              to_port: 80
                              cidr_ip: 0.0.0.0/0
                            - proto: tcp
                              from_port: 22
                              to_port: 22
                              cidr_ip: 0.0.0.0/0
            
            register: sgweb

Then we created a security group for our instance and we saved the output in sgweb variable as we will need the security group name in while creating an ec2 instance.

          - name: creating key
            ec2_key:
                    name: ansiblewebos
                    region: ap-south-1
                    aws_secret_key: "{{ awssecret }}"
                    aws_access_key: "{{ awsaccess }}"
            register: ec2key


          - name: saving key
            copy:
                    content: "{{ ec2key.key.private_key }}"
                    dest: "/ansible_code/aws-ec2/ansiblewebos"
                    
                    mode: "0600" 

Here, we are creating a key that helps us logging inside the instance in the future. Someone who is familiar with the AWS knows that we even have to save the key or else we won't be able to log in the OS using it. So, first, we will generate a key using ec2_key module then we will save it using copy module.

We have all the minimum requirements to launch an instance and configure it. Note: We haven't used anything manually here. Even if you want to create your own VPC use the following code. We don't need this because we have used ec2_vpc_subnet_info module to get the subnet info otherwise you need to create vpc for your own and save the output in a variable and use it while creating instance which will eventually help you get public IP.

- name: creating vpc
            ec2_vpc:
                    aws_secret_key: "{{ awssecret }}"
                    aws_access_key: "{{ awsaccess }}"
                    state: present
                    cidr_block: 172.22.0.0/16
                    region: ap-south-1
                    subnets:
                            - cidr: 172.22.1.0/24
                              az: ap-south-2a
                            - cidr: 172.22.2.0/24
                              az: ap-south-2b
                            - cidr: 172.22.3.0/24
                              az: ap-south-2c
                    internet_gateway: True
                    route_tables:
                            - subnets:
                                    - 172.22.2.0/24
                                    - 172.22.3.0/24
                              routes:
                                      - dest: 0.0.0.0/24
                                        gw: igw
                            - subnets:
                                    - 172.22.1.0/24
                              routes:
                                      - dest: 0.0.0.0/24
                                        gw: igw
            
            register: vpc

Note: We don't need this if you are using my approach of using ec2_vpc_subnet_info or else you need to create vpc.

Now, let's see how to provision and configure at the same time.

          - name: provisioning and configuring ec2 instance
            ec2:
                    assign_public_ip: yes
                    aws_access_key: "{{ awsaccess }}"
                    aws_secret_key: "{{ awssecret }}"
                    count: 1
                    group_id: "{{ sgweb.group_id }}"
                    image: ami-0ebc1ac48dfd14136
                    instance_tags:
                            webos: httpd
                    instance_type: t2.micro
                    vpc_subnet_id: "{{ vpc.subnets[0].subnet_id }}"
                    wait: yes
                    key_name: "{{ ec2key.key.name }}"
                    region: ap-south-1
                    state: present
                    user_data: | 
                               #!/bin/bash
                               sudo yum install httpd php -y
                               sudo systemctl start httpd
                               sudo systemctl enable httpd
                               
                               echo "Website created by Shubham Bhalala" >> /var/www/html/index.html

Here you see we have used vpc_subnet_id, key_name, group_id using the register values from the above code. The main thing here which we used to configure webserver is user_data using this we set the metadata of the instance.

Finally, we have to retrieve the public DNS name of the instance using which we will access the website.

          - name: gathering instance info
            ec2_instance_info:
                    aws_access_key: "{{ awsaccess }}"
                    aws_secret_key: "{{ awssecret }}"
                    filters:
                            instance-state-name: running
            register: ec2instance
          - name: url to access website
            debug:
                    var: ec2instance.instances[0].network_interfaces[0].association.public_dns_name 





We have used ec2_instance_info for getting all the information about the ec2 instance which is in running state. Then using the info we collect we got the public_dns_name using json logic ec2instance.instances[0].network_interfaces[0].association.public_dns_name

It's the time to launch it and see what output we get and whether we are getting everything right or not.

No alt text provided for this image

we have added --vault-id shubham@prompt while running ansible-playbook because we are using a variable file which is locked by vault id and it will prompt to add the password which we have initially set while creating the vault. Finally, we can see it successfully executed and gave the URL through which we can access the website.

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

We can also check from the AWS portal that it's launched and running successfully.

No alt text provided for this image

Inside the code we have written a code for saving the key to our system, that's also been done and you can see it.

No alt text provided for this image

Thank you for reading this article! Please give a start to the GitHub repository if you like it.?

??GitHub: Link

要查看或添加评论,请登录

社区洞察

其他会员也浏览了