4.4 KiB
Assignment
Some of the Nautilus team developers are developing a static website and they want to deploy it on Kubernetes cluster. They want it to be highly available and scalable. Therefore, based on the requirements, the DevOps team has decided to create a deployment for it with multiple replicas. Below you can find more details about it:
Create a deployment using nginx image with latest tag only and remember to mention the tag i.e nginx:latest. Name it as nginx-deployment. The container should be named as nginx-container, also make sure replica counts are 3.
Create a NodePort type service named nginx-service. The nodePort should be 30011.
Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.
Solution
Kubernetes Deployment + NodePort Service — nginx-deployment / nginx-service
A 3-replica nginx Deployment exposed by a NodePort Service on port 30011. Both objects in one
multi-document heredoc — no manifest file on disk.
Apply (heredoc → kubectl)
kubectl apply -f - <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30011
EOF
How it works
The heredoc apply pattern
kubectl apply -f -reads from stdin;---separates the two documents, applied in order.<<'EOF'(delimiter quoted) keeps the manifest literal — the right default for k8s YAML.
The Deployment
apps/v1/kind: Deployment— manages a ReplicaSet, which keeps the desired number of pods running and self-heals; the basis for the "highly available and scalable" requirement.metadata.name: nginx-deploymentand containername: nginx-container— exactly as required.replicas: 3— three identical pods spread across the cluster for availability.image: nginx:latest— tag stated explicitly, as required.selector.matchLabels: app: nginxmust equaltemplate.metadata.labels: app: nginx— a Deployment finds the pods it owns by this label match; a mismatch makes the API reject the manifest.
The Service ties to pods by label, not to the Deployment
-
type: NodePortopens a port on every node that forwards into the cluster. -
selector: app: nginx— this is what connects the Service to the Deployment's pods. The Service targets any pod labeledapp: nginx— which is exactly what the Deployment stamps on its three pods — and load-balances across them. The Service has no direct reference to the Deployment; the sharedapp: nginxlabel is the entire link. A mismatched selector would leave the Service with zero endpoints. -
Port fields:
port: 80— the Service's own ClusterIP port.targetPort: 80— the container port traffic is forwarded to (nginx serves on 80).nodePort: 30011— the port opened on each node for external access.30011is inside the valid range (30000–32767), so the API accepts it.
Traffic path:
<node-ip>:30011→ Service:80→ one of the three pods:80.
Why the label must be consistent in three places
app: nginx appears in the Deployment selector, the pod template labels, and the Service
selector. The first two tie the Deployment to its pods; the third ties the Service to those same
pods. Keeping the label identical across all three is what makes the whole chain — Deployment →
pods → Service — connect.
Verify
# Deployment with 3 ready replicas
kubectl get deployment nginx-deployment
# Service is NodePort on 30011
kubectl get service nginx-service
# Endpoints populated = selector matched the pods (key check)
kubectl get endpoints nginx-service
# Reachable via the node port
curl -s http://<node-ip>:30011 | head -n 5
Expected — deployment READY 3/3, nginx-service of type NodePort showing 80:30011/TCP,
and kubectl get endpoints nginx-service listing three pod IPs. Empty endpoints ⇒ selector/label
mismatch (check kubectl get pods --show-labels).