Load Balance

Kubernetes MetalLB Load Balancer 設定多個 address pool

Before Start

首先你先要安裝好:

  • Kubernetes 1.9 版以上,以及可以使用 kubeadmkubectlkubelet 指令
  • MetalLB Layer2 Load Balancer

由於我們會使用 bgp 的 protocol,可以直接在 minikube 上使用,如果你是在 bare metal 上操作的話,必須做額外的設定,可以參考官方文件

Configure Load Balancer

MetalLB 設定 Load Balancer 需要提供 ConfigMap 裡面包涵我們給定的網段範圍

會需要分別使用不同的 address pool 是有原因的,有申請過網路的都知道,固定 IP 是很貴的,而且數量有限,只會在有需要的時候才會使用公開固定 IP 網域池,像是產品 production 的網頁。

至於其他還在測試 staging 的網頁,使用私人網域池即可,最後在設定個 VPN 連線進來看,就能夠減少申請固定 IP 的費用。

這裡我們建立了兩個網域池,相關的設定如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: production
protocol: bgp
auto-assign: false
addresses:
- 17.95.16.28-17.95.16.32
- name: staging
protocol: bgp
avoid-buggy-ips: true
addresses:
- 192.168.144.0/20
address pool 1 address pool 2
名稱 production staging
協定 bgp bgp
網段 17.95.16.28-17.95.16.32 192.168.144.0/20

這裡假設我們申請到這個範圍的固定 IP 17.95.16.28-17.95.16.32,可以供 Load Balancer 來分配。

至於設定 avoid-buggy-ips: true 參數的話, MetalLB 避免 .0.255 的 IP。

如果想要手動指派 IP 的話,可以設定成 auto-assign: false,不設定的話預設是 true

寫好設定檔,我們就立即套用它:

1
kubectl apply -f configmap.yaml

測試

現在我們來測試剛剛設定的 Load Balancer 有沒有成功。

我會執行兩份 deployment,一個會使用 production 的網域池,另一個會使用 staging 的網域池,兩個設定檔分別是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# hello-production.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-production
labels:
run: hello-production
spec:
replicas: 3
selector:
matchLabels:
run: hello-production
template:
metadata:
labels:
run: hello-production
spec:
containers:
- name: hello-production
image: k8s.gcr.io/echoserver:1.10
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: hello-production
annotations:
metallb.universe.tf/address-pool: production
spec:
ports:
- port: 8080
targetPort: 8080
selector:
run: hello-production
type: LoadBalancer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# hello-staging.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-staging
labels:
run: hello-staging
spec:
replicas: 3
selector:
matchLabels:
run: hello-staging
template:
metadata:
labels:
run: hello-staging
spec:
containers:
- name: hello-staging
image: k8s.gcr.io/echoserver:1.10
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: hello-staging
annotations:
metallb.universe.tf/address-pool: staging
spec:
ports:
- port: 8080
targetPort: 8080
selector:
run: hello-staging
type: LoadBalancer

這裡需要在 metadata.annotations 裡面設定 metallb.universe.tf/address-pool: staging 參數,後面接值必須跟前面 ConfigMap 裡 address pool 的名稱一樣。

1
2
3
metadata:
annotations:
metallb.universe.tf/address-pool: staging

然後套用設定:

1
kubectl apply -f hello-production.yaml,hello-staging.yaml

查看我們現在正在運行的容器與網路設定:

1
2
3
4
5
6
7
8
9
10
11
12
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-production-b58c4488d-fxj7d 1/1 Running 0 19m
hello-production-b58c4488d-kx2nh 1/1 Running 0 19m
hello-production-b58c4488d-tp8f6 1/1 Running 0 19m
hello-staging-c8fc9f69d-4gmfr 1/1 Running 0 19m
hello-staging-c8fc9f69d-rhh7q 1/1 Running 0 19m
hello-staging-c8fc9f69d-vdwt2 1/1 Running 0 19m
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-production LoadBalancer 10.109.99.105 17.95.16.28 8080:31532/TCP 19m
hello-staging LoadBalancer 10.110.199.100 192.168.144.1 8080:32603/TCP 19m

有被分配到外部固定 IP 的 service,就能夠使用透過外面的網路連進來,可以馬上找其他電腦來試試。

Reference

MetalLB 在 Kubernetes Bare Metal 上安裝 Layer 2 Load Balancer

準備

假設你已經先裝好 Kubernetes cluster 了,由於是 bare metal,你必須把 Kubernetes 裝載三台不同電腦上,或是使用三個 Raspberry Pi,然後使用 kubeadm 指令串起來。

Cluster Addresses

我們現在有三台電腦,它的名稱與 IP 分別是:

  • Master192.168.1.100

  • Node1192.168.1.101

  • Node2192.168.1.102

    當你在安裝電腦時,名稱與 IP 必須是唯一的,否則在 join 的時候會出現錯誤。

這裡使用的 IP 是 DHCP 所分配的 IP,IP 的範圍是 192.168.1.100—192.168.1.150,如果你有足夠的 public IP address,可以分別對每台電腦做設定。

假設我申請了 17.95.16.0-17.95.16.32,就可以把 IP 設定成這樣:

  • Master17.95.16.1
  • Node117.95.16.2
  • Node217.95.16.3

雖然只用了三個,但我們保留剩下的 17.95.16.10-17.95.16.32 讓 Load Balancer 來分配這些網址

