# 使用 MetalLB 暴露 Nginx Ingress 的 80 和 443 端口 MetalLB 是一种用于裸机 Kubernetes 集群的负载均衡器实现,能够通过发布集群外部的 IP 地址来暴露服务。此部分文档介绍 MetalLB 的地址发布模式、安装步骤、以及如何配置地址池并发布服务。 ## 1. [地址发布模式](https://metallb.universe.tf/concepts/#external-announcement) MetalLB 提供两种主要的地址发布模式: - [**Layer 2(L2)模式**:](https://metallb.universe.tf/concepts/layer2/) - 在 L2 模式下,MetalLB 通过 ARP (IPV4)/ NDP(IPv6)通告将服务的 IP 地址分配给集群节点,并由集群中的节点直接响应 ARP 请求。这种模式适用于与 Kubernetes 集群处于同一二层网络的环境。 - [**BGP 模式**:](https://metallb.universe.tf/concepts/bgp/) - 在 BGP 模式下,MetalLB 通过 Border Gateway Protocol (BGP) 将服务的 IP 地址通告给外部网络设备,如路由器。此模式适用于需要跨多个网络段进行负载均衡的场景。 在裸机环境中,Layer 2 模式通常更容易配置和管理,因此我们将重点介绍 Layer 2 模式。 ## 2. [安装 MetalLB](https://metallb.universe.tf/installation/) 1. **准备** 如果您在 IPVS 模式下使用 kube-proxy,自 Kubernetes v1.14.2 起您必须启用严格 ARP 模式。 *请注意,如果您使用 kube-router 作为服务代理,则不需要此功能,因为它默认启用严格 ARP。* 您可以通过编辑当前集群中的 kube-proxy 配置来实现此目的: ```bash kubectl edit configmap -n kube-system kube-proxy ``` 并设置: ```yaml apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: "ipvs" ipvs: strictARP: true ``` 如果您尝试自动执行此更改,这些 shell 代码片段可能会对您有所帮助: ```sh # 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\ ``` 2. **安装 MetalLB**: 安装 MetalLB 组件: ```sh wget https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml kubectl apply -f metallb-native.yaml ``` 通过helm安装: ```sh helm install metallb metallb/metallb -n metallb-system --create-namespace ``` 3. **验证安装**: 使用以下命令检查 MetalLB 是否成功部署: ```sh kubectl get pods -n metallb-system ``` 确保所有 Pod 都在 `Running` 状态。 ## 3. [配置地址池并发布服务](https://metallb.universe.tf/configuration/#layer-2-configuration) 1. **配置 IP 地址池**: 创建一个 IPAddressPool,用于定义 MetalLB 使用的 IP 地址池。在此示例中,我们使用 `Layer 2` 模式。 创建一个名为 `metallb-addresspool.yaml` 的配置文件: ```yaml apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: first-pool namespace: metallb-system spec: addresses: - 192.168.11.64/27 ``` 创建一个名为 `metallb-l2advertisement.yaml` 的配置文件: ```yaml apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: layer2publish namespace: metallb-system spec: ipAddressPools: - first-pool ``` 请将`192.168.11.64/27`改成你自己本地的地址池。 2. **应用配置**: 将 `metallb-config.yaml` 应用到 Kubernetes 集群: ```sh 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的节点。 ```sh 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 服务提供可靠的负载均衡功能。