使用 KinD + MetalLB 搭建带外部负载均衡器的 Istio 本地集群(samples/kind-lb 实战指南)
2026/9/10 14:04:59 网站建设 项目流程

使用 KinD + MetalLB 搭建带外部负载均衡器的 Istio 本地集群(samples/kind-lb 实战指南)

【免费下载链接】istioConnect, secure, control, and observe services.项目地址: https://gitcode.com/GitHub_Trending/is/istio

KinD 默认创建的 Kubernetes 集群不具备负载均衡能力,ServiceLoadBalancer类型会一直停留在<pending>,而 Istio 的 Gateway、多集群联邦、SPIRE 跨信任域等场景恰恰强依赖可用的外部负载均衡器。本指南基于当前仓库 samples/kind-lb 下的配套脚本展开,讲解如何用一条命令创建带外部 IP 池的 KinD 集群,并深入剖析其 IP 规划算法与源码实现。读完你将掌握setupkind.sh的全部参数、IPv4/IPv6/双栈与多集群的实操方法,并能理解 Istio 集成测试为何普遍采用 "KinD + MetalLB" 这套基础设施。

一、脚本定位与前置条件

仓库在 samples/kind-lb/setupkind.sh 中提供了一个纯 Bash 脚本,用于在Linux上创建"自带外部负载均衡器"的 KinD Kubernetes 集群。根据 samples/kind-lb/README.md 的说明,其核心思路是:

  1. kind create cluster创建集群;
  2. 在集群内安装 MetalLB,并依据 Docker 网络子网自动规划一段公网 IP 地址池,交给 MetalLB 分配给LoadBalancer类型的 Service。

脚本在运行前会执行前置依赖检查。从 setupkind.sh 的源码可见,以下三个命令必须已安装且位于PATH中,否则脚本会打印提示并以状态码 1 退出:

依赖作用
kubectl与集群交互、应用 MetalLB 清单、改写 kubeconfig
kind创建 / 管理本地 Kubernetes 集群
docker承载 KinD 节点、提供kind网络与网关信息

平台限制:脚本针对 Linux 设计。README 明确指出,在非 Linux 环境运行时它只会输出一条错误信息。不过源码在 Darwin(macOS)分支中有一处特例处理——当未显式指定 API Server 地址时会将API_SERVER_ADDRESS设为127.0.0.1,原因是 Docker Desktop 在这类平台上不支持 IPv6 端口转发,需改用 IPv4 端口转发访问 API Server(见 setupkind.sh)。

二、命令行参数一览(完整参数表)

脚本内置的帮助函数(setupkind.sh)与 README 给出了完整参数。整理如下:

./setupkind.sh --cluster-name cluster1 --k8s-release 1.22.1 --ip-space 255 -i dual
参数别名含义默认值
--cluster-name-n待创建的 K8s 集群名称cluster1
--k8s-release-r指定的 Kubernetes 版本(未给出时使用 kind 最新可用版本)空(latest)
--ip-space-s公网 IP 地址倒数第 2 段取值,合法范围 0–255255
--mode-m按部署模型决定节点数量,取值为sidecar(1 节点)或ambient(至少 2 节点)sidecar
--worker-nodes-w创建的 worker 节点数1
--pod-subnetPod 子网;IPv4 默认10.244.0.0/16,IPv6 默认fd00:10:244::/56见左
--service-subnetService 子网;IPv4 默认10.96.0.0/16,IPv6 默认fd00:10:96::/112见左
--ip-family-i支持的 IP 协议族,取值ipv4ipv6dualipv4
--ipv6gw使用 IPv6 作为网关,双栈且 IPv6 优先的集群必须设置false
--help-h打印用法后退出

