Kubernetes Service và Ingress: Quản lý lưu lượng nội bộ và bên ngoài

1. Các mô hình triển khai dịch vụ trong Kubernetes

1.1 Phân loại mô hình triển khai dịch vụ

  • Truy cập từ người dùng
  • Giao tiếp giữa các dịch vụ nội bộ
  • Truy cập các thành phần hạ tầng (database, cache...)

1.2 Thiết kế kiến trúc không có registry trung tâm

Không sử dụng registry, các client tìm và kết nối trực tiếp tới Pod thông qua Service và DNS.

1.3 Thiết kế kiến trúc có registry trung tâm

Sử dụng registry (như etcd, Consul) để đăng ký/danh mục dịch vụ, giúp quản lý động các endpoint.

1.4 Cơ chế Proxy của Service

Label là cặp key/value gắn vào resource để tổ chức, phân loại các đối tượng (Pod, Deployment, Node...). Ví dụ: app=frontend, region=subnet7.

Selector cho phép truy vấn các resource có label phù hợp qua các biểu thức logic như app in (frontend, backend), env!=prod,...

1.5 Khái niệm Service

Service là một abstract layer đại diện cho một nhóm các Pod có cùng chức năng, đảm bảo endpoint tĩnh ngay cả khi Pod restart, scale hoặc di chuyển.

Tính năng chính:

  • Service Discovery (qua DNS hoặc biến môi trường)
  • Load balancing nội bộ
  • Support port mapping & session persistence

1.6 Endpoints

Endpoints là resource lưu trữ danh sách IP + port của các Pod được Service selector chọn. Khi Pod thay đổi, controller cập nhật tự động Endpoints.

Service và Endpoints liên kết khi:

  • Cùng名称 service name và namespace
  • Đủ thông tin port matching

2. Quản lý East-West traffic qua Service

2.1 Label & Selector nâng cao

Thêm label
kubectl label deployment nginx version=1

# Thêm nhiều label trên tất cả deployment trong namespace
kubectl label deployment --all env=prod tier=v2

# Thêm label có điều kiện
kubectl label service -l app=inventory secure=true

# Thêm nhiều nhãn đồng thời
kubectl label pod app=web appVer=2.0 tier=cache --overwrite
Sửa & xóa label
# Ghi đè label đã tồn tại phải dùng --overwrite
kubectl label deploy nginx version=2 --overwrite

# Xóa nhãn: thêm dấu "-" sau key
kubectl label node k8s-node01 region-

#####Selector mẫu

  • (app=nginx) → chỉ service có label app=nginx
  • app in (nginx,counter) → chọn nhiều giá trị
  • app in (nginx,counter), version!=2 → lọc phức tạp hơn
Ứng dụng bài toán network isolation

Giả sử yêu cầu chỉ giao tiếp với ngân hàng qua subnet 192.168.7.0/24 → gắn node label:

kubectl label node k8s-node02 region=subnet7

# Deployment yêu cầu node selector
spec:
  template:
    spec:
      nodeSelector:
        region: subnet7

2.2 Định nghĩa Service

# Tạo Service từ Deployment sẵn
kubectl expose deploy nginx --port=80 --target-port=8080
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
  - port: 80         # Cổng ClusterIP thấy được
    targetPort: 80   # Cổng Pod cần nhận
    protocol: TCP
  type: ClusterIP
  • Nếu targetPort bỏ trống → tự động bằng port
  • targetPort có thể là tên port định nghĩa trong container → giữ vững khi cập nhật image

2.3 Các loại Service

Loại Mô tả 适用场景
ClusterIP Mặc định, chỉ truy cập trong cluster Internal service, DB, cache...
NodePort Mở port 30000~32767 trên mỗi node Dev/test, API exposed đơn giản
LoadBalancer Sam với cloud LoadBalancer (AWS GCP...) Production cần load-balancing cấp độ hạ tầng
ExternalName Trả về CNAME → trỏ sang DNS bên ngoài Truy cập service bên ngoài cluster

2.4 Thực hành NodePort Service

kubectl expose deploy nginx --type=NodePort --port=80 --target-port=80
kubectl get svc nginx
# output: 80:31532/TCP

2.5 ExternalName Service

# ExternalName mẫu
apiVersion: v1
kind: Service
metadata:
  name: external-dbf
