Ubuntu 上使用 kind 快速搭建本地 Kubernetes 开发集群
如果你正在学习 Kubernetes,或者需要在本地快速搭建一个用于开发测试的集群,那么你一定遇到过资源消耗大、环境配置复杂、清理困难等问题。在虚拟机里跑 Minikube 太笨重,用云服务又太贵,有没有一种轻量、快速、用完即抛的方案?
答案是肯定的,这就是 kind (Kubernetes in Docker) 。它不是一个图形处理软件,而是一个使用 Docker 容器作为“节点”来运行 Kubernetes 集群的工具。听起来有点绕?简单说,它能在你的一台机器上,用几个 Docker 容器,瞬间“变”出一个功能完整的 K8s 集群。这对于开发者、CI/CD 流水线、或者只是想快速验证一个 K8s 概念的你来说,简直是“神器”。
但别急着去官网复制命令。在 Ubuntu 上安装 kind,远不止 curl 和 chmod 那么简单。很多人卡在 Docker 环境、权限问题或者网络配置上,最终得到一个无法启动的集群。这篇文章的目的,就是帮你绕过这些坑,从零开始,在 Ubuntu 上搭建一个稳定可用的 kind 集群。我们不仅会完成安装,还会深入理解其工作原理,并给出生产级的最佳实践建议,让你真正掌握这个高效的本地 K8s 开发工具。
1. 为什么选择 kind:重新定义本地 K8s 开发体验
在深入安装步骤之前,我们必须先搞清楚 kind 到底解决了什么痛点,以及它和 Minikube、k3s、Docker Desktop 内置 K8s 等方案的本质区别。这决定了它是否适合你的场景。
传统本地 K8s 方案的三大痛点:
- 资源消耗大 :无论是 Minikube 启动一个虚拟机,还是 k3s 运行一堆系统服务,都会占用可观的 CPU 和内存。
- 环境隔离差 :很多工具会直接修改你的主机网络、系统服务,容易造成环境污染,清理不彻底。
- 启动速度慢 :从启动虚拟机到拉取镜像,再到初始化集群,动辄几分钟,打断了开发的流畅性。
kind 的颠覆性思路:容器即节点。 kind 的核心思想非常巧妙:既然 Docker 容器本身就是一个轻量级的隔离环境,那为什么不直接用容器来模拟 K8s 的节点(Node)呢?一个 kind 集群由两个或多个 Docker 容器组成:
- 一个容器作为 控制平面(Control Plane) ,运行
kube-apiserver、kube-scheduler、kube-controller-manager等核心组件。 - 一个或多个容器作为 工作节点(Worker Node) ,运行
kubelet和containerd(或 Docker)来托管你的业务 Pod。
所有这些都是跑在你自己主机 Docker 守护进程里的容器。这意味着:
- 极致轻量 :节点本身就是一个容器,资源开销极小。
- 完美隔离 :整个集群生命周期被封装在 Docker 中,
kind delete cluster即可彻底清理,不留任何系统级残留。 - 秒级启动 :基于现有的 Docker 镜像,集群创建通常在 30 秒到 2 分钟内完成。
- 高度一致 :集群组件以容器镜像形式分发,确保了环境的一致性,非常适合 CI/CD。
那么,谁最适合使用 kind?
- Kubernetes 学习者 :快速搭建实验环境,反复创建销毁无压力。
- 应用开发者 :在本地验证 Helm Chart、Operator 或自定义资源定义(CRD)。
- CI/CD 工程师 :在流水线中集成一个临时的、干净的 K8s 集群进行集成测试。
- 项目贡献者 :为 Kubernetes 上游项目(如 SIG Testing)贡献代码,kind 是官方推荐的本地测试环境。
如果你的需求是在一台 Ubuntu 开发机上,获得一个最接近生产环境架构(多节点)、且管理成本最低的 K8s 沙盒,那么 kind 几乎是当前的最优解。
2. 核心概念与架构解析:理解 kind 如何工作
要玩转一个工具,不能只停留在命令层面。理解 kind 的架构,能帮助你在出问题时快速定位。
2.1 kind 的三层架构 我们可以把 kind 的架构分为三层:
- kind 命令行工具 :这是你直接交互的客户端。它负责根据配置文件创建 Docker 容器(节点),并在容器内部部署和配置 Kubernetes 组件。
- Docker 容器(节点) :每个容器都运行一个特制的 Linux 发行版镜像(通常是
kindest/node),里面预装了systemd、containerd、kubeadm、kubelet等必要组件。控制平面节点容器会额外运行etcd和核心控制面组件。 - Kubernetes 集群 :运行在上述容器内部,对外提供完整的 K8s API。
kubectl通过一个kind生成的 kubeconfig 文件来连接这个集群。
2.2 关键组件交互流程 当你执行 kind create cluster 时:
-
kind工具拉取kindest/node镜像(如果本地没有)。 - 根据配置,启动一个或多个容器,并为它们配置独立的网络和存储。
- 在控制平面容器内,使用
kubeadm初始化一个 Kubernetes 集群。 - 将生成的 admin kubeconfig 从容器内提取到主机,并更新本地
~/.kube/config文件。 - 如果需要,部署 CoreDNS、CNI 网络插件(默认使用
kindnet,一种简单的基于ptp的 CNI)等插件。
2.3 与 Docker Desktop Kubernetes 的对比 很多人分不清 kind 和 Docker Desktop 自带的 Kubernetes。它们有本质区别:
- Docker Desktop K8s :是一个单节点的、高度集成的、黑盒式的 K8s 环境。它方便,但不可配置节点数,且与 Docker Desktop 深度绑定。
- kind :是一个创建和管理多节点 K8s 集群的 工具 。它更灵活,你可以定义多个控制平面和工作节点,模拟更复杂的拓扑结构,并且完全独立于任何桌面环境。
理解了这些,你就知道 kind 不是一个“玩具”,而是一个用于创建标准化、可移植 K8s 集群的 基础设施工具 。
3. 环境准备:确保你的 Ubuntu 系统就绪
安装 kind 本身很简单,难点在于确保其依赖环境正确。请严格按照以下步骤检查你的 Ubuntu 系统。
3.1 系统要求
- 操作系统 :Ubuntu 18.04 LTS, 20.04 LTS, 22.04 LTS 或更高版本。本文以 Ubuntu 22.04 LTS 为例。
- 架构 :x86_64 (amd64) 或 arm64。确保你的 CPU 支持虚拟化(对于 Docker 运行容器是必要的)。
- 权限 :你需要拥有
sudo权限来安装软件包。
3.2 安装并配置 Docker(最关键的一步) kind 完全依赖 Docker 运行时。如果你的 Docker 安装有问题,kind 绝对无法工作。
# 1. 卸载旧版本 Docker(如果存在)
sudo apt-get remove docker docker-engine docker.io containerd runc
# 2. 更新 apt 包索引并安装依赖包
sudo apt-get update
sudo apt-get install -y \
ca-certificates \
curl \
gnupg \
lsb-release
# 3. 添加 Docker 官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 4. 设置 Docker 稳定版仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 5. 安装 Docker Engine
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 6. 验证 Docker 安装
sudo docker run hello-world
如果看到 “Hello from Docker!” 的信息,说明 Docker 安装成功。
3.3 将当前用户加入 docker 组(避免每次使用 sudo) 默认情况下,运行 docker 命令需要 sudo 权限。为了方便,将你的用户加入 docker 组。
# 将当前用户加入 docker 组
sudo usermod -aG docker $USER
# 重要:注销并重新登录,或者执行以下命令使组更改生效
newgrp docker
# 验证无需 sudo 即可运行 docker
docker run hello-world
注意 : newgrp 命令只对当前 shell 会话生效。最可靠的方法是 完全注销系统再重新登录 。
3.4 检查 Docker 服务状态与 cgroup 驱动 Kubernetes 推荐使用 systemd 作为 cgroup 驱动。我们需要确保 Docker 也使用 systemd 。
# 检查 Docker 服务状态
sudo systemctl status docker --no-pager -l
# 创建或修改 Docker 的 daemon.json 配置文件
sudo tee /etc/docker/daemon.json > /dev/null <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
# 重启 Docker 服务使配置生效
sudo systemctl daemon-reload
sudo systemctl restart docker
# 验证 cgroup 驱动
docker info | grep -i cgroup
输出中应包含 Cgroup Driver: systemd 。
至此,一个为运行 Kubernetes 优化过的 Docker 环境已经准备就绪。这是 kind 能成功运行的基石。
4. 安装 kind 命令行工具
有了健康的 Docker 环境,安装 kind 本身就像喝水一样简单。kind 是一个单独的 Go 二进制文件,我们直接下载即可。
4.1 使用 curl 下载最新稳定版(推荐) 访问 kind 官方 GitHub Releases 页面,找到最新版本的 Linux amd64 二进制文件。以下命令会自动获取最新版本号并下载。
# 下载最新的 kind 二进制文件
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
# 或者,指定一个具体版本(例如 v0.20.0)
# curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.20.0/kind-linux-amd64
# 赋予执行权限
chmod +x ./kind
# 将 kind 移动到系统 PATH 目录(例如 /usr/local/bin)
sudo mv ./kind /usr/local/bin/
# 验证安装
kind version
你应该能看到类似 kind v0.20.0 go1.20.4 linux/amd64 的输出。
4.2 (备选)使用包管理器安装 如果你更喜欢使用包管理器,也可以通过 snap 安装,但版本可能不是最新的。
# 使用 snap 安装
sudo snap install kind --classic
# 验证安装
kind version
4.3 安装 kubectl(Kubernetes 命令行工具) kind 创建集群后,你需要 kubectl 来管理它。
# 下载最新稳定版 kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
# 赋予执行权限并移动到 PATH
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# 验证安装
kubectl version --client --output=yaml
现在, kind 和 kubectl 都已就位。
5. 创建你的第一个 kind 集群
现在进入最激动人心的环节。我们将用最简单的命令创建一个集群,然后逐步深入高级配置。
5.1 基础创建:单控制平面集群 这是最常用的场景,创建一个包含一个控制平面节点和一个工作节点的集群。
# 使用默认配置创建集群,集群名称默认为 “kind”
kind create cluster
# 或者,显式指定集群名称
kind create cluster --name my-cluster
这个命令会执行以下操作:
- 在后台拉取
kindest/node镜像(约 500MB)。 - 启动两个 Docker 容器:一个作为控制平面,一个作为工作节点。
- 在容器内初始化 Kubernetes 集群,并配置网络。
- 生成 kubeconfig 文件,并合并到你的
~/.kube/config中。 - 将当前
kubectl的上下文切换到新创建的集群。
整个过程大约需要 1-2 分钟。完成后,你会看到类似 Creating cluster “my-cluster” ... ✓ 的成功信息。
5.2 验证集群状态 创建完成后,立即验证集群是否健康。
# 查看集群节点状态
kubectl get nodes
# 查看所有命名空间下的 Pod 状态
kubectl get pods --all-namespaces
# 查看 kind 创建的 Docker 容器
docker ps
kubectl get nodes 的输出应该显示两个节点,状态都是 Ready 。 docker ps 会显示两个名为 my-cluster-control-plane 和 my-cluster-worker 的容器在运行。
5.3 理解 kind 的 kubeconfig kind 不会覆盖你原有的 ~/.kube/config 文件,而是将新集群的配置作为一个新的上下文(context)添加进去。
# 查看当前的 kubeconfig 上下文
kubectl config get-contexts
# 查看当前正在使用的上下文
kubectl config current-context
# 切换回其他集群的上下文(如果你有多个)
kubectl config use-context your-other-context
kind 创建的上下文名称通常是 kind-my-cluster 格式。这种设计让你可以轻松在多个集群(本地 kind、Minikube、远程 EKS/AKS)之间切换。
6. 高级配置:使用 kind 配置文件
默认配置适合快速上手,但真实场景往往需要定制:指定 Kubernetes 版本、配置多节点、映射本地端口、预加载镜像等。这就需要使用 kind 配置文件 (一个 YAML 文件)。
6.1 配置文件基础结构 创建一个名为 kind-config.yaml 的文件:
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
# 配置集群的网络
networking:
# API Server 的监听地址,设置为 0.0.0.0 允许从主机外部访问(谨慎使用)
apiServerAddress: "127.0.0.1"
# API Server 端口,默认为 6443
apiServerPort: 6443
# 节点配置
nodes:
# 控制平面节点
- role: control-plane
# 将主机端口 80 映射到容器的 80 端口,便于访问 Ingress 服务
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
# 工作节点
- role: worker
- role: worker
这个配置定义了一个 1 个控制平面 + 2 个工作节点的集群,并将宿主机的 80 和 443 端口映射到了控制平面节点。
6.2 使用配置文件创建集群
# 使用配置文件创建集群
kind create cluster --name multi-node-cluster --config kind-config.yaml
# 验证节点数量
kubectl get nodes
现在你应该能看到三个节点。
6.3 关键配置项详解
- 指定 Kubernetes 版本 :通过
node的镜像标签指定。
注意 :镜像标签必须使用完整的镜像摘要(SHA256),你可以在 kind 发布说明 中找到对应版本的正确镜像名。nodes: - role: control-plane image: kindest/node:v1.27.3@sha256:... # 使用特定版本镜像 - 预加载本地 Docker 镜像到集群 :在 CI/CD 中,避免从远程仓库拉取镜像,可以极大加速部署。
但更常用的方法是使用nodes: - role: control-plane - role: worker # 这个配置段告诉 kind,在创建节点时,将主机上的指定镜像加载到节点容器中 containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5000"] endpoint = ["http://kind-registry:5000"]kind load docker-image命令:# 假设你本地构建了一个镜像 my-app:v1 docker build -t my-app:v1 . # 将该镜像加载到名为 multi-node-cluster 的集群的所有节点中 kind load docker-image my-app:v1 --name multi-node-cluster # 之后在集群中部署时,Pod 会直接使用节点本地已加载的镜像,无需拉取。 - 配置持久化存储 :默认情况下,节点容器内的数据在容器删除后会丢失。你可以将主机目录挂载到节点容器内。
nodes: - role: worker extraMounts: - hostPath: /path/on/host/data containerPath: /data # readOnly: true # 可选,默认为 false (读写)
7. 在 kind 集群中部署应用实战
理论说再多,不如动手跑一个应用。我们来部署一个经典的 Nginx 服务,并通过 NodePort 和 Ingress 两种方式访问它。
7.1 部署 Nginx Deployment 和 Service
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort # 使用 NodePort 类型,K8s 会分配一个主机端口
# 应用配置
kubectl apply -f nginx-deployment.yaml
# 查看部署状态
kubectl get deployments
kubectl get pods
kubectl get svc nginx-service
查看 nginx-service 时,你会看到类似 80:3xxxx/TCP 的输出,其中 3xxxx 是随机分配的 NodePort。
7.2 通过 NodePort 访问 由于 kind 节点是 Docker 容器,你需要访问 宿主机 的 IP 和 NodePort。但注意,NodePort 是在 容器内部 暴露的,你需要将其映射到宿主机。这就是前面配置文件中 extraPortMappings 的用处。
如果你创建集群时没有映射端口,可以临时使用 kubectl port-forward :
# 将本地的 8080 端口转发到 nginx-service 的 80 端口
kubectl port-forward service/nginx-service 8080:80
然后在浏览器访问 http://localhost:8080 。
7.3 部署 Ingress Controller 并配置 Ingress(更生产化的方式) NodePort 不适合生产。我们部署一个 Ingress Controller(如 NGINX Ingress Controller),并利用之前映射的宿主机 80/443 端口。
# 使用官方 Manifest 部署 NGINX Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
# 等待 Ingress Controller 的 Pod 变为 Ready
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=90s
创建 Ingress 资源:
# nginx-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
spec:
ingressClassName: nginx
rules:
- host: myapp.local
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: nginx-service
port:
number: 80
kubectl apply -f nginx-ingress.yaml
由于我们在 kind-config.yaml 中将宿主机的 80 端口映射到了控制平面节点,并且 Ingress Controller 监听节点的 80 端口,现在你可以在宿主机上编辑 /etc/hosts 文件,添加一行 127.0.0.1 myapp.local ,然后在浏览器访问 http://myapp.local ,就能看到 Nginx 欢迎页面了。这完全模拟了生产环境通过域名访问服务的流程。
8. 集群管理与故障排查
8.1 日常管理命令
# 列出所有 kind 集群
kind get clusters
# 获取指定集群的 kubeconfig
kind get kubeconfig --name my-cluster
# 导出 kubeconfig 到文件
kind get kubeconfig --name my-cluster > my-cluster-kubeconfig.yaml
# 删除集群(彻底清理所有相关容器和资源)
kind delete cluster --name my-cluster
# 删除所有 kind 集群
kind delete clusters --all
8.2 常见问题与排查思路
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
kind create cluster 卡在 Ensuring node image ... | 网络问题,无法拉取 kindest/node 镜像。 | 1. 检查网络连接。 2. docker pull kindest/node:v1.27.3 手动拉取。 | 使用代理或更换镜像源。手动拉取后重试。 |
ERROR: failed to create cluster: docker run error | Docker 守护进程未运行或权限不足。 | 1. systemctl status docker 。 2. docker ps 测试。 | 启动 Docker 服务 ( sudo systemctl start docker )。确保用户已在 docker 组并重新登录。 |
kubectl get nodes 显示 NotReady | CNI 网络插件未成功安装或 Pod 网络有问题。 | 1. kubectl get pods -n kube-system 查看 coredns 是否 Running。 2. docker logs <control-plane-container-id> 查看节点日志。 | 通常等待几分钟会自动恢复。可尝试 kubectl delete pod -n kube-system -l k8s-app=kube-dns 重启 CoreDNS。 |
| 无法从宿主机访问 NodePort 服务 | NodePort 在容器网络内,未映射到宿主机。 | 检查服务类型是否为 NodePort 以及分配的端口。 | 1. 使用 kubectl port-forward 临时转发。 2. 在 kind 配置文件中使用 extraPortMappings 永久映射。 |
kind load docker-image 失败 | 集群名称错误或集群未运行。 | kind get clusters 确认集群状态。 | 确保集群正在运行,并使用正确的 --name 参数。 |
| 节点磁盘空间不足 | 容器内日志或镜像占满空间。 | docker exec <node-container> df -h 进入容器查看。 | 1. 清理无用镜像: docker system prune 。 2. 扩展 Docker 根目录大小。 |
8.3 深入节点容器内部调试 有时需要进入节点容器内部查看情况。
# 获取控制平面节点的容器 ID
docker ps --filter "name=my-cluster-control-plane" --format "{{.ID}}"
# 进入容器内部的 shell
docker exec -it <control-plane-container-id> /bin/bash
# 在容器内,你可以像在普通 Linux 系统一样操作
# 查看 kubelet 日志
journalctl -u kubelet -f
# 查看容器运行时 (containerd) 状态
crictl ps
9. 生产级最佳实践与进阶指南
将 kind 用于本地开发很方便,但遵循一些最佳实践能让体验更顺畅,甚至可以在 CI 中发挥更大作用。
9.1 镜像管理与加速
- 预加载镜像 :在 CI 流水线中,先使用
kind load docker-image将构建好的镜像加载到集群,再运行测试。这比每次从仓库拉取快得多。 - 使用本地镜像仓库 :可以部署一个
registry:2容器作为本地仓库,并在 kind 配置中配置镜像仓库镜像。
然后在配置文件中添加# 创建本地仓库容器 docker run -d -p 5000:5000 --restart=always --name kind-registry registry:2 # 连接仓库到 kind 网络(如果集群已创建) docker network connect kind kind-registrycontainerdConfigPatches来配置镜像仓库。
9.2 配置管理
- 版本化配置文件 :将你的
kind-config.yaml纳入 Git 版本控制,确保团队环境和 CI 环境一致。 - 多集群配置 :为不同的项目或测试目的创建不同的配置文件(如
kind-config-dev.yaml,kind-config-integration.yaml)。
9.3 集成到 CI/CD(例如 GitHub Actions) kind 是 CI 中运行 Kubernetes 集成测试的绝佳选择。以下是一个简化的 GitHub Actions 工作流步骤:
# .github/workflows/k8s-test.yaml 片段
jobs:
integration-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker
uses: docker/setup-buildx-action@v3
- name: Set up kind
uses: helm/kind-action@v1.8.0 # 使用社区 Action 安装 kind
- name: Create kind cluster
run: |
kind create cluster --config ./kind-config-ci.yaml
kubectl cluster-info --context kind-kind
- name: Build and load image
run: |
docker build -t my-app:ci-${{ github.sha }} .
kind load docker-image my-app:ci-${{ github.sha }}
- name: Run tests
run: |
kubectl apply -f ./k8s/manifests/
# 运行你的测试脚本,例如使用 `kubectl` 或 `helm test`
9.4 性能与资源限制 默认情况下,kind 节点容器没有资源限制。在资源有限的机器上,你可以通过 Docker 在创建集群前设置资源限制(但这需要修改 Docker 的启动配置,或使用 docker run 的参数,而 kind 本身不直接支持)。更常见的做法是调整集群规模,使用单节点集群(只有控制平面,也是工作节点)来节省资源。
# 单节点集群配置 (控制平面节点也承担工作)
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
# 此节点也将运行工作负载
9.5 清理策略 养成随手清理的习惯,避免残留容器占用磁盘。
# 定期清理未使用的 Docker 资源
docker system prune -af
# 删除所有不再需要的 kind 集群
kind delete clusters --all
通过以上步骤,你不仅能在 Ubuntu 上顺利安装和使用 kind,更能理解其设计哲学,掌握定制化配置、应用部署和故障排查的完整技能链。kind 将本地 Kubernetes 体验提升到了一个全新的高度——快速、轻量、可重复且与生产环境高度相似。无论是用于日常开发、学习验证,还是集成到自动化流水线中,它都是一个值得你放入工具箱的强力伙伴。建议你将本文中的配置文件和命令保存下来,作为日后搭建本地 K8s 环境的快速参考。
更多推荐

所有评论(0)