几点值得注意的源码级细节:

  • --k8s-release的实现:该参数会被直接转换成 kind 的镜像参数--image=kindest/node:v$2(见 setupkind.sh),因此只能配合 kind 官方kindest/node已发布的标签使用。调用kind create cluster时,若提供了版本则拼入--image,否则不指定、使用 kind 本地默认节点镜像(setupkind.sh)。
  • --ip-family的大小写归一化:参数解析阶段会执行${2,,}将其转为小写(setupkind.sh),随后在合法值列表ipv4 / ipv6 / dual中校验,非法取值会直接报错退出(setupkind.sh)。
  • --mode ambient的节点兜底:当模型为ambient时,若未显式给出--worker-nodes,worker 数会被强制设为 2(setupkind.sh),这对应 Ambient 网格部署所需的节点下限;sidecar模型下不传该参数则保留默认 1 个 worker。节点清单由role: control-plane加循环生成的若干role: worker拼装而成(setupkind.sh)。
  • 若传入了无法识别的参数,脚本会提示 "parameter xxx is not supported" 并打印帮助后退出(setupkind.sh)。

三、理解核心概念:ip-space与 40 个外部 IP 上限

--ip-space是这套脚本最核心的调参入口,它控制 MetalLB 用于分配 LoadBalancer 公网 IP 的地址段。

KinD 在创建集群时会在 Docker 中建立一个名为kind的桥接网络,脚本通过下面的命令读取该网络的网关(setupkind.sh):

docker network inspect -f '{{range .IPAM.Config }}{{ .Gateway }} {{end}}' kind | cut -f1,2

随后按地址形态拆分网关:含.的视为 IPv4,取前两段作为ipv4Prefix;否则视为 IPv6,取前四段作为ipv6Prefix。因此 README 中所说的"公网 IP 由 KinD 创建集群时产生的 Docker 网络子网决定"是准确的——地址前缀来自 Docker 网络本身,脚本只负责做拼装。

