Amazon EKS — AWS CodePipeline
AWS CodePipeline orchestrates CI/CD natively. Combined with CodeBuild and CodeCommit (or GitHub), you get a fully AWS-managed pipeline that builds images, pushes to ECR, and deploys to EKS.
Architecture
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ GitHub / │ │ CodeBuild │ │ CodeBuild │ │ EKS │
│ CodeCommit │───▶│ (Build) │───▶│ (Deploy) │───▶│ Cluster │
│ Source │ │ Push ECR │ │ kubectl │ │ │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
▲ │
└────────── CodePipeline orchestrates ───────────────────┘
buildspec.yml for ECR Build
version: 0.2
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_REGISTRY
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
- echo Building Docker image...
- docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
- docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
post_build:
commands:
- echo Pushing to ECR...
- docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
- docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
- printf '[{"name":"%s","imageUri":"%s"}]' $CONTAINER_NAME $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG > imagedefinitions.json
artifacts:
files: imagedefinitions.json
buildspec.yml for EKS Deploy
version: 0.2
phases:
install:
commands:
- curl -LO "https://dl.k8s.io/release/$(curl -Ls https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
- chmod +x ./kubectl
- mv ./kubectl /usr/local/bin/kubectl
pre_build:
commands:
- echo Updating kubeconfig...
- aws eks update-kubeconfig --name $EKS_CLUSTER_NAME --region $AWS_DEFAULT_REGION
build:
commands:
- echo Deploying to EKS...
- kubectl set image deployment/$DEPLOYMENT_NAME $CONTAINER_NAME=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -n production
- kubectl rollout status deployment/$DEPLOYMENT_NAME -n production --timeout=300s
CodeBuild IAM Role for kubectl Access
The CodeBuild service role needs access to call eks:DescribeCluster and the cluster needs an access entry for it:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:DescribeCluster",
"eks:ListClusters"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
"Resource": "*"
}
]
}
Grant kubectl access:
aws eks create-access-entry \
--cluster-name my-cluster \
--principal-arn arn:aws:iam::123456789012:role/codebuild-deploy-role \
--type STANDARD
aws eks associate-access-policy \
--cluster-name my-cluster \
--principal-arn arn:aws:iam::123456789012:role/codebuild-deploy-role \
--policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy \
--access-scope type=cluster
Multi-Stage Pipeline with Approval
resource "aws_codepipeline" "eks_pipeline" {
name = "eks-deploy-pipeline"
role_arn = aws_iam_role.codepipeline.arn
artifact_store {
location = aws_s3_bucket.pipeline.bucket
type = "S3"
}
stage {
name = "Source"
action {
name = "Source"
category = "Source"
owner = "AWS"
provider = "CodeStarSourceConnection"
version = "1"
output_artifacts = ["source_output"]
configuration = {
ConnectionArn = aws_codestarconnections_connection.github.arn
FullRepositoryId = "my-org/my-repo"
BranchName = "main"
}
}
}
stage {
name = "Build"
action {
name = "Build"
category = "Build"
owner = "AWS"
provider = "CodeBuild"
input_artifacts = ["source_output"]
output_artifacts = ["build_output"]
version = "1"
configuration = {
ProjectName = aws_codebuild_project.build.name
}
}
}
stage {
name = "DeployStaging"
action {
name = "Deploy"
category = "Build"
owner = "AWS"
provider = "CodeBuild"
input_artifacts = ["build_output"]
version = "1"
configuration = {
ProjectName = aws_codebuild_project.deploy_staging.name
}
}
}
stage {
name = "Approval"
action {
name = "ManualApproval"
category = "Approval"
owner = "AWS"
provider = "Manual"
version = "1"
configuration = {
NotificationArn = aws_sns_topic.approval.arn
CustomData = "Review staging deployment before promoting to production"
}
}
}
stage {
name = "DeployProduction"
action {
name = "Deploy"
category = "Build"
owner = "AWS"
provider = "CodeBuild"
input_artifacts = ["build_output"]
version = "1"
configuration = {
ProjectName = aws_codebuild_project.deploy_prod.name
}
}
}
}
Best Practices
- Use CodeStar Connections for GitHub integration — not OAuth tokens
- Separate build and deploy stages — different IAM roles per stage
- Add manual approval before production — SNS notification to team
- Store build artifacts in S3 — enables deploy rollback to previous artifacts
- Use parameter store for environment config — not hardcoded in buildspec
- Enable CloudWatch Logs for CodeBuild — debug failed builds