AWS provides certain services to create a fully automated CI/CD pipeline to implement e.g. a blue/green deployment triggered by git push
.
-
ECS : Elastic Container Service
managed docker container environment, compatible with Fargate and EC2. We will use Fargate as container launch type. By that we do not have to take care of underlying cluster resources (in contrast to use EC2 launch type). -
ECR : Elastic Container Repository
container repository, like e.g. DockerHub -
CodeCommit
source code repository, basically Git by AWS -
CodeBuild
CodeBuild is a fully managed continuous integration service that compiles source code, runs tests, and produces software packages that are ready to deploy. -
CodeDeploy
CodeDeploy is a fully managed deployment service that automates software deployments to a variety of compute services such as Amazon EC2, AWS Fargate, AWS Lambda, and your on-premises servers -
CodePipeline
CodePipeline is the orchestrator which glues together the VCS-,build- and deploy steps. Not only AWS internal services are possible, e.g. you can also integrate GitHub as VCS.
This demo CI/CD pipeline will
- run container on AWS ECS cluster
- fetch the container from AWS ECR
- store the container implementation within CodeCommit
- use CodeBuild to build the container and push it to ECR
- use CodeDeploy to deploy updated container to ECS cluster, replacing the "old" container
To keep the infrastructure somehow simple, the whole setup uses a VPC with only 2 public subnets (in 2 different AZs) to show HA across availability zones.
The creation of the following resources is automated via terraform:
- vpc
- subnets (2 public)
- security groups
- loadbalancer (ALB)
- ECS cluster
- ECR (container) repository
- CodeCommit (code) repository
After those resources are up, the remaining steps are:
- push the code to CodeCommit repository
- create the CI/CD pipeline
prerequisites :
- aws cli installed and configured (by default terraform takes the AWS_ACCESS_KEY and AWS_SECRET_KEY from ~/.aws/credentials , from the profile default )
- the user you configured needs to have proper permissions to create the resources
- terraform installed v0.12+ ==> instructions
- to execute the terratest IaC tests you need to have golang installed. It uses the built-in package testing to run
go test xyz_test.go
( details of Terratest here)
cd terraform/terraform-s3-remote-state
#run once
terraform init
#check your terraform code
terraform validate
terraform plan
#deploy
terraform apply
run the tests upfront
cd <repo-root-dir>/terraform/core-aws/terratest
go test terraform-core-aws_test.go
# for verbose output add flag -v
# go test -v terraform-core-aws_test.go
and then create the resources
cd <repo-root-dir>/terraform/core-aws
#run once
terraform init
#check your terraform code
terraform validate
terraform plan
#deploy
terraform apply
cd <repo-root-dir>/terraform/services/ecs
#run once
terraform init
#check your terraform code
terraform validate
terraform plan
#deploy
terraform apply
cd <repo-root-dir>/terraform/services/cicd
#run once
terraform init
#check your terraform code
terraform validate
terraform plan
#deploy
terraform apply
prerequisite: you have Git installed
attach the predefined policies AWSCodeCommitPowerUser to your IAM user
- grab the sourcecode
git clone [email protected]:gkoenig/go-simplehttp.git
- setup ssh and clone CodeCommit repo get instructions from the CodeCommit repo page here , and how to setup ssh ħere
git clone ssh://git-codecommit.eu-central-1.amazonaws.com/v1/repos/aws-cicd-demo-code-repo
- add code to CodeCommit repo
cp ./go-simplehttp/Dockerfile ./go-simplehttp/simpleHTTP.go ./aws-cicd-demo-code-repo
cp ./scripts/buildspec.yml ./aws-cicd-demo-code-repo
cd aws-cicd-demo-code-repo/
git add .
git commit -m "Initial commit"
git push
Configre a CodeBuild project which builds a new container image and pushes it to ECR, triggered by a code change in our CodeCommit repository.
Create a dedicated role for CodeBuild. It will assume that role with its certain permissions, especially in our case permissions for ECR.
In IAM section of AWS console
- click Policies
- click create Policy ==> choose JSON
- paste the following JSON as policy content
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CloudWatchLogsPolicy",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"*"
]
},
{
"Sid": "CodeCommitPolicy",
"Effect": "Allow",
"Action": [
"codecommit:GitPull"
],
"Resource": [
"*"
]
},
{
"Sid": "S3GetObjectPolicy",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"*"
]
},
{
"Sid": "S3PutObjectPolicy",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"*"
]
},
{
"Sid": "ECRPullPolicy",
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": [
"*"
]
},
{
"Sid": "ECRAuthPolicy",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": [
"*"
]
},
{
"Sid": "S3BucketIdentity",
"Effect": "Allow",
"Action": [
"s3:GetBucketAcl",
"s3:GetBucketLocation"
],
"Resource":
"*"
}
]
}
- set CodeBuildServiceRolePolicy as policy name
- in the main navigation choose Roles
- click create Role
- choose CodeBuild as AWS service to add and click Next::Permissions
- on attach permissions policies page, select CodeBuildServiceRolePolicy and AmazonEC2ContainerRegistryPowerUser to add
- save the role as CodeBuildServiceRole
-
open CodeBuild service page within AWS mgm console Link
-
click Create build project
-
configure the Source provider by linking it to our CodeCommit repository, master branch
-
configure the build environment
-
click Create build project
- in the Build projects overview click on the previously created project demo-cicd-cb
- click on Start build in top right corner
- keep settings, scroll down and click Start build
- observe the build log output ...
After a successfull build you'll find your new image listed in the ECR repository
- Open the CodePipeline page ħere
- click Create pipeline in the top right corner
- configure Pipeline settings
- configure Source stage
- configure Build stage
- configure Deploy stage
- on the Review page scroll down and click Create pipeline
the pipeline will start immediately !!
You can ovserve the details of each phase by clicking on the Details link. E.g. for the build phase you'll be forwarded to the build log as we have seen in the CodeBuild chapter.
keep in mind that the deploy phase will take at least 5 minutes, because it waits for the old task(s) to be stopped. This, by default, will take roughly 5 minutes. you can observe this in the ECS service overview, clicking on the tab Events