Kubernetes开发运维-使用 kind 搭建K8S多节点集群

Kind简介

Kubernetes 的开发、测试和学习过程中,快速搭建一个本地多节点集群是提升效率的关键。kind(Kubernetes IN Docker)作为 Kubernetes 官方推出的工具,凭借其轻量、快速、基于容器的特性,成为搭建本地多节点集群的理想选择。本文将详细介绍如何使用kind搭建 K8s 多节点集群,并对比其与同类工具的差异,同时解答使用中可能遇到的问题。

什么是 kind?

kind是一个通过 Docker 容器模拟 Kubernetes 节点,快速创建本地 Kubernetes 集群的工具。它由 Kubernetes 官方开发维护,专为开发、测试和学习场景设计(请勿用于生产环境)。

使用kind安装配置集群的步骤相对简单,核心依赖是Docker(用于运行节点容器)和Go环境(部分场景下需要)。与传统基于虚拟机的工具不同,kind直接将 Kubernetes 组件运行在 Docker 容器中,无需额外的虚拟化层,这使得它的启动速度更快、资源占用更可控。

此外,kind支持通过配置文件定义集群参数(如节点数量、网络配置、Kubernetes 版本等),可灵活满足多节点、高可用等场景的模拟需求,非常适合验证分布式应用在 K8s 环境中的兼容性。

kind 的主要用途

  1. 本地开发
    开发者可以通过kind在本地快速搭建与生产环境相似的 Kubernetes 集群,实时调试应用部署配置(如 Deployment、Service、ConfigMap 等),加速应用从开发到测试的迭代过程。
  2. 测试验证
    由于集群完全运行在本地,kind适合进行单元测试、集成测试和 CI/CD 流水线中的自动化测试,确保应用在 Kubernetes 环境中的兼容性和稳定性,降低直接在生产集群测试的风险。
  3. 教育和学习
    对于 Kubernetes 初学者或教学场景,kind提供了低成本、易操作的实践环境,帮助理解 K8s 的核心概念(如节点、Pod、控制器、服务发现等),通过实际操作加深对集群架构的认知。

kind 与 Minikube 和 k3s 对比

在本地 Kubernetes 工具中,kindMinikubek3s是最常用的三个选择,它们的设计目标和适用场景各有侧重,以下从核心特性进行对比:

关键信息minikubekindk3s
运行时虚拟机(VM)容器原生
支持的架构AMD64AMD64AMD64、ARMv7、ARM64
支持的容器运行时Docker、CRI-O、containerd、gvisorDockerDocker、containerd
启动时间(首次/后续)5分19秒 / 3分15秒2分48秒 / 1分06秒15秒 / 15秒
内存要求2GB8GB(Windows、MacOS)512 MB
是否需要 root 权限是(无 root 权限模式为实验性)
多集群支持否(可通过容器实现)
多节点支持
项目页面minikubekindk3s

kindMinikubek3s 优缺点对比:

对比项MinikubeKindK3s
优点轻便且易于安装和使用

提供对Kubernetes仪表板的一流支持

通过插件系统集成其他工具和服务
快速创建本地Kubernetes集群

支持多节点集群

与Docker容器兼容,易于使用和管理
轻量级且易于部署

支持云边协同,方便云端管理边缘节点、设备和工作负载的增删改查

边缘节点的系统升级和应用程序更新可以直接从云端下发,提升边缘的运维效率
缺点仅为测试而设计,与生产差异过大与Docker强依赖K3s < K8s

基于 Docker 而不是虚拟化

运行架构图如下:
架构这种设计带来了三大优势:

  1. 资源占用更低
    无需运行 GuestOS(虚拟机操作系统),直接复用主机的 Docker 环境,内存和磁盘占用显著低于基于虚拟机的工具。
  2. 环境兼容性更强
    不依赖虚拟化技术,可在已运行虚拟机的环境中使用(如 VMware、VirtualBox 虚拟机内),解决了 “虚拟机中嵌套虚拟机” 的兼容性问题。
  3. 便携性更好
    集群配置通过 Docker 镜像和配置文件定义,文件体积小,便于复制和分享,适合团队内统一开发环境。

使用kind安装配置集群

前提条件

  • 已安装 Docker(建议版本 20.10+),并确保 Docker 服务正常运行。
  • 本地操作系统可为 Linux、macOS 或 Windows(Windows 需使用 PowerShell)。
  • (可选)Go 环境(部分高级功能需要,基础使用可忽略)。

