Degraded LB with K8S
1. Tổng Quan Vấn Đề
Khi Cloud Controller Manager (CCM) tích hợp giữa Kubernetes và nhà cung cấp dịch vụ đám mây, quá trình tạo một dịch vụ (Service) với kiểu LoadBalancer sẽ thực hiện việc thêm tất cả các worker (node) vào thành phần listener của LoadBalancer. Sau đó, LoadBalancer tiến hành kiểm tra tình trạng (health check) trên các endpoint được expose ra.
Tuy nhiên, việc chọn lựa node cũng như cấu hình thuộc tính externalTrafficPolicy của Service có ảnh hưởng đáng kể đến trạng thái của LoadBalancer. Cụ thể:
- externalTrafficPolicy: Local:
- Chỉ expose port trên các node đang chạy pod tương ứng.
- Khi LoadBalancer thêm tất cả các node nhưng pod không được schedule trên tất cả các node, chỉ có một số ít node thực sự nhận được traffic và thực hiện health check thành công. Điều này dẫn đến tình trạng một số node được đánh dấu là unhealthy, làm cho trạng thái tổng thể của LoadBalancer trở nên “Degraded”.
- externalTrafficPolicy: Cluster:
- Expose port trên toàn bộ các node trong cluster.
- Do đó, tất cả các node đều có thể tiếp nhận health check, dẫn đến việc toàn bộ các node đều được đánh dấu là healthy và trạng thái LoadBalancer được duy trì ổn định.
2. Ví Dụ Cấu Hình Dịch Vụ
Để minh họa rõ ràng hơn, dưới đây là ví dụ về hai dịch vụ với cấu hình khác nhau:
a) Dịch vụ nginx-service với externalTrafficPolicy là Local
apiVersion: v1
kind: Service
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx-service","namespace":"default"},"spec":{"ports":[{"port":80,"protocol":"TCP","targetPort":80}],"selector":{"app":"nginx"},"type":"LoadBalancer"}}
name: nginx-service
namespace: default
spec:
allocateLoadBalancerNodePorts: true
clusterIP: 10.93.70.107
**externalTrafficPolicy: Local**
healthCheckNodePort: 32483
internalTrafficPolicy: Cluster
ports:
- nodePort: 30860
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 123.31.39.43
ipMode: VIP
Với cấu hình này, do chỉ những node chứa pod của nginx mới nhận được traffic, nên nếu các pod chỉ được schedule trên một vài node thay vì tất cả các node, các node không có pod sẽ không đáp ứng health check, dẫn đến trạng thái LoadBalancer bị đánh giá là “Degraded”.
b) Dịch vụ ingress-nginx-controller với externalTrafficPolicy là Cluster
apiVersion: v1
kind: Service
metadata:
annotations:
meta.helm.sh/release-name: ingress-nginx
meta.helm.sh/release-namespace: ingress-nginx
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
allocateLoadBalancerNodePorts: true
clusterIP: 10.93.161.16
**externalTrafficPolicy: Cluster**
internalTrafficPolicy: Cluster
ports:
- appProtocol: http
name: http
nodePort: 30351
port: 80
protocol: TCP
targetPort: http
- appProtocol: https
name: https
nodePort: 30141
port: 443
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 123.31.39.189
ipMode: VIP
Với cấu hình này, do port được expose trên tất cả các node, các node đều có khả năng tiếp nhận health check, từ đó trạng thái của LoadBalancer luôn được đánh giá là “Healthy”.
3. Các Giải Pháp Để Duy Trì Trạng Thái Healthy Khi Sử Dụng externalTrafficPolicy: Local
Để có thể sử dụng externalTrafficPolicy: Local mà vẫn đảm bảo trạng thái LoadBalancer hiển thị “Healthy”, có thể áp dụng một trong các giải pháp sau:
-
Mở rộng số lượng node chứa pod:
Đảm bảo rằng các pod của dịch vụ được schedule trên tất cả các node trong cluster. Tuy nhiên, phương án này có thể dẫn đến việc tiêu thụ tài nguyên không cần thiết khi phải scale cluster ra toàn bộ node.
-
Sử dụng annotation
kubernetes.bizflycloud.vn/target-node-labels
cho Service:Cấu hình thêm annotation này theo hướng dẫn tại tài liệu BizflyCloud để yêu cầu CCM chỉ lựa chọn những node có nhãn (label) được chỉ định khi thêm vào LoadBalancer. Đồng thời, điều chỉnh cấu hình scheduler để đảm bảo các pod được phân phối đều trên các node tương ứng với nhãn đã định, từ đó giúp duy trì trạng thái “Healthy” cho LoadBalancer.
Hình ảnh minh hoạ