This is the Ansible section complementing the Weatherapp challenge/project. This solution includes playbooks for the creation of a Base web server instance, Docker setup, AMI creation, scaling out and in, load balancing and deployment with two methods: an inefficient one with pre-built image tarballs, and an efficient one using git and docker-compose. It also includes tasks for rolling-back/destroying the resources it created.
- Clone the repo and
cd weatherapp-ansible
- From AWS IAM, create a new user named
ansible
and give it programmatic access ONLY - Copy the newly generated access key ID and secret access key before moving on
- Create a git-ignored file called
aws_secrets
in the root directory with the following information:export AWS_ACCESS_KEY_ID="<YOUR_ANSIBLE_ACCESS_KEY_ID>" export AWS_SECRET_ACCESS_KEY="<YOUR_ANSIBLE_SECRET_ACCESS_KEY>" export AWS_REGION="<YOUR_DESIRED_REGION>"
- You can skip this step if you have
aws-cli
configured with the same information - Attach the
AdministratorAccess
AWS-managed policy toansible
user- This may be changed later to only allow access as necessary
- Make sure to have a default VPC built for the AWS region specified
- Locally source
ansible
user access information - Gather default VPC and subnets facts
- Create a new SSH key pair and copy to a
.keypairs
folder with the correct file mode - Ensure that
.keypairs
folder is git-ignored - Create a new security group with limited SSH access and public HTTP
- Create an EC2 instance within the security group and gather facts
- Add instance to inventory
- Install Docker and essential packages
- Deploy by pulling from GitHub and using docker-compose
- Create an Amazon Machine Image (AMI) from the instance
- Create a scaling workflow
- Create an Elastic Load Balancer (ELB) with basic health checks and note the domain name
Note: Terraform or CloudFormation are more "right" Infrastructure as Code (IaC) tools than Ansible (especially for more complicated setups and managing rollbacks) but this is an Ansible exercise in trying out different modules. I may revisit this project later to use one of those tools for a more complete infrastructure build.
-
Once the app is ready to deploy, load the AWS credentials (Skip if it's not needed):
$ source ./aws_secrets
-
You can add it with absolute path to your
.bash_profile
-
Check the path to your system or venv Python interpreter and update the
ansible_python_interpreter
field in the inventory file -
Make sure the AWS Boto3 and Botocore packages are installed on that Python
-
Update the
./group_vars/webservers/vars
file to point to your Docker-ized app repo -
Also, make sure to make the necessary edits with the backend service URL and port if any are required
-
In the same folder, create a new file
secrets
and set your OpenWeatherMap key as follows;vault_app_id: <YOUR_OPENWEATHERMAP_KEY>
-
The file will be git-ignored, but you can use
ansible-vault
to encrypt it for extra security -
You now have access to three deployment playbooks in the folder root
- Run
$ ansible-playbook base.yml
to:- Gather information for a subnet in the default VPC
- Get the ID of the latest Amazon Linux 2 AMI
- Create a "facts" folder to hold the information in YAML
- Create a new SSH key pair, and webserver security group
- Build the base webserver EC2 instance using all previous details
- The VM type is t3.nano, but you can change it in
./group_vars/all/vars
- The VM type is t3.nano, but you can change it in
- Add the created instance to the inventory file
- Create an ELB and target group to be used later when scaling
- Note the DNS name of the ELB to the file
facts/elb_url.yml
- Run
$ ansible-playbook setup.yml
to:- Update the Linux system packages
- Install Git, Docker and docker-compose
- Start and enable the Docker service
- Reboot the EC2 instance
- Create an AMI of the instance
- Run
ansible-playbook deploy.yml
to:- Pull the app from the repo
- Set the proper environment variables
- Cleanup previous Docker containers and images
- Build and run the app using docker-compose
- You can now see the app running on its public DNS/IP or the URL to the ELB
- [
as needed
] Runansible-playbook ami.yml
to:- Create AMIs manually for your RPO needs
- [
as needed
] Runansible-playbook scale.yml
to:- Scale out/add 3 new webserver instances based on the created AMI
- 3 is the default based on the number of AZ's in the EU-North-1 region
- This
scale_count
variable can be changed in thegroup_vars/all/vars
file
- Add the created instances to the inventory
- Scale out/add 3 new webserver instances based on the created AMI
- [
as needed
] Runansible-playbook scale.yml --tags in
to:- Scale in/terminate 1 webserver instance and remove it from the target group
- Remove its reference in the inventory
- Run
-
Whenever you run the
deploy.yml
later, it will deploy to all the webservers -
If you have the
secrets
variables file encrypted, make sure to use the--ask-vault-pass
or--vault-id xxx@prompt
flags in stepsii
andiii
-
Alternatively, and highly not recommended, you can deploy using the inefficient
deploy_tar.yml
playbook method to upload the docker images pre-built locally. Just make sure they have the production environment variables set. -
To rollback/destroy all the AWS resources created, run:
$ ansible-playbook base.yml --tags=cleanup
$ ansible-playbook ami.yml --tags=cleanup