Linux:

1
2
3
4
5
6
7
# 对于AMD64 / x86_64架构
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.29.0/kind-linux-amd64
# 对于ARM64架构
[ $(uname -m) = aarch64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.29.0/kind-linux-arm64
# 赋予执行权限并移动到PATH路径下
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

macOS:

1
2
3
4
5
6
7
# 对于Intel芯片Mac
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.29.0/kind-darwin-amd64
# 对于M1/M2等ARM芯片Mac
[ $(uname -m) = arm64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.29.0/kind-darwin-arm64
# 赋予执行权限并移动到PATH路径下
chmod +x ./kind
mv ./kind /some-dir-in-your-PATH/kind # 替换为本地的PATH路径(如~/bin)

Windows in PowerShell:

1
2
curl.exe -Lo kind-windows-amd64.exe https://kind.sigs.k8s.io/dl/v0.29.0/kind-windows-amd64
Move-Item .\kind-windows-amd64.exe c:\some-dir-in-your-PATH\kind.exe

注意:Kind 在 0.20 版本之后强制启用了 Cgroup v2,要求内核版本高于 4.6。老系统(如 CentOS 7)可能需要使用低版本(如 v0.19)。

创建多节点集群

  1. 创建集群配置文件(例如local-cluster.yaml),定义控制节点和工作节点数量:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    networking:
    disableDefaultCNI: true # 禁用默认CNI
    podSubnet: "10.244.0.0/16" # POD容器地址网段
    nodes:
    - role: control-plane # 控制节点
    image: wangxiansen/kindest:v1.27.3 # 指定控制平面节点镜像
    - role: worker01 # 工作节点1
    image: wangxiansen/kindest:v1.27.3 # 指定工作节点镜像
    - role: worker02 # 工作节点2
    image: wangxiansen/kindest:v1.27.3 # 指定工作节点镜像
    containerdConfigPatches:
    - |-
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
    endpoint = ["https://docker.1ms.run"]

    https://docker.1ms.run 配置 Docker Hub 加速镜像站点

  2. 通过配置文件创建集群:

    1
    kind create cluster --name local-k8s-cluster --config local-cluster.yaml

    Kind 创建集群完成后会将集群的访问配置写入到 ~/.kube/config 中,可以复制或加入到有 kubectl 工具的环境中。

    1
    kubectl cluster-info --context local-k8s-cluster
  3. 验证集群状态:

    1
    2
    3
    4
    5
    6
    7
    # 查看集群节点
    kubectl get nodes
    # 输出示例(3个节点,1个控制节点+2个工作节点):
    # NAME STATUS ROLES AGE VERSION
    # local-k8s-cluster-control-plane Ready control-plane 5m v1.33.1
    # local-k8s-cluster-worker Ready <none> 5m v1.33.1
    # local-k8s-cluster-worker2 Ready <none> 5m v1.33.1
  4. 删除集群(如需清理环境):

    1
    kind delete cluster --name local-k8s-cluster

遇到问题及解决办法

问题 1:CentOS 7 使用 v0.20 + 版本 Kind 报错

1
2
3
4
5
6
7
8
9
$ kind create cluster
Creating cluster "kind" ...
✓ Ensuring node image (kindest/node:v1.30.0) 🖼
✗ Preparing nodes 📦
Deleted nodes: ["kind-control-plane"]
ERROR: failed to create cluster: command "docker run --name kind-control-plane --hostname kind-control-plane --label io.x-k8s.kind.role=control-plane --privileged --security-opt seccomp=unconfined --security-opt apparmor=unconfined --tmpfs /tmp --tmpfs /run --volume /var --volume /lib/modules:/lib/modules:ro -e KIND_EXPERIMENTAL_CONTAINERD_SNAPSHOTTER --detach --tty --label io.x-k8s.kind.cluster=kind --net kind --restart=on-failure:1 --init=false --cgroupns=private --volume /dev/mapper:/dev/mapper --publish=127.0.0.1:43665:6443/TCP -e KUBECONFIG=/etc/kubernetes/admin.conf kindest/node:v1.30.0@sha256:047357ac0cfea04663786a612ba1eaba9702bef25227a794b52890dd8bcd692e" failed with error: exit status 125
Command Output: WARNING: Your kernel does not support cgroup namespaces. Cgroup namespace setting discarded.
c55774d6753f3d8e257fb4f1dae6c10d12db12b44a933f65649da6df0c7351df
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: cgroup namespaces aren't enabled in the kernel: unknown.

解决办法:使用v0.19版本kind。

问题 2:内核高于 4.6 但未启用 Cgroup v2 导致启动失败

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# 内核版本
$ uname -r
5.4.119-20.0009.32

# docker 使用cgroup
$ docker info |grep Cgroup
Cgroup Driver: cgroupfs
Cgroup Version: 1

$ kind create cluster --name local-k8s-cluster --config local-cluster.yaml
Creating cluster "local-k8s-cluster" ...
✓ Ensuring node image (kindest/node:v1.33.1) 🖼
✓ Preparing nodes 📦 📦 📦
✓ Writing configuration 📜
✗ Starting control-plane 🕹️
Deleted nodes: ["local-k8s-cluster-worker2" "local-k8s-cluster-control-plane" "local-k8s-cluster-worker"]
ERROR: failed to create cluster: failed to init node with kubeadm: command "docker exec --privileged local-k8s-cluster-control-plane kubeadm init --config=/kind/kubeadm.conf --skip-token-print --v=6" failed with error: exit status 1
Command Output: I0722 08:05:29.122347 238 initconfiguration.go:261] loading configuration from "/kind/kubeadm.conf"
W0722 08:05:29.122774 238 common.go:101] your configuration file uses a deprecated API spec: "kubeadm.k8s.io/v1beta3" (kind: "ClusterConfiguration"). Please use 'kubeadm config migrate --old-config old-config-file --new-config new-config-file', which will write the new, similar spec using a newer API version.
W0722 08:05:29.123194 238 common.go:101] your configuration file uses a deprecated API spec: "kubeadm.k8s.io/v1beta3" (kind: "InitConfiguration"). Please use 'kubeadm config migrate --old-config old-config-file --new-config new-config-file', which will write the new, similar spec using a newer API version.
W0722 08:05:29.123557 238 common.go:101] your configuration file uses a deprecated API spec: "kubeadm.k8s.io/v1beta3" (kind: "JoinConfiguration"). Please use 'kubeadm config migrate --old-config old-config-file --new-config new-config-file', which will write the new, similar spec using a newer API version.
W0722 08:05:29.123789 238 initconfiguration.go:362] [config] WARNING: Ignored configuration document with GroupVersionKind kubeadm.k8s.io/v1beta3, Kind=JoinConfiguration
[init] Using Kubernetes version: v1.33.1
[certs] Using certificateDir folder "/etc/kubernetes/pki"
I0722 08:05:29.124893 238 certs.go:112] creating a new certificate authority for ca
[certs] Generating "ca" certificate and key
I0722 08:05:29.266069 238 certs.go:473] validating certificate period for ca certificate
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local local-k8s-cluster-control-plane localhost] and IPs [10.96.0.1 172.18.0.2 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
I0722 08:05:29.807898 238 certs.go:112] creating a new certificate authority for front-proxy-ca
[certs] Generating "front-proxy-ca" certificate and key
I0722 08:05:29.941326 238 certs.go:473] validating certificate period for front-proxy-ca certificate
[certs] Generating "front-proxy-client" certificate and key
I0722 08:05:30.247917 238 certs.go:112] creating a new certificate authority for etcd-ca
[certs] Generating "etcd/ca" certificate and key
I0722 08:05:30.601358 238 certs.go:473] validating certificate period for etcd/ca certificate
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [local-k8s-cluster-control-plane localhost] and IPs [172.18.0.2 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [local-k8s-cluster-control-plane localhost] and IPs [172.18.0.2 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
I0722 08:05:31.637396 238 certs.go:78] creating new public/private key files for signing service account users
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
I0722 08:05:31.787176 238 kubeconfig.go:111] creating kubeconfig file for admin.conf
[kubeconfig] Writing "admin.conf" kubeconfig file
I0722 08:05:32.125316 238 kubeconfig.go:111] creating kubeconfig file for super-admin.conf
[kubeconfig] Writing "super-admin.conf" kubeconfig file
I0722 08:05:32.195015 238 kubeconfig.go:111] creating kubeconfig file for kubelet.conf
[kubeconfig] Writing "kubelet.conf" kubeconfig file
I0722 08:05:32.404581 238 kubeconfig.go:111] creating kubeconfig file for controller-manager.conf
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
I0722 08:05:32.956342 238 kubeconfig.go:111] creating kubeconfig file for scheduler.conf
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
I0722 08:05:33.223304 238 local.go:66] [etcd] wrote Static Pod manifest for a local etcd member to "/etc/kubernetes/manifests/etcd.yaml"
I0722 08:05:33.223340 238 manifests.go:104] [control-plane] getting StaticPodSpecs
I0722 08:05:33.223504 238 certs.go:473] validating certificate period for CA certificate
I0722 08:05:33.223568 238 manifests.go:130] [control-plane] adding volume "ca-certs" for component "kube-apiserver"
I0722 08:05:33.223579 238 manifests.go:130] [control-plane] adding volume "etc-ca-certificates" for component "kube-apiserver"
I0722 08:05:33.223582 238 manifests.go:130] [control-plane] adding volume "k8s-certs" for component "kube-apiserver"
I0722 08:05:33.223586 238 manifests.go:130] [control-plane] adding volume "usr-local-share-ca-certificates" for component "kube-apiserver"
I0722 08:05:33.223589 238 manifests.go:130] [control-plane] adding volume "usr-share-ca-certificates" for component "kube-apiserver"
I0722 08:05:33.224386 238 manifests.go:159] [control-plane] wrote static Pod manifest for component "kube-apiserver" to "/etc/kubernetes/manifests/kube-apiserver.yaml"
I0722 08:05:33.224401 238 manifests.go:104] [control-plane] getting StaticPodSpecs
[control-plane] Creating static Pod manifest for "kube-controller-manager"
I0722 08:05:33.224524 238 manifests.go:130] [control-plane] adding volume "ca-certs" for component "kube-controller-manager"
I0722 08:05:33.224534 238 manifests.go:130] [control-plane] adding volume "etc-ca-certificates" for component "kube-controller-manager"
I0722 08:05:33.224538 238 manifests.go:130] [control-plane] adding volume "flexvolume-dir" for component "kube-controller-manager"
I0722 08:05:33.224541 238 manifests.go:130] [control-plane] adding volume "k8s-certs" for component "kube-controller-manager"
I0722 08:05:33.224544 238 manifests.go:130] [control-plane] adding volume "kubeconfig" for component "kube-controller-manager"
I0722 08:05:33.224547 238 manifests.go:130] [control-plane] adding volume "usr-local-share-ca-certificates" for component "kube-controller-manager"
I0722 08:05:33.224550 238 manifests.go:130] [control-plane] adding volume "usr-share-ca-certificates" for component "kube-controller-manager"
I0722 08:05:33.225089 238 manifests.go:159] [control-plane] wrote static Pod manifest for component "kube-controller-manager" to "/etc/kubernetes/manifests/kube-controller-manager.yaml"
I0722 08:05:33.225103 238 manifests.go:104] [control-plane] getting StaticPodSpecs
[control-plane] Creating static Pod manifest for "kube-scheduler"
I0722 08:05:33.225224 238 manifests.go:130] [control-plane] adding volume "kubeconfig" for component "kube-scheduler"
I0722 08:05:33.225661 238 manifests.go:159] [control-plane] wrote static Pod manifest for component "kube-scheduler" to "/etc/kubernetes/manifests/kube-scheduler.yaml"
I0722 08:05:33.225683 238 kubelet.go:70] Stopping the kubelet
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
I0722 08:05:33.302151 238 loader.go:402] Config loaded from file: /etc/kubernetes/admin.conf
I0722 08:05:33.302483 238 envvar.go:172] "Feature gate default state" feature="InOrderInformers" enabled=true
I0722 08:05:33.302498 238 envvar.go:172] "Feature gate default state" feature="WatchListClient" enabled=false
I0722 08:05:33.302503 238 envvar.go:172] "Feature gate default state" feature="ClientsAllowCBOR" enabled=false
I0722 08:05:33.302507 238 envvar.go:172] "Feature gate default state" feature="ClientsPreferCBOR" enabled=false
I0722 08:05:33.302510 238 envvar.go:172] "Feature gate default state" feature="InformerResourceVersion" enabled=false
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests"
[kubelet-check] Waiting for a healthy kubelet at http://127.0.0.1:10248/healthz. This can take up to 4m0s
[kubelet-check] The kubelet is not healthy after 4m0.00070732s

