Skip to content

K8S本地负载均衡

前置

如果在 IPVS 模式下使用 kube-proxy, 从 Kubernetes v1.14.2 开始,必须启用严格的 ARP 模式。

如果使用 kube-router 作为 service-proxy,则不需要它,因为它默认启用严格的 ARP。

查看kube-proxy中的strictARP配置

bash
kubectl get configmap -n kube-system kube-proxy -o yaml | grep strictARP

通过在当前集群中编辑 kube-proxy 配置来实现这一点:

bash
kubectl edit configmap -n kube-system kube-proxy
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true

重启kube-proxy

bash
kubectl rollout restart daemonset kube-proxy -n kube-system

负载均衡表

ipvsadm -l

ipvsadm -l 命令用于在 Linux 系统中列出当前的 IP 虚拟服务器(IPVS)的转发表(也称为负载均衡表)

Metallb

https://metallb.io/

部署metallb

使用资源清单部署

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml

此操作会将 MetalLB 部署到您的集群中,在 metallb-system 命名空间。清单中的组件包括:

bash
Deployment: metallb-system/controller这是集群范围的 处理 IP 地址分配的控制器
DaemonSet:metallb-system/speaker 根据选择的协议进行服务到达
controller和speaker的服务帐户,以及 组件运行所需的 RBAC 权限

创建IP地址池

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.240-192.168.1.250

addresses支持样例:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.10.0/24
  - 192.168.9.1-192.168.9.5
  - fc00:f853:0ccd:e799::/124

查看

bash
kubectl get ipaddresspool -n metallb-system

Layer2模式-开启2层通告

Layer2模式的配置最简单:在许多情况下,您不需要 需要任何协议特定的配置,只需要 IP 地址

Layer2模式不需要将 IP 绑定到网络接口 的 Worker 节点。它的工作原理是响应本地的 ARP 请求 network 的 MAC 地址,将机器的 MAC 地址提供给客户端

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: example
  namespace: metallb-system

查看

kubectl get l2advertisement -n metallb-system

Ingress-Nginx安装

Ingress-Nginx支持的k8s版本对应关系

支持Ingress-Nginx 版本K8s 支持的版本Alpine 版本Nginx 版本Helm Chart 版本
🔄v1.11.21.30, 1.29, 1.28, 1.27, 1.263.20.01.25.54.11.2
🔄v1.11.11.30, 1.29, 1.28, 1.27, 1.263.20.01.25.54.11.1
🔄v1.11.01.30, 1.29, 1.28, 1.27, 1.263.20.01.25.54.11.0
🔄v1.10.41.30, 1.29, 1.28, 1.27, 1.263.20.01.25.54.10.4
🔄v1.10.31.30, 1.29, 1.28, 1.27, 1.263.20.01.25.54.10.3
🔄v1.10.21.30, 1.29, 1.28, 1.27, 1.263.20.01.25.54.10.2
🔄v1.10.11.30, 1.29, 1.28, 1.27, 1.263.19.11.25.34.10.1
🔄v1.10.01.29, 1.28, 1.27, 1.263.19.11.25.34.10.0
v1.9.61.29, 1.28, 1.27, 1.26, 1.253.19.01.21.64.9.1
v1.9.51.28, 1.27, 1.26, 1.253.18.41.21.64.9.0
v1.9.41.28, 1.27, 1.26, 1.253.18.41.21.64.8.3
v1.9.31.28, 1.27, 1.26, 1.253.18.41.21.64.8.*
v1.9.11.28, 1.27, 1.26, 1.253.18.41.21.64.8.*
v1.9.01.28, 1.27, 1.26, 1.253.18.21.21.64.8.*
v1.8.41.27, 1.26, 1.25, 1.243.18.21.21.64.7.*
v1.7.11.27, 1.26, 1.25, 1.243.17.21.21.64.6.*
v1.6.41.26, 1.25, 1.24, 1.233.17.01.21.64.5.*
v1.5.11.25, 1.24, 1.233.16.21.21.64.4.*
v1.4.01.25, 1.24, 1.23, 1.223.16.21.19.10†4.3.0
v1.3.11.24, 1.23, 1.22, 1.21, 1.203.16.21.19.10†4.2.5

获取部署描述文件

image-20240913110300893

image-20240913110338846

bash
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml

需要注意:

yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.11.2
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  externalTrafficPolicy: Local
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - appProtocol: http
    name: http
    port: 80
    protocol: TCP
    targetPort: http
  - appProtocol: https
    name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: LoadBalancer

如果最后一行:type: LoadBalancertype: ClusterIP,则需要改下

如果想在k8s所有节点都能进行访问的话:

yaml
externalTrafficPolicy: Local
# 改为
externalTrafficPolicy: Cluster

查看

bash
kubectl get svc -n ingress-nginx

正常情况就能看到地址信息了

测试