spec:
  type: ExternalName
  externalName: db.prod.internal.svc.cluster.local
Ứng dụng quản lý nhiều môi trường chung config
  • Dev: Redis trong namespace basic-dev
  • UAT: Redis trong namespace basic-uat
# Service proxy trong namespace projecta-dev
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: projecta-dev
spec:
  type: ExternalName
  externalName: redis.basic-component-dev.svc.cluster.local
---
# مشروع aUAT
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: projecta-uat
spec:
  type: ExternalName
  externalName: redis.basic-component-uat.svc.cluster.local

Từ ứng dụng clockwise: redis:6379 → tự chuyển tới môi trường tương ứng.

2.6 Service đại diện external service (không có selector)

apiVersion: v1
kind: Service
metadata:
  name: external-baidu
spec:
  ports:
  - port: 80
    targetPort: 80
---
apiVersion: v1
kind: Endpoints
metadata:
  name: external-baidu
subsets:
- addresses: [{ip: "182.61.201.211"}]
  ports: [{port: 80}]

Các IP không được là loopback, link-local hay multicast.

2.7 Service đa cổng (multi-port)

# RabbitMQ: AMQP (5672),Management (15672)
spec:
  ports:
  - name: amqp
    port: 5672
    targetPort: 5672
  - name: mgmt
    port: 15672
    targetPort: 15672

2.8 Session persistence

spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800

2.9 Headless Service (ไม่ม ClusterIP)

spec:
  clusterIP: None
  selector:
    app: redis-stateful

DNS trả pod hostname dạng <pod-name>.<service>.<namespace>.svc.cluster.local

Ứng dụng:
  • StatefulSet (Database, Kafka, Zookeeper…)
  • Yêu cầu kết nối trực tiếpPod
  • Mô hình mpich no central scheduler
Ví dụ tạo Headless Service:
kubectl create -f headless.yaml

# Output Service: clusterIP = None
# Tạo pod: headless-0, headless-1, headless-2

# Kiểm tra DNS
nslookup headless-1.headless.default.svc.cluster.local
# → trả về IP cụ thể của Pod

2.10 Các chế độ proxy của kube-proxy

Iptables mode
  • kube-proxy theo dõi API server, tự động cập nhật rule iptables
  • nodes xử lý load-balance nội tại

Ưu điểm:

  • Không cần daemon riêng, hiệu quả giai đoạn đầu
  • Tích hợp sẵn trên Linux

Hạn chế:

  • Scaling kém khi số service lớn → rule iptables tăng tuyến tính
  • Rebuild rule gây lag ngắn
IPVS mode (khuyến nghị production Scale cao)
  • Dùng🐇 kernel modules: ip_vs, ip_vs_rr, ip_vs_wrr,...
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr

Các thuật toán:

  • rr (round-robin)
  • lc (least-connection)
  • sh (source-address hash → session affinity)
  • sed (shortest-exp-delay)
  • nq (never-queue)

Ưu điểm:

  • Thời gian truy suất O(1) nhờ cấu trúc hash-table
  • Hỗ trợ server health check nâng cao
  • Không khởi tạo lại toàn bộ rule khi thay đổi

3. Quản lý North-South traffic qua Ingress

3.1 Ingress là gì?

Ingress là resource API định nghĩa rules routing HTTP/HTTPS truy cập vào service bên trong cluster.

Ingress Controller: thực thi logic routing (Nginx, Traefik, HAProxy, Istio).

Các chức năng:

  • HTTP(S) routing theo hostname/path
  • TLS termination
  • Basic / OAuth2 auth
  • Rate-limiting, black/white-listing
  • Canary / blue-green deployment
  • Rewriting, redirect, retry-policy

3.2 Cài đặt Ingress Controller thực tế

Sử dụng DaemonSet trên dedicated worker node:

spec:
  template:
    spec:
      nodeSelector:
        ingress: "true"
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet

Gán label node:

kubectl label node k8s-node02 ingress=true
kubectl apply -f ingress-nginx-daemonset.yaml

3.3 Cấu trúc Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
  - hosts: ["app.example.com"]
    secretName: app-tls-secret
  rules:
  - host: "app.example.com"
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-svc
            port:
              number: 8080

