昨天文章中,我們提到想要讓同一個叢集能夠支援兩個同樣的 TCP/UDP 曝露給外部存取,雖然能夠利用 Service LoadBalancer 或 NodePort 類型來達到需求,但是這兩者依然存在著限制,比如說 NodePort 使用叢集節點 IP:Port 方式來提供存取,這存在著單點故障問題,且建立一個 Port 就會在所有節點綁定;而 LoadBalancer 則不支援地端分配負載平衡 IP 的機制,只能透過手動在externalIPs
欄位指定,若沒指定的話,其功能只是繼承 NodePort 機制,多了個 Target Port 能夠直接存取而已,而且儘管能夠在externalIPs
指定 IP,但這些 IP 又該從哪邊來呢?又怎麼分配呢?那該怎麼解決呢?
很慶幸的是國外有人開發了一個開源專案 MetalLB 來幫助我們解決這些問題,而今天就是要來探討這個專案如何使用。
本部分將說明如何部署與使用 MetalLB,並用於後續架構分使用。
部署沿用之前文章建置的 HA 環境進行測試,全部都採用裸機部署,作業系統為Ubuntu 18.04+
:
IP Address | Hostname | CPU | Memory | Role |
---|---|---|---|---|
172.22.132.11 | k8s-m1 | 4 | 16G | Master |
172.22.132.12 | k8s-m2 | 4 | 16G | Master |
172.22.132.13 | k8s-m3 | 4 | 16G | Master |
172.22.132.21 | k8s-n1 | 4 | 16G | Node |
172.22.132.22 | k8s-n2 | 4 | 16G | Node |
172.22.132.31 | k8s-g1 | 4 | 16G | Node |
172.22.132.32 | k8s-g2 | 4 | 16G | Node |
另外所有 Master 節點將透過 Keepalived 提供一個 Virtual IP
172.22.132.10
作為使用。
在開始部署時,請確保滿足以下條件:
172.22.132.150-172.22.132.200
。MetalLB 提供了以容器方式部署到 Kubernetes,且官方也有提供 YAML 讓我們執行:
$ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.1/manifests/metallb.yaml
namespace/metallb-system created
podsecuritypolicy.policy/speaker created
serviceaccount/controller created
serviceaccount/speaker created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
role.rbac.authorization.k8s.io/config-watcher created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/config-watcher created
daemonset.apps/speaker created
deployment.apps/controller created
使用 Helm 也能參考這邊 Installation With Helm 安裝
只要執行上面指令後,即可完成部署。這時可以透過 kubectl 來查看metallb-system
的 Namespace:
$ kubectl -n metallb-system get po
NAME READY STATUS RESTARTS AGE
controller-6bcfdfd677-q9fzp 1/1 Running 0 5m
speaker-8648w 1/1 Running 0 5m
speaker-8h4gs 1/1 Running 0 5m
speaker-f9zh4 1/1 Running 0 5m
speaker-dc134 1/1 Running 0 5m
speaker-xnkt5 1/1 Running 0 5m
speaker-zczp5 1/1 Running 0 5m
speaker-zzn5v 1/1 Running 0 5m
若這邊沒問題,就表示已經完成 MetalLB 安裝。接著需要新增 IP Pools 設定,以讓 MetalLB 能夠自動分配 IP 給 Service 的 LoadBalancer 類型使用,下面為一個 L2 的範例:
$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
auto-assign: true
addresses:
- 172.22.132.150-172.22.132.200
# - name: production
# auto-assign: false
# avoid-buggy-ips: true
# addresses:
# - 172.22.131.0/24
EOF
- 這邊也可以用 CIDR 來表示。更多的設定可以參考 MetalLB Configuration
- 另外由於測試環境限制,僅以 L2 範例為主。
當安裝與設定完成後,即可新增一個 Service 來驗證功能:
$ kubectl run nginx --image nginx --port 80
deployment.apps/nginx created
$ kubectl expose deploy nginx --port 8080 --target-port 80 --type LoadBalancer
service/nginx exposed
建立好後,透過 kubectl 來查看 Service:
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 10.111.63.50 172.22.132.153 8080:31827/TCP 59s
這時會看到,MetalLB 在 Service 為 LoadBalancer 時,會自動從前面設定的default
Pool 中,分配一個 IP 給 Service 使用。當有 IP 時,可以嘗試利用 cURL 來存取看看:
$ curl 172.22.132.153:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...
接著若再新建一個不同 Port 的 Service 會怎樣呢?
$ kubectl expose deploy nginx --name nginx-80 --port 80 --target-port 80 --type LoadBalancer
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 10.111.63.50 172.22.132.153 8080:31827/TCP 5m16s
nginx-80 LoadBalancer 10.97.188.162 172.22.132.154 80:30218/TCP 4s
大家會發現 MetalLB 又分配了另一個 IP 來使用,這時肯定會覺得這樣是不是每個 IP 只能使用一個 Port,事實上 MetalLB 能夠在 Service 的 Annotation 中,新增metallb.universe.tf/allow-shared-ip
欄位來達到 IP Sharing 功能,這邊可以參考 IP Address Sharing。
今天利用 MetalLB 達成了裸機負載平衡功能,而明天我將針對該專案進行原理分析。
最近都沒啥時間好好寫,所以一些缺少內容後續會再慢慢補齊。只能說一天寫一篇真的不簡單...