19 K3s 上的 MetalLB(使用 L2) #
MetalLB 是使用标准路由协议的裸机 Kubernetes 群集的负载平衡器实现。
本指南演示如何以第 2 层模式部署 MetalLB。
19.1 为何使用此方法 #
在第 2 层模式下,一个节点负责向本地网络播发服务。从网络的角度看,似乎为该计算机的网络接口分配了多个 IP 地址。
第 2 层模式的主要优势在于其通用性:它可以在任何以太网上正常工作,不需要任何特殊硬件,甚至不需要各种形式的路由器。
19.2 K3s 上的 MetalLB(使用 L2) #
本快速入门将使用 L2 模式,这意味着我们不需要任何特殊网络设备,而只需设置网络范围内的几个可用 IP(最好是 DHCP 池以外的 IP,因为这些 IP 尚未分配)。
在此示例中,192.168.122.0/24
网络的 DHCP 池为
192.168.122.100-192.168.122.200
(是的,有三个 IP,有关出现额外 IP
的原因,请参见“Traefik 和 MetalLB”一节(第 19.3.3 节 “Traefik 和 MetalLB”)),因此可以使用此范围以外的任何 IP(对于网关和其他可能已运行的主机也是如此!)
19.3 先决条件 #
要在其中部署 MetalLB 的 K3s 群集。
K3S 附带自身的服务负载平衡器(名为 Klipper)。需要禁用 Klipper 才能运行
MetalLB。要禁用 Klipper,需使用 ‑‑disable=servicelb
标志安装
K3s。
Helm
我们的网络范围内有少量多个可用 IP,在本例中为
192.168.122.10-192.168.122.12
19.3.1 部署 #
MetalLB 利用 Helm(及其他方法),因此请运行:
helm repo add metallb https://metallb.github.io/metallb
helm install --create-namespace -n metallb-system metallb metallb/metallb
while ! kubectl wait --for condition=ready -n metallb-system $(kubectl get\
pods -n metallb-system -l app.kubernetes.io/component=controller -o name)\
--timeout=10s; do
sleep 2
done
19.3.2 配置 #
安装现已完成。接下来请使用示例值进行配置:
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ip-pool
namespace: metallb-system
spec:
addresses:
- 192.168.122.10/32
- 192.168.122.11/32
- 192.168.122.12/32
EOF
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-pool-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- ip-pool
EOF
现在,MetalLB 可供您使用。可以自定义 L2 模式的许多设置,例如:
还可以对 BGP 进行其他许多自定义设置。
19.3.3 Traefik 和 MetalLB #
默认情况下,Traefik 会随 K3s 一起部署(可以使用 --disable=traefik
禁用
Traefik),并作为 LoadBalancer
公开(与 Klipper 一起使用)。但是,由于需要禁用
Klipper,用于入口的 Traefik 服务仍是 LoadBalancer
类型。因此在部署 MetalLB
的那一刻,第一个 IP 将自动分配给 Traefik 入口。
# Before deploying MetalLB kubectl get svc -n kube-system traefik NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE traefik LoadBalancer 10.43.44.113 <pending> 80:31093/TCP,443:32095/TCP 28s # After deploying MetalLB kubectl get svc -n kube-system traefik NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE traefik LoadBalancer 10.43.44.113 192.168.122.10 80:31093/TCP,443:32095/TCP 3m10s
我们将在稍后的过程(第 19.4 节 “MetalLB 的入口”)中应用此操作。
19.3.4 用法 #
我们来创建示例部署:
cat <<- EOF | kubectl apply -f -
---
apiVersion: v1
kind: Namespace
metadata:
name: hello-kubernetes
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: hello-kubernetes
namespace: hello-kubernetes
labels:
app.kubernetes.io/name: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes
namespace: hello-kubernetes
labels:
app.kubernetes.io/name: hello-kubernetes
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: hello-kubernetes
template:
metadata:
labels:
app.kubernetes.io/name: hello-kubernetes
spec:
serviceAccountName: hello-kubernetes
containers:
- name: hello-kubernetes
image: "paulbouwer/hello-kubernetes:1.10"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
env:
- name: HANDLER_PATH_PREFIX
value: ""
- name: RENDER_PATH_PREFIX
value: ""
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: KUBERNETES_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: CONTAINER_IMAGE
value: "paulbouwer/hello-kubernetes:1.10"
EOF
最后创建服务:
cat <<- EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: hello-kubernetes
namespace: hello-kubernetes
labels:
app.kubernetes.io/name: hello-kubernetes
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: hello-kubernetes
EOF
我们来看看此示例的实际效果:
kubectl get svc -n hello-kubernetes NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-kubernetes LoadBalancer 10.43.127.75 192.168.122.11 80:31461/TCP 8s curl http://192.168.122.11 <!DOCTYPE html> <html> <head> <title>Hello Kubernetes!</title> <link rel="stylesheet" type="text/css" href="/css/main.css"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" > </head> <body> <div class="main"> <img src="/images/kubernetes.png"/> <div class="content"> <div id="message"> Hello world! </div> <div id="info"> <table> <tr> <th>namespace:</th> <td>hello-kubernetes</td> </tr> <tr> <th>pod:</th> <td>hello-kubernetes-7c8575c848-2c6ps</td> </tr> <tr> <th>node:</th> <td>allinone (Linux 5.14.21-150400.24.46-default)</td> </tr> </table> </div> <div id="footer"> paulbouwer/hello-kubernetes:1.10 (linux/amd64) </div> </div> </div> </body> </html>
19.4 MetalLB 的入口 #
由于 Traefik 已用作入口控制器,我们可以通过 Ingress
对象公开任何 HTTP / HTTPS
流量,例如:
IP=$(kubectl get svc -n kube-system traefik -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
cat <<- EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-kubernetes-ingress
namespace: hello-kubernetes
spec:
rules:
- host: hellok3s.${IP}.sslip.io
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: hello-kubernetes
port:
name: http
EOF
然后运行:
curl http://hellok3s.${IP}.sslip.io <!DOCTYPE html> <html> <head> <title>Hello Kubernetes!</title> <link rel="stylesheet" type="text/css" href="/css/main.css"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" > </head> <body> <div class="main"> <img src="/images/kubernetes.png"/> <div class="content"> <div id="message"> Hello world! </div> <div id="info"> <table> <tr> <th>namespace:</th> <td>hello-kubernetes</td> </tr> <tr> <th>pod:</th> <td>hello-kubernetes-7c8575c848-fvqm2</td> </tr> <tr> <th>node:</th> <td>allinone (Linux 5.14.21-150400.24.46-default)</td> </tr> </table> </div> <div id="footer"> paulbouwer/hello-kubernetes:1.10 (linux/amd64) </div> </div> </div> </body> </html>
另外,要校验 MetalLB 是否正常工作,可如下所示使用 arping
:
arping hellok3s.${IP}.sslip.io
预期结果:
ARPING 192.168.64.210 60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=0 time=1.169 msec 60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=1 time=2.992 msec 60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=2 time=2.884 msec
在以上示例中,流量的流动方式如下:
hellok3s.${IP}.sslip.io
解析为实际 IP。然后,流量由
metallb-speaker
Pod 处理。metallb-speaker
将流量重定向到traefik
控制器。最后,Traefik 将请求转发到
hello-kubernetes
服务。