This repository demonstrates a simple Blue-Green deployment strategy on Kubernetes for a small Node.js web app. It contains:
- A sample app (Express) exposing
/and/healthon port 3000. - Two Deployments (blue and green), a Service, and optional Ingress.
- Helper scripts to deploy a new image, switch traffic, port-forward for local testing, and run health checks.
Note: Filenames for the deployments use deployement-*.yaml (with an extra ‘e’) to match the current repo.
- Namespace:
blue-green-demo - Deployments:
- Blue:
k8s/deployement-blue.yaml→Deployment/app-blueusing imageinestmimi123/blue-green-app:1.0.0 - Green:
k8s/deployement-green.yaml→Deployment/app-greenusing imageinestmimi123/blue-green-app:1.1.0
- Blue:
- Service:
k8s/service.yamlnamedwebtargets label selectorapp=web,color=<blue|green>- Default selector is
color: blueso “blue” receives traffic initially.
- Default selector is
- Ingress (optional):
k8s/ingress.yamlfor hostbg.localtest.merouting to thewebService.
The app reports its color and version from environment variables and exposes a GET /health endpoint for probes and external checks.
- A working Kubernetes cluster with
kubectlconfigured. - Optional: an Ingress controller (e.g., NGINX Ingress) if you plan to use the provided Ingress.
- If running the helper scripts:
- They are Bash scripts meant for macOS/Linux. On Windows, run them under WSL or Git Bash. Alternatively, adapt the shown
kubectlcommands manually in PowerShell.
- They are Bash scripts meant for macOS/Linux. On Windows, run them under WSL or Git Bash. Alternatively, adapt the shown
- Create the namespace
kubectl apply -f k8s/namespace.yaml- Deploy blue and green (both can exist; Service points to blue initially)
kubectl apply -f k8s/deployement-blue.yaml
kubectl apply -f k8s/deployement-green.yaml
kubectl apply -f k8s/service.yaml- (Optional) Apply Ingress
kubectl apply -f k8s/ingress.yaml- Access the app
- Port-forward the Service:
scripts/port_forward.sh
# or manually
kubectl -n blue-green-demo port-forward svc/web 8080:80- Open:
- http://localhost:8080/ → JSON info including color and version
- http://localhost:8080/health → should return 200 OK
Assume blue is serving traffic and a new version should be rolled out to green.
- Update the green deployment to a new image and wait for rollout
Using the helper script (Bash):
# Deploy new image to green and switch the Service selector to green once ready
scripts/deploy.sh green <REGISTRY>/<REPO>/blue-green-app:<TAG>What the script does:
- kubectl set image on
deployment/app-green(namespaceblue-green-demo) - Waits for rollout to complete
- Switches Service
webselector tocolor: green
Manual commands equivalent:
# Set image and wait for rollout
kubectl -n blue-green-demo set image deployment/app-green app=<REGISTRY>/<REPO>/blue-green-app:<TAG>
kubectl -n blue-green-demo rollout status deployment/app-green
# Switch traffic to green
kubectl -n blue-green-demo patch service web -p '{"spec":{"selector":{"app":"web","color":"green"}}}'- Verify
With port-forward still active:
curl -fsS http://localhost:8080/health && echo OK
curl -fsS http://localhost:8080/ | jq .Or use the provided script:
scripts/health_check.sh http://localhost:8080/health 30 1- Roll back (if needed)
To route traffic back to blue quickly:
scripts/switch_traffic.sh blue
# or manually
kubectl -n blue-green-demo patch service web -p '{"spec":{"selector":{"app":"web","color":"blue"}}}'- Scale down the idle color (optional)
To save resources you can scale down the non-active color after confidence:
kubectl -n blue-green-demo scale deployment/app-blue --replicas=0
# or for green if blue is active
kubectl -n blue-green-demo scale deployment/app-green --replicas=0If you need to build your own image:
cd app
# Build image
docker build -t <REGISTRY>/<REPO>/blue-green-app:<TAG> .
# Push image
docker push <REGISTRY>/<REPO>/blue-green-app:<TAG>Then use that image with the deployment flow above.
- app/Dockerfile — Node 20-alpine base, installs deps, runs
npm start. - app/src/server.js — Express server exposing
/and/health. - k8s/namespace.yaml — Creates namespace
blue-green-demo. - k8s/deployement-blue.yaml — Deployment
app-blue, default imageinestmimi123/blue-green-app:1.0.0. - k8s/deployement-green.yaml — Deployment
app-green, default imageinestmimi123/blue-green-app:1.1.0. - k8s/service.yaml — Service
web, selector defaults tocolor: blue, port 80 → targetPort 3000. - k8s/ingress.yaml — Ingress for host
bg.localtest.meto Serviceweb(requires Ingress controller). - scripts/deploy.sh — Update target deployment image, wait for rollout, switch Service.
- scripts/switch_traffic.sh — Patch Service selector to
blueorgreenand wait for endpoints. - scripts/port_forward.sh — Port-forward
webService to localhost:8080. - scripts/health_check.sh — Simple curl-based health checker.
- Probes failing: Ensure the container responds on
/healthand thattargetPortmatchescontainerPort(here 3000). - Service not switching: Verify labels on Pods include both
app=weband the correctcolor. Check with:
kubectl -n blue-green-demo get pods -l app=web -L color
kubectl -n blue-green-demo get svc web -o yaml
kubectl -n blue-green-demo get endpoints web -o wide- Script usage on Windows: Run under WSL or Git Bash. Otherwise, copy the shown
kubectlcommands to PowerShell.
- Windows users: scripts are Bash. Use WSL/Git Bash or run the equivalent kubectl commands shown.
- GitOps flow: This repo pairs with a GitOps repository (see Jenkinsfile env GITOPS_REPO_SSH). The pipeline updates deployment-green.yaml and switches Service selector via PR/commit.
- Health gates: Before switching traffic, ensure /health returns 200 for the target color. Example curl probes are provided.
- Rollback strategy: Switch back selector and optionally scale down the bad color. Keep both colors for fast recovery.
The included Jenkinsfile performs:
- Build Node app and Docker image, push to registry.
- Update GitOps repo with the new image in deployment-green and APP_VERSION env.
- Wait for GREEN health via HEALTH_URL.
- Switch Service selector to green. On failure, auto-rollback selector to blue.
Required Jenkins credentials:
- docker-registry: Docker username/password
- gitops-bot: credentials to push to the GitOps repo
Key env vars in Jenkinsfile:
- REGISTRY, APP_NAME, GITOPS_REPO_SSH, GITOPS_BRANCH, HEALTH_URL, NAMESPACE
To add Prometheus metrics to the app, install prom-client and expose /metrics:
npm i prom-clientAdd to app/src/server.js:
const client = require('prom-client');
client.collectDefaultMetrics();
app.get('/metrics', async (req, res) => {
res.set('Content-Type', client.register.contentType);
res.end(await client.register.metrics());
});Then deploy kube-prometheus-stack and a ServiceMonitor as shown in GUIDE.md.
MIT