环境配置
- 3节点的K8S
- 1+2配置
[root@rocky9-1 dashboard]# kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
rocky9-1 Ready control-plane 2d21h v1.28.2 192.168.100.21 <none> Rocky Linux 9.2 (Blue Onyx) 5.14.0-284.30.1.el9_2.x86_64 containerd://1.6.24
rocky9-2 Ready <none> 2d21h v1.28.2 192.168.100.22 <none> Rocky Linux 9.2 (Blue Onyx) 5.14.0-284.30.1.el9_2.x86_64 containerd://1.6.24
rocky9-3 Ready <none> 2d21h v1.28.2 192.168.100.23 <none> Rocky Linux 9.2 (Blue Onyx) 5.14.0-284.30.1.el9_2.x86_64 containerd://1.6.24
[root@rocky9-1 dashboard]# kubectl cluster-info
Kubernetes control plane is running at https://192.168.100.21:6443
CoreDNS is running at https://192.168.100.21:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
网络设计
- 节点网络使用192.168.100.21-29网段
- VIP网络使用192.168.100.90-99网段
安装MetalLB
检查最新版本
[root@rocky9-1 dashboard]# MetalLB_RTAG=$(curl -s https://api.github.com/repos/metallb/metallb/releases/latest|grep tag_name|cut -d '"' -f 4|sed 's/v//')
[root@rocky9-1 dashboard]#
[root@rocky9-1 dashboard]# echo $MetalLB_RTAG
0.13.12
创建目录
mkdir ~/metallb
cd ~/metallb
现在最新版本
wget https://raw.githubusercontent.com/metallb/metallb/v$MetalLB_RTAG/config/manifests/metallb-native.yaml
- The metallb-system/controller deployment – Cluster-wide controller that handles IP address assignments.
- The metallb-system/speaker daemonset – Component that speaks the protocol(s) of your choice to make the services reachable. - 运行在每个节点上
- Service accounts for both controller and speaker, along with RBAC permissions that the needed by the components to function.
[root@rocky9-1 metallb]# kubectl apply -f metallb-native.yaml
namespace/metallb-system created
customresourcedefinition.apiextensions.k8s.io/addresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io created
customresourcedefinition.apiextensions.k8s.io/communities.metallb.io created
customresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io created
serviceaccount/controller created
serviceaccount/speaker created
role.rbac.authorization.k8s.io/controller created
role.rbac.authorization.k8s.io/pod-lister created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/controller created
rolebinding.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
configmap/metallb-excludel2 created
secret/webhook-server-cert created
service/webhook-service created
deployment.apps/controller created
daemonset.apps/speaker created
$ watch kubectl get all -n metallb-system
Every 2.0s: kubectl get all -n metallb-system Thu Jul 20 10:18:38 2023
NAME READY STATUS RESTARTS AGE
pod/controller-595f88d88f-6pk24 1/1 Running 0 47m
pod/speaker-2gthf 1/1 Running 0 47m
pod/speaker-4nxnf 1/1 Running 0 47m
pod/speaker-nqt7r 1/1 Running 0 47m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/webhook-service ClusterIP 10.96.235.219 <none> 443/TCP 47m
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/speaker 3 3 3 3 3 kubernetes.io/os=linux 47m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/controller 1/1 1 1 47m
NAME DESIRED CURRENT READY AGE
replicaset.apps/controller-595f88d88f 1 1 1 47m
[root@rocky9-1 metallb]# kubectl get pod -n metallb-system -w
NAME READY STATUS RESTARTS AGE
controller-786f9df989-fh679 1/1 Running 0 48s
speaker-24dcb 1/1 Running 0 48s
speaker-4v5ll 1/1 Running 0 48s
speaker-cvtlp 0/1 Running 0 48s
speaker-cvtlp 1/1 Running 0 56s
使用IPPool方式
编辑IP池配置文件
[root@rocky9-1 metallb]# cat ipaddress_pools.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: production
namespace: metallb-system
spec:
addresses:
- 192.168.100.90-192.168.100.99
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2-advert
namespace: metallb-system
The IPs that MetalLB uses to assign IPs to services. In the configuration the pool has IPs range 192.168.92.30-192.168.92.50.
The IP addresses can be defined by CIDR, by range, and both IPV4 and IPV6 addresses can be assigned.
- 192.168.1.30-192.168.1.50
- 192.168.1.0/24
- fc00:f853:0ccd:e799::/124
Announce service IPs after the creation. This is a sample configuration used to advertise all IP address pools created in the cluster.
Advertisement can also be limited to a specific Pool. In the example the limit is to the production pool.
[root@rocky9-1 metallb]# kubectl apply -f ipaddress_pools.yaml
ipaddresspool.metallb.io/production created
l2advertisement.metallb.io/l2-advert created
[root@rocky9-1 metallb]# kubectl get ipaddresspools.metallb.io -n metallb-system
NAME AUTO ASSIGN AVOID BUGGY IPS ADDRESSES
production true false ["192.168.100.90-192.168.100.99"]
[root@rocky9-1 metallb]# kubectl get l2advertisements.metallb.io -n metallb-system
NAME IPADDRESSPOOLS IPADDRESSPOOL SELECTORS INTERFACES
l2-advert
[root@rocky9-1 metallb]# kubectl describe ipaddresspools.metallb.io production -n metallb-system
Name: production
Namespace: metallb-system
Labels: <none>
Annotations: <none>
API Version: metallb.io/v1beta1
Kind: IPAddressPool
Metadata:
Creation Timestamp: 2023-11-12T13:43:43Z
Generation: 1
Resource Version: 379843
UID: 432e795d-612f-45f5-83d1-7c2c424093e1
Spec:
Addresses:
192.168.100.90-192.168.100.99
Auto Assign: true
Avoid Buggy I Ps: false
Events: <none>
[root@rocky9-1 metallb]# kubectl get pod -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
default mypod 1/1 Running 0 175m 10.244.1.2 rocky9-2 <none> <none>
kube-flannel kube-flannel-ds-5hhr7 1/1 Running 0 2d21h 192.168.100.22 rocky9-2 <none> <none>
kube-flannel kube-flannel-ds-jsw6l 1/1 Running 0 2d21h 192.168.100.23 rocky9-3 <none> <none>
kube-flannel kube-flannel-ds-qcjnx 1/1 Running 0 2d21h 192.168.100.21 rocky9-1 <none> <none>
kube-system coredns-5dd5756b68-bscgh 1/1 Running 0 2d22h 10.244.2.3 rocky9-3 <none> <none>
kube-system coredns-5dd5756b68-lgl54 1/1 Running 0 2d22h 10.244.2.2 rocky9-3 <none> <none>
kube-system etcd-rocky9-1 1/1 Running 1 2d22h 192.168.100.21 rocky9-1 <none> <none>
kube-system kube-apiserver-rocky9-1 1/1 Running 1 2d22h 192.168.100.21 rocky9-1 <none> <none>
kube-system kube-controller-manager-rocky9-1 1/1 Running 1 2d22h 192.168.100.21 rocky9-1 <none> <none>
kube-system kube-proxy-7sc8l 1/1 Running 0 2d21h 192.168.100.23 rocky9-3 <none> <none>
kube-system kube-proxy-jfb45 1/1 Running 0 2d22h 192.168.100.22 rocky9-2 <none> <none>
kube-system kube-proxy-t49dk 1/1 Running 0 2d22h 192.168.100.21 rocky9-1 <none> <none>
kube-system kube-scheduler-rocky9-1 1/1 Running 1 2d22h 192.168.100.21 rocky9-1 <none> <none>
kubernetes-dashboard dashboard-metrics-scraper-5657497c4c-gzf89 1/1 Running 0 121m 10.244.2.4 rocky9-3 <none> <none>
kubernetes-dashboard kubernetes-dashboard-78f87ddfc-nd5tb 1/1 Running 0 121m 10.244.1.4 rocky9-2 <none> <none>
metallb-system controller-786f9df989-fh679 1/1 Running 0 4m34s 10.244.1.5 rocky9-2 <none> <none>
metallb-system speaker-24dcb 1/1 Running 0 4m34s 192.168.100.23 rocky9-3 <none> <none>
metallb-system speaker-4v5ll 1/1 Running 0 4m34s 192.168.100.22 rocky9-2 <none> <none>
metallb-system speaker-cvtlp 1/1 Running 0 4m34s 192.168.100.21 rocky9-1 <none> <none>
方式#1 配置测试Pod - 不指定IP
apiVersion: v1
kind: Namespace
metadata:
name: web
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
namespace: web
spec:
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: httpd
image: httpd:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web-server-service
namespace: web
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
创建Pod
[root@rocky9-1 metallb]# kubectl apply -f web-app-demo.yaml
namespace/web created
deployment.apps/web-server created
service/web-server-service created
检查SVC
[root@rocky9-1 metallb]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d22h
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 2d22h
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.96.229.191 <none> 8000/TCP 122m
kubernetes-dashboard kubernetes-dashboard ClusterIP 10.100.187.236 <none> 443/TCP 122m
metallb-system webhook-service ClusterIP 10.103.240.127 <none> 443/TCP 5m44s
web web-server-service LoadBalancer 10.107.126.246 192.168.100.90 80:32181/TCP 9s
验证
➜ ~ curl http://192.168.100.90
<html><body><h1>It works!</h1></body></html>
方式#2 配置测试Pod - 指定IP
$ vim web-app-demo.yaml
apiVersion: v1
kind: Namespace
metadata:
name: web
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
namespace: web
spec:
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: httpd
image: httpd:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web-server-service
namespace: web
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
loadBalancerIP: 192.168.91.35 # <-------------
高级用法
指定IP池地址
- When creating a service of type LoadBalancer, you can request a specific address pool. This is a feature supported by MetalLB out of the box.
- A specific pool can be requested for IP address assignment by adding the metallb.universe.tf/address-pool annotation to your service, with the name of the address pool as the annotation value.
apiVersion: v1
kind: Service
metadata:
name: web-server-service
namespace: web
annotations:
metallb.universe.tf/address-pool: production ###<-----
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
控制IP地址分配
- 例如公网IP数量有限,因此不希望自动分配
- This is a reasonable application for smaller pools of “expensive” IPs (e.g. leased public IPv4 addresses). By default, MetalLB allocates free IP addresses from any configured address pool.
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: expensive
namespace: metallb-system
spec:
addresses:
- 42.175.26.64/30
autoAssign: false
IP Address Sharing
-
In Kubernetes services don’t share IP addresses by default. For any need to colocate services on a single IP, add the metallb.universe.tf/allow-shared-ip annotation to enable selective IP sharing for your services.
-
The value of this annotation is a “sharing key“. For the Services to share an IP address the following conditions has to be met:
- Both services should share the same sharing key.
- Services should use different ports (e.g. tcp/80 for one and tcp/443 for the other).
- The two services should use the Cluster external traffic policy, or they both point to the exact same set of pods (i.e. the pod selectors are identical).
-
By using spec.loadBalancerIP, it means the two services share a specific address. See below example configuration of two services that share the same ip address:
apiVersion: v1
kind: Service
metadata:
name: dns-service-tcp
namespace: demo
annotations:
metallb.universe.tf/allow-shared-ip: "key-to-share-192.168.1.36" # 相同的KEY
spec:
type: LoadBalancer
loadBalancerIP: 192.168.1.36
ports:
- name: dnstcp
protocol: TCP
port: 53
targetPort: 53
selector:
app: dns
---
apiVersion: v1
kind: Service
metadata:
name: dns-service-udp
namespace: demo
annotations:
metallb.universe.tf/allow-shared-ip: "key-to-share-192.168.1.36" # 相同的KEY
spec:
type: LoadBalancer
loadBalancerIP: 192.168.1.36
ports:
- name: dnsudp
protocol: UDP
port: 53
targetPort: 53
selector:
app: dns
Setting Nginx Ingress to use MetalLB
- If you’re using Nginx Ingress Controller in your cluster, you can configure it to use MetalLB as its Load Balancer. Refer to the following guide for steps on the configurations.
- https://computingforgeeks.com/deploy-nginx-ingress-controller-on-kubernetes-using-helm-chart/?expand_article=1
参考文档
https://metallb.universe.tf/installation/
https://computingforgeeks.com/deploy-metallb-load-balancer-on-kubernetes/?expand_article=1
https://computingforgeeks.com/best-kubernetes-study-books/?expand_article=1
https://metallb.universe.tf/installation/
https://logz.io/blog/best-open-source-load-balancers/