Mạng Linux & Container
19/21
Bài 19 / 21~14 phútKubernetes Networking (nhập môn)Miễn phí… lượt xem

Ingress & load balancing — L4 vs L7 vào cluster

So sánh ClusterIP, NodePort, LoadBalancer và Ingress: chiều traffic L4/L7, host/path, TLS termination, pitfall thiếu ingress controller.

TL;DR: ClusterIP chỉ trong cluster. NodePort mở port trên mọi node → kube-proxy forward vào Service. LoadBalancer (cloud/MetalLB…) cấp IP ngoài, thường bọc NodePort/ClusterIP. Ingress là API L7 (HTTP/HTTPS host/path) — không tự listen; cần Ingress controller (nginx, Traefik, cloud…) làm reverse proxy → Service backends. TLS thường terminate tại controller. Pitfall cứng: apply Ingress YAML xanh, 0 controller → không có data path; nhầm Ingress thay Service (vẫn cần Service); nhầm L4 LB với route Host header.

Demo sprint: junior kubectl apply -f ingress.yaml, kubectl get ingress ADDRESS trống hoặc localhost, curl -H "Host: api.example.com" http://… fail. Ticket: “Ingress K8s hỏng”. Bạn hỏi: “Cluster có IngressClass / controller pod chưa? Service backend type gì? TLS secret đúng namespace?” Nhiều lab kind chưa cài controller — object API có, dataplane không. Cùng class “API xanh / effect 0” như NetworkPolicy thiếu enforce CNI.

Bài 03 chốt VIP nội bộ. Bài này so sánh bốn cửa đưa traffic (đặc biệt từ ngoài) và L7 host/path/TLS.

Bài faded: bảng so sánh worked; bạn tự chọn expose type theo scenario, và tự điền chỗ TLS terminate trước khi đối chiếu.

1. Analogy — Cửa nội bộ, chuông tầng, cổng chính, lễ tân đọc phong bì

Tiếp số tổng đài ảo = ClusterIP:

  1. ClusterIP — chỉ máy trong toà quay số nội bộ.
  2. NodePort — mỗi tầng có chuông phụ cùng số (port 30000–32767); khách biết IP máy tầng + chuông vẫn vào được dịch vụ.
  3. LoadBalancer — cổng chính cloud/provider gắn một số ngoài; bên trong vẫn nối tổng đài/Service.
  4. Ingress — lễ tân đọc phong bì HTTP: “Host api.shop.vn path /v1 → quầy payment-api”; nhiều shop chung một cửa chính nhờ tên trên phong bì (L7), không cần mỗi shop một cổng L4.
Đời thườngKubernetes
Số nội bộ toàClusterIP
Chuông phụ mỗi tầngNodePort
Cổng chính + số publicLoadBalancer Service
Lễ tân đọc Host/pathIngress + controller
Quầy thật sau lễ tânService → pods (bài 03)
💡 Cách nhớ

Service types = L4 (TCP/UDP) expose. Ingress = L7 HTTP(S) routing — luôn ngồi trên Service, không thay Endpoints.

2. Bốn kiểu expose khác nhau chỗ nào?

2.1 So sánh theo chiều traffic

ClusterIPNodePortLoadBalancerIngress
LớpL4 VIPL4L4 (+ cloud)L7 HTTP/HTTPS (chủ đạo)
Ai gọi đượcTrong clusterBiết nodeIP:nodePortClient Internet/LAN qua LB IPClient qua IP/DNS controller/LB
ObjectServiceService type: NodePortService type: LoadBalancerIngress (+ controller)
Ổn định bên ngoàiKhông (private CIDR)nodeIP đổi/scale nodeLB IP/hostname providerDNS → controller/LB
Host/path routeKhôngKhôngKhông (thuần L4)Có
TLSApp/mesh tự loApp tự loThường app hoặc LB annotTerminate tại controller phổ biến
Phụ thuộckube-proxy/dataplane+ mở port node+ cloud controller / MetalLB+ Ingress controller

Các cửa ngõ lưu lượng vào Kubernetes: L4 vs L7

2.2 ClusterIP — baseline (nhắc ngắn)

Đã mổ bài 03: VIP nội bộ, DNS, kube-proxy. Không thay thế cửa Internet. Mọi Ingress/NodePort/LB cuối vẫn thường kết vào Service ClusterIP (hoặc type khác) + Endpoints.

2.3 NodePort

YAML
apiVersion: v1
kind: Service
metadata:
  name: payment-api
spec:
  type: NodePort
  selector:
    app: payment
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080   # optional; else allocated from range
  • kube-proxy mở cùng nodePort trên mọi node (model).
  • Client: http://<any-node-ip>:30080 → DNAT/path vào backend pod (có thể pod nằm node khác).
  • Ops: firewall security group phải mở nodePort; node IP thay khi ASG rotate — DNS/LB phía trước thường cần.
  • Không an toàn hơn vì “port lạ”: vẫn TCP expose app L4.