Unfortunately, an error has occurred, likely caused by:
- The kubelet is not running
- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)

If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
- 'systemctl status kubelet'
- 'journalctl -xeu kubelet'

The HTTP call equal to 'curl -sSL http://127.0.0.1:10248/healthz' returned error: Get "http://127.0.0.1:10248/healthz": context deadline exceeded

k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient.(*KubeWaiter).WaitForKubelet.func1
k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/wait.go:401
k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient.(*KubeWaiter).WaitForKubelet.func2
k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/wait.go:418
k8s.io/apimachinery/pkg/util/wait.loopConditionUntilContext.func2
k8s.io/apimachinery/pkg/util/wait/loop.go:87
k8s.io/apimachinery/pkg/util/wait.loopConditionUntilContext
k8s.io/apimachinery/pkg/util/wait/loop.go:88
k8s.io/apimachinery/pkg/util/wait.PollUntilContextTimeout
k8s.io/apimachinery/pkg/util/wait/poll.go:48
k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient.(*KubeWaiter).WaitForKubelet
k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/wait.go:405
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/init.runWaitControlPlanePhase
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go:87
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow.(*Runner).Run.func1
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow/runner.go:261
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow.(*Runner).visitAll
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow/runner.go:450
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow.(*Runner).Run
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow/runner.go:234
k8s.io/kubernetes/cmd/kubeadm/app/cmd.newCmdInit.func1
k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go:132
github.com/spf13/cobra.(*Command).execute
github.com/spf13/cobra@v1.8.1/command.go:985
github.com/spf13/cobra.(*Command).ExecuteC
github.com/spf13/cobra@v1.8.1/command.go:1117
github.com/spf13/cobra.(*Command).Execute
github.com/spf13/cobra@v1.8.1/command.go:1041
k8s.io/kubernetes/cmd/kubeadm/app.Run
k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go:47
main.main
k8s.io/kubernetes/cmd/kubeadm/kubeadm.go:25
runtime.main
runtime/proc.go:283
runtime.goexit
runtime/asm_amd64.s:1700
failed while waiting for the kubelet to start
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/init.runWaitControlPlanePhase
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go:89
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow.(*Runner).Run.func1
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow/runner.go:261
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow.(*Runner).visitAll
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow/runner.go:450
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow.(*Runner).Run
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow/runner.go:234
k8s.io/kubernetes/cmd/kubeadm/app/cmd.newCmdInit.func1
k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go:132
github.com/spf13/cobra.(*Command).execute
github.com/spf13/cobra@v1.8.1/command.go:985
github.com/spf13/cobra.(*Command).ExecuteC
github.com/spf13/cobra@v1.8.1/command.go:1117
github.com/spf13/cobra.(*Command).Execute
github.com/spf13/cobra@v1.8.1/command.go:1041
k8s.io/kubernetes/cmd/kubeadm/app.Run
k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go:47
main.main
k8s.io/kubernetes/cmd/kubeadm/kubeadm.go:25
runtime.main
runtime/proc.go:283
runtime.goexit
runtime/asm_amd64.s:1700
error execution phase wait-control-plane
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow.(*Runner).Run.func1
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow/runner.go:262
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow.(*Runner).visitAll
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow/runner.go:450
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow.(*Runner).Run
k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow/runner.go:234
k8s.io/kubernetes/cmd/kubeadm/app/cmd.newCmdInit.func1
k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go:132
github.com/spf13/cobra.(*Command).execute
github.com/spf13/cobra@v1.8.1/command.go:985
github.com/spf13/cobra.(*Command).ExecuteC
github.com/spf13/cobra@v1.8.1/command.go:1117
github.com/spf13/cobra.(*Command).Execute
github.com/spf13/cobra@v1.8.1/command.go:1041
k8s.io/kubernetes/cmd/kubeadm/app.Run
k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go:47
main.main
k8s.io/kubernetes/cmd/kubeadm/kubeadm.go:25
runtime.main
runtime/proc.go:283
runtime.goexit
runtime/asm_amd64.s:1700

