Example of a complete DevOps CI/CD pipeline implementation to deploy an application on AWS EKS.
- Package the vue3 realworld frontend application into a Docker container image
- Push it to AWS Elastic Container Registry (ECR)
- Create an AWS Elastic Kubernetes Service (EKS) cluster
- Use AWS CodeBuild to automate the CI/CD pipeline by:
- Check for changes in the code repository
- Create new docker image, tag it and push it to AWS ECR
- Update deployment file with new image version and reload k8s cluster configuration
- Fork vue3 realworld, rename the repository to aws-eks-cicd and clone it to your local machine
git clone https://github.com/jpmmota/aws-eks-cicd.git
cd aws-eks-cicd
-
Create Dockerfile in the project root folder
-
Build the container image locally and test it
docker build -t jpmmota/aws-eks-cicd:latest .
docker run --rm -it -d -p 3000:80 jpmmota/aws-eks-cicd:latest
curl localhost:3000
- Create AWS Elastic Container Registry (ECR)
aws ecr create-repository --repository-name aws-eks-cicd
- Push docker image to AWS (ECR)
aws ecr get-login-password --region ca-central-1 | docker login --username AWS --password-stdin 577620766037.dkr.ecr.ca-central-1.amazonaws.com
docker build -t aws-eks-cicd:1.0 .
docker tag aws-eks-cicd:1.0 577620766037.dkr.ecr.ca-central-1.amazonaws.com/aws-eks-cicd:1.0
docker push 577620766037.dkr.ecr.ca-central-1.amazonaws.com/aws-eks-cicd:1.0
- Create AWS Elastic Kubernetes Service (EKS) cluster
eksctl create cluster --name eks-cicd --node-type t2.micro --nodes 2
- Create create-role.json file
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "codebuild.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
- Create put-role-policy.json file:
{
"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": "S3BucketIdentity",
"Effect": "Allow",
"Action": [
"s3:GetBucketAcl",
"s3:GetBucketLocation"
],
"Resource": "*"
},
{
"Sid": "ElasticContainerRegistryPolicy",
"Effect": "Allow",
"Action": [
"ecr:*"
],
"Resource": "*"
},
{
"Sid": "CodeBuildAssumeRolePolicy",
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": "*"
},
{
"Sid": "EKSPolicy",
"Effect": "Allow",
"Action": [
"eks:*"
],
"Resource": "*"
}
]
}
- Apply policies
aws iam create-role --role-name CodeBuildServiceRole --assume-role-policy-document file://create-role.json
aws iam put-role-policy --role-name CodeBuildServiceRole --policy-name CodeBuildServiceRolePolicy --policy-document file://put-role-policy.json
- Add user to eks rbac configuration
eksctl create iamidentitymapping --cluster eks-cicd --arn <EKS_ROLE_ARN> --group system:masters --username CodeBuildServiceRole
-
Create deployment.yaml and service.yaml files
-
Create buildspec.yaml file that will be used by AWS CodeBuild
-
Create AWS CodeBuild project
- Project name: eks-cicd
- Source provider: Github
- Connect using OAuth
- Repository URL: https://github.com/jpmmota/aws-eks-cicd
- Operating System: Ubuntu
- Runtime: Standard
- Image: aws/codebuild/standard:5.0
- Privileged: check the box
- Existing Service Role: selected
- Provide Role ARN that was previously created
- Allow AWS CodeBuild to modify this service role so it can be used with this build project: unselected
- Deploy service and get the load balancer URL to test the application (wait a few minutes until the load balancer becomes available):
kubectl apply -f service.yaml
kubectl get services eks-cicd