2.4 LoadBalancer

YAML
spec:
  type: LoadBalancer
  # cloud assigns status.loadBalancer.ingress hostname/ip
  • Trên cloud: cloud-controller tạo LB (NLB/CLB/…) trỏ node/NodePort hoặc mode tương đương.
  • On-prem: MetalLB, kube-vip… hoặc LB thủ công — không có magic chỉ vì field LoadBalancer.
  • Thường tạo kèm NodePort + ClusterIP (implementation detail — đọc kubectl get svc -o yaml).
  • Một Service ≈ một (hoặc pool) frontend L4 — nhiều app HTTP → nhiều LB IP hoặc gộp bằng Ingress L7.

2.5 Ingress — API + controller

Ingress resource mô tả luật HTTP:

  • host api.example.com
  • path /v2 → Service payment-api:80
  • TLS secret api-tls cho host đó

Ingress controller (Deployment/DaemonSet + thường Service LB/NodePort):

  1. Watch Ingress (+ IngressClass).
  2. Render config (nginx.conf, Envoy…) / program dataplane.
  3. Nhận traffic ngoài, proxy L7 tới Service ClusterIP.

Không controller = không ai đọc object (trừ khi provider gắn default — đừng assume).

Thử ngẫmmột microservice cần expose gRPC thuần ra ngoài cluster, không phải REST HTTP/1.1 thông thường. Ingress L7 kiểu path-routing quen thuộc có phải lựa chọn tự nhiên nhất cho ca này không?

3. L7 host/path routing hoạt động thế nào?

3.1 Vì sao cần L7?

L4 chỉ thấy IP:port. Nhiều site/API chung :443:

  • shop.example.com → frontend Service
  • api.example.com → API Service
  • api.example.com/v1/payments → payment Service

Host header / SNI (TLS) + path = chìa L7.

3.2 Ví dụ luật (minh hoạ)

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - api.example.com
      secretName: api-tls
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /v1/payments
            pathType: Prefix
            backend:
              service:
                name: payment-api
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-gateway
                port:
                  number: 80
FieldÝ nghĩa
ingressClassNameController nào implement (tránh nhiều controller tranh)
hostKhớp Host / SNI
path + pathTypePrefix / Exact / ImplementationSpecific
backend.serviceService đã có Endpoints (bài 03)
tls.secretNameSecret kubernetes.io/tls trong cùng namespace (thường)

Ingress L7 Routing: Phân nhánh theo Host và Path

3.3 pathType — đừng đoán

  • Prefix: /v1 khớp /v1, /v1/… (chi tiết trailing slash theo controller — test).
  • Exact: khớp đúng path.
  • ImplementationSpecific: phụ thuộc controller — đọc docs controller, không portable mù.

Thử ngẫmhai Ingress object khác nhau cùng khai host api.example.com, một object path / và một object path /v1/payments. Controller có tự biết ưu tiên rule cụ thể hơn rule tổng quát không?

4. TLS terminate ở đâu trên đường Ingress?

4.1 Mô hình phổ biến

  1. Client TLS → controller (cert trong Secret).
  2. Controller terminate TLS, HTTP (hoặc TLS lại) tới Service/pod.
  3. App pod có thể chỉ HTTP nội bộ — giảm phân tán cert (trade-off trust network nội bộ).

TLS passthrough (controller không decrypt, SNI route) là mode khác — app terminate; không mặc định mọi Ingress.

4.2 Secret

Bash
kubectl create secret tls api-tls \
  --cert=fullchain.pem --key=privkey.pem \
  -n <ingress-namespace-or-app-ns>

Sai namespace / sai secretName / cert không cover host → browser lỗi cert, controller log warn — không phải “Service Endpoints trống” (khác class).

4.3 Faded — terminate ở đâu?

Tự điền

Scenario: app container chỉ listen plain :8080, Secret TLS gắn Ingress, curl -k https://api.example.com từ ngoài OK, kubectl exec vào pod ss không thấy :443.
TLS terminate ở object nào? Gói giữa controller → Service còn encrypt không (mô hình terminate edge mặc định)?

Đáp án kỳ vọng: Terminate tại Ingress controller. Nội bộ controller→Service thường HTTP plain (trừ mTLS/re-encrypt config). Pod không listen 443 là đúng với edge terminate.

5. Traffic ngoài vào pod đi qua những hop nào?

5.1 Path ngoài → pod (HTTP)

  1. DNS api.example.com → IP LoadBalancer của controller (hoặc node/NodePort lab).
  2. TCP 443 → pod controller.
  3. TLS + Host/path match → chọn backend Service.
  4. Controller outbound tới ClusterIP:port (hoặc pod IP tùy mode) — từ đây path bài 03 (kube-proxy → pod).
  5. Response ngược chuỗi.