http

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-http
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: nginx.mytest.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80

使用https

apiVersion: v1
kind: Secret
metadata:
  name: nginx-tls-secret
  namespace: default
type: kubernetes.io/tls
data:
  tls.crt: base64 编码的 cert
  tls.key: base64 编码的 key
 
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-https
spec:
  rules:
  - host: nginx.mytest.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80
  tls:
  - hosts:
    - nginx.mytest.org
    secretName: nginx-tls-secret

OpenELB

前置条件

部署

下载资源清单

建议在生产环境中使用稳定版本,记录时间最新稳定版本为:v0.6

bash
wget https://raw.githubusercontent.com/openelb/openelb/release-0.6/deploy/openelb.yaml
registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.1.1
可以使用以下镜像代替
k8smirror/ingress-nginx-kube-webhook-certgen:v1.1.1

如果对最新的功能感兴趣:

bash
wget https://raw.githubusercontent.com/openelb/openelb/master/deploy/openelb.yaml

安装

使用资源清单

bash
kubectl apply -f openelb.yaml

执行以下命令,查看 penelb-controlleropenelb-speaker 的状态是否为: READY: 1/1STATUS: Running ,如果是,则表示 OpenELB 安装成功。

kubectl get po -n openelb-system

例如:

bash
NAME                                  READY   STATUS      RESTARTS   AGE
openelb-admission-create-fv8jb        0/1     Completed   0          41s
openelb-admission-patch-887qh         0/1     Completed   0          41s
openelb-controller-6d59c894c9-jgfks   1/1     Running     0          41s
openelb-speaker-dnkcr                 1/1     Running     0          41s
openelb-speaker-fmkxb                 1/1     Running     0          41s
openelb-speaker-trh6p                 1/1     Running     0          41s
...

删除

要删除 OpenELB,请登录 Kubernetes 集群并运行以下命令

bash
kubectl delete -f openelb.yaml

注意:在删除 OpenELB 之前,您应该先删除所有使用 OpenELB 的 Service。

执行以下命令查看结果。如果命名空间openelb-system不存在,则表示 OpenELB 删除成功。

bash
kubectl get ns

创建地址池

yaml
apiVersion: network.kubesphere.io/v1alpha2
kind: Eip
metadata:
    name: eip-layer2-pool
spec:
    address: 10.31.88.101-10.31.88.200
    protocol: layer2
    interface: eth0
yaml
apiVersion: network.kubesphere.io/v1alpha2
kind: Eip
metadata:
   # Eip 对象的名称。
   name: eip-layer2-pool
spec:
   # Eip 对象的地址池
   address: 10.31.88.101-10.31.88.200
   # openELB的运行模式,默认为bgp
   protocol: layer2
   # OpenELB 在其上侦听 ARP/NDP 请求的网卡。该字段仅在protocol设置为时有效layer2。
   interface: eth0
   # 指定是否禁用 Eip 对象
   # false表示可以继续分配
   # true表示不再继续分配
   disable: false
status:
   # 指定 Eip 对象中的IP地址是否已用完。
   occupied: false
   # 指定 Eip 对象中有多少个 IP 地址已分配给服务。
   # 直接留空,系统会自动生成
   usage: 
   # Eip 对象中的 IP 地址总数。
   poolSize: 100
   # 指定使用的 IP 地址和使用 IP 地址的服务。服务以Namespace/Service name格式显示(例如,default/test-svc)。
   # 直接留空,系统会自动生成
   used: 
   # Eip 对象中的第一个 IP 地址。
   firstIP: 10.31.88.101
   # Eip 对象中的最后一个 IP 地址。
   lastIP: 10.31.88.200
   ready: true
   # 指定IP协议栈是否为 IPv4。目前,OpenELB 仅支持 IPv4,其值只能是true.
   v4: true

查看

kubectl get eip

Ingress-Nginx安装

主要内容参考 Metallb部分的 Ingress-Nginx安装 这里主要写上述之外针对openELB的内容调整

增加注解,告诉Ingress-Nginx去找哪个负载均衡器,能够给你提供地址池

yaml
annotations:
    lb.kubesphere.io/v1alpha1: openelb   # 负载均衡器名称
    protocol.openelb.kubesphere.io/v1alpha1: layer2    # 几层的负载均衡器
    eip.openelb.kubesphere.io/v1alpha2: eip-layer2-pool     # 地址池名称

如:

yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    lb.kubesphere.io/v1alpha1: openelb
    protocol.openelb.kubesphere.io/v1alpha1: layer2
    eip.openelb.kubesphere.io/v1alpha2: eip-layer2-pool
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.11.2
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  externalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - appProtocol: http
    name: http
    port: 80
    protocol: TCP
    targetPort: http
  - appProtocol: https
    name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: LoadBalancer

查看EIP使用情况

kubectl get eip
kubectl describe eip eip-name