Trang chủHướng dẫnCấu hình Load Balancing cho Kubernetes sử dụng HAProxy và Nginx Ingress
Networking

Cấu hình Load Balancing cho Kubernetes sử dụng HAProxy và Nginx Ingress

CyStack blog 7 phút để đọc
CyStack blog02/10/2025
Reading Time: 7 minutes

Cấu hình Load Balancing cho Kubernetes

Khi triển khai K8S on premise, để các ứng dụng có thể truy cập từ bên ngoài, một cách phổ biến là expose service bằng NodePort type, cho phép bạn truy cập qua địa chỉ IP của node và một port trong khoảng từ 30000 đến 32767.

Tuy nhiên, NodePort có một số hạn chế như số lượng port bị giới hạn, gây khó khăn khi có nhiều service; đồng thời, đường dẫn truy cập (ví dụ: http://node_ip:port) trông không chuyên nghiệp so với tên miền chuẩn như git.example.com.

Ngoài ra, khi sử dụng NodePort type thì entry point sẽ là địa chỉ IP của node. Trong trường hợp có nhiều node, để đảm bảo các request được chia đều tới các node, bạn cần cấu hình load balancing để thực hiện nhiệm vụ đó.

Thông thường ta sẽ sử dụng HA Proxy hoặc Nginx để cấu hình, Trong bài hướng dẫn này, chúng ta sẽ sử dụng HAProxy trên một server riêng biệt để làm load balancer, kết hợp với Nginx Ingress Controller để quản lý định tuyến request trong cluster và Cert-Manager để tự động hóa cấu hình SSL. Hướng dẫn cấu hình High Availability (HA) cho HAProxy sẽ được trình bày trong một bài viết riêng.

Yêu cầu

  • Đã cài đặt K8S Cluster.
  • Một server riêng để cài đặt HA Proxy (trong bài thực hành mình đang sử dụng Ubuntu 22.04, 1GB ram, 1 cpu, 10GB SSD)
  • Có hiểu biết về Load Balance HA Proxy, Ingress, Nginx và một số workload trong K8S.

Trong phần hướng dẫn này, mình đã cài đặt K8S Cluster với 2 worker với IP lần lượt là 100.64.0.1, 100.64.0.2 và load balancer server với IP 100.64.0.4.

Mô hình

Mô hình Load balancing

Mô tả các thành phần:

Client: người dùng gửi request https đến hệ thống.

Load Balancer (HAProxy):

  • Nhận traffic từ client qua HTTPS.
  • Không giải mã SSL → chỉ chuyển tiếp request đến Ingress Controller, sử dụng mode tcp trong HAProxy → TCP passthrough.
  • Client → HA Proxy: HTTPS, HA Proxy → Ingress Controller: HTTPS (giữ nguyên vẹn gói tin).

Ingress Controller Service:

  • Là một pod trong cluster.
  • Xử lý SSL Termination: nhận HTTPS từ LB → giải mã ra HTTP.
  • Đọc domain/path trong request → áp dụng Ingress Rules để route.

Ingress Rule:

Thực hiện routing theo quy định:

  • Theo domain (ví dụ: hello.manhtx.click)
  • Theo path (ví dụ: /login, /shop)

Cert Manager:

  • Tự động tạo SSL cert (qua Let’s Encrypt, Self Sign, …).
  • Gắn cert vào đúng Ingress (bằng cách quản lý Secret).
  • Gia hạn chứng chỉ tự động.

Service:

  • Là Kubernetes Service route request đến đúng Pod backend (Deployment).
  • Mỗi Service có thể đại diện cho một microservice khác nhau.

Deployment:

  • Các Pod chạy ứng dụng backend thật sự.
  • Mỗi Deployment có nhiều Pod, quản lý tự động bởi Kubernetes.

Luồng xử lý yêu cầu

  • Client gửi request:

    hello.manhtx.click

  • HAProxy Load Balancer:
    • Nhận gói HTTPS.
    • Dùng mode tcp, truyền thẳng đến Ingress Controller (không giải mã).
  • Ingress Controller Service:
    • Terminate SSL (giải mã HTTPS → HTTP).
    • Đọc domain hello.manhtx.click, path /cart.
    • So khớp với Ingress Rule.
  • Ingress Rule chọn đúng Service (ví dụ: service-cart).
  • Service route đến đúng Pod trong Deployment để xử lý.

Hướng dẫn cấu hình

Cài đặt Nginx Ingress:

Trong hướng dẫn này mình sẽ sử dụng helm để cài nginx ingress lên k8s cluster, ngoài ra bạn có thể cài trực tiếp bằng file manifest (phần cài helm các bạn có thể xem các bài hướng dẫn khác nhé):

  • Tạo namespace để dễ dàng hơn trong việc quản lý các resource
kubectl create namespace ingress-nginx
  • Thêm repo của ingress-nginx
helm repo add ingress-nginx <https://kubernetes.github.io/ingress-nginx>
helm repo update
  • Tải về chart và file cấu hình values.yaml
helm pull ingress-nginx/ingress-nginx --untar
cd ingress-nginx

Sau đó bạn sẽ thấy thư mục có sẵn file values.yaml. Bạn nên copy ra 1 file mới và update value trong file đó.

  • Chỉnh sửa file values.new.yaml copy từ values.yaml
nano values.new.yaml
  • Tìm đến controller block, do cluster đang cài on premise, cập nhật lại service type từ LoadBalancer (chỉ support cho cloud provider) sang NodePort để có thể truy cập vào nginx ingress qua IP của node

Load balancing

  • Chỉ định port cho cần expose với http chạy port 31080 và https chạy port 31443

Load Balancing cho Kubernetes

  • Chạy lệnh sau để cài ingress nginx lên cluster với file values mới
helm install ngix-ingress ingress-nginx -f values.new.yaml -n ingress-nginx
  • Sau khi chạy xong, kiểm tra các resource được tạo ra.
kubectl get all -n ingress-nginx

load balancing cho Kubernetes

Ta thấy đã có service type là NodePort đang expose 2 port 31080 với 31443 ra ngoài.

Cài đặt Cert Manager:

Ta cũng dùng helm để cài đặt

  • Thêm Helm repo của Jetstack
helm repo add jetstack <https://charts.jetstack.io>
helm repo update
  • Cài đặt cert manager
helm install cert-manager jetstack/cert-manager \\
	--namespace cert-manager \\ 
	--create-namespace \\
	--version v1.14.5 \\
	--set installCRDs=true
  • Kiểm tra các resouce được khởi tạo
kubectl get all -n cert-manager

Load Balancing cho Kubernetes

Cài đặt HA Proxy:

  • Cập nhật hệ thống
sudo apt update
sudo apt upgrade -y
  • Cài đặt HA Proxy
sudo apt install haproxy -y
  • Kiểm tra phiên bản
haproxy -v

Hiện tại mình đang sử dụng phiên bản 2.4.24-0ubuntu0.22.04.2

Load Balancing cho Kubernetes

  • Cấu hình HA Proxy
sudo nano /etc/haproxy/haproxy.cfg
  • Sử dụng cấu hình sau
global
    log /dev/log local0
    log /dev/log local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon
    maxconn 20000 # Điều chỉnh nếu cần

defaults
    log global
    mode tcp # Quan trọng: Sử dụng mode tcp cho NodePort
    option tcplog
    option dontlognull
    timeout connect 5000
    timeout client 50000
    timeout server 50000

frontend http_frontend
    bind 100.64.0.4:80  # Lắng nghe trên IP thật của server LB và port 80
    mode tcp
    default_backend k8s_workers_http

frontend https_frontend
    bind 100.64.0.4:443 # Lắng nghe trên IP thật của server LB và port 443
    mode tcp
    default_backend k8s_workers_https

backend k8s_workers_http
    mode tcp
    balance roundrobin # Thuật toán cân bằng tải
    # Server worker 1, trỏ đến NodePort HTTP
    server worker1 100.64.0.1:31080 check port 31080 inter 2000 rise 2 fall 3 send-proxy-v2
    # Server worker 2, trỏ đến NodePort HTTP
    server worker2 100.64.0.2:31080 check port 31080 inter 2000 rise 2 fall 3 send-proxy-v2

backend k8s_workers_https
    mode tcp
    balance roundrobin
    # Server worker 1, trỏ đến NodePort HTTPS
    server worker1 100.64.0.1:31443 check port 31443 inter 2000 rise 2 fall 3 send-proxy-v2
    # Server worker 2, trỏ đến NodePort HTTPS
    server worker2 100.64.0.2:31443 check port 31443 inter 2000 rise 2 fall 3 send-proxy-v2

Hãy thay thế IP và port đúng với cấu hình của bạn, nếu server của bạn có cấu hình firewall thì hãy mở các port này ra tránh trường hợp không kết nối đươc nhé.

  • Kiểm tra cấu hình
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
  • Khởi động lại dịch vụ HAProxy
sudo systemctl restart haproxy
sudo systemctl enable haproxy
  • Kiểm tra trạng thái
sudo systemctl status haproxy
  • Kiểm tra xem HA Proxy đã chuyển tiếp request với nginx ingress chưa, nếu trỏ về trang 404 Not Found của Nginx thì chính xác
curl -L <http://100.64.0.4/>
  • Cũng có thể kiểm tra trên trình duyệt

Load Balancing cho Kubernetes

Như thế ta đã cấu hình xong HA Proxy để forward request về các worker node.

Triển khai ứng dụng

Sau khi đã cấu hình xong, ta sẽ triển khai demo 1 ứng dụng nhỏ để xem các cài đặt của chúng ta hoạt động đúng không.

  • Đầu tiên, tạo 1 ClusterIssuer sử dụng self-signed certificate (do đang dựng lab ở local) với file selfsigned-issuer.yaml có nội dung sau:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: selfsigned-cluster-issuer
spec:
  selfSigned: {}
  • Apply file
kubectl apply -f selfsigned-issuer.yaml
  • Kiểm tra ClusterIssuer được tạo chưa
kubectl get clusterissuer

Nếu cột READYTrue thì issuer đã sẵn sàng dùng.

  • Tạo file demo_app.yaml với nội dung sau
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-app
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-container
        image: nginxdemos/hello
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  selector:
    app: hello-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-ingress
  annotations:
    cert-manager.io/cluster-issuer: selfsigned-cluster-issuer
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls: # lấy https
    - hosts:
        - hello.manhtx.click
      secretName: domain-tls-self-signed-attacks-hello.manhtx.click
  rules:
  - host: hello.manhtx.click
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello-service
            port:
              number: 80
  • Apply file
kubectl create ns demo
kubectl apply -f demo_app.yaml -n demo
  • Cấu hình domain để trỏ về load balancer IP hoặc bạn có thể config local dns trong /etc/hosts.

Load Balancing cho Kubernetes

  • Sau khi cấu hình xong, ta có thể truy cập bằng domain đã config trước đó.

Cấu hình Load Balancing cho Kubernetes

Ta có thể truy cập vào trang web với https, nó sẽ hiện cảnh báo do mình đang sử dụng self sign cert. HA Proxy sẽ tự động điều hướng các request lần lượt vào các worker node theo đúng thuật toán roundrobin được cấu hình trong trước đó.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất