Infrastructure Deployment Automation with Terraform, Ansible, and Parker
Published: 2024-01-11 06:41:44

In today’s world, companies leverage devops principles and tools to ensure the rapid deployment and efficient maintenance of their software and multiple cloud infrastructure. Having a uniform template through which the infrastructure can be re-created at any time as part of the process of accelerating deployment processes or swift disaster recovery would always give businesses competitive advantage in the market place.

By utilizing Terraform, companies are able to provision and mention their infrastructure on demand. This project rapidly empowers teams with the processes required for them to be operational efficient. It leverages Terraform - Infrastructure as Code tool that allows for declarative provisioning and configuration of resources which ensure scalability, replication, traceability, and efficient management of company infrastructure in the cloud. Infrastructure changes are meticulously tracked, making it easier to replicate at any time. 

Parker tool will be used to automate the creation AMIs on AWS Cloud, Ansible will be used to automate the creation servers and Terraform will be used to automate the end-to-end configuration of company resources that are setup on servers. Terraform will be used to create a codebase with separate files for variables and providers as part of best practices, ensuring the infrastructure remains flexible, scalable, and easily maintainable. Github will be used to host the codebase.
**Requirements:**
1.	AWS Free Tier Account
2.	GitHub Account (Free)
3.	Parker
4.	Ansible
5.	Terraform

**Migrate codes to Terraform Cloud**
- Create a Terraform Cloud Account
- Create an organization
- Configure a Workspace 


![Workspace](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ezi01z1xrptzxgdazit8.png)

- Configure Environment variables such as secrete key and access key.


![Workspace2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/utn41iq1sikxzy5b3kex.png)

- Build AMIs using packer (using an available ami ID teir 2 micro intance from AWS) since AMI owners ID number is not readily available.

```bash
packer build .\web.pkr.hcl
packer build .\bastion.pkr.hcl
packer build .\nginx.pkr.hcl  
packer build .\ubuntu.pkr.hcl   
```

![building AMIs with Packer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr6e0pgpcb8y8ftf7tw9.png)
![building AMIs with Packer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8zdmqbpw3zk7rfed1s3.png)

- AMIs created and available on the console.

![AMIs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/51uxei6bryoubqj9kl0k.png)

- Copy AMI id's from packer build and update details in terraform.auto.tfvars file and update terraform cloud settings in backend.tf on the local files then push to update repo on Gitlab. 

![updated terraform.auto.tfvars file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/918q9fmo3b82uc7vj0dl.png)
![backend file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/klzpc6kd666tgeqf3w9w.png)


### Build Infrastructure With Terraform
- First, comment out listiner, target groups and autoscalling attachment resources (for nginx/web/tooling,  ALB/alb.tf, autoscalling group attachments in  Autoscalling/asg-bastion-nginx.tf, and Autoscaling/asg-webserver.tf). This is to avoid target groups from failing health checks since intances have not been configure.  Then update repo by pushing to gitlab.

    - Run ```terraform plan``` and ```terraform apply``` from Terraform cloud console to automatically deploy the infrastructure. Then confirm and apply!

![TestApply](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7thv6yop0rgqklde8l0a.png)

    Automated terraform plan

![AutoTest](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/430aof8js987i46zqt38.png)



## Run Ansible Script 
- Connect to bastion host instance via SSH agent (ensure to add your keypair via the agent), Clone down the ansible script from  Gitlab repo, update the scipt with values from terraform infrastrutcture output and verify configuration settings are accurate before running ansible script.

![bastion instance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5iiisepzw4ue7ce71nm.png)
![bastion instance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1w4sd10itgjta42l731b.png)
![clone repo to bastion instance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kxawa3en01ukjc0zpom9.png)

- Since ansible needs to obtain ip addresses of each of the instances form the aws console then configure secrete environment variables on the bastion instance.


- Run aws configure and add Access Key and Secrete Key
- Then confirm that bastion host can connect to aws.

![confirm access to aws console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1lvgieur1c4lxnbw8u27.png)