pathType:

  • Exact: khớp danh sách path chính xác → /api/api/
  • Prefix: khớp tiền tố /abc sẽ khớp /abc/x
  • ImplementationSpecific: ứng xử tùy controller (mặc định trước v1.18)

3.4 Hướng dẫn thực hành Ingress

3.4.1 Ví dụ basic routing
kubectl create deploy nginx --image=nginx:1.15 --replicas=2
kubectl expose deploy nginx --port=80

# Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
spec:
  rules:
  - host: demo.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80

Cập nhật /etc/hosts → truy cập http://demo.local

3.4.2 HTTPS rate-limit user-auth
# Generate self-signed cert
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=demo.local"

kubectl create secret tls demo-tls --cert=tls.crt --key=tls.key

# Ingress HTTPS + basic auth
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/limit-rps: "10"
spec:
  rules:
  - host: demo.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80
  tls:
  - hosts: ["demo.local"]
    secretName: demo-tls
3.4.3 Stripping prefix & rewrite
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /service(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: service-svc
            port:
              number: 8080

URL https://api.example.com/service/users/123 → backend nhận /users/123

3.4.4 Ví dụ stream (SSE, gRPC)
annotations:
  nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
  nginx.ingress.kubernetes.io/proxy-buffering: "off"
  nginx.ingress.kubernetes.io/configuration-snippet: |
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
3.4.5 Redirect và Rewrite
# Redirect 308
annotations:
  nginx.ingress.kubernetes.io/permanent-redirect: https://newsite.com
  nginx.ingress.kubernetes.io/permanent-redirect-code: "308"
3.4.6 Thanh toán điều kiện IP (whitelist/blacklist)
# Blacklist cụ thể
annotations:
  nginx.ingress.kubernetes.io/denylist-source-range: "10.20.0.0/16,192.168.1.1"

# Whitelist toàn cluster
annotations:
  nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8"

Cấu hình global qua ConfigMap ingress-nginx-controller:

data:
  denylist-source-range: "192.168.100.0/24"
  whitelist-source-range: "10.0.0.0/8"
3.4.7 Custom error page
# Deploy default backend server
apiVersion: apps/v1
kind: Deployment
metadata:
  name: custom-error
spec:
  template:
    spec:
      containers:
      - image: your-registry/custom-error-pages:v1.0
        ports:
        - containerPort: 8080

Cấu hình controller args:

args:
- --default-backend-service=ingress-nginx/custom-error

ConfigMap:

data:
  custom-http-errors: "404,502,503"
3.4.8 Phân luồng theo User-Agent (Mobile/Desktop)
# laptop web
annotations:
  nginx.ingress.kubernetes.io/server-snippet: |
    set $isMobile 0;
    if ($http_user_agent ~* "Mobile|Android|iPhone") {
      set $isMobile 1;
    }
    if ($isMobile = 1) {
      return 302 http://m.example.com;
    }
3.4.9 Canaryblue-green deployment

Canary qua annotation:

annotations:
  nginx.ingress.kubernetes.io/canary: "true"
  nginx.ingress.kubernetes.io/canary-weight: "10"   # 10% traffic tới v2

Ví dụ:

  • v1 deployments ở production/ns
  • v2 (canary) ở canary/ns

Tạo Ingress cho v1, sau đó tạo v2canary-weight.

Kiểm tra bằng script:

(0..200).each do |i|
  r = `curl -s http://canary.local/`
  puts r.include?("v2") ? "2" : "1"
end | sort | uniq -c

4. Chẩn đoán sự cố Ingress

ErrorCode Nguyên nhân Giải pháp
404 Domain/path không tồn tại trong Ingress Kiểm tra kubectl get ingress -A, kubectl describe ingress
413 Body quá lớn (upload) Set nginx.ingress.kubernetes.io/proxy-body-size: 64m
502/503 Backend dịch vụ không khả dụng Kiểm tra pod status, service endpoint, kubectl get ep
504 Gateway timeout Tăng proxy-read-timeout qua annotation
CORS errors Thiếu header access-control-* Khai báo nginx.ingress.kubernetes.io/cors-allow-origin

Thẻ: Service Ingress Kubernetes NodePort ClusterIP

Đăng vào ngày 13 tháng 6 lúc 05:58