Hai lớp LB: cloud LB (L4) tới controller replicas + kube-proxy tới app pods. Debug phải biết đang soi layer nào.

5.2 Faded — chọn expose

Tự chọn trước khi xem đáp án

Chọn một primary expose cho mỗi case (ClusterIP / NodePort / LoadBalancer / Ingress). Viết lý do một câu.
(A) Service payment chỉ gọi từ order-pod trong cluster.
(B) Lab kind, một API, không DNS đa host, dev curl nodeIP.
(C) Production cloud, 12 microservice HTTP, một domain, path split, TLS Let’s Encrypt.
(D) TCP database expose (không HTTP), client ngoài VPC.

Đáp án kỳ vọng:

  • (A) ClusterIP — không cần cửa ngoài.
  • (B) NodePort (hoặc LB nếu kind/metallb có) — đơn giản lab.
  • (C) Ingress (+ thường LB trước controller) — L7 host/path/TLS gom.
  • (D) LoadBalancer hoặc NodePort L4 — Ingress HTTP-centric không phải chỗ TCP DB mặc định (có TCP route controller riêng — ngoài nhập môn).

6. Pitfall — vì sao Ingress YAML xanh mà traffic chết?

6.1 Ingress without controller

Quan sátÝ nghĩa
kubectl get ingress có ruleChỉ etcd/API
ADDRESS trống mãiKhông ai gán IP / chưa controller
Controller pod CrashLoopDataplane chết
Sai ingressClassNameController khác (hoặc không ai) nhận

Verify controller:

Bash
kubectl get pods -A | grep -i ingress
kubectl get ingressclass
kubectl describe ingress shop

6.2 Nhầm Ingress với Service

  • Ingress không thay Endpoints/kube-proxy.
  • Backend phải là Service khỏe (bài 03 checklist).
  • curl trúng controller nhưng 502/503 → hay backend Service/endpoints/app — không phải “DNS domain sai” một mình.

6.3 NodePort “giấu” app

Port 3xxxx vẫn public nếu SG mở. Không thay authn. Không thay NetworkPolicy.

6.4 Một LB IP, nhiều host — kỳ vọng đúng

L4 LB một IP vẫn phục vụ nhiều Host nhờ Ingress L7. Đòi “mỗi Service một LB IP” khi đã có Ingress thường lãng phí — trừ isolation/compliance.

Lưu đồ chẩn đoán sự cố Kubernetes Ingress

📚 Deep Dive — tài liệu gốc

📚 Deep Dive — tài liệu gốc

Spec / docs:

Nội bộ OLHub:

Liên hệ các bài khác

Tóm tắt

  • ClusterIP nội bộ; NodePort L4 mọi node; LoadBalancer IP ngoài provider; Ingress L7 qua controller.
  • Route Host/path; TLS thường terminate tại controller + Secret.
  • Ingress YAML không đủ — thiếu controller = không dataplane.
  • Debug ngoài→trong: DNS/LB → controller → rule/TLS → Service/Endpoints → app (tách lớp).

7. Tự kiểm tra

Tự kiểm tra
0/7 câu đã trả lời
  1. Q1
    So sánh ClusterIP, NodePort, LoadBalancer, Ingress theo: ai reach được, L4 hay L7, object Kubernetes chính. Client trong cluster gọi API nội bộ — type tối thiểu nào?
  2. Q2
    Vì sao 'kubectl get ingress' có resource chưa chứng minh traffic HTTP vào được? Liệt kê dependency dataplane.
  3. Q3
    Trace external HTTPS → pod qua Ingress: các hop (DNS, LB, controller, Service, kube-proxy, pod). TLS terminate điển hình ở hop nào?
  4. Q4
    Khi nào chọn NodePort thay Ingress? Khi nào Ingress thắng nhiều LoadBalancer Service riêng cho từng HTTP app?
  5. Q5
    pathType Prefix vs Exact — junior path /api khớp /api/v2 không? Vì sao ImplementationSpecific nguy hiểm khi đổi controller?
  6. Q6
    502 từ Ingress controller, Service ClusterIP curl từ pod debug OK. Class lỗi nghi đâu? Ngược lại curl ClusterIP fail — nghi đâu trước controller?
  7. Q7
    LoadBalancer Service trên bare-metal không cloud controller — external IP pending mãi. Root cause class gì? Hướng fix khái niệm (không cần tên hãng cụ thể)?

Bài tiếp theo: NetworkPolicy — chặn east-west có chủ đích

Bài này có giúp bạn hiểu bản chất không?

Bài này đáng gửi cho bạn học cùng?

Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.

Thảo luận & góp ý

Hỏi đáp về bài này

Bài tiếp theo

NetworkPolicy — zero-trust giữa các pod