Files

3.8 KiB
Raw Permalink Blame History

Assignment

The Nautilus DevOps team has already deployed a ReplicaSet to host an application that requires a highly available infrastructure. Your task is to expose the application running in the existing ReplicaSet by creating a Kubernetes NodePort Service.

Follow the specifications below to create the Service and ensure the application pods are accessible:

A ReplicaSet named httpd-replicaset is already running in the cluster.

The pods managed by the ReplicaSet use the following labels: Assign labels app as httpd_app, and type as front-end.

Create a NodePort Service named httpd-service to expose the application.

Set the NodePort to 30080.

Expose port 80 of the application.

Note: Do not delete or modify the configuration of the deployed ReplicaSet application.

Solution

Kubernetes NodePort Service — httpd-service

A NodePort Service that exposes the pods already managed by the httpd-replicaset, matched by their labels. Applied inline via a heredoc — no manifest file on disk, and the ReplicaSet is left untouched.

Apply (heredoc → kubectl)

kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Service
metadata:
  name: httpd-service
spec:
  type: NodePort
  selector:
    app: httpd_app
    type: front-end
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080
EOF

How it works

The heredoc apply pattern

  • kubectl apply -f - reads from stdin; nothing written to disk.
  • <<'EOF' (delimiter quoted) disables shell expansion — the right default for k8s YAML.

A Service finds pods by label selector

A Service has no direct link to the ReplicaSet — it targets pods whose labels match its selector. This is the crux of the task:

  • selector: {app: httpd_app, type: front-end} — must exactly match the labels on the pods the ReplicaSet manages. Any pod carrying both labels becomes an endpoint of this Service, regardless of what created it. Since the ReplicaSet stamps its pods with these labels, the Service automatically picks them up. A mismatched selector would yield a Service with zero endpoints — it'd exist but route nowhere.

This is also why we don't touch the ReplicaSet: the Service attaches by label, so exposing the app needs no change to the existing workload at all.

NodePort and the port fields

type: NodePort opens a port on every node that forwards to the Service, which in turn load-balances across the matching pods. The three port fields each mean something distinct:

Field Meaning
port: 80 The port the Service itself listens on (its ClusterIP:80).
targetPort: 80 The port on the pod/container traffic is forwarded to — Apache's port 80.
nodePort: 30080 The port opened on each node's IP for external access.

So the path is: <node-ip>:30080 → Service :80 → pod :80. 30080 is inside the valid NodePort range (3000032767), so the API accepts it.

Why all three ports are set explicitly

targetPort defaults to port if omitted (both 80 here, so it'd work either way), and nodePort would be auto-assigned from the range if omitted — but the task pins it to 30080, so it's set explicitly. Being explicit also makes the manifest self-documenting.

Verify

# Service created as NodePort with the right ports
kubectl get service httpd-service

# Endpoints populated = selector matched the ReplicaSet's pods (this is the key check)
kubectl get endpoints httpd-service

# Confirm it reaches the app (from a node or the jump-host)
curl -s http://<node-ip>:30080 | head -n 5

Expected — httpd-service of type NodePort showing 80:30080/TCP, and kubectl get endpoints httpd-service listing one IP per matching pod. If endpoints is empty, the selector doesn't match the pods' labels — recheck them with kubectl get pods --show-labels.