Metallb

安裝 metallb 的步驟非常的簡單:

1
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml

然後查看目前的狀態,是否有一個 controller 跟多個 speaker:

1
2
3
4
5
$ kubectl get pods -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-cd8657667-2znm8 1/1 Running 0 22h
speaker-m95vd 1/1 Running 0 22h
speaker-shq8s 1/1 Running 0 22h

因為我們還沒有提供 load balance 的網址給他,所以接下來要設定 ConfigMap

Configure

架設我們想提供 load balance 的網址是 192.168.1.240-192.168.1.250,看一下我們的設定檔:

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: my-ip-space
protocol: layer2
addresses:
- 192.168.1.240-192.168.1.250

我們把 protocol: layer2 套用在 192.168.1.240-192.168.1.250 這個網段上

如果想要使用外網的話,直接把網段的範圍改成外網即可

MetalLB 提供了 layer2bgp 兩種 protocol,這裡使用 layer2,如果使用 bgp 的話還需要另外做設定,可以參考官方文件

套用上面的 ConfigMap:

1
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/example-layer2-config.yaml

查看 Log:

1
kubectl logs -l component=speaker -n metallb-system

測試

執行一些簡單的容器,然後使用 LoadBalancer 暴露它:

1
2
kubectl run hello-world --image=k8s.gcr.io/echoserver:1.10 --port=8080 --replicas=3
kubectl expose deployment hello-world --type=LoadBalancer

查看 pods 是否有在運行

1
2
3
4
5
6
7
8
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pod/hello-world-6cdb64fdcd-7bfgq 1/1 Running 0 17s
pod/hello-world-6cdb64fdcd-82mtv 1/1 Running 0 17s
pod/hello-world-6cdb64fdcd-rhxp2 1/1 Running 0 17s
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world LoadBalancer 10.106.40.173 192.168.1.240 8080:30700/TCP 11s

我們現在有外部 IP 了!馬上測試看看能不能連得到:

1
2
3
$ curl 192.168.1.240:8080
Hostname: hello-world-1-6cdb64fdcd-7bfgq
...

如果有看到跟請求 http 有關的資訊的話,就代表你成功了。

Reference

在 Kubernetes Minikube 上安裝 Load Balancer MetalLB

MetalLB

MetalLB 是 Bare metal Kubernetes 的 load balancer,如果原先你使用 --type=LoadBalancer 來暴露你的 port 的話,service 裡的 EXTERNAL-IP 會一直是 pending 的狀態:

1
2
3
4
$ kubectl expose deployment hello-world --type=LoadBalancer
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world LoadBalancer 10.102.80.194 <pending> 3000:31118/TCP 17m

要解決這個方法其實有很多種,你可以使用現有的雲端平台,像是 GCP、AWS 等等,這些雲端平台上都有提供 Load Balancer 的服務,當然你需要付些費用,如果要免費的話,可以自己安裝 OpenStack。

但是我們只需要 Kubernetes 的功能,卻要把整個 OpenStack 安裝好,然後只用其中的 Load Balancer 的話,這個作法實在有點殺雞焉用牛刀。

如同 GitHub 上這篇 issue 所說的,為何不單把 Load Balancer 的服務抽出來安裝就好呢,於是 MetalLB 就這樣誕生了

Installation

首先你必須先安裝好 minikube,minikube 的安裝就自行 google 了,而且還需要對 Kubernetes 的指令有一些基礎。

BGP Router UI

查看 BGP router 狀態,你可以使用網頁查看 BGP router 目前的狀態

1
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/test-bgp-router.yaml

使用 minikube 開啟網頁:

1
minikube service -n metallb-system test-bgp-router-ui

MetalLB

安裝最重要的 Metallb,他會在 metallb-system namespace 底下產生 daemonset speaker 跟 deployment controller

1
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml

這時候重新刷新 BGP Router UI 的話,裡面的內容會跟安裝前的不一樣。

ConfigMap

MetalLB 的設定檔是透過 Kubernetes 裡面的 config map 下去做設定的,你必須跟他講他能夠分配的 IP 池,跟一些相關設定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- my-asn: 64500
peer-asn: 64500
peer-address: 10.96.0.100
- my-asn: 64500
peer-asn: 64500
peer-address: 10.96.0.101
address-pools:
- name: my-ip-space
protocol: bgp
avoid-buggy-ips: true
addresses:
- 198.51.100.0/24

看到後面倒數幾行

  • avoid-buggy-ips: true:代表 Load Balancer 在分配 IP 的時候,會從 .1 開始分配,而不會從 .0 開始
  • 198.51.100.0/24:Load Balancer 能分配的 IP 池

然後我們就套用這些設定吧:

1
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/tutorial-3.yaml

檢查

來跑一些簡單的容器,然後使用 LoadBalancer 暴露它:

1
2
kubectl run hello-world --image=k8s.gcr.io/echoserver:1.10 --port=8080
kubectl expose deployment hello-world --type=LoadBalancer

使用 kubectl get service 指令查看現在 service 的狀態,可能需要等個幾秒鐘,EXTERNAL-IP 這個欄位就會是 MetalLB 從 IP 池分配給我們的 IP:

1
2
3
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world LoadBalancer 10.103.246.36 198.51.100.1 8080:31504/TCP 11s

沒有看到 pending 的話,就代表你成功了。

Reference