75.2 Project 32: Deploy an app with a Deployment and a Service
Friends, a Pod alone is not enough. Today we ship a Deployment with two replicas, expose it with a ClusterIP Service, prove DNS inside the cluster, and reach it with port-forward.
मित्रांनो, एकटा Pod पुरेसा नाही. आज Deployment दोन replicas, ClusterIP Service, cluster DNS, port-forward.
दोस्तों, अकेला Pod काफी नहीं. आज Deployment दो replicas, ClusterIP Service, cluster DNS, port-forward.
What you will build in this project
- Deployment shop-web with 2 replicas.
- ClusterIP Service on port 80.
- Pods selected by label app=shop-web.
- curl via port-forward returns 200.
1. Start from a real company story
At Infosys in Pune, a demo app ran as a lone Pod. When the node rebooted, the Pod vanished and the client demo failed.
The account team lost face. Rough cost: about ₹8 lakh in a delayed deal.
Rohit replaced the Pod with a Deployment and a Service so the name stayed stable even when Pods restarted.
Today we build that Deployment plus Service pair.
Ravindra Bagale's Tip
Many students expose a Pod by its IP. Pod IPs change. Always put a Service in front. Keep that habit.
खूप students Pod IP expose करतात. Pod IP बदलते. नेहमी Service समोर ठेवा. सवय ठेवा.
बहुत students Pod IP expose करते हैं. Pod IP बदलता है. हमेशा Service आगे रखें. आदत रखिए.
2. Start and prepare
Step 1: Write Deployment YAML
Why: YAML is desired state. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: printf. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 1: yaml
Type this:
mkdir -p /tmp/k8s32 && printf '%s\n' 'apiVersion: apps/v1' 'kind: Deployment' 'metadata: {name: shop-web}' 'spec:' ' replicas: 2' ' selector: {matchLabels: {app: shop-web}}' ' template:' ' metadata: {labels: {app: shop-web}}' ' spec:' ' containers:' ' - name: web' ' image: nginx:1.27-alpine' ' ports: [{containerPort: 80}]' > /tmp/k8s32/deploy.yaml && wc -l /tmp/k8s32/deploy.yaml
You will see:
12 /tmp/k8s32/deploy.yaml
What it means: Deployment YAML with two replicas and app label.
Example 2: grep rep
Type this:
grep replicas /tmp/k8s32/deploy.yaml
You will see:
replicas: 2
What it means: Replica count pinned at two.
Example 3: grep img
Type this:
grep image: /tmp/k8s32/deploy.yaml
You will see:
image: nginx:1.27-alpine
What it means: Pinned nginx Alpine image.
Step 2: Apply Deployment
Why: apply creates the controller. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: kubectl apply. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 4: apply
Type this:
kubectl apply -f /tmp/k8s32/deploy.yaml
You will see:
deployment.apps/shop-web created
What it means: Deployment created in the current namespace.
Example 5: get
Type this:
kubectl get deploy shop-web
You will see:
NAME READY UP-TO-DATE AVAILABLE
shop-web 0/2 2 0
What it means: Controller is reconciling two Pods.
Example 6: rs
Type this:
kubectl get rs -l app=shop-web --no-headers | awk '{print $2,$3,$4}'
You will see:
2 2 2
What it means: ReplicaSet desired and current match eventually.
Step 3: Wait Available
Why: Available means ready replicas. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: kubectl wait. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 7: wait
Type this:
kubectl wait --for=condition=available deploy/shop-web --timeout=90s
You will see:
deployment.apps/shop-web condition met
What it means: Both replicas Available.
Example 8: pods
Type this:
kubectl get pods -l app=shop-web --no-headers | wc -l
You will see:
2
What it means: Two Pods exist.
Example 9: ready
Type this:
kubectl get pods -l app=shop-web --no-headers | awk '{print $2}' | sort | uniq
You will see:
1/1
What it means: Every Pod reports 1/1 Ready.
3. Build the main pieces
Step 4: List Pods
Why: Pods must match labels. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: kubectl get pods. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 10: labels
Type this:
kubectl get pods -l app=shop-web --show-labels | head -3
You will see:
NAME READY STATUS LABELS
shop-web-... 1/1 Running app=shop-web,...
What it means: Label app=shop-web is on each Pod.
Example 11: jsonpath
Type this:
kubectl get pods -l app=shop-web -o jsonpath='{.items[*].metadata.labels.app}'; echo
You will see:
shop-web shop-web
What it means: Both Pods carry the selector label.
Example 12: why
Type this:
echo 'Service selector must match these Pod labels exactly'
You will see:
Service selector must match these Pod labels exactly
What it means: Label contract tip.
Step 5: Write Service YAML
Why: Service selects those labels. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: printf Service. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 13: svc yaml
Type this:
printf '%s\n' 'apiVersion: v1' 'kind: Service' 'metadata: {name: shop-web}' 'spec:' ' selector: {app: shop-web}' ' ports: [{port: 80, targetPort: 80}]' > /tmp/k8s32/svc.yaml && cat /tmp/k8s32/svc.yaml
You will see:
apiVersion: v1
kind: Service
...
What it means: ClusterIP Service YAML selecting app=shop-web.
Example 14: type default
Type this:
grep -c type /tmp/k8s32/svc.yaml || echo 0
You will see:
0
What it means: No type field means ClusterIP by default.
Example 15: port
Type this:
grep port: /tmp/k8s32/svc.yaml
You will see:
port: 80, targetPort: 80
What it means: Service port 80 to container 80.
Step 6: Apply Service
Why: ClusterIP is virtual. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: kubectl apply. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 16: apply svc
Type this:
kubectl apply -f /tmp/k8s32/svc.yaml
You will see:
service/shop-web created
What it means: Service object created.
Example 17: get svc
Type this:
kubectl get svc shop-web
You will see:
NAME TYPE CLUSTER-IP PORT(S)
shop-web ClusterIP 10.96.x.x 80/TCP
What it means: ClusterIP allocated.
Example 18: clusterip
Type this:
kubectl get svc shop-web -o jsonpath='{.spec.clusterIP}'; echo
You will see:
10.96.183.44
What it means: Stable virtual IP inside the cluster.
4. Automate and verify
Step 7: Check Endpoints
Why: Endpoints prove selection. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: kubectl get ep. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 19: ep
Type this:
kubectl get endpoints shop-web
You will see:
NAME ENDPOINTS
shop-web 10.244.0.5:80,10.244.0.6:80
What it means: Two Pod IPs behind the Service.
Example 20: ep count
Type this:
kubectl get endpoints shop-web -o jsonpath='{.subsets[0].addresses[*].ip}' | wc -w
You will see:
2
What it means: Endpoint address count matches replicas.
Example 21: not ready tip
Type this:
echo 'If Endpoints empty, check labels and readiness'
You will see:
If Endpoints empty, check labels and readiness
What it means: Debug tip when Service seems dead.
Step 8: DNS from a debug pod
Why: CoreDNS resolves the name. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: kubectl run debug. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 22: debug
Type this:
kubectl delete pod dnscheck --ignore-not-found >/dev/null 2>&1; kubectl run dnscheck --image=busybox:1.36 --restart=Never -- sleep 300 && kubectl wait --for=condition=Ready pod/dnscheck --timeout=60s
You will see:
pod/dnscheck condition met
What it means: Debug pod Ready for DNS tests.
Example 23: nslookup
Type this:
kubectl exec dnscheck -- nslookup shop-web.default.svc.cluster.local
You will see:
Name: shop-web.default.svc.cluster.local
Address: 10.96.x.x
What it means: CoreDNS resolves the Service name.
Example 24: wget
Type this:
kubectl exec dnscheck -- wget -qO- http://shop-web.default.svc.cluster.local/ | head -c 20
You will see:
<!DOCTYPE html>
What it means: HTTP body from nginx via Service DNS.
Step 9: Port-forward curl
Why: port-forward for local curl. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: kubectl port-forward. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 25: pf
Type this:
kubectl port-forward svc/shop-web 8081:80 >/tmp/k8s32/pf.log 2>&1 & echo $! > /tmp/k8s32/pf.pid; sleep 1; curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8081/
You will see:
200
What it means: Laptop curl through Service port-forward.
Example 26: stop
Type this:
kill $(cat /tmp/k8s32/pf.pid); echo stopped
You will see:
stopped
What it means: Forward stopped.
Example 27: why pf
Type this:
echo 'port-forward is for demos; Ingress comes in project 34'
You will see:
port-forward is for demos; Ingress comes in project 34
What it means: When to use port-forward.
5. Harden and accept
Step 10: Scale to 3
Why: scale changes replicas. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: kubectl scale. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 28: scale
Type this:
kubectl scale deploy/shop-web --replicas=3 && kubectl wait --for=condition=available deploy/shop-web --timeout=90s
You will see:
deployment.apps/shop-web condition met
What it means: Scaled to three and still Available.
Example 29: pods3
Type this:
kubectl get pods -l app=shop-web --no-headers | wc -l
You will see:
3
What it means: Three Pods now.
Example 30: ep3
Type this:
kubectl get endpoints shop-web -o jsonpath='{.subsets[0].addresses[*].ip}' | wc -w
You will see:
3
What it means: Endpoints grew with the scale.
Step 11: Describe Service
Why: describe shows events. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: kubectl describe. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 31: describe
Type this:
kubectl describe svc shop-web | head -15
You will see:
Name: shop-web
Type: ClusterIP
...
What it means: Describe confirms type and selector.
Example 32: cleanup debug
Type this:
kubectl delete pod dnscheck --ignore-not-found
You will see:
pod "dnscheck" deleted
What it means: Debug pod removed.
Example 33: leave
Type this:
echo 'Leave shop-web running for later projects or delete when done'
You will see:
Leave shop-web running for later projects or delete when done
What it means: Lab note.
Step 12: Acceptance checklist
Why: Rohit signs off. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: All green. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 34: ready
Type this:
kubectl get deploy shop-web -o jsonpath='{.status.readyReplicas}'; echo
You will see:
3
What it means: Three ready replicas.
Example 35: svc ok
Type this:
kubectl get svc shop-web -o jsonpath='{.spec.type}'; echo
You will see:
ClusterIP
What it means: Type still ClusterIP.
Example 36: Sign-off
Type this:
echo 'Rohit: PASS'
You will see:
Rohit: PASS
What it means: Project 32 accepted.
Check yourself
Q1. Who fixed Infosys demo?
Rohit
Q2. Replicas?
2
Q3. Service type?
ClusterIP
Q4. Label key?
app
Q5. Service name?
shop-web
Q6. Port?
80
Friends, you ran two replicas behind a ClusterIP Service. Did you understand? Let us try it once more. Scale to three and confirm Endpoints grows.
मित्रांनो, तुम्ही ClusterIP मागे दोन replicas चालवले. तीनवर scale करा.
दोस्तों, आपने ClusterIP के पीछे दो replicas चलाए. तीन पर scale करें.
Lab: try at home
- Write Deployment YAML.
- Apply and wait Available.
- Write Service YAML.
- Prove Endpoints and DNS.
- Port-forward and curl.
Recap
- Deployment keeps replicas alive.
- Labels link Pods to Services.
- ClusterIP is stable inside the cluster.
- Endpoints list ready Pod IPs.
- port-forward is for laptop tests.