返回文章列表

MetalLB 多 IP Pool 與多協定負載平衡設定

本文探討 MetalLB 的元件運作機制,包含 Speaker 和 Controller 的協作方式,以及如何設定多個 IP Pool 和多協定負載平衡。文章以 CoreDNS 為例,示範如何利用 MetalLB 建立 TCP 和 UDP 服務,並結合 external-dns 實作外部 DNS

Kubernetes 網路

MetalLB 作為 Kubernetes 叢集的負載平衡解決方案,提供 Layer 4 的負載平衡功能,讓應用服務得以暴露於外部網路。其核心元件 Speaker 和 Controller 負責服務宣告、IP 位址分配和服務狀態更新,並透過 ETCD 儲存服務狀態。MetalLB 支援多 IP Pool 設定,允許管理員依據服務需求分配不同的子網路,例如區分網頁服務和資料函式庫服務的 IP 範圍。文章以新增 IP Pool subnet-201 為例,示範如何透過修改 ConfigMap 和新增 Service 註解來分配特定 IP 範圍。此外,MetalLB 也支援多協定負載平衡,透過 allow-shared-ip 註解,允許多個服務分享同一個 IP 位址。文章以 CoreDNS 為例,說明如何建立 TCP 和 UDP 服務並確保其分享同一個外部 IP,解決 Kubernetes Service 物件預設不支援多協定的限制。最後,文章也提及 external-dns 的整合,補充 MetalLB 缺少的 DNS 解析功能,讓外部網路能透過網域名稱存取叢集服務。

MetalLB 元件與 LoadBalancer 服務詳解

在前面的章節中,我們介紹瞭如何佈署 MetalLB 並組態其基本設定。在本章節中,我們將探討 MetalLB 的內部元件,以及如何使用 LoadBalancer 服務。

MetalLB 元件

MetalLB 的佈署包含兩個主要元件:speaker 和 controller。這些元件共同工作以維護服務列表和分配的 IP 位址。

Speaker 元件

Speaker 元件負責在節點上宣告 LoadBalancer 服務。它被佈署為 DaemonSet,因為佈署可以在任何工作節點上進行,因此每個工作節點都需要宣告正在執行的工作負載。

當使用 LoadBalancer 型別建立服務時,speaker 將宣告該服務。從節點的 speaker 日誌中,我們可以看到如下宣告:

{"caller":"main.go:176","event":"startUpdate","msg":"start of service update","service":"my-grafana-operator/grafana-operator-metrics","ts":"2020-04-21T21:10:07.437231123Z"}
{"caller":"main.go:189","event":"endUpdate","msg":"end of service update","service":"my-grafana-operator/grafana-operator-metrics","ts":"2020-04-21T21:10:07.437516541Z"}
{"caller":"main.go:176","event":"startUpdate","msg":"start of service update","service":"my-grafana-operator/grafana-operator-metrics","ts":"2020-04-21T21:10:07.464140524Z"}
{"caller":"main.go:246","event":"serviceAnnounced","ip":"10.2.1.72","msg":"service has IP, announcing","pool":"default","protocol":"layer2","service":"my-grafana-operator/grafana-operator-metrics","ts":"2020-04-21T21:10:07.464311087Z"}

Controller 元件

Controller 元件接收來自每個工作節點上的 speaker 的宣告。使用相同的服務宣告,controller 日誌顯示了宣告和分配給服務的 IP 位址:

{"caller":"main.go:49","event":"startUpdate","msg":"start of service update","service":"my-grafana-operator/grafana-operator-metrics","ts":"2020-04-21T21:10:07.437701161Z"}
{"caller":"service.go:98","event":"ipAllocated","ip":"10.2.1.72","msg":"IP address assigned by controller","service":"my-grafana-operator/grafana-operator-metrics","ts":"2020-04-21T21:10:07.438079774Z"}
{"caller":"main.go:96","event":"serviceUpdated","msg":"updated service object","service":"my-grafana-operator/grafana-operator-metrics","ts":"2020-04-21T21:10:07.467998702Z"}

建立 LoadBalancer 服務

現在我們已經安裝了 MetalLB 並瞭解了其元件的工作原理,讓我們在 KinD 叢集上建立第一個 LoadBalancer 服務。

步驟 1:建立 NGINX 佈署

首先,我們需要建立一個 NGINX 佈署。可以使用以下命令快速建立:

kubectl run nginx-web --image bitnami/nginx

步驟 2:建立 LoadBalancer 服務

接下來,我們需要建立一個新的服務,該服務將使用 LoadBalancer 型別。可以透過建立一個新的 manifest 檔案或僅使用 kubectl 暴露佈署。

建立一個名為 nginx-lb.yaml 的檔案,並新增以下內容:

apiVersion: v1
kind: Service
metadata:
  name: nginx-lb
spec:
  ports:
  - port: 8080
    targetPort: 8080
  selector:
    run: nginx-web
  type: LoadBalancer

步驟 3:應用 manifest 檔案

使用 kubectl 將檔案應用到叢集:

kubectl apply -f nginx-lb.yaml

步驟 4:驗證服務建立

列出服務以驗證是否正確建立了新的 LoadBalancer 服務:

kubectl get services

將看到一個新的 LoadBalancer 服務被建立,並且 MetalLB 從組態的 IP 地址池中分配了一個 IP 位址。

檢視 controller 日誌,可以驗證 MetalLB controller 分配了 IP 位址:

{"caller":"service.go:114","event":"ipAllocated","ip":"172.16.200.100","msg":"IP address assigned by controller","service":"default/nginx-lb","ts":"2020-04-25T23:54:03.668948668Z"}

步驟 5:測試服務

現在可以使用 curl 命令測試服務,使用分配給服務的 IP 位址和埠 8080:

curl 172.17.200.100:8080

圖表翻譯:MetalLB 元件互動圖示

圖表翻譯: 此圖示展示了 MetalLB 的 Speaker 和 Controller 元件之間的互動作用。Speaker 負責宣告 LoadBalancer 服務,而 Controller 負責分配 IP 位址並更新服務狀態。ETCD 用於儲存服務狀態。

Layer 4 負載平衡器與 MetalLB 多 IP Pool 設定

在 Kubernetes 叢集中,MetalLB 提供了一個強大的 Layer 4 負載平衡解決方案。透過 MetalLB,可以將應用服務暴露給外部網路,而不僅僅依賴 Layer 7 的負載平衡器。

為 MetalLB 新增多個 IP Pool

在某些場景下,您可能需要為不同的服務提供不同的子網路。例如,當您最初為服務建立了一個 IP 範圍,但後來發現這個範圍不夠用時,您就需要擴充套件或新增 IP 範圍。

編輯 ConfigMap 並新增 IP Pool

首先,編輯 metallb-config.yaml 檔案,新增新的 IP 範圍資訊:

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 172.17.200.100-172.17.200.125
    - name: subnet-201
      protocol: layer2
      addresses:
      - 172.17.201.100-172.17.201.125

套用更新後的 ConfigMap:

kubectl apply -f metallb-config.yaml

這樣,MetalLB 就擁有了兩個 IP Pool:defaultsubnet-201

從新的 IP Pool 建立服務

要從 subnet-201 Pool 建立一個新的服務,需要在服務請求中新增註解。以下是一個範例:

apiVersion: v1
kind: Service
metadata:
  name: nginx-lb2
  annotations:
    metallb.universe.tf/address-pool: subnet-201
spec:
  ports:
  - port: 8080
    targetPort: 8080
  selector:
    run: nginx-web
  type: LoadBalancer

建立服務:

kubectl apply -f nginx-lb2.yaml

驗證服務是否被分配了來自 subnet-201 Pool 的 IP 位址:

kubectl get services

使用多個 IP Pool 的好處

擁有不同的 IP Pool 可以讓您根據服務型別分配特定的 IP 位址區塊。例如,您可以將一個 IP Pool 用於網頁服務,另一個用於資料函式庫服務等。

在 MetalLB 中使用多協定

預設情況下,Kubernetes 的 Service 物件不支援多協定(例如同時使用 TCP 和 UDP)。然而,MetalLB 提供了一個解決方案:建立兩個不同的 Service 物件,一個用於 TCP,另一個用於 UDP。

建立多協定服務的步驟

  1. 建立兩個 Service 物件,分別用於 TCP 和 UDP。
  2. 為每個 Service 物件指定不同的協定。

例如,為 CoreDNS 建立一個同時支援 TCP 和 UDP 的服務:

# TCP Service
apiVersion: v1
kind: Service
metadata:
  name: coredns-tcp
spec:
  ports:
  - port: 53
    targetPort: 53
    protocol: TCP
  selector:
    app: coredns
  type: LoadBalancer

# UDP Service
apiVersion: v1
kind: Service
metadata:
  name: coredns-udp
spec:
  ports:
  - port: 53
    targetPort: 53
    protocol: UDP
  selector:
    app: coredns
  type: LoadBalancer

圖表說明

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title MetalLB 多 IP Pool 與多協定負載平衡設定

package "網路架構" {
    package "應用層" {
        component [HTTP/HTTPS] as http
        component [WebSocket] as ws
        component [gRPC] as grpc
    }

    package "傳輸層" {
        component [TCP] as tcp
        component [UDP] as udp
        component [TLS/SSL] as tls
    }

    package "網路層" {
        component [IP] as ip
        component [ICMP] as icmp
        component [路由協議] as routing
    }

    package "鏈路層" {
        component [Ethernet] as eth
        component [WiFi] as wifi
        component [ARP] as arp
    }
}

http --> tcp
ws --> tcp
grpc --> tcp
tcp --> tls : 加密
tls --> ip
udp --> ip
ip --> routing
routing --> eth
routing --> wifi
eth --> arp

@enduml

圖表翻譯: 此圖示展示了客戶端如何透過 LoadBalancer 同時存取 CoreDNS 的 TCP 和 UDP 服務,最終將請求轉發到 CoreDNS Pod。

使用MetalLB實作多協定負載平衡

在Kubernetes叢集中,佈署服務時常常需要使用多種協定,例如TCP和UDP。然而,預設的LoadBalancer服務型別在多協定支援上存在限制。本章節將探討如何使用MetalLB來解決這一問題,並以CoreDNS為例,展示如何組態多協定的LoadBalancer服務。

MetalLB的多協定支援

MetalLB透過引入allow-shared-ip註解,支援為多個服務分配相同的IP地址,從而實作多協定的負載平衡。這一功能對於需要同時使用TCP和UDP協定的服務(如DNS服務)至關重要。

組態CoreDNS的多協定LoadBalancer服務

要為CoreDNS組態多協定的LoadBalancer服務,需要建立兩個獨立的服務:一個用於TCP協定,另一個用於UDP協定。並且,這兩個服務必須使用相同的allow-shared-ip註解值,以確保它們分享同一個IP地址。

步驟1:檢視kube-system名稱空間中的服務

首先,檢視kube-system名稱空間中的現有服務:

kubectl get svc -n kube-system

這將列出該名稱空間下的所有服務,包括預設的kube-dns服務。

步驟2:建立TCP和UDP服務的Manifest檔案

建立兩個Manifest檔案:coredns-tcp.yamlcoredns-udp.yaml,分別定義TCP和UDP協定的服務。

coredns-tcp.yaml
apiVersion: v1
kind: Service
metadata:
  name: coredns-tcp
  namespace: kube-system
  annotations:
    metallb.universe.tf/allow-shared-ip: "coredns-ext"
spec:
  selector:
    k8s-app: kube-dns
  ports:
  - name: dns-tcp
    port: 53
    protocol: TCP
    targetPort: 53
  type: LoadBalancer
coredns-udp.yaml
apiVersion: v1
kind: Service
metadata:
  name: coredns-udp
  namespace: kube-system
  annotations:
    metallb.universe.tf/allow-shared-ip: "coredns-ext"
spec:
  selector:
    k8s-app: kube-dns
  ports:
  - name: dns-udp
    port: 53
    protocol: UDP
    targetPort: 53
  type: LoadBalancer

#### 內容解密:

  • 這兩個Manifest檔案定義了兩個LoadBalancer型別的服務,分別用於TCP和UDP協定。
  • metadata.annotations中的metallb.universe.tf/allow-shared-ip註解確保了兩個服務分享同一個IP地址。
  • spec.selector欄位指定了服務選擇器,以選擇正確的Pod。
  • spec.ports欄位定義了服務的埠和協定。

步驟3:套用Manifest檔案

使用kubectl apply命令套用這兩個Manifest檔案:

kubectl apply -f coredns-tcp.yaml
kubectl apply -f coredns-udp.yaml

步驟4:驗證服務組態

套用Manifest檔案後,檢視kube-system名稱空間中的服務,以驗證兩個新服務是否已正確建立並分配了相同的IP地址:

kubectl get svc -n kube-system

這將顯示兩個新的服務:coredns-tcpcoredns-udp,並且它們應該具有相同的外部IP地址。

使用external-dns實作外部DNS解析

雖然MetalLB提供了負載平衡功能,但它並不提供DNS解析。要實作外部可存取的服務名稱,需要使用Kubernetes的external-dns專案。該專案支援多種DNS伺服器,包括Google Cloud DNS、Amazon Route 53、Azure DNS等。

external-dns的主要功能

  • 自動為LoadBalancer服務建立DNS記錄。
  • 支援多種DNS提供者。

透過結合MetalLB和external-dns,可以為Kubernetes叢集中的服務提供完整的負載平衡和DNS解析解決方案,從而提升叢集的可存取性和管理效率。