Mạng Linux & Container/Ingress & load balancing — L4 vs L7 vào cluster
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 , 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. LoadBalancercổng chính cloud/provider gắn một số ngoài; bên trong vẫn nối tổng đài/Service.
  4. Ingresslễ 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)
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
flowchart TB
    EXT["External client"] --> NP["NodePort on nodeIP"]
    EXT --> LB["LoadBalancer IP"]
    EXT --> ING["Ingress controller HTTP"]
    NP --> SVC["Service"]
    LB --> SVC
    ING --> SVC
    SVC --> PODS["Pods via kube-proxy path"]
    INT["In-cluster client"] --> CIP["ClusterIP only"]
    CIP --> PODS

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

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

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).

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ạ)

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)
flowchart LR
    C["Client Host api.example.com"] --> CTRL["Ingress controller"]
    CTRL -->|"/v1/payments"| PAY["Svc payment-api"]
    CTRL -->|"/"| GW["Svc api-gateway"]
    PAY --> P1["Pods"]
    GW --> P2["Pods"]

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ù.

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

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:

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.

flowchart TD
    FAIL["External HTTP fail"] --> Q1{"Controller running + IngressClass?"}
    Q1 -->|No| C1["Install or fix controller"]
    Q1 -->|Yes| Q2{"DNS or LB IP hits controller?"}
    Q2 -->|No| C2["DNS SG NodePort LB"]
    Q2 -->|Yes| Q3{"Host path TLS match?"}
    Q3 -->|No| C3["Fix Ingress rules secrets"]
    Q3 -->|Yes| Q4{"Service Endpoints ready?"}
    Q4 -->|No| C4["Debug Service like lesson 03"]
    Q4 -->|Yes| C5["App logs in pod"]

📚 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
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?
ClusterIP: trong cluster, L4 VIP/Service. NodePort: ngoài qua nodeIP:port, L4. LoadBalancer: IP ngoài provider, L4. Ingress: HTTP(S) L7 + controller. Nội bộ: ClusterIP đủ.
Q2
Vì sao 'kubectl get ingress' có resource chưa chứng minh traffic HTTP vào được? Liệt kê dependency dataplane.
Ingress là spec luật. Cần controller chạy, IngressClass khớp, cửa LB/NodePort/DNS tới controller, rule host/path/TLS đúng, Service backend Endpoints Ready. Thiếu controller = API no-op.
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?
DNS→LB/IP controller→controller pod terminate TLS→match Host/path→proxy tới Service→kube-proxy DNAT/IPVS→pod. Terminate điển hình tại controller (edge), trừ passthrough.
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?
NodePort: lab đơn giản, không đa host L7, hoặc non-HTTP. Ingress: nhiều host/path, TLS gom, một (vài) IP public cho nhiều Service HTTP — giảm số LB L4.
Q5
pathType Prefix vs Exact — junior path /api khớp /api/v2 không? Vì sao ImplementationSpecific nguy hiểm khi đổi controller?
Prefix thường khớp /api và /api/.... Exact chỉ đúng chuỗi. ImplementationSpecific hành vi theo vendor — đổi nginx↔khác có thể vỡ route im lặng; ưu tiên Prefix/Exact portable + test.
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?
502 + backend ClusterIP OK: nghi config Ingress (sai service name/port), network policy chặn controller→pod, timeout app. ClusterIP fail: Endpoints/kube-proxy/app (bài 03) trước khi mổ TLS Ingress.
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ể)?
Không có implementation gán IP (cloud controller/MetalLB/tương đương). type LoadBalancer chỉ là API desire — cần controller LB on-prem hoặc chuyển NodePort/Ingress + LB thủ công.

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

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.

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

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

Chưa có câu hỏi

Đặt câu hỏi

Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).

Đặt câu hỏi đầu tiên

Bài tiếp theo

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