解决办法:

  1. 检查当前 cgroups 版本:使用命令stat -fc %T /sys/fs/cgroup/查看当前系统使用的 cgroups 版本。如果输出是cgroup2fs,则表示使用的是 v2 版本;如果输出是tmpfs,则表示使用的是 v1 版本。

  2. 修改内核引导参数:如果你的发行版使用 GRUB,需要编辑/etc/default/grub文件,找到GRUB_CMDLINE_LINUX这一行,在其引号内添加systemd.unified_cgroup_hierarchy=1,修改后内容类似GRUB_CMDLINE_LINUX="quiet splash systemd.unified_cgroup_hierarchy=1"

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $  cat /etc/default/grub 
    GRUB_TIMEOUT=5
    GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
    GRUB_DEFAULT=saved
    GRUB_DISABLE_SUBMENU=true
    GRUB_TERMINAL_OUTPUT="console"
    GRUB_CMDLINE_LINUX="net.ifnames=0 consoleblank=600 console=tty0 console=ttyS0,115200n8 spectre_v2=off nopti crashkernel=auto systemd.unified_cgroup_hierarchy=1 "
    GRUB_DISABLE_RECOVERY="true"
    GRUB_ENABLE_BLSCFG=true
  3. 更新 GRUB 配置:执行命令sudo update-grub,更新 GRUB 配置,使内核引导参数的修改生效。

  4. 确认配置修改:可以通过命令cat /boot/grub/grub.cfg | grep "systemd.unified_cgroup_hierarchy=1"查看启动参数,确认配置已修改。

  5. 重启系统:执行命令sudo reboot,重启系统后,cgroups v2 将生效。

  6. 验证是否切换成功:系统重启后,再次使用命令stat -fc %T /sys/fs/cgroup/,如果输出为cgroup2fs,则说明已成功切换到 cgroups v2 版本。