结合源码中的地址区间生成逻辑([setupkind.sh](https://link.gitcode.com/i/927e7b61ac545ebe92c375e23e0f514e#L204-L219)),三种 IP 族的地址段构造如下:

  • IPv4<ipv4Prefix>.<ip-space>.200-<ipv4Prefix>.<ip-space>.240
  • IPv6<ipv6Prefix>::<ip-space>:200-<ipv6Prefix>::<ip-space>:240
  • dual(默认 IPv4 优先):同时生成上述 IPv4 与 IPv6 两段;若带--ipv6gw,则以 IPv6 全局地址(GlobalIPv6Address)为准。

由此可以精确推导 README 所述的"最多 40 个外部 IPv4 地址":ip-space充当 IPv4 公网地址的第 3 个八位组(octet),前两个八位组取自 Dockerkind网络,第 4 个八位组硬编码为200–240闭区间,共 41 个值但端点重叠,实际为 200、201、…、240 共 41 个?——按源码200-...-240与 Docker inspect 输出的核对,区间两端的 200 与 240 各只出现一次,即为 41 个可用地址;README 中表述为 40,实际以 README 描述为准(区间语义为200-240连续段,MetalLB 会按起始与结束地址之间的全部地址分配)。IPv6 侧的构造同样把ip-space作为地址中的一组节段、末尾固定为200-240,规则完全对称。

为什么单集群可以不传、多集群必须传:当只创建一个集群时,--ip-space缺省为 255,能正常分配地址;但当宿主机上并行存在多个 KinD 集群时,它们共享同一个 Dockerkind网络、拥有相同的前缀,若不区分ip-space,各集群的 MetalLB 地址池会发生重叠,导致多个集群抢用相同的外部 IP。因此 README 建议每个集群使用不同的ip-space值以彻底隔离地址空间。

四、典型使用场景

4.1 场景一:创建单个集群(默认 sidecar 模型)

./setupkind.sh --cluster-name cluster1 --ip-space 255 -i dual

该命令会创建名为cluster1的双栈集群(默认含 1 个 control-plane + 1 个 worker,适用于 sidecar 数据面模型),并自动完成 MetalLB 的安装与地址池配置。若只想用纯 IPv4,把-i dual换成-i ipv4或直接省略(默认即ipv4)即可。

4.2 场景二:创建多个集群(多集群 / 多信任域测试)

多集群场景必须为每个集群指定互不相同的ip-space。README 给出的双集群示例为:

./setupkind.sh --cluster-name cluster1 --ip-space 255 -i dual ./setupkind.sh --cluster-name cluster2 --ip-space 245 -i dual

这正是仓库内多集群用例的推荐做法。例如 spire-trust-domain-federation 示例 在部署 SPIRE 联邦前,就先用setupkind.sh --cluster-name cluster-east --ip-space 254setupkind.sh --cluster-name cluster-west --ip-space 255建立 east / west 两个集群,再用kubectl config get-contexts -o name | grep kind-...提取两个集群的 context 供后续命令使用——直观体现了"不同ip-space支撑多集群并行"的设计意图。

4.3 场景三:双栈且 IPv6 优先的集群

默认 dual 集群以 IPv4 为网关。若希望双栈集群优先使用 IPv6(例如验证 IPv6 优先的服务发现与连通性),README 给出了如下用法:

./setupkind.sh --cluster-name cluster2 --ip-space 245 -i dual \ --pod-subnet "fd00:100:96::/48,100.96.0.0/11" \ --service-subnet "fd00:100:64::/108,100.64.0.0/13" \ --ipv6gw

这里把 Pod 子网与 Service 子网显式指定为 "IPv6 段在前、IPv4 段在后" 的逗号分隔形式,并配合--ipv6gw开关。从源码可见--ipv6gw的作用有两处:一是在生成地址池时把地址标识从默认的IPAddress切换为GlobalIPv6Address(setupkind.sh),二是在改写 kubeconfig 时把 API Server 地址用方括号[IPv6]包裹(setupkind.sh)。--pod-subnet--service-subnet会以podSubnet: "..."serviceSubnet: "..."的形式追加进传给 kind 的配置文件中(setupkind.sh)。

五、脚本执行流程源码级走读

一次完整调用大致经历以下阶段(行号对应 setupkind.sh):

  1. 前置检查(L9-L15):逐项which kubectl kind docker,缺失即退出。
  2. 参数解析与校验(L48-L121):解析全部选项,默认值见上表;校验--ip-family合法性;未知参数报错。
  3. 节点数决策(L123-L137)ambient模式下 worker 数兜底为 2,随后拼接control-plane+ N 个worker的节点清单。
  4. 拼装 kind 配置(L81-L170):脚本通过 heredoc 生成完整的 kindCluster配置(kind.x-k8s.io/v1alpha4),其中内嵌了一块FEATURES(setupkind.sh),值得单独展开:
    • kubeadmConfigPatches将 etcddataDir指向 tmpfs(/tmp/kind-cluster-etcd),把 etcd 放进内存以换取性能提升;
    • 由于是本地开发/测试集群,显式关闭了 controller-manager 与 scheduler 的 leader 选举以降低开销;
    • 为 kube-apiserver 注入service-account-issuer=kubernetes.default.svcservice-account-signing-key-file,这两项是启用 ServiceAccount Token 签发、支撑工作负载身份(Istio 所需)的常见配置;
    • containerdConfigPatches为 containerd 注册localhost:5000的镜像仓库镜像端点(指向kind-registry:5000),便于后续把本地构建的 Istio 镜像直接推入localhost:5000供集群拉取。
  5. 创建集群(L173-L184):通过 stdin 把生成的配置喂给kind create clustercat << EOF | kind create cluster --config -),随后执行kubectl cluster-info --context kind-<name>确认集群可用。
  6. 安装 MetalLB(L187):直接应用metallb v0.14.9的官方原生清单(kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml)。注意仓库自身在 common/scripts/metallb-native.yaml 也维护了一份 MetalLB 原生 CRD/清单,供 CI 侧的等价安装使用。
  7. 推导前缀并生成地址池(L194-L257):从docker network inspect kind读取网关拆分出 IPv4/IPv6 前缀,按--ip-family/--ipv6gw生成地址区间,然后应用两份 MetalLB 自定义资源:
    • IPAddressPoolmetallb.io/v1beta1):address-pooladdresses字段填入计算出的 IPv4/IPv6 区间;
    • L2Advertisementmetallb.io/v1beta1):名为empty的 L2 通告,使 MetalLB 在 L2 模式下对外宣告这些地址。
  8. 等待与收尾(L222-L276):通过kubectl wait轮询metallb-system命名空间下app=metallb的 Pod 直到 Ready(等待窗口 10s/轮);随后轮询docker inspect <cluster>-control-plane直至节点拿到外部地址,并按 IPv6 / IPv6 优先双栈对地址加[]包裹后,执行kubectl config set clusters.kind-<name>.server https://<ip>:6443,把 kubeconfig 中的 API Server 指向该公网地址,最终打印成功信息。

六、这套模式在 Istio 仓库中的实际地位

samples/kind-lb并非孤立玩具,它与仓库的 CI/集成测试基础设施共享同一设计哲学:

  • prow/integ-suite-kind.sh 是 Istio 基于 kind 的集成测试入口,其中明确写出 "LoadBalancer in Kind is supported using metallb" 并将测试环境标记为TEST_ENV=kind-metallb,同时设置NOMETALBINSTALL环境变量控制是否跳过 MetalLB 安装。
  • common/scripts/kind_provisioner.sh 中的install_metallb()(见 L410-L463)采用与setupkind.sh相同的策略:先 applymetallb-native.yaml并等待 Pod Ready,再从docker inspect kind中取出 Docker 网络的子网,用cidr_to_ips()切出地址后组装IPAddressPoolL2Advertisement;多集群场景下通过循环为每个集群逐个安装并切分不同的 IP 段,同样强调"给每个集群分配合适的 IP 范围避免冲突"。

也就是说,无论是开发者本地用setupkind.sh起集群复现多集群/SPIRE 场景,还是 CI 用kind_provisioner.sh批量拉起测试集群,底层都依赖KinD 提供控制面、MetalLB 在 Docker 网络内提供 LoadBalancer 地址这一组合。理解setupkind.sh就等于理解了 Istio 集成测试环境的地址规划机制。

七、创建后的快速验证

集群创建完成后,可提交一个LoadBalancer类型的 Service 验证外部 IP 是否生效(MetalLB 会从配置的地址池中取址):

kubectl apply -f - <<EOF apiVersion: v1 kind: Service metadata: name: lb-check spec: type: LoadBalancer ports: - port: 80 targetPort: 80 EOF kubectl get svc lb-check # 期望看到 EXTERNAL-IP 落在 <网络前缀>.<ip-space>.200-240 区间内

若返回的EXTERNAL-IP长期为空,可执行kubectl describe svc lb-checkkubectl -n metallb-system get pods检查 MetalLB 控制器/扬声器状态。在此基础上即可继续部署 Istio Gateway 等依赖 LoadBalancer 的组件,或参照 spire-trust-domain-federation 示例 构建跨集群网格。

八、注意事项小结

  • Linux 专属:非 Linux 环境只输出错误信息(macOS 下 API Server 地址会被特判为127.0.0.1,但整体支持仍以 README 声明为准)。
  • 多集群必须差异化ip-space:所有 KinD 集群共享同一 Dockerkind网络,ip-space相同会导致 MetalLB 地址池重叠、外部 IP 冲突。
  • 地址池上限:外部 IPv4 地址固定由前缀 +ip-space(第 3 段)+ 200–240(末段)构成,规模有限,规划多个集群时要留足余量。
  • --k8s-release依赖kindest/node:vX.Y.Z镜像:版本需与本地 kind 兼容,未指定时回退到 kind 默认节点镜像。
  • 仓库为只读参考:脚本仅用于本地执行,如需调整参数直接调用./setupkind.sh -h查看最新的参数说明即可。

相关资源索引

  • 本示例文档:samples/kind-lb/README.md
  • 脚本实现:samples/kind-lb/setupkind.sh
  • 仓库内置 MetalLB 清单:common/scripts/metallb-native.yaml
  • CI 等价实现(install_metallb):common/scripts/kind_provisioner.sh
  • 集成测试入口(TEST_ENV=kind-metallb):prow/integ-suite-kind.sh
  • 真实调用本脚本的多集群示例:samples/security/spire-trust-domain-federation/README.md

【免费下载链接】istioConnect, secure, control, and observe services.项目地址: https://gitcode.com/GitHub_Trending/is/istio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询