The purpose of this lab is to expose infrastructure and operations engineers to infrastructure as code. We use CodePipeline to practice continuous integration/ continuous deployment of our code. We create a single instance, then auto scale it in response to load. We the use the auto scale group to facilitate a rolling refresh of our operating system.
- This lab supports the following regions:
- us-east-1
- us-east-1
- us-west-2
- Additional regions can be supported if the AMIs are provided in the AMI map
- Case matters, especially when it comes to stack names
- Create architecture diagrams for each phase
- Add SMS notification for auto scaling events
- Add out of the box support for other regions
Install the following software on your laptop/desktop:
This section is only completed once and likely already has been done for you.
-
We need a few roles for CodePipeline
Windows:
aws cloudformation create-stack ^ --stack-name iac-prereq-access ^ --template-body file://prereq-access.yml ^ --capabilities CAPABILITY_NAMED_IAM
Mac/Linux:
aws cloudformation create-stack \ --stack-name iac-prereq-access \ --template-body file://prereq-access.yml \ --capabilities CAPABILITY_NAMED_IAM
-
We also need a VPC and subnet
Windows:
aws cloudformation create-stack ^ --stack-name iac-prereq-network ^ --template-body file://prereq-network.yml ^ --parameters file://prereq-parameters.json
Mac/Linux:
aws cloudformation create-stack \ --stack-name iac-prereq-network \ --template-body file://prereq-network.yml \ --parameters file://prereq-parameters.json
-
Users creating a CodePipeline will need the ability to pass an IAM role. Here is the policy needed:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "IaCPassRole", "Effect": "Allow", "Action": "iam:PassRole", "Resource": "*" } ] }
We're going to create CodeCommit and CodePipeline resources to help us execute new CloudFormation templates after committing them to a source code repository
Steps:
- Open
0-parameters.json
and provide a value forYourName
andPipelineRoleArn
. - Save this file.
- Run the following command to set up CodeCommit and CodePipeline:
Windows:
aws cloudformation create-stack ^
--stack-name <your_cicd_stack_name> ^
--template-body file://0-ci-cd.yml ^
--parameters file://0-parameters.json
Mac/Linux:
aws cloudformation create-stack \
--stack-name <your_cicd_stack_name> \
--template-body file://0-ci-cd.yml \
--parameters file://0-parameters.json
- The CodeCommit and CodePipeline resources should be created in less than 30 seconds. Run the following command to check the status. Or check the console.
aws cloudformation describe-stacks --stack-name <your_cicd_stack_name>
- When the pipeline is created you can grab just the repository URL and clone it: Windows:
aws cloudformation describe-stacks ^
--stack-name <your_cicd_stack_name> ^
--query "Stacks[0].Outputs[0].OutputValue" ^
--output text
git clone <repo_url>
Mac/Linux:
aws cloudformation describe-stacks \
--stack-name <your_cicd_stack_name> \
--query 'Stacks[0].Outputs[0].OutputValue' \
--output text | xargs -I {} \
git clone {}
- Stop here and take a moment to review the resources you have just created.
Review:
Review the CloudFormation template, 1-instance.yml
, for this module and try to answer the questions below before getting started.
Questions:
- What are we creating?
- Where are the resources being created? How do we control this?
- What will the resources do when they start?
- What does CodePipeline expect our files to be named?
- Will these instructions cause any resources to be destroyed/recreated?
Steps:
- Open
1-parameters.json
and provide a value forYourName
andSubnetId
. - Save this file.
- Deploy infrastructure as code through the CI/CD pipeline:
Windows:
copy 1-instance.yml <your_repo_name>\template.yml
copy 1-parameters.json <your_repo_name>\parameters.json
cd <your_repo_name>
git add -A
git commit -m "Creating an instance"
git push
cd ..
Mac/Linux:
cp 1-instance.yml <your_repo_name>/template.yml
cp 1-parameters.json <your_repo_name>/parameters.json
cd <your_repo_name>
git add -A
git commit -m "Creating an instance"
git push
cd ..
- Monitor the pipeline through the console.
- Once the 'Deploy' stage is complete review the following:
- Your Code Pipeline has created a CloudFormation stack with your name
- EC2 instance is created (Console > EC2 > Instances)
- CPU has spiked to ~100% (Select instance > Monitoring tab > CPU Utilization)
- Don't complete the 'Approve' stage yet because doing so will delete your infrastructure in the next step
- Adjust the size of the instance and create a new commit.
- Set the size to
t2.small
- Verify your change in the console.
- Change the user data to run less frequently and create a new commit.
- Set the cron to
*/2 * * * *
- Verify your change in the console.
Review the CloudFormation template, 2-auto-scale.yml
, for this module and try to answer the questions below before getting started.
Questions:
- What resources are being added?
- How will our resources scale? How can we control this?
Steps:
- Deploy autoscale resources through your CI/CD pipeline:
Windows:
copy 2-auto-scale.yml <your_repo_name>\template.yml
cd <your_repo_name>
git add -A
git commit -m "Creating instance with auto scale capabilities"
git push
cd ..
Mac/Linux:
cp 2-auto-scale.yml <your_repo_name>/template.yml
cd <your_repo_name>
git add -A
git commit -m "Creating instance with auto scale capabilities"
git push
cd ..
- Adjust the amount of time between scaling events and create a new commit.
- Set the new value to
120
seconds
- Verify your change in the console.
- Adjust the max number of instances and create a new commit.
- Set the new value to
3
- Verify your change in the console.
Review:
Review the CloudFormation template, 3-refresh.yml
, for this module and try to answer the questions below before getting started.
Questions:
- How could we apply patches to an instance?
Steps:
- Complete the 'Approve' step in your pipeline.
- Confirm the 'Delete' step completes.
- Open
3-parameters.json
and provide a value forYourName
,SubnetId
, andOS
(use "AmazonLinux2" as the OS value) - Save this file.
- Deploy resources through your CI/CD pipeline:
Windows:
copy 3-refresh.yml <your_repo_name>\template.yml
copy 3-parameters.json <your_repo_name>\parameters.json
cd <your_repo_name>
git add -A
git commit -m "Creating instances that need to be refreshed"
git push
cd ..
Mac/Linux:
cp 3-refresh.yml <your_repo_name>/template.yml
cp 3-parameters.json <your_repo_name>/parameters.json
cd <your_repo_name>
git add -A
git commit -m "Creating instances that need to be refreshed"
git push
cd ..
- Change the
OS
value toRedHat7
in your parameters file and create a new commit. - Watch what happens to your instances in the console.
Review:
Review the CloudFormation template, 4-dr.yml
, for this module and try to answer the questions below before getting started.
Questions:
- What region and availability zone will the resources be created in?
- Where is the AMI magic happening? How would you expand this?
Steps:
- Change your profile to another region
aws configure set region us-west-2
- Open 4-parameters.json and provide a value for YourName and OS (use "AmazonLinux2" or "RedHat7" as the OS value)
- Deploy CloudFormation
Windows:
aws cloudformation create-stack ^
--stack-name <your_dr_stack_name> ^
--template-body file://4-dr.yml ^
--parameters file://4-parameters.json
Mac/Linux:
aws cloudformation create-stack \
--stack-name <your_dr_stack_name> \
--template-body file://4-dr.yml \
--parameters file://4-parameters.json
- Add another availability zone and create a new commit.
Review:
- Go to CodePipeline and complete the 'Approve' stage. Confirm the 'Delete' stage completes.
- Tear down the DR stack:
aws cloudformation delete-stack --stack-name <your_dr_stack_name>
- Change your profile back to the original region
aws configure set region us-east-1
- Delete the contents of the CI/CD artifact bucket:
Windows:
(Or use the console because I'm not sure how to write this as a one-liner)
aws cloudformation describe-stack-resources ^
--stack-name <your_cicd_stack_name> ^
--query "StackResources[?LogicalResourceId==`Artifacts`].PhysicalResourceId" ^
--output text
aws s3 rm s3://<output_from_line_above> --recursive
Mac/Linux:
aws cloudformation describe-stack-resources \
--stack-name <your_cicd_stack_name> \
--query 'StackResources[?LogicalResourceId==`Artifacts`].PhysicalResourceId' \
--output text | xargs -I {} \
aws s3 rm s3://{} --recursive
- Tear down the CI/CD stack:
aws cloudformation delete-stack --stack-name <your_cicd_stack_name>
- (Optional) If you created the prereq resources, tear those down:
aws cloudformation delete-stack --stack-name iac-prereq-network
aws cloudformation delete-stack --stack-name iac-prereq-access
Required software:
- AWS CLI
- jq library
List Amazon Linux 2 AMIs in a region:
aws ec2 describe-images \
--filters "Name=owner-alias,Values=amazon" \
"Name=name,Values=amzn2-ami-hvm-*-gp2" \
"Name=architecture,Values=x86_64" \
--owner "amazon" \
--region us-east-1 | \
jq '.Images | sort_by(.CreationDate) | .[] | {Name: .Name, Created: .CreationDate, Id: .ImageId}' \
> amazonlinux-east-2
List Red Hat AMIs in a region:
aws ec2 describe-images \
--filters "Name=name,Values=RHEL*" \
"Name=architecture,Values=x86_64" \
--region us-east-1 | \
jq '.Images | sort_by(.CreationDate) | .[] | {Name: .Name, Created: .CreationDate, Id: .ImageId}' \
> rhel-east-2