学习目标
学完本章你应该能够:
- 讲清 kind 是什么:用 Docker 容器当节点的「伪集群」,适合资源有限的本地学习环境。
- 写一份
kind.yaml配置:多节点(1 control-plane + 2 worker)、ingress 端口映射、私有镜像仓库接入。 - 用 kind 起集群并把一个本地镜像(如 nginx)跑起来,通过 NodePort 从宿主机访问。
- 在同事面前把「为什么本地要用 kind 而不是 minikube」讲清楚取舍。
前置知识:
- 已安装 Docker 与
kubectl - 知道 Pod / Deployment / Service 是 K8s 基本资源(哪怕只在别处看过)
- 建议配合「容器和 k8s 入门」一起看,那里讲了 kind 的完整搭建脚本
本章你会动手做的事:
- 用文末
kind.yamlkind create cluster起一个 3 节点集群。 - 把 nginx 的 Deployment + NodePort Service apply 起来,从宿主机
curl通。 - 故意多映射一个端口,观察
extraPortMappings怎么把节点容器端口暴露到宿主机。
一、Kind 集群长什么样
类比:kind 就像「用乐高积木拼出一座 mini 城市」——每个 Docker 容器是一块积木,kind 把它们拼成 control-plane(市政府)和 worker(各个街区),外面用
extraPortMappings打通「城市道路」让你从宿主机的浏览器进城。比起真在云上开几台虚拟机,这城市零成本、说拆就拆。
下面这张图把「1 个 control-plane + 2 个 worker + 端口映射」的拓扑画出来:
flowchart LR
CP[control-plane
ingress-ready=true] --> W1[worker]
CP --> W2[worker]
subgraph 端口映射[extraPortMappings]
M[80 / 443 / 30080-30090 / 31272
容器端口 → 宿主机端口]
end
CP --- M二、Kind 的 yaml 配置文件
下面这份是完整的 kind.yaml。逐行看可能晕,先抓主干:nodes 定义几个节点、containerdConfigPatches 给节点配镜像加速、extraPortMappings 把节点内端口暴露到宿主机。
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://ustc-edu-cn.mirror.aliyuncs.com", "https://ccr.ccs.tencentyun.com", "https://docker.m.daocloud.io"]
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 30080
hostPort: 30080
protocol: TCP
- containerPort: 30081
hostPort: 30081
protocol: TCP
- containerPort: 30082
hostPort: 30082
protocol: TCP
- containerPort: 30083
hostPort: 30083
protocol: TCP
- containerPort: 30084
hostPort: 30084
protocol: TCP
- containerPort: 30085
hostPort: 30085
protocol: TCP
- containerPort: 30086
hostPort: 30086
protocol: TCP
- containerPort: 30087
hostPort: 30087
protocol: TCP
- containerPort: 30088
hostPort: 30088
protocol: TCP
- containerPort: 30089
hostPort: 30089
protocol: TCP
- containerPort: 30090
hostPort: 30090
protocol: TCP
- containerPort: 31272
hostPort: 31272
protocol: TCP
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- role: worker
- role: worker
几个关键点(按「步骤」拆开看):
- 步骤 1:control-plane 打
ingress-ready=true标签 —— 这是给 ingress-nginx 用的;ingress controller 只会调度到带这个标签的节点上当「入口」。 - 步骤 2:
extraPortMappings端口映射 —— 把节点容器里的端口(如 30080)映射到宿主机同号端口,这样你在本机浏览器localhost:30080就能访问到集群内的服务。 - 步骤 3:
containerdConfigPatches镜像加速 —— 给容器运行时配国内镜像源,拉docker.io的镜像更快,否则 kind 起集群会卡在拉镜像。 - 步骤 4:2 个 worker —— 加上 control-plane,凑成「1 控制面 + 2 工作节点」的真实多节点感,才能演练调度。
起集群的命令(同样按步骤拆):
# 步骤 1:用上面的配置创建名为 dev 的集群
kind create cluster --config kind.yaml --name dev
# 步骤 2:验证节点都就绪
kubectl get nodes
# 步骤 3:装 ingress-nginx(它会找 ingress-ready 标签的节点)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
三、安装 nginx 测试集群
先用一个最朴素的 nginx 验证「镜像能跑、端口能通」。
类比:NodePort 像是给每栋楼(节点)统一开了一个「对外营业的旁门」——你不用知道楼里哪个房间(Pod)在处理,只要敲这个固定门牌号(30080),请求就会被转发进去。
下面把「宿主机 → NodePort → Pod」的转发链画出来:
flowchart LR
U[宿主机浏览器
curl localhost:30080] --> NP[NodePort 30080
Service nginx-nodeport]
NP --> P1[Pod nginx]
NP --> P2[Pod nginx]apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.22
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080 # 可以指定一个端口号,如果不指定,会自动分配一个
⚠️ 新手必踩的坑:NodePort 端口范围 +
extraPortMappings是两回事。K8s 的 NodePort 默认只允许30000–32767区间,本文nodePort: 30080落在区间里没问题。但extraPortMappings是把节点容器的端口映射到宿主机(kind 特有),和 Service 的nodePort是两个不同层面——前者让「宿主机↔节点容器」通,后者让「集群内 Service↔Pod」通,别混为一谈。另外 M1/M2 Mac 上要docker buildx build --platform linux/arm64构建镜像,否则跑 amd64 镜像会因 QEMU 模拟很慢。
跑起来后验证:
# 步骤 1:部署 Deployment + Service
kubectl apply -f nginx.yaml
# 步骤 2:等 Pod 都 Running
kubectl get pods -l app=nginx
# 步骤 3:从宿主机访问 NodePort
curl localhost:30080
自测题与动手练习
自测题(合上书能答出来,才算懂):
- kind 用的是什么来模拟 K8s 节点?为什么它比在云上开真虚拟机更适合本地学习?
extraPortMappings把端口映射到了哪一层(宿主机 ↔ 节点容器),它和 Service 的nodePort是一回事吗?control-plane上打的ingress-ready=true标签是给谁用的?为什么 ingress controller 需要它?- 文末 nginx 用 NodePort 暴露,
nodePort: 30080落在 K8s 允许的端口区间里吗? - 起完集群后
kubectl get nodes看到 worker 是Ready,但 Pod 一直Pending,最可能缺什么(提示:看本文资源声明与调度)?
动手练习(建议真做一遍):
- 用文末
kind.yaml起集群,kubectl get nodes确认 1 个 control-plane + 2 个 worker 都 Ready。 - apply nginx 的 Deployment + NodePort Service,从宿主机
curl localhost:30080验证能拿到 nginx 默认页。 - 改
kind.yaml多加一个extraPortMappings(比如 30091→30091),kind delete cluster重建后curl新端口,理解映射机制。
本章小结
- kind 用 Docker 容器模拟 K8s 节点,1 个 control-plane + 2 个 worker 即可在笔记本上跑出「多节点调度」的真实感,零成本、易销毁。
extraPortMappings负责把节点容器端口暴露到宿主机,和 Service 的nodePort是两个不同层面,调试时别混淆。- ingress 需要 control-plane 打
ingress-ready=true标签,再 apply ingress-nginx 才能接管 80/443。 - 下一步可回到「容器和 k8s 入门」用这份 kind 集群跑通 Helm / Kustomize 交付的应用。