Sau bài này bạn làm được: chọn đúng Service type cho từng tình huống; debug “traffic không tới pod” bằng kiểm tra endpoints; hiểu kube-proxy làm gì ở tầng kernel.


Vấn đề: Pod IP không ổn định

Pod restart → IP mới. Scale up/down → IP thay đổi. Bạn không thể hardcode IP của pod vào config.

Service giải quyết bằng:

  • VIP (ClusterIP): IP ảo ổn định không đổi suốt vòng đời Service.
  • DNS: <service>.<namespace>.svc.cluster.local.
  • Load balancing: forward tới nhiều pod backend.
Client pod
Service (ClusterIP: 10.96.0.15)
    │  kube-proxy / eBPF forward
    ├──► Pod 1 (10.244.0.5:8080)
    ├──► Pod 2 (10.244.1.3:8080)
    └──► Pod 3 (10.244.2.7:8080)

Service spec cơ bản

apiVersion: v1
kind: Service
metadata:
  name: my-api
  namespace: default
spec:
  type: ClusterIP              # Mặc định
  selector:
    app: my-api                # Chọn pod có label app=my-api
  ports:
  - name: http
    port: 80                   # Port của Service
    targetPort: 8080           # Port container đang listen
    protocol: TCP

selector → Endpoints

Service selector chọn pod → Kubernetes tự tạo Endpoints object chứa danh sách pod IP:

kubectl get endpoints my-api
# NAME     ENDPOINTS                                      AGE
# my-api   10.244.0.5:8080,10.244.1.3:8080,10.244.2.7:8080   5m

Endpoints trống = traffic không đi đâu. Nguyên nhân: label selector không match pod, pod không Ready.

# Debug: kiểm tra selector match
kubectl get pods -l app=my-api
kubectl get endpoints my-api

# Nếu endpoints trống:
# 1. Pod có label đúng không? kubectl get pods --show-labels
# 2. Pod có Ready không? kubectl get pods (READY 1/1?)
# 3. readinessProbe fail? kubectl describe pod <name>

Các loại Service

ClusterIP (mặc định)

  • Chỉ truy cập trong cluster.
  • Dùng cho: service-to-service communication (API gọi DB, frontend gọi backend).

NodePort

spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080            # Mặc định: random trong 30000-32767
  • Mở port trên tất cả node (NodeIP:NodePort).
  • Traffic: NodeIP:30080 → Service → Pod.
  • Dùng cho: test nhanh, bare-metal không có cloud LB.
  • Không dùng production trên cloud — có LoadBalancer type.

LoadBalancer

spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  • Cloud controller tạo external load balancer (AWS ELB/NLB, GCP LB, Azure LB).
  • Được gán external IP.
  • Traffic: External IP:80 → LB → NodePort → Service → Pod.
  • Dùng cho: expose service ra internet (hoặc qua Ingress).

ExternalName

spec:
  type: ExternalName
  externalName: db.external.example.com
  • Không tạo proxy/VIP. Chỉ trả CNAME record trong DNS.
  • Dùng cho: alias service bên ngoài cluster bằng tên K8s.

Headless Service

spec:
  clusterIP: None              # ← Headless
  selector:
    app: my-db
  ports:
  - port: 5432
  • Không có VIP. DNS trả trực tiếp danh sách Pod IP.
  • Client chọn pod nào connect (client-side load balancing).
  • Dùng cho: StatefulSet (cần address từng pod), service discovery custom.
# DNS lookup headless service
nslookup my-db.default.svc.cluster.local
# Address: 10.244.0.5
# Address: 10.244.1.3
# Address: 10.244.2.7

kube-proxy — ai forward traffic

kube-proxy chạy trên mỗi node, watch Service + Endpoints, cập nhật network rules:

ModeCơ chếKhi nào
iptablesNAT rules (DNAT + random probability)Mặc định hầu hết cluster
IPVSKernel IPVS module (round-robin, least-conn…)Cluster > 1000 Service
eBPF (Cilium)Thay thế hoàn toàn kube-proxyCilium kubeProxyReplacement=true
# Xem mode kube-proxy đang dùng
kubectl -n kube-system get cm kube-proxy -o yaml | grep mode

# Xem iptables rules (trên node)
iptables -t nat -L KUBE-SERVICES | head -20

kube-proxy không proxy traffic qua process — nó chỉ cấu hình kernel để kernel forward.


EndpointSlice (K8s 1.21+ GA)

Cluster lớn (hàng nghìn pod) → Endpoints object quá lớn → mỗi thay đổi phải broadcast full list. EndpointSlice chia nhỏ (mỗi slice max 100 endpoints mặc định), chỉ broadcast slice thay đổi.

kubectl get endpointslice -l kubernetes.io/service-name=my-api

Bạn không cần tạo EndpointSlice — K8s tự quản lý. Chỉ cần biết khi debug ở cluster lớn.


Service without selector

Khi bạn muốn Service trỏ tới IP bên ngoài cluster (legacy DB, external API):

apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  ports:
  - port: 5432
---
apiVersion: v1
kind: Endpoints
metadata:
  name: external-db            # Cùng tên với Service
subsets:
- addresses:
  - ip: 192.168.1.100          # IP bên ngoài
  ports:
  - port: 5432

Pod trong cluster gọi external-db:5432 → forward tới 192.168.1.100:5432.


Multi-port Service

spec:
  ports:
  - name: http                 # Bắt buộc name khi > 1 port
    port: 80
    targetPort: 8080
  - name: grpc
    port: 9090
    targetPort: 9090

Session affinity

Mặc định: kube-proxy round-robin. Nếu cần sticky session:

spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800    # 3 giờ

Tóm tắt

  • Service = VIP + DNS + load balancing cho pod. Pod IP thay đổi, Service IP ổn định.
  • ClusterIP cho internal, NodePort cho test, LoadBalancer cho production cloud.
  • Headless (clusterIP: None) khi cần DNS trả pod IP trực tiếp.
  • Endpoints trống = lỗi #1: label selector không match hoặc pod không Ready.
  • kube-proxy cấu hình kernel rules, không proxy traffic qua userspace.

Câu hỏi hay gặp

Service port và targetPort khác nhau — dùng port nào khi gọi?

Trả lời: Client gọi <service-name>:<port> (port của Service). Kubernetes forward tới <pod-ip>:<targetPort>. Ví dụ: Service port 80, targetPort 8080 → client gọi my-api:80, pod listen :8080.

Pod đã Running nhưng endpoints vẫn trống?

Trả lời: Kiểm tra: (1) Pod label có match Service selector không (kubectl get pods --show-labels); (2) Pod có Ready không (readiness probe pass); (3) Pod cùng namespace với Service. Ba điều kiện phải đúng hết.

Khi nào dùng Ingress thay vì LoadBalancer Service?

Trả lời: LoadBalancer tạo một LB per Service → tốn tiền khi có nhiều service. Ingress dùng một LB cho nhiều service, route theo host/path. Chi tiết → Bài 09.


Bài tiếp theo (Giai đoạn III): DNS, CoreDNS và service discovery — resolve tên service thành IP.