```
Note: By default python3.6 might be in use by bastion instance. However, ansible version requires pythin3.8 or higher version.
Run sudo update-alternatives --config python3 (to display available python version).
then select Python3.8 from the options.
Next install boto3 again - run - sudo python3 -m pip install boto3

```
![ensure python3.8 or higher is enabled](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/necui6ynte7jy67jkm13.png)
![re-install boto3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/si0d36dnhz5ibgdfmdbj.png)

- Confirm that ansible can pull down the IP addresses of the instances from aws.


```
Run: ansible-inventory -i inventory/aws_ec2.yml --graph
```

![confirm ansible can pull down instance IPs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6nlt6tm3x9scatzo42yf.png)



- Update the ansible scipt with values from terraform infrastrutcture output and verify configuration settings are accurate.
    - update dns name for the intenal loadbalancer details in /roles/nginx/templates/nginx.conf.j2
    - update RDS endpoint for tooling and wordpress in  setup-db.yml
    - ensure username and password are same in tf.auto.var.
    -  mount points from Amazon EFS - access points each for tooling and wordpress (values for fsap and fs-) in tasks/main.yml.
    - update roles folder path in ansible.cfg file.
    - notify ansible to lookup ansible.cfg file. Run : export ANSIBLE_CONFIG=/home/../ansible.cfg.

![update dns name for nginx](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g64ivdtnuwryj0sxe3r0.png)
![update dns name for nginx](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bqtde18ac3n02cfvpwi1.png)
![update roles folder path in ansible.cfg](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z0mryy6gch8afizo7fu9.png)

![export path to ansible.cfg](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vn4mtq5d76f8pm3ra2km.png)

![update RDS endpoint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6z4zs1mi592uu9i50afd.png)

![update RDS endpoint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ww52l1rnyebt53up74s5.png)

![update efs mount point](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5bwvgpi630pu2kg86khu.png)

![update efs mount point](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n022dug5o59vfdt6irtn.png)

![update efs mount point](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ljgli9q5kdzjo9zzxvlh.png)

```
Run ansible script: 
ansible-playbook - i inventory/aws_ec2.yml playbooks/site.yml
```

![run ansible script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0hnkafe2avt706fcvyz.png)
![run ansible script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/faug8shpz6ymcm9aikld.png)



- Check that Configuration was successful
    - login to bastion host (via ssh -A ec2-user@IP) and connect to nginx, tooling and wordpress instances and check that setup configurations are accurate.
    - If need be update some settings. Ensure website is available locally by troubleshooting.


![update-config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvpvq2g67krgiqepn03s.png)

![update-config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8lzeijl4ogew4i6jfab8.png)



- Enable target group and autoscalling group by uncommenting 
    - From terraform local folder, uncomment listen resources for nginx/web/tooling in ALB/alb.tf
    - Also Autoscalling/asg-bastion-nginx.tf uncomment the autoscalling group attachment @ d botton of the file. 
    - Also uncomment attachments & target group in Autoscaling/asg-webserver.tf.
    - then push to repo gitlab and check terraform cloud for automatic plan then confirm and apply.

![update-config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oditfhxf7hxi5vppvvfx.png)

![update-config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pihj7x4nxbag6fjv7ua6.png)
![update-config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6j2acd7irfzbdl6hgx5m.png)



## If Issues occur:
- Check that nginx proxy is attached to lb 
- Check status of autoscaling goup
- Check status of listener, rules,
- might need to restart nginx and httpd manually. 

- Confirm url is accessible by visiting URLs: - wordpress.mtrone.ml and tooling.mtrone.ml

![update-config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pihj7x4nxbag6fjv7ua6.png)
![update-config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6j2acd7irfzbdl6hgx5m.png)
 
### Practice Task 1

<!-- - Configure 3 branches in terraform-cloud repository for _dev_, _test_ and _prod_ environments
- Make neccesary configurations to trigger runs automatically for the _dev_ environment -->
- Create an Email nofitications for certain events

![Mail](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bbsezofwmloa76on880v.png)

- Apply _destroy_ from Terraform Cloud web console


![Destroy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qcsrben26uvmzbxew4yr.png)