问题 3:创建多集群出错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 添加新集群
$ cat <<EOF | KIND_EXPERIMENTAL_DOCKER_NETWORK=kind kind create cluster --name=flannel-ipip --image=wangxiansen/kindest:v1.27.3 --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
disableDefaultCNI: true
podSubnet: "10.244.0.0/16"
nodes:
- role: control-plane
- role: worker
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://docker.1ms.run"]
EOF

# 报错信息
I0801 14:56:58.198503 177 round_trippers.go:553] GET https://flannel-ipip-control-plane:6443/api/v1/nodes/flannel-ipip-worker?timeout=10s 404 Not Found in 1 milliseconds
I0801 14:56:58.698722 177 round_trippers.go:553] GET https://flannel-ipip-control-plane:6443/api/v1/nodes/flannel-ipip-worker?timeout=10s 404 Not Found in 2 milliseconds
I0801 14:56:59.198049 177 round_trippers.go:553] GET https://flannel-ipip-control-plane:6443/api/v1/nodes/flannel-ipip-worker?timeout=10s 404 Not Found in 2 milliseconds
I0801 14:56:59.698995 177 round_trippers.go:553] GET https://flannel-ipip-control-plane:6443/api/v1/nodes/flannel-ipip-worker?timeout=10s 404 Not Found in 2 milliseconds
I0801 14:57:00.198293 177 round_trippers.go:553] GET https://flannel-ipip-control-plane:6443/api/v1/nodes/flannel-ipip-worker?timeout=10s 404 Not Found in 1 milliseconds
I0801 14:57:00.199855 177 round_trippers.go:553] GET https://flannel-ipip-control-plane:6443/api/v1/nodes/flannel-ipip-worker?timeout=10s 404 Not Found in 1 milliseconds
nodes "flannel-ipip-worker" not found
error uploading crisocket

解决办法:

1
2
3
$ cat /etc/sysctl.conf | rg inotify
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 512

总结

kind作为 Kubernetes 官方工具,以 “基于 Docker 容器运行 K8s 组件” 为核心优势,在本地多节点集群搭建、开发测试和学习场景中表现出色。相比 Minikube(虚拟机依赖)和 k3s(边缘侧重),它兼顾了启动速度、资源效率和多节点模拟能力,是开发者快速上手 Kubernetes 的理想选择。

通过本文的步骤,你可以轻松搭建 kind 集群,并解决常见的版本兼容问题。如需进一步深入,建议参考kind 官方文档,探索更多高级配置(如网络插件、镜像加载、自定义 Kubernetes 版本等)。