Real-Life Kubernetes Project: Production App Deployment
Deploy a production-ready microservice on Kubernetes
This project walks through a realistic Kubernetes deployment pattern used by platform and DevOps teams: container image, namespace, deployment, service, ingress, config, secrets, autoscaling, monitoring, and GitOps-style delivery.
If you want to learn Kubernetes for real work, do not stop at creating a pod. In most companies, the useful skill is knowing how an application moves from code to a stable URL, how it scales during traffic, how it gets monitored, and how the team can roll it back when something goes wrong.
Architecture | Repository layout | Kubernetes manifests | Deployment steps | Monitoring and troubleshooting | GitOps workflow
1. Architecture: what happens when a user opens the app?
The application follows a common production pattern. A user sends an HTTPS request to your domain. The ingress controller receives the request, routes it to a Kubernetes Service, and the Service load-balances traffic to healthy pods created by a Deployment. Configuration comes from ConfigMaps, sensitive values come from Secrets, and the Horizontal Pod Autoscaler adds more pods when CPU usage increases.
2. Repository layout
A clean repository makes the project easier to understand in interviews and easier to automate in CI/CD.
k8s-real-life-project/
├── app/
│ ├── Dockerfile
│ └── src/
├── k8s/
│ ├── namespace.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ └── hpa.yaml
└── README.md
3. Kubernetes manifests
Start with a separate namespace so the application is isolated from default workloads.
apiVersion: v1
kind: Namespace
metadata:
name: production-demo
Use a ConfigMap for non-sensitive application settings.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production-demo
data:
APP_ENV: "production"
LOG_LEVEL: "info"
Use a Secret for sensitive values. In a real company, this usually comes from a secret manager, sealed secret, or external secrets operator.
apiVersion: v1
kind: Secret
metadata:
name: app-secret
namespace: production-demo
type: Opaque
stringData:
DATABASE_URL: "postgres://user:password@postgres:5432/appdb"
The Deployment controls replicas, rolling updates, resource limits, and health checks.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-api
namespace: production-demo
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: web-api
template:
metadata:
labels:
app: web-api
spec:
containers:
- name: web-api
image: ghcr.io/your-org/web-api:1.0.0
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secret
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 20
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
The Service gives the pods a stable internal endpoint.
apiVersion: v1
kind: Service
metadata:
name: web-api-service
namespace: production-demo
spec:
selector:
app: web-api
ports:
- port: 80
targetPort: 8080
type: ClusterIP
The Ingress exposes the app through a real domain.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-api-ingress
namespace: production-demo
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-api-service
port:
number: 80
Finally, HPA lets Kubernetes add pods when the app gets busy.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api-hpa
namespace: production-demo
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
minReplicas: 2
maxReplicas: 6
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
4. Deploy the project
Build and push the image
Build the application image and push it to a registry such as Docker Hub, Amazon ECR, GitHub Container Registry, or Google Artifact Registry.
docker build -t ghcr.io/your-org/web-api:1.0.0 ./app
docker push ghcr.io/your-org/web-api:1.0.0
Apply Kubernetes resources
Apply the manifests in order. Namespace first, then config, secret, deployment, service, ingress, and autoscaling.
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secret.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml
kubectl apply -f k8s/hpa.yaml
Verify the rollout
Do not just check whether pods exist. Check rollout status, endpoints, logs, and ingress routing.
kubectl -n production-demo rollout status deployment/web-api
kubectl -n production-demo get pods -o wide
kubectl -n production-demo get svc,ingress,hpa
kubectl -n production-demo logs deploy/web-api --tail=100
5. Monitoring and troubleshooting
A real project is not complete until you can see what the application is doing. At minimum, expose a health endpoint, readiness endpoint, and metrics endpoint. Then connect metrics to Prometheus and dashboards to Grafana.
- Readiness failures: check app startup time, config values, and database connectivity.
- CrashLoopBackOff: inspect logs with
kubectl logsand describe the pod events. - Ingress returns 404: verify host name, path, ingress class, and service port.
- HPA does not scale: confirm Metrics Server is installed and resource requests are defined.
kubectl -n production-demo describe pod <pod-name>
kubectl -n production-demo describe ingress web-api-ingress
kubectl top pods -n production-demo
6. Make it a GitOps project
In a real team, engineers should not manually run kubectl apply from their laptop for every production change. Store manifests in Git and let Argo CD or Flux sync the desired state into the cluster.
A simple GitOps flow looks like this:
- Developer pushes application code.
- CI builds and pushes a new container image.
- CI updates the image tag in the Kubernetes manifest repository.
- Argo CD detects the Git change and syncs the cluster.
- If the rollout fails, Argo CD shows drift and the team can revert the Git commit.
7. What to show in your portfolio
If you are using this as a portfolio or interview project, do not only show YAML files. Show the thinking behind them.
Final thoughts
This Kubernetes project is small enough to build in a weekend, but realistic enough to discuss in interviews. It proves you understand the important parts of Kubernetes: deployments, services, ingress, configuration, secrets, health checks, scaling, observability, and delivery workflow.
If you are preparing for a DevOps role, CKAD, CKA, or a Kubernetes-heavy interview, build this once manually and then rebuild it with GitOps. That second version is where the real learning starts.
