This repository contains a demo project created as part of my DevOps studies in the TechWorld with Nana – DevOps Bootcamp.
Demo Project: Complete CI/CD Pipeline with EKS and AWS ECR
Technologies used: Kubernetes, Jenkins, AWS EKS, AWS ECR, Java, Maven, Linux, Docker, Git
Project Description:
- Create private AWS ECR Docker repository
- Adjust Jenkinsfile to build and push Docker Image to AWS ECR
- Integrate deploying to K8s cluster in the CI/CD pipeline from AWS ECR private registry
- So the complete CI/CD project we build has the following configuration:
- a.CI step:Increment version
- b.CI step: Build artifact for Java Maven application
- c.CI step: Build and push Docker image to AWS ECR
- d.CD step: Deploy new application version to EKS cluster
- e.CD step: Commit the version update
Before starting, complete the following module:
About ECR:
- You can create an unlimited number of private repositories
- Each application gets its own repository
- Each repository holds multiple image versions via tags
- Navigate to Elastic Container Registry → Create repository
- Set the repository name to
java-maven-app - Click Create
-
Navigate to Elastic Container Registry → java-maven-app
-
Click View push commands
-
Run the following command to retrieve your ECR password:
aws ecr get-login-password --region <REGION>- In Jenkins, navigate to Manage Jenkins → Credentials → System → Global
- Click Add Credentials and fill in:
| Field | Value |
|---|---|
| Kind | Username with password |
| Username | AWS |
| Password | The output from aws ecr get-login-password |
| ID | ecr |
- Click Create
Note: ECR login tokens expire after 12 hours. If builds fail with authentication errors, regenerate the password and update this credential.
The EKS cluster needs a docker-registry secret to pull images from the private ECR repository.
- Configure your local connection to the EKS cluster:
aws configure list
aws eks update-kubeconfig --name demo-cluster --region <REGION>- Get the Docker server URL from the ECR push commands:
- Create the Docker registry secret:
kubectl create secret docker-registry ecr \
--docker-server=<ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com \
--docker-username=AWS \
--docker-password=$(aws ecr get-login-password --region <REGION>)- Verify the secret was created:
kubectl get secret ecrNote: Like the Jenkins credential, this secret uses a 12-hour ECR token. For production setups, consider automating token refresh with a CronJob or an ECR credential helper.
The gettext-base package provides the envsubst command, which is used to substitute environment variables in Kubernetes manifest templates during deployment.
- Connect to the Jenkins server and enter the Jenkins container:
ssh root@<DROPLET_IP>
docker ps
docker exec -it -u 0 <CONTAINER_ID> bash- Install
gettext-baseand verify the installation:
apt-get update && apt-get install -y gettext-base
envsubst -VThe Kubernetes manifest files define how the application is deployed and exposed:
- kubernetes/deployment.yaml — creates a Deployment with 2 replicas, referencing the
ecrimage pull secret - kubernetes/service.yaml — exposes the application on port 80 (forwarding to container port 8080)
Note: The variables
$APP_NAMEand$APP_IMAGEin these files are not Kubernetes-native variables. They are placeholders thatenvsubstreplaces with actual values during the pipeline's deploy stage.
See the full pipeline definition: Jenkinsfile
Key configuration to update:
| Parameter | Description | Example |
|---|---|---|
DOCKER_SERVER |
Your ECR registry URL | 123456789012.dkr.ecr.eu-central-1.amazonaws.com |
DOCKER_REPO |
The ECR repository name | java-maven-app |
GITHUB_REPO |
Your GitHub repository (owner/repo) | explicit-logic/eks-module-11.7 |
- Navigate to Manage Jenkins → Plugins → Available Plugins
- Search for and install: Ignore Committer Strategy
This plugin prevents multibranch pipelines from triggering new builds when commits are made by specified email addresses — used here to break the CI commit loop caused by Jenkins version-bump commits.
Jenkins needs a GitHub Personal Access Token to clone the repository and update commit statuses.
Create the token:
- Go to github.com/settings/tokens/new
- Set Note to
jenkins - Select the following scopes:
| Scope | Reason |
|---|---|
admin:repo_hook |
Create, read, and delete webhooks |
public_repo |
Access public repositories |
repo:status |
Update commit statuses |
- Click Generate token and copy it immediately
Add the token to Jenkins:
- Navigate to Manage Jenkins → Credentials
- Click Add Credentials and fill in:
| Field | Value |
|---|---|
| Kind | Username with password |
| ID | github |
| Username | Your GitHub username (not your email) |
| Password | Your personal access token (starts with ghp_) |
- Go to Dashboard → New Item
- Name it
cicd-ecr, select Multibranch Pipeline, click OK
Branch Sources:
Click Add source → GitHub and configure:
| Field | Value |
|---|---|
| Credentials | github |
| Repository HTTPS URL | https://github.com/<YOUR_USER>/eks-module-11.7 |
Click Validate to confirm access.
Behaviors — click Add and enable:
Discover branches
Build Configuration:
- Script Path:
Jenkinsfile
Build Strategies:
- Add Ignore Committer Strategy
- List of author emails to ignore:
jenkins@example.com
- List of author emails to ignore:
- Check Allow builds when a changeset contains non-ignored author(s)
This combination ensures that version-bump commits made by Jenkins do not re-trigger the pipeline, preventing an infinite build loop.
- Click Save — Jenkins will scan the repository and create a job for each branch.
- Go to IAM → Users → Create user
- Name:
jenkins
- Name:
- Select Attach policies directly and attach the following managed policies:
AmazonEKSClusterPolicyAmazonEKSWorkerNodePolicyAmazonEC2ContainerRegistryFullAccess
- Complete user creation.
- Find the user's ARN in the IAM console:
- Map the IAM user to the cluster:
eksctl create iamidentitymapping \
--cluster demo-cluster \
--region <REGION> \
--arn arn:aws:iam::<ACCOUNT_ID>:user/jenkins \
--group system:masters \
--username jenkins- In IAM, open the
jenkinsuser → Security credentials → Create access key - Use case: Application running outside AWS
- Copy the Access key and Secret access key
- Navigate to the
cicd-ecrpipeline → Credentials → Global → Add Credentials - Add two Secret text credentials:
| ID | Secret |
|---|---|
AWS_ACCESS_KEY_ID |
Your access key |
AWS_SECRET_ACCESS_KEY |
Your secret access key |
Once all credentials and configurations are in place, trigger the pipeline:
- Navigate to the
cicd-ecrpipeline in Jenkins - Select the
mainbranch and click Build Now - Monitor the build stages: version increment → build → Docker image push → deploy → version commit
After a successful run, verify the deployment:
kubectl get pods
kubectl get svcDemo:










