ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Kind实战:本地快速搭建Kubernetes三节点集群

Kind实战:本地快速搭建Kubernetes三节点集群 写这篇文章之前我特意翻了一下群里最近的聊天记录发现不少人还在用 kubeadm 或 minikube 折腾本地集群。用 kubeadm 搭一套多节点环境步骤繁琐不说还容易把本机系统搞乱minikube 虽然轻量但默认只支持单节点想模拟真正的多节点调度场景总觉得差点意思。如果你也遇到同样的问题我强烈建议试试 Kind。这篇文章我会完整记录用 Kind 搭建三节点 K8s 集群的整个过程从原理到配置再到验证把我在实操中踩过的坑和总结的经验一并分享出来希望能帮你少走弯路。1. 为什么我推荐用 Kind 在本地复刻多节点集群Kind 的全称是 Kubernetes in Docker核心思路很直接把 K8s 的每个节点都跑成一个 Docker 容器容器内部通过 kubeadm 完成初始化。这样做的好处是你不需要在物理机或虚拟机上装操作系统也不用担心污染开发环境一条命令就能在本地拉起一个完整的集群。1.1 三个常见本地集群方案的对比先说结论如果你需要的是“能在笔记本上跑起来的、具备完整 K8s 功能的多节点集群”Kind 是兼顾成本与效果的最佳选择。我本地之前试过三种方案简单对比一下方案多节点支持启动速度资源占用维护成本适合场景minikube较弱需额外驱动中等较高中等单节点快速体验kubeadm支持但需手动初始化慢高高生产或准生产环境Kind原生支持快低低本地开发、CI、多节点验证minikube 其实也能开多节点但它在网络和存储层面的限制比较多容器化程度不如 Kind 彻底。kubeadm 是生产环境的标准安装方式但在本地用它折腾多节点集群意味着你要自己处理 systemd、容器运行时、网络插件等一系列问题一晚上能搭好就算顺利了。Kind 则把这些问题全部封装在镜像里节点容器启动后自动完成 kubeadm init 和 join整个过程几乎不需要人工干预。1.2 Kind 的工作方式节点本身就是容器Kind 的核心设计理念非常巧妙通过 Docker 容器来模拟物理节点。每个节点容器内部运行着一套完整的 K8s 组件包括 kubelet、containerd、kubeadm 等。节点之间通过 Docker 自定义网络互通网络层用 kind 自带的 CNI 插件保证 Pod 与 Service 的通信正常。你可以把 Kind 的每个节点容器理解为“一台带电线的迷你虚拟机”。虽然它不像虚拟机那样提供完整的操作系统隔离但对于跑 K8s 来说完全够用。更重要的是因为每个节点是一个容器你可以在 Docker 层面直接操作它 —— 比如用docker stop暂停某个节点模拟节点宕机场景这对验证集群的高可用和故障恢复非常有价值。1.3 Kind 适合谁不适合谁从我个人的使用体验看Kind 适合这几类人开发人员需要在本地验证 Deployment、Service、Ingress 等资源的行为。CI/CD 工程师需要在流水线中快速拉起一个临时集群跑自动化测试。K8s 学习者想体验多节点集群的调度、故障转移等特性但不想投入过多资源。平台工程师在开发 Operator 或自定义控制器时需要一套可随时销毁重建的环境。Kind 不适合的场景也很明确需要模拟真实网络延迟、存储持久化、GPU 调度等底层特性的场景。因为容器毕竟不是虚拟机网络和 IO 层面还存在一些抽象无法完全模拟生产环境的物理行为。2. 搭建前的环境准备Docker 资源与版本匹配Kind 最常用的运行时是 Docker所以环境准备的核心就是把 Docker 配好、版本选对。2.1 安装 Docker 时容易被忽视的两个点第一个是资源配额。我最初在 Docker Desktop 上安装完成后默认是给了 2 核 CPU 和 2GB 内存这个配置在启动单节点集群时勉强够用但一旦创建三节点集群会有三个 kubelet 和三个容器运行时同时运行内存占用瞬间飙升。我第一次没注意结果集群创建后节点一直处于 NotReady 状态排查了半天才发现是资源不够。建议在 Docker Desktop 中把内存设置到至少 6GBCPU 给到 4 核以上。第二个是网络模式。如果你用的是 macOS 或 Windows 的 Docker DesktopKind 默认的网络模式处理得比较好基本不需要额外配置。但如果你在 Linux 上使用并且 Docker 是通过代理访问镜像仓库的需要在 Docker daemon 的配置中提前搞定代理设置否则后面拉取 kindest/node 镜像时大概率会失败。2.2 选择 Kind 和 Kubernetes 版本版本匹配很关键。Kind 每个版本支持的 Kubernetes 版本是固定的不是说你装个最新版 Kind 就能创建任意版本的集群。我在下载时查看了 Kind 的 release 页面常见情况是 Kind v0.20 及以上版本默认支持 Kubernetes 1.29 和 1.30。建议选择你实际生产环境用到的 K8s 版本因为本地集群的一个重要用途就是和应用的真实运行环境保持一致。一个实用技巧想查看当前 Kind 支持哪些 K8s 版本可以运行kind create cluster --help里面默认参数会标明默认镜像版本或者直接访问 kindest/node 镜像仓库看最新的 tag。2.3 提前搞定镜像源问题这一点单独拿出来说是因为真的会卡住不少人。Node 容器需要拉取kindest/node:v1.29.2这类镜像还有后续的registry.k8s.io下的若干组件镜像。如果你所在网络环境访问这些仓库速度慢或不稳定集群创建过程会很痛苦。我测试时发现一个省时省力的方案提前把镜像拉下来手动打 tag。比如先拉取一个镜像再执行docker tag把镜像重新标记成 Kind 需要的名称和 tag这样创建集群时 Kind 就会使用本地已有的镜像不会再去远端拉取。3. 搞定三节点拓扑的配置文件Kind 支持通过 YAML 配置文件来定义集群拓扑包括节点数量、角色、端口映射等。这是搭建多节点集群的核心环节。3.1 一份能跑通的最小配置下面是我测试通过的配置文件保存在kind-config.yaml中kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane - role: worker - role: worker这个配置的含义很直白集群包含 1 个控制面节点和 2 个工作节点。Kind 会自动完成控制面初始化以及工作节点的 join 操作。3.2 initialNodes 参数的作用如果你使用的是 Kind 较高版本可能会在官方文档中看到initialNodes这个字段。它的作用是预先声明集群的节点数量和角色并要求第一次创建时全部节点必须成功启动。这种方式为后续的节点扩容操作提供了便利。kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 initialNodes: - role: control-plane - role: worker - role: worker使用initialNodes和直接用nodes在创建三节点集群的最终效果上是一致的。但initialNodes的语义更明确它强调这是一次“初始创建”后续可以在集群运行中通过kind scale或其他方式扩展节点。3.3 每个节点的角色分配三节点 K8s 集群可以有多种角色分配方式。最经典也是最合理的分配是一个 control-plane两个 worker。这样既保证了控制面独立运行又有两个工作节点可以展示 K8s 的调度能力。有人可能会问能不能用三个控制面节点技术上可以但控制面会承担更多选举和协调的负载本地实验没必要这么做。还有人会问能不能一个节点既当控制面又当 worker可以通过设置Labels或去除控制面节点的默认 Taint 来实现但默认情况下 control-plane 节点是不参与业务 Pod 调度的如果你的目的是验证多节点调度还是建议用 1 2 的布局。4. 创建集群并验证控制面状态配置搞定后创建集群只需一条命令。但命令执行完之后要做几条验证动作确认集群真的健康。4.1 执行创建命令在终端中执行kind create cluster --name k8s-multi --config kind-config.yaml--name参数用于指定集群名称不指定的话默认是kind。使用自定义名称的好处是如果本地有多个集群可以通过名称区分避免混淆。创建过程大概需要 3 到 5 分钟。期间 Kind 会先拉取节点镜像再创建三个容器然后启动 kubeadm 初始化流程。日志中会出现类似Creating node、Installing CNI的信息如果你看到红色的ERROR或WARNING说明某个环节出了问题需要往下排查。4.2 检查节点状态与角色集群创建成功后通过kubectl命令验证节点状态kubectl get nodes正常输出类似这样NAME STATUS ROLES AGE VERSION k8s-multi-control-plane Ready control-plane 5m v1.29.2 k8s-multi-worker Ready none 4m v1.29.2 k8s-multi-worker2 Ready none 4m v1.29.2三个节点都处于Ready状态说明控制面的 API Server 健康各节点的 kubelet 也与控制面正常通信。如果你看到某个节点是NotReady多半是容器资源不足或网络插件未正确安装可以先用docker logs container-name查看该节点的系统组件日志。验证控制面状态还有一个方法kubectl get componentstatuses输出中controller-manager和scheduler都应该是Healthy状态。这条命令虽然在新版 K8s 中略显“过时”但用来快速判断控制面组件是否健康仍然很直观。4.3 把 kubectl context 指过去如果你本地之前配置过其他集群需要确认当前 context 指向的是这个新建的 Kind 集群。查看当前 contextkubectl config current-context如果不对切换方式kubectl config use-context kind-k8s-multiKind 创建的 context 名称格式为kind- 集群名。这个细节很容易被忽略我试过几次第一次没切换 context结果在旧集群上执行命令白白困惑了十分钟。5. 用真实负载验证三节点可行性集群状态 Ready 只代表控制面没问题真正检验多节点集群是否可靠要把应用跑起来让数据说话。5.1 部署一个三副本应用我选择部署一个经典的三副本 Nginx 应用。创建一个配置apiVersion: apps/v1 kind: Deployment metadata: name: nginx-multi spec: replicas: 3 selector: matchLabels: app: nginx-multi template: metadata: labels: app: nginx-multi spec: containers: - name: nginx image: nginx:1.25-alpine ports: - containerPort: 80保存为nginx.yaml然后执行kubectl apply -f nginx.yaml kubectl get pods -o wide这里多加了-o wide参数输出的 Pod 信息会包含所在节点名称这在验证多节点调度时非常有用。5.2 验证 Pod 在多节点间的分布正常情况下三个 Nginx Pod 会被调度到两个 worker 节点上分布不会均匀而是由调度器基于资源可用性决定。我的测试结果就出现了两个 Pod 在同一节点、一个 Pod 在另一个节点的情况这很常见。看到这种分布后可以进一步验证集群的 DNS 和 Service 通信能力。创建一个 ClusterIP 类型的 Service并从集群内部发起访问kubectl expose deployment nginx-multi --port80 --target-port80 kubectl run curl-test --imagecurlimages/curl --rm -it --restartNever -- curl http://nginx-multi如果返回了 Nginx 的欢迎页 HTML说明集群内部的 Pod 网络和 Service 路由都正常工作。5.3 模拟节点故障与恢复三节点集群的一个重要价值是验证故障转移能力。打开另一个终端直接停掉一个 worker 节点容器docker stop k8s-multi-worker2然后回到主终端稍等片刻检查节点状态kubectl get nodes此时能看到k8s-multi-worker2的状态变成了NotReady。再观察 Pod 的运行情况kubectl get pods -o wide因为 ReplicaSet 需要维持副本数量原本运行在故障节点上的 Pod 会被重新调度到其他节点。这个过程中你可能看到某个 Pod 先进入Pending状态随后在另一个节点上变成Running。验证完故障场景后重新启动节点容器docker start k8s-multi-worker2等节点重新回到Ready状态集群会自动恢复正常。这一步是你真正体会到 K8s 多节点集群价值的地方单个节点坏了应用依然可用。6. 我在搭建过程中踩过的几个坑这部分我总结一下实战中踩过的坑有些是网上常见问题的复发有些则是很容易被忽略的细节。6.1 证书过期时间问题Kind 创建的集群默认各组件证书有效期是一年。如果你想长期使用这个集群到期后 API Server 会拒绝连接。处理方式有两种思路。第一种是执行 kubeadm 的证书更新命令在 control-plane 容器内操作第二种是关闭集群后用kind delete cluster重建一个。本地实验环境我一般选第二种因为新建集群只要几分钟省去了繁琐的证书续期操作。如果是 CI 环境建议定期重建集群这样比续期证书更靠谱。6.2 端口占用与冲突Kind 的 control-plane 节点默认会把${kubernetesVersion}的 API Server 端口映射到宿主机通常是 6443。如果你本地已经运行了其他 K8s 环境或某个服务占了 6443 端口创建集群会失败。解决办法是在配置文件中显式指定宿主机的映射端口nodes: - role: control-plane extraPortMappings: - containerPort: 6443 hostPort: 6443 protocol: TCP换个端口比如 8443就能避开冲突。6.3 清理不彻底的残留配置反复创建、删除集群的人通常都会遇到这个问题。执行kind delete cluster后虽然节点容器被删除了但 Docker 网络和卷可能依然残留。如果发现后续创建的集群网络不正常把 Docker 网络检查一下docker network ls你可能会看到若干kind相关的网络残留。手动清理的方式docker network prune -f这个命令会删除所有未使用的 Docker 网络请确认没有其他容器正在使用这些网络再执行。还有一种残留是 kubeconfig。删除集群后Kind 会自动清理它创建的 context但有时候也会出现残留。可以手动删除kubectl config delete-context kind-k8s-multi kubectl config delete-cluster kind-k8s-multi kubectl config unset users.kind-k8s-multi6.4 镜像拉取超时这个问题在部分网络环境下尤其突出。解决办法前面提过就是预先拉取镜像并重新打 tag。具体做法是先查看你使用的 Kind 版本对应的 node 镜像版本比如kindest/node:v1.29.2然后手动拉取docker pull kindest/node:v1.29.2如果从原始仓库拉取超时可以在镜像站拉取后再重新打 tag。Kind 创建集群时如果本地存在匹配的镜像就不会再去请求远端仓库。还有一个容易忽视的点如果修改了 Docker 的存储驱动或使用了特定的 storage driver可能会影响 Kind 节点容器中 overlay 文件系统的行为。这种情况下节点 Pod 可能出现Failed to create pod sandbox之类的错误。如果是这种情况检查 Docker 的 overlay2 配置是否正常必要时在 Docker daemon 层面重新定制存储配置。7. 如何进一步扩展这套三节点集群三节点只是起点。根据你的工作内容Kind 集群还可以做很多实用扩展。想要搭建高可用集群可以在配置中加入三个 control-plane 节点和两个 worker 节点并用外部负载均衡器或 Keepalived 提供虚拟 IP。Kind 支持这种模式集群创建后kubeadm 会自动完成控制面的多实例配置。不过在本地跑五个节点的集群对资源要求比较高建议至少给 Docker 分配 8GB 内存和 6 核 CPU。想要测试 Ingress 资源可以在控制面节点上添加端口映射并安装 NGINX Ingress Controller。Kind 官方文档在推荐方案中是加载一个负载均衡镜像把入口流量转发到 ingress-nginx Pod。想要直观的管理界面也可以在这套集群上安装 KubeSphere 这样的一体化可视化集群管理工具。它的安装过程不复杂但涉及大量组件。创建完成后通过面板查看节点状态、工作负载、日志等功能很适合作为团队内部体验环境。8. 写在最后的使用体会用 Kind 搭建多节点集群这件事我前后实践了好几轮最大的体会是它把传统集群搭建过程中最耗时、最易出错的部分全部自动化了。你再也不需要因为某个组件版本不兼容或 systemd 配置错误而反复重装环境只要把配置文件和镜像版本固定好就能高效复用这一套环境。如果非要说一个缺点那就是 Kind 终归是本地开发环境它帮你隐藏了生产环境里那些繁琐细节。用 Kind 学习 K8s 能让你的知识体系快速建立起来但在真正上生产前还是要去读读 kubeadm 相关的底层原理。毕竟一个工具太顺滑了反而容易让人忽略它背后的运作机制。最后分享一个我实际工作中的习惯每验证完一个项目或功能我会立即把当前的集群删掉并重新拉一个全新集群。这样既保证了每次实验的干净环境也让自己对 Kind 的创建流程保持着熟练度。你可以试试时间长了会发现创建集群这套动作已经成了你肌肉记忆的一部分。
返回列表