expose-via-metallb.md 5.9 KB

使用 MetalLB 暴露 Nginx Ingress 的 80 和 443 端口

MetalLB 是一种用于裸机 Kubernetes 集群的负载均衡器实现,能够通过发布集群外部的 IP 地址来暴露服务。此部分文档介绍 MetalLB 的地址发布模式、安装步骤、以及如何配置地址池并发布服务。

1. 地址发布模式

MetalLB 提供两种主要的地址发布模式:

  • Layer 2(L2)模式
    • 在 L2 模式下,MetalLB 通过 ARP (IPV4)/ NDP(IPv6)通告将服务的 IP 地址分配给集群节点,并由集群中的节点直接响应 ARP 请求。这种模式适用于与 Kubernetes 集群处于同一二层网络的环境。
  • BGP 模式
    • 在 BGP 模式下,MetalLB 通过 Border Gateway Protocol (BGP) 将服务的 IP 地址通告给外部网络设备,如路由器。此模式适用于需要跨多个网络段进行负载均衡的场景。

在裸机环境中,Layer 2 模式通常更容易配置和管理,因此我们将重点介绍 Layer 2 模式。

2. 安装 MetalLB

  1. 准备

如果您在 IPVS 模式下使用 kube-proxy,自 Kubernetes v1.14.2 起您必须启用严格 ARP 模式。

请注意,如果您使用 kube-router 作为服务代理,则不需要此功能,因为它默认启用严格 ARP。

您可以通过编辑当前集群中的 kube-proxy 配置来实现此目的:

   kubectl edit configmap -n kube-system kube-proxy

并设置:

   apiVersion: kubeproxy.config.k8s.io/v1alpha1
   kind: KubeProxyConfiguration
   mode: "ipvs"
   ipvs:
     strictARP: true

如果您尝试自动执行此更改,这些 shell 代码片段可能会对您有所帮助:

   # see what changes would be made, returns nonzero returncode if different
   kubectl get configmap kube-proxy -n kube-system -o yaml | \
   sed -e "s/strictARP: false/strictARP: true/" | \
   kubectl diff -f - -n kube-system
   
   # actually apply the changes, returns nonzero returncode on errors only
   kubectl get configmap kube-proxy -n kube-system -o yaml | \
   sed -e "s/strictARP: false/strictARP: true/" | \
   kubectl apply -f - -n kube-system\
  1. 安装 MetalLB

安装 MetalLB 组件:

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

通过helm安装:

   helm install metallb metallb/metallb -n metallb-system --create-namespace
  1. 验证安装

使用以下命令检查 MetalLB 是否成功部署:

   kubectl get pods -n metallb-system

确保所有 Pod 都在 Running 状态。

3. 配置地址池并发布服务

  1. 配置 IP 地址池

创建一个 IPAddressPool,用于定义 MetalLB 使用的 IP 地址池。在此示例中,我们使用 Layer 2 模式。

创建一个名为 metallb-addresspool.yaml 的配置文件:

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

创建一个名为 metallb-l2advertisement.yaml 的配置文件:

   apiVersion: metallb.io/v1beta1
   kind: L2Advertisement
   metadata:
     name: layer2publish
     namespace: metallb-system
   spec:
     ipAddressPools:
     - first-pool

请将192.168.11.64/27改成你自己本地的地址池。

  1. 应用配置

metallb-config.yaml 应用到 Kubernetes 集群:

   kubectl apply -f metallb-addresspool.yaml
   kubectl apply -f metallb-l2advertisement.yaml

4. 部署 Nginx Ingress Controller

安装 Nginx Ingress Controller,并将 Service 类型设置为 LoadBalancer,让 MetalLB 为其分配一个外部 IP 地址:

为了确保客户端的真实 IP 地址能够在 NodePort 类型的服务中正确传递,你需要将 externalTrafficPolicy 设置为 Local。这将保留客户端源地址(source IP preservation)。

使用 Layer 2 模式时,MetalLB 将会感知 ingress-nginx-controller Pod的所在节点,并让所在节点响应EXTERNAL-IP ARP/NDP 请求,确保请求不发送到不存在ingress-nginx-controller Pod的节点。

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
kubectl create namespace ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx \
    --set controller.service.type=LoadBalancer \
    --set controller.service.externalTrafficPolicy=Local \
    --set ingressClassResource.default=true \
    --set controller.watchIngressWithoutClass=true \
    --namespace ingress-nginx
  1. 验证服务暴露

使用以下命令检查 Nginx Ingress Controller 的 Service,确保它获得了一个 MetalLB 分配的外部 IP 地址:

   kubectl get svc -n ingress-nginx

输出应包含类似如下的信息:

   NAME                                 TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                      AGE
   ingress-nginx-controller             LoadBalancer   10.96.122.1   192.168.11.64   80:30820/TCP,443:31867/TCP   2m

5. DNS 配置

将域名的 DNS A 记录指向 MetalLB 分配的外部 IP 地址(如 192.168.11.64),以便外部用户能够通过域名访问 Nginx Ingress Controller。

6. 总结

通过 MetalLB,您可以在裸机 Kubernetes 集群中轻松暴露 Nginx Ingress 的 80 和 443 端口。Layer 2 模式的配置相对简单,非常适合小型集群或与 Kubernetes 节点处于同一网络的环境。通过正确配置 IP 地址池和地址发布模式,MetalLB 能够为 Kubernetes 服务提供可靠的负载均衡功能。