在 kind(本地docker模拟k8s集群) 部署MetalLB¶
在 kind Ingress 采用 Kubernetes Ingress控制器Nginx 实现服务对外输出后,如果要像云计算厂商一样提供完整可控的服务,还需要部署 Kubernetes MetalLB 负载均衡 来为 裸金属(bare-metal) NGINX Ingress 提供类似云厂商的 LoadBalancer
。Kind通过安装标准的 Kubernetes MetalLB 负载均衡 就能具备完整的服务输出能力。
安装¶
安装MetalLB 有多种方法,比较简单的是采用 kubectl apply
通过Manifest方式安装:
通过编辑当前集群的
kube-proxy
配置实现:
kubectl edit configmap -n kube-system kube-proxy
设置:
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
strictARP: true
执行以下
manifest
完成MetalLB安装:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml
执行以下命令等待 MetalLB pods (controller 和 speakers)就绪:
kubectl wait --namespace metallb-system \
--for=condition=ready pod \
--selector=app=metallb \
--timeout=90s
一切正常的话会看到以下输出:
pod/controller-84d6d4db45-xtgmj condition met
pod/speaker-2cpfg condition met
pod/speaker-2ffjg condition met
pod/speaker-8t8tj condition met
pod/speaker-9c727 condition met
pod/speaker-l942f condition met
pod/speaker-tmxt8 condition met
pod/speaker-wjxhh condition met
pod/speaker-x4fv4 condition met
配置¶
首先检查
kind
(bridge)网络 docker 分配的IP地址段:
docker network inspect -f '{{.IPAM.Config}}' kind
可能类似以下输出信息(我的kind网络):
[{172.22.0.0/16 172.22.0.1 map[]}]
可以看到我部署的 kind
集群分配的节点网络IP地址(可路由访问外网的IP地址,也就是每个node节点分配的IP地址) 是 172.22.0.0/16
需要 挖 一部分地址保留给 MetalLB 来分配作为负载均衡对外VIP的地址,所以配置
metallb-config.yaml
如下:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: dev-ip-pool
namespace: metallb-system
spec:
addresses:
- 172.22.255.200-172.22.255.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: dev-ip-pool
namespace: metallb-system
spec:
ipAddressPools:
- dev-ip-pool
备注
这里同时定义了 dev-ip-pool
地址池( kind: IPAddressPool
),并且声明了ARP公告( kind: L2Advertisement
) 这样外部才能访问到
奇怪,我这里在 ARP公告( kind: L2Advertisement
) 没有像 在Cilium网络部署MetalLB 那样设置spec,似乎也能访问
应用地址:
kubectl apply -f metallb-config.yaml
提示信息:
ipaddresspool.metallb.io/dev-pool created
l2advertisement.metallb.io/dev created
应用LoadBalancer¶
之前 kind部署 fedora-dev-tini (tini替代systmed) 使用的
fedora-dev-tini-deployment.yaml
部署pods 和 service,当时service
没有配置LoadBalancer
类型,则默认是ClusterIP
:
% kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
fedora-dev-service ClusterIP 10.96.175.32 <none> 22/TCP,80/TCP,443/TCP 47h
之前 kind部署 fedora-dev-tini (tini替代systmed) 使用的
fedora-dev-tini-deployment.yaml
修订将服务类型修改成LoadBalancer
:
---
apiVersion: v1
kind: Service
metadata:
name: fedora-dev-service
labels:
app: fedora-dev-tini
spec:
type: LoadBalancer
ports:
- name: ssh
protocol: TCP
port: 22
targetPort: 22
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
selector:
app: fedora-dev-tini
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: fedora-dev-tini
spec:
replicas: 1
selector:
matchLabels:
app: fedora-dev-tini
template:
metadata:
labels:
app: fedora-dev-tini
spec:
containers:
- name: fedora-dev-tini
image: localhost:5001/fedora-dev-tini:latest
ports:
- containerPort: 22
name: ssh
protocol: TCP
执行修订:
kubectl apply -f fedora-dev-tini-deployment.yaml
检查服务,可以看到 fedora-dev-service
类型已经从 ClusterIP
改为 LoadBalancer
,并且分配了一个外部可访问IP 172.22.255.201
,这个地址就是Kubernetes集群外面的用户可以访问的服务IP地址(而不是之前只能在Kubernetes集群内部访问的IP地址 10.96.175.32
)
% kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
fedora-dev-service LoadBalancer 10.96.175.32 172.22.255.201 22:32440/TCP,80:31218/TCP,443:32049/TCP 4d1h
备注
这里 Ports
显示是 22:32440/TCP,80:31218/TCP,443:32049/TCP
表示什么意思?
不过,我确实从 kind集群本地Registry 部署的 registry
容器(这个容器比较特殊,配置了 kind
网络,也配置了docker默认 bridge
网络,是一个跨网络pod,所以可以作为桥接测试)能够直接 ssh 172.22.255.201
登陆到容器 fedora-dev-tini
了,证明负载均衡转发是成功的
接下来是如何结合 Kubernetes Ingress控制器Nginx 来构建完成的网络流量链路了(HTTP/HTTPS)
此外,还需要解决 Docker Desktop for mac 端口转发(port forwarding) 以便能够从外部访问Docker VM内部构建的 kind(本地docker模拟k8s集群) 集群输出的 LoadBalancer ( MetalLB ) 的IP对应服务(折腾^_^)