Sửa lỗi trạng thái của LoadBalancer: Hướng dẫn sử dụng MetalLB trên Kubernetes Bare-Metal

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Trạng thái <pending> gây ức chế trong Kubernetes On-Premise

Bạn đã dành hàng giờ để triển khai một cụm Kubernetes bare-metal. Cho dù đó là một dàn Dell PowerEdge trên tủ rack hay ba chiếc Raspberry Pi 5 trên bàn làm việc, thiết lập này có vẻ rất ổn định. Bạn triển khai ứng dụng Nginx đầu tiên, tạo một dịch vụ LoadBalancer, và chạy lệnh kubectl get svc. Sau đó, bạn chờ đợi. Cột EXTERNAL-IP cứ lì lợm hiển thị <pending>. Năm phút trôi qua. Rồi mười phút. Nó chẳng bao giờ thay đổi.

Đây là khoảnh khắc mà mọi kỹ sư đều nhận ra rằng Kubernetes bare-metal hoạt động khác hẳn với cloud. Trên AWS EKS hoặc Google GKE, nhà cung cấp đám mây sẽ tự động khởi tạo một Network Load Balancer (NLB) và tính phí bạn. Trong môi trường tự quản lý (self-managed), sự tự động hóa đó không tồn tại. Kubernetes không đi kèm sẵn bộ cân bằng tải mạng cho bare-metal. Nếu không có một bộ điều khiển bên ngoài (external controller), cụm cluster sẽ không có cách nào để giao tiếp với router nội bộ và yêu cầu một địa chỉ IP.

Làm chủ khoảng cách về mạng này là điều thiết yếu cho các thiết lập on-premise cấp độ production. Việc dựa vào các giải pháp tình thế như NodePort làm cho hạ tầng của bạn trở nên mong manh và thiếu chuyên nghiệp trong mắt người dùng cuối – những người vốn mong đợi các cổng tiêu chuẩn như 80 và 443.

Nguyên nhân gốc rễ: Thiếu Cloud Controller

Vấn đề bắt nguồn từ việc thiếu Cloud Controller Manager (CCM). Trong môi trường managed (được quản lý), CCM đóng vai trò cầu nối giữa Kubernetes API và phần cứng của nhà cung cấp. Khi bạn yêu cầu một LoadBalancer, CCM sẽ gọi một API, lấy một IP công cộng và cấu hình các router của nhà cung cấp để gửi lưu lượng truy cập đến các node của bạn.

Trên bare-metal, không có API nền tảng nào để gọi. Kubernetes không biết cách tự “quảng bá” chính nó tới mạng của bạn thông qua ARP (Address Resolution Protocol) hoặc BGP (Border Gateway Protocol). Vì cụm cluster không thể thông báo với router gia đình hoặc switch văn phòng rằng nó “sở hữu” một IP cụ thể, bộ điều khiển dịch vụ chỉ đứng đó chờ đợi một tín hiệu không bao giờ tới.

Tại sao các giải pháp tạm thời thường thất bại

Trước khi thực hiện cách sửa lỗi đúng đắn, hãy cùng xem tại sao các phương pháp khác thường không đáp ứng được yêu cầu trong môi trường chuyên nghiệp.

1. NodePort: Cách sửa lỗi cồng kềnh

NodePort mở một cổng số cao (30000-32767) trên mọi node đơn lẻ. Nó hoạt động, nhưng trông rất tệ. Chẳng ai muốn truy cập https://myapp.com:31045 cả. Hơn nữa, nếu node cụ thể mà bạn đang trỏ DNS vào bị sập, toàn bộ dịch vụ của bạn sẽ biến mất, ngay cả khi các node còn lại trong cụm vẫn khỏe mạnh.

2. ExternalIPs: Cơn ác mộng thủ công

Bạn có thể gán thủ công trường externalIPs cho một dịch vụ. Điều này yêu cầu Kubernetes chấp nhận lưu lượng truy cập trên IP đó nếu nó đến được một node. Tuy nhiên, bạn vẫn phải cấu hình mạng bên ngoài một cách thủ công để định tuyến lưu lượng đó. Đây là một gánh nặng bảo trì và rất khó mở rộng khi bạn thêm nhiều dịch vụ hơn.

3. MetalLB: Tiêu chuẩn của ngành

MetalLB là một bộ cân bằng tải mạng được thiết kế riêng cho bare-metal. Nó cung cấp một giải pháp dựa trên phần mềm sử dụng các giao thức định tuyến tiêu chuẩn. Nó mô phỏng hiệu quả hành vi của một bộ cân bằng tải đám mây bằng cách “quảng bá” các IP từ một dải (pool) mà bạn định nghĩa. Đây là cách mạnh mẽ nhất để có được địa chỉ IP thực cho các dịch vụ nội bộ của bạn.

Triển khai MetalLB: Cách tiếp cận từng bước

MetalLB tích hợp nguyên bản với vòng đời của Kubernetes. Nó theo dõi bất kỳ dịch vụ nào có kiểu LoadBalancer và ngay lập tức gán cho nó một IP từ dải đã cấu hình trước.

Bước 1: Bật chế độ Strict ARP

Nếu bạn sử dụng kube-proxy ở chế độ IPVS—tiêu chuẩn cho các cụm có hơn 10 node vì lý do hiệu suất—bạn phải bật strict ARP. Điều này cho phép MetalLB trả lời các yêu cầu ARP một cách chính xác. Hãy chỉnh sửa cấu hình bằng lệnh sau:

