Chuyển đến nội dung chính

Lesson 9: Services & Ingress

Service types: ClusterIP, NodePort, LoadBalancer, ExternalName. kubectl expose. Ingress resources, IngressClass, TLS termination and path-based routing.

Service Types and Ingress Routing — ClusterIP, NodePort, LoadBalancer

1. Service Types

TypeAccessWhen to Use
ClusterIPInternal only (cluster DNS)Service-to-service communication (default)
NodePortNodeIP:30000-32767Dev/test external access
LoadBalancerCloud LB external IPProduction external access (cloud)
ExternalNameCNAME DNS aliasRoute to external DNS name
ClusterIP (default):
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
spec:
  type: ClusterIP     # Can omit — default
  selector:
    app: myapp
  ports:
  - port: 80          # Service port (what clients connect to)
    targetPort: 8080  # Container port (where app listens)

NodePort:
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080   # Optional: 30000-32767 range (auto-assigned if omitted)

2. kubectl expose

# Expose Deployment as ClusterIP (default)
kubectl expose deployment myapp --port=80 --target-port=8080

# Expose as NodePort
kubectl expose deployment myapp --port=80 --target-port=8080 --type=NodePort

# Expose a Pod
kubectl expose pod mypod --port=80 --name=mypod-svc

# Expose existing service quickly and redirect traffic
kubectl run nginx --image=nginx --port=80 --expose
# This creates both the Pod AND the ClusterIP Service

Exam tip: kubectl expose requires a selector that matches Pod labels. If a Deployment uses app: myapp, the Service selector must be app: myapp. The --expose flag with kubectl run creates both the Pod and the Service at once — very fast during the exam.

3. Ingress

Ingress provides L7 HTTP/HTTPS routing — a single entry point that routes to multiple Services based on host/path.

                     ┌─────────────────────────────────┐
Internet ──────────►│   Ingress Controller (nginx)     │
                     │                                  │
                     │  /api  ──────────► api-service   │
                     │  /web  ──────────► web-service   │
                     │  blog.example.com → blog-service │
                     └─────────────────────────────────┘
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx       # Which IngressClass to use
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls       # TLS cert stored as Secret
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix        # Prefix or Exact
        backend:
          service:
            name: api-service
            port:
              number: 80
      - path: /web
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
pathTypeBehaviorExample
ExactMatches the path exactly/api only matches /api
PrefixMatches the path prefix/api matches /api, /api/v1, /api/users
ImplementationSpecificDepends on IngressClassDepends on controller

Exam tip: Ingress requires an Ingress Controller (like nginx, traefik) to function — the Ingress resource is just configuration. IngressClass specifies which controller handles requests. In the exam, the IngressClass is usually pre-configured. Remember to check kubectl get ingressclass for the name.

4. Debug Service Connectivity

# Check service exists and endpoints
kubectl get services
kubectl get endpoints myapp-svc

# Test connectivity from inside the cluster (create temp pod)
kubectl run test --image=busybox --rm -it -- wget -qO- http://myapp-svc
kubectl run test --image=curlimages/curl --rm -it -- curl http://myapp-svc:80

# Check if selector matches pods
kubectl get pods -l app=myapp  # Should match service selector
kubectl describe service myapp-svc  # Shows Endpoints section

# If Endpoints is empty: selector mismatch!
# Check: kubectl get pods --show-labels

5. Cheat Sheet

TaskCommand
Expose Deploymentkubectl expose deploy/app --port=80 --type=NodePort
Create Pod + Servicekubectl run nginx --image=nginx --port=80 --expose
Check service endpointskubectl get endpoints svc-name
Test service from inside clusterkubectl run tmp --image=busybox --rm -it -- wget -O- http://svc
Ingress with TLStls: secretName + hosts in rules

6. Practice Questions

Q1: A Deployment named "webapp" with selector app=webapp runs on port 8080. You need to create a Service that makes it accessible within the cluster on port 80. Which command creates this correctly?

  • A) kubectl expose deployment webapp --port=8080
  • B) kubectl expose deployment webapp --port=80 --target-port=8080 ✓
  • C) kubectl create service clusterip webapp --port=8080:80
  • D) kubectl expose deployment webapp --type=ClusterIP --port=80

Explanation: --port=80 is the Service port (what clients use), --target-port=8080 is the container port (where the app listens). Without --target-port, Kubernetes assumes target-port equals port. Option D would work but uses same port 80 for both.

Q2: An Ingress resource exists but traffic doesn't reach the backend Services. kubectl get endpoints shows the correct Pod IPs. What is the most likely cause?

  • A) The Service type should be LoadBalancer instead of ClusterIP
  • B) No Ingress Controller is installed or the ingressClassName is wrong ✓
  • C) The Ingress needs TLS configured
  • D) The pathType should be Exact instead of Prefix

Explanation: Ingress resources are just configuration objects. Without an Ingress Controller, nothing processes the rules. If the ingressClassName doesn't match an IngressClass connected to a running controller, the Ingress is effectively ignored. Always verify kubectl get ingressclass and that the controller Pod is running.

Q3: Which Service type provides external access using a port in the range 30000-32767 on every cluster node?

  • A) ClusterIP
  • B) ExternalName
  • C) NodePort ✓
  • D) LoadBalancer

Explanation: NodePort opens a port in the 30000-32767 range on every Node in the cluster. External traffic can reach the Service via NodeIP:NodePort. This is typically used for development and testing. LoadBalancer provides a cloud load balancer with a stable external IP, which is preferred for production.