Chuyển đến nội dung chính

BÀI 9: METALLB — LOADBALANCER CHO ON-PREMISES

Cài đặt MetalLB cung cấp LoadBalancer IP cho services trong on-premises cluster, cấu hình L2 mode và BGP mode, IPAddressPool, và expose service ra external network.

🔒 DevSecOps — Bài 9 BÀI 9: METALLB — LOADBALANCER CHO ON-PREMISES

Deploy Microservices On-Premises với Kubernetes HA

Phần 2: Kubernetes HA Cluster với kubeadm

xdev.asia

🎯 MỤC TIÊU BÀI HỌC

Sau khi hoàn thành bài học này, bạn sẽ:

  • ✅ Hiểu vấn đề LoadBalancer trong on-premises (không có cloud LB)
  • ✅ Cài đặt MetalLB bằng Helm
  • ✅ Cấu hình L2 mode với IPAddressPool
  • ✅ Hiểu BGP mode cho datacenter lớn
  • ✅ Expose services với type LoadBalancer

PHẦN 1: VẤN ĐỀ LOADBALANCER TRÊN ON-PREMISES

1.1. Cloud vs On-Premises


Cloud (AWS/GCP/Azure):
┌─────────┐     ┌──────────────────┐     ┌──────────────────┐
│  User   │────►│  Cloud LB (ELB)  │────►│  K8s Service     │
│         │     │  (tự động tạo)   │     │  type:LoadBalancer│
└─────────┘     └──────────────────┘     └──────────────────┘
                ✅ Tự động provisioning    ✅ External IP tự gán

On-Premises (KHÔNG có MetalLB): ┌─────────┐ ┌──────────────────┐ ┌──────────────────┐ │ User │────►│ ??? │────►│ K8s Service │ │ │ │ Không có LB! │ │ type:LoadBalancer│ └─────────┘ └──────────────────┘ │ ⚠️ PENDING... │ └──────────────────┘ ❌ External IP = <pending> ← Mãi mãi pending!

On-Premises (CÓ MetalLB): ┌─────────┐ ┌──────────────────┐ ┌──────────────────┐ │ User │────►│ MetalLB │────►│ K8s Service │ │ │ │ (announce IP) │ │ type:LoadBalancer│ └─────────┘ └──────────────────┘ │ ✅ 10.10.40.201 │ ✅ MetalLB gán IP └──────────────────┘


PHẦN 2: CÀI ĐẶT METALLB

2.1. Prerequisites

# MetalLB yêu cầu kube-proxy strictARP (đã cấu hình ở Bài 6):
# Verify:
kubectl get configmap kube-proxy -n kube-system -o yaml | grep strictARP
# strictARP: true  ← ✅ OK

Nếu đã xóa kube-proxy (dùng Cilium replacement):

→ Không cần verify, Cilium handle ARP

2.2. Install MetalLB bằng Helm

# Add MetalLB Helm repo:
helm repo add metallb https://metallb.universe.tf
helm repo update

Install MetalLB:

helm install metallb metallb/metallb
--namespace metallb-system
--create-namespace
--set speaker.frr.enabled=true

Verify installation:

kubectl -n metallb-system get pods

NAME READY STATUS RESTARTS AGE

metallb-controller-xxxxx-xxxxx 1/1 Running 0 30s

metallb-speaker-xxxxx 4/4 Running 0 30s (DaemonSet)

metallb-speaker-xxxxx 4/4 Running 0 30s

metallb-speaker-xxxxx 4/4 Running 0 30s

...


PHẦN 3: CẤU HÌNH L2 MODE

3.1. IPAddressPool

# metallb-config.yaml:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: external-pool
  namespace: metallb-system
spec:
  addresses:
    - 10.10.40.200-10.10.40.250         # 51 IPs cho services
  autoAssign: true                       # Tự động gán IP
  avoidBuggyIPs: true                    # Bỏ qua .0 và .255

apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: internal-pool namespace: metallb-system spec: addresses: - 10.10.20.200-10.10.20.220 # Internal services autoAssign: false # Phải specify manually


apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: l2-advertisement namespace: metallb-system spec: ipAddressPools: - external-pool - internal-pool nodeSelectors: - matchLabels: node-role.kubernetes.io/worker: "" # Chỉ announce từ worker nodes

kubectl apply -f metallb-config.yaml
# ipaddresspool.metallb.io/external-pool created
# ipaddresspool.metallb.io/internal-pool created
# l2advertisement.metallb.io/l2-advertisement created

3.2. L2 Mode hoạt động như thế nào?


L2 Mode (ARP/NDP):
┌─────────────┐                    ┌─────────────────┐
│  Client     │  ARP: Who has     │  MetalLB        │
│  (external) │  10.10.40.201?    │  Speaker         │
│             │──────────────────►│  (trên worker1)  │
│             │                    │  "Tôi có!"       │
│             │◄──────────────────│  ARP Reply       │
│             │                    └─────────────────┘
│             │  Traffic:
│             │──────────────────►  worker1 → kube-proxy/Cilium → Pod
└─────────────┘