kubectl edit configmap -n kube-system kube-proxy

Đặt strictARP thành true trong cấu trúc YAML:

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true

Bước 2: Cài đặt MetalLB Operator

Mặc dù Helm rất tốt cho việc quản lý phiên bản, nhưng file manifest chính thức là cách nhanh nhất để bắt đầu. Tính đến phiên bản 0.14.3, bạn có thể triển khai các thành phần controller và speaker bằng một lệnh duy nhất:

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.3/config/manifests/metallb-native.yaml

Thành phần controller xử lý việc gán IP, trong khi speaker (một DaemonSet) xử lý các giao thức mạng thực tế trên mỗi node.

Bước 3: Định nghĩa dải IP (IP Pool)

MetalLB cần một dải IP riêng dụng. Những IP này phải nằm trong subnet nội bộ của bạn nhưng nằm ngoài dải DHCP của router. Ví dụ: nếu router của bạn cấp IP từ .2 đến .150, bạn có thể sử dụng từ .200 đến .250 cho Kubernetes.

Tạo file metallb-config.yaml:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: main-static-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.200-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: l2-adv
  namespace: metallb-system
spec:
  ipAddressPools:
  - main-static-pool

Áp dụng cấu hình: kubectl apply -f metallb-config.yaml.

Bước 4: Kiểm tra kết quả

Triển khai một dịch vụ thử nghiệm để xem nó hoạt động. Nếu bạn đã có sẵn deployment Nginx, hãy chạy:

kubectl expose deployment nginx --port=80 --type=LoadBalancer

Kiểm tra trạng thái: kubectl get svc. Chỉ trong vài giây, trạng thái <pending> sẽ biến mất, thay thế bằng một IP như 192.168.1.200. Giờ đây bạn có thể truy cập IP đó từ bất kỳ trình duyệt nào trong mạng của mình.

Layer 2 và BGP: Chọn chế độ phù hợp

Sự lựa chọn của bạn phụ thuộc vào phần cứng và lưu lượng truy cập dự kiến mà bạn mong đợi.

Chế độ Layer 2 (Tốt nhất cho Homelab)

Ở chế độ Layer 2, một node sẽ “thắng” trong cuộc bầu chọn để host một IP dịch vụ. Nó sẽ phản hồi các yêu cầu ARP cho địa chỉ đó. Chế độ này đơn giản và hoạt động trên bất kỳ switch hoặc router cơ bản nào (như TP-Link hoặc Asus). Nhược điểm là tất cả lưu lượng truy cập cho một dịch vụ cụ thể sẽ đổ dồn vào một node trước tiên. Nó tuyệt vời cho các văn phòng nhỏ nhưng tạo ra một nút thắt cổ chai nhỏ cho các ứng dụng có băng thông cao.

Chế độ BGP (Lựa chọn cho Production)

BGP là bước đi “chuyên nghiệp”. Mỗi node thiết lập một phiên peering với router mạng của bạn. Khi một dịch vụ khởi chạy, tất cả các node sẽ thông báo với router rằng chúng có thể xử lý lưu lượng đó. Sau đó, router sử dụng Equal-Cost Multi-Path (ECMP) để phân chia lưu lượng trên tất cả các node ở cấp độ phần cứng. Điều này yêu cầu một router hỗ trợ BGP, chẳng hạn như Ubiquiti EdgeRouter, MikroTik hoặc thiết bị chạy pfSense.

Bài học từ thực tế

Sau khi triển khai MetalLB trên nhiều trung tâm dữ liệu khác nhau, tôi đã rút ra một vài quy tắc quan trọng cần tuân thủ:

  • Loại trừ IP khỏi DHCP: Nếu router cấp IP 192.168.1.201 cho một laptop trong khi MetalLB cấp nó cho một Ingress, bạn sẽ gặp tình trạng mất kết nối chập chờn. Đây là một cơn ác mộng khi debug. Luôn thiết lập dải loại trừ thủ công trong cài đặt router của bạn.
  • Sử dụng IP tĩnh cho Node: Nếu IP chính của một node thay đổi qua DHCP, bảng ARP trên switch của bạn có thể bị lỗi. Luôn gán IP tĩnh cho các worker Kubernetes.
  • Địa chỉ IP là hữu hạn: Đừng cấp cho 50 microservices 50 địa chỉ IP LoadBalancer khác nhau. Hãy dùng MetalLB để cấp một IP cho một Ingress Controller (như Nginx Ingress hoặc Traefik). Sau đó sử dụng hostname (ví dụ: api.example.com) để định tuyến lưu lượng nội bộ.
  • Lưu ý về ARP Timeout: Ở chế độ Layer 2, nếu một node bị lỗi, node khác sẽ tiếp quản IP. Các router gia đình rẻ tiền có thể mất 30-60 giây để cập nhật bộ nhớ đệm ARP, gây ra tình trạng gián đoạn ngắn trong quá trình failover.

Lời kết

Chuyển sang bare-metal không nên mang lại cảm giác thụt lùi về sự tiện lợi. MetalLB lấp đầy khoảng cách giữa phần cứng vật lý và Kubernetes API, mang lại trải nghiệm mượt mà như trên đám mây. Một khi bạn vượt qua được trạng thái <pending>, cụm cluster on-premise của bạn cuối cùng sẽ bắt đầu hoạt động như một môi trường chuyên nghiệp. Bạn có được sự kiểm soát của bare-metal cùng với sự tự động hóa của đám mây.

Share: