Amazon EKS — CI/CD & GitOps Hands-On Lab
In this lab, you will set up ECR, build and push a container image, install ArgoCD on EKS, and deploy an application using GitOps.
Prerequisites
- Running EKS cluster
- AWS CLI, kubectl, Helm configured
- GitHub account
Step 1 — Create ECR Repository
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION=us-east-1
aws ecr create-repository \
--repository-name demo-app \
--image-scanning-configuration scanOnPush=true \
--image-tag-mutability IMMUTABLE
ECR_REPO="$ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/demo-app"
Step 2 — Build and Push a Sample Image
# Create a simple app
mkdir demo-app && cd demo-app
cat > main.go << 'EOF'
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
version := os.Getenv("APP_VERSION")
if version == "" {
version = "1.0.0"
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello from EKS! Version: %s\n", version)
})
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
fmt.Println("Starting server on :8080")
http.ListenAndServe(":8080", nil)
}
EOF
cat > Dockerfile << 'EOF'
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY main.go .
RUN go build -o demo-app main.go
FROM alpine:3.19
COPY --from=builder /app/demo-app /demo-app
EXPOSE 8080
CMD ["/demo-app"]
EOF
# Build and push
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com
docker build -t $ECR_REPO:v1.0.0 .
docker push $ECR_REPO:v1.0.0
Step 3 — Create Kubernetes Manifests in Git
Create a GitHub repository called demo-app-manifests with this structure:
demo-app-manifests/
├── deployment.yaml
├── service.yaml
└── namespace.yaml
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: demo
Replace ACCOUNT_ID with your actual AWS account ID:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app
namespace: demo
spec:
replicas: 2
selector:
matchLabels:
app: demo-app
template:
metadata:
labels:
app: demo-app
spec:
containers:
- name: demo-app
image: ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/demo-app:v1.0.0
ports:
- containerPort: 8080
env:
- name: APP_VERSION
value: "1.0.0"
livenessProbe:
httpGet:
path: /health
port: 8080
readinessProbe:
httpGet:
path: /health
port: 8080
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: demo-app
namespace: demo
spec:
selector:
app: demo-app
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Push to GitHub.
Step 4 — Install ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=300s
# Get admin password
ARGOCD_PASSWORD=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d)
echo "ArgoCD password: $ARGOCD_PASSWORD"
# Port forward to access UI
kubectl port-forward svc/argocd-server -n argocd 8080:443 &
Access ArgoCD at https://localhost:8080 (username: admin).
Step 5 — Create ArgoCD Application
# Install ArgoCD CLI
brew install argocd
argocd login localhost:8080 --username admin --password $ARGOCD_PASSWORD --insecure
# Create application
argocd app create demo-app \
--repo https://github.com/YOUR_ORG/demo-app-manifests.git \
--path . \
--dest-server https://kubernetes.default.svc \
--dest-namespace demo \
--sync-policy automated \
--auto-prune \
--self-heal
# Check status
argocd app get demo-app
Or apply as YAML:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/YOUR_ORG/demo-app-manifests.git
targetRevision: main
path: .
destination:
server: https://kubernetes.default.svc
namespace: demo
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
kubectl apply -f argocd-app.yaml
Step 6 — Verify Deployment
# Check ArgoCD sync status
argocd app get demo-app
# Check pods
kubectl get pods -n demo
# Test the app
kubectl port-forward svc/demo-app -n demo 9090:80 &
curl http://localhost:9090
# Output: Hello from EKS! Version: 1.0.0
Step 7 — Test GitOps (Update via Git)
Update the image tag in deployment.yaml:
image: ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/demo-app:v2.0.0
Commit and push. ArgoCD will detect the change and deploy automatically within ~3 minutes.
# Watch ArgoCD sync
argocd app get demo-app --refresh
# Verify new version
curl http://localhost:9090
# Output: Hello from EKS! Version: 2.0.0
Cleanup
argocd app delete demo-app --cascade
kubectl delete namespace argocd
kubectl delete namespace demo
aws ecr delete-repository --repository-name demo-app --force
kill %1 %2 # Stop port-forwards