✅ Đơn giản, không cần router hỗ trợ ❌ Failover chậm hơn BGP (~10 giây) ❌ Một node handle tất cả traffic cho 1 IP (không true LB)


PHẦN 4: TEST LOADBALANCER SERVICE

4.1. Deploy test application

# Deploy nginx test:
kubectl create deployment nginx-test --image=nginx:alpine --replicas=3

Expose với type LoadBalancer:

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

Kiểm tra service:

kubectl get svc nginx-test

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

nginx-test LoadBalancer 10.96.xxx.xx 10.10.40.200 80:3xxxx/TCP 10s

↑ MetalLB assigned! ✅

4.2. Test access từ external

# Từ máy trong cùng network:
curl http://10.10.40.200
# 
# 
# Welcome to nginx!
# ...  ← OK! ✅

Kiểm tra MetalLB speaker IP assignment:

kubectl -n metallb-system get ipaddresspool

NAME AUTO ASSIGN AVOID BUGGY IPS ADDRESSES

external-pool true true 10.10.40.200-10.10.40.250

4.3. Specify IP cụ thể

# Service với IP cụ thể:
apiVersion: v1
kind: Service
metadata:
  name: my-app
  annotations:
    metallb.universe.tf/address-pool: internal-pool   # Chọn pool
spec:
  type: LoadBalancer
  loadBalancerIP: 10.10.20.210                         # IP cụ thể
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080

PHẦN 5: BGP MODE (DATACENTER LỚN)

5.1. Khi nào dùng BGP?

Tiêu chí L2 Mode BGP Mode
Yêu cầu router Không Cần BGP-capable router
Failover ~10 giây ~3 giây
True load balancing ❌ (1 node handle) ✅ ECMP across nodes
Cross-subnet ❌ Same L2 segment ✅ Works across subnets
Complexity Đơn giản Cần router config
Best for SMB, single rack Large DC, multi-rack

5.2. BGP Configuration Example

# metallb-bgp.yaml (chỉ dùng khi có BGP router):
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: tor-switch
  namespace: metallb-system
spec:
  myASN: 64512                          # K8s cluster ASN
  peerASN: 64501                        # ToR switch ASN
  peerAddress: 10.10.20.1               # Router IP
  holdTime: 90s
  keepaliveTime: 30s
  nodeSelectors:
    - matchLabels:
        node-role.kubernetes.io/worker: ""

apiVersion: metallb.io/v1beta1 kind: BGPAdvertisement metadata: name: bgp-advertisement namespace: metallb-system spec: ipAddressPools: - external-pool localPref: 100 communities: - 64512:100


PHẦN 6: IP SHARING VÀ ADVANCED FEATURES

6.1. Shared IP (nhiều services dùng 1 IP)

# Nhiều services share cùng 1 external IP (khác port):
apiVersion: v1
kind: Service
metadata:
  name: web-http
  annotations:
    metallb.universe.tf/allow-shared-ip: "shared-web"
spec:
  type: LoadBalancer
  loadBalancerIP: 10.10.40.210
  selector:
    app: web
  ports:
    - port: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-https
  annotations:
    metallb.universe.tf/allow-shared-ip: "shared-web"
spec:
  type: LoadBalancer
  loadBalancerIP: 10.10.40.210          # Same IP!
  selector:
    app: web
  ports:
    - port: 443

6.2. Cleanup test

kubectl delete deployment nginx-test
kubectl delete svc nginx-test

💡 KEY TAKEAWAYS

  1. MetalLB giải quyết LoadBalancer cho on-premises — không cần cloud provider
  2. L2 Mode đơn giản, phù hợp single rack/small cluster
  3. BGP Mode cho datacenter lớn, multi-rack với ECMP true load balancing
  4. IPAddressPool quản lý dải IP, có thể tạo nhiều pools (external, internal)
  5. IP Sharing cho phép nhiều services dùng chung 1 external IP
  6. strictARP: true trong kube-proxy là requirement cho L2 mode

🎯 BÀI TẬP

Bài tập 1: Install MetalLB

  • Cài MetalLB bằng Helm
  • Tạo IPAddressPool với dải IP phù hợp lab
  • Deploy service type LoadBalancer, verify external IP

Bài tập 2: Multiple pools

  • Tạo 2 pools: external-pool và internal-pool
  • Deploy 2 services, mỗi service dùng 1 pool khác nhau
  • Test IP sharing với 2 services cùng IP khác port

📚 BÀI TIẾP THEO

Trong Bài 10: etcd — Vận hành, Backup và Disaster Recovery, chúng ta sẽ deep dive vào etcd operations, backup strategies, và restore procedure.