准备 Kubernetes 练习环境
本篇目标是创建一个可随时删除的练习集群。单机学习资源对象时选择 kind;需要理解节点、容器运行时和集群初始化时,选择 kubeadm。生产集群的准入、网络、备份和权限策略复杂得多,第一次学习不应直接在生产环境试命令。
完成后,你应能确认当前 kubectl 操作的是哪一个集群,并能创建和删除一个本地集群。

1. 安装 kubectl
kubectl 是 Kubernetes API 的命令行客户端。安装方式随系统不同而变化,请以 Kubernetes 官方安装说明 为准。安装后先验证客户端:
kubectl version --client
kubectl config get-contexts
kubectl config get-contexts 会列出所有已知集群。星号所在行是当前上下文,任何有修改效果的命令都应先确认它。
kubectl delete、apply、scale 等命令会直接调用当前 context 对应的集群。不要把生产 context 设为默认练习环境;生产操作应明确指定 context 和 Namespace,并经评审执行。
2. 用 kind 创建本地集群
kind 使用 Docker 容器模拟 Kubernetes 节点,适合练习资源对象和发布流程。先确保 Docker Engine 正在运行,再安装 kind:
# macOS
brew install kind kubectl
# 创建名为 k8s-lab 的单节点集群
kind create cluster --name k8s-lab
# 确认 kubectl 已切换到对应 context
kubectl config current-context
kubectl get nodes
预期看到一个状态为 Ready 的 control-plane 节点。首次创建会拉取节点镜像,需要一些时间。
3. 用 kubeadm 创建多节点练习集群(可选)
kind 已足够完成本系列的大多数练习。若你有可重装的 Linux 虚拟机或云主机,可通过 kubeadm 搭建一套更接近真实架构的集群。推荐准备两台:一台控制面节点和一台工作节点;只有一台时也能完成单节点实验。
以下步骤以 Ubuntu 22.04/24.04、Kubernetes v1.34 和 containerd 为例。不要直接复制到生产环境:生产集群还需要高可用控制面、etcd 备份、受控的镜像仓库、节点加固、网络隔离和监控告警。
3.1 规划节点与网络
示例使用下列地址。控制面和工作节点必须能通过内网互通,且各节点主机名唯一。Pod CIDR 192.168.0.0/16 会交由 Calico 使用,不能与主机网络、VPN 或现有 Pod 网络重叠。
| 节点 | 主机名 | 示例内网地址 | 角色 |
|---|---|---|---|
| 控制面 | k8s-control-01 | 192.168.56.10 | API Server、etcd、调度和控制器 |
| 工作节点 | k8s-worker-01 | 192.168.56.11 | 运行业务 Pod |
每台虚拟机建议至少 2 vCPU、2 GiB 内存和 20 GiB 磁盘;控制面建议 2 vCPU、4 GiB 内存。云安全组或主机防火墙至少应允许节点间的 Kubernetes 控制面和 CNI 通信。练习时最简单的做法是仅在可信的私有网段内放通节点之间的流量。
3.2 在所有节点安装 containerd 与 kubeadm
以下命令需要在控制面和每个工作节点执行。Kubernetes 使用 containerd 作为 CRI 容器运行时;禁用 swap 并让 containerd 使用 systemd cgroup,是 kubelet 正常运行的前提。
# 所有节点执行:加载容器网络所需的内核模块
sudo tee /etc/modules-load.d/k8s.conf >/dev/null <<'EOF'
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 所有节点执行:让 iptables 能看到经过网桥的流量,并启用转发
sudo tee /etc/sysctl.d/k8s.conf >/dev/null <<'EOF'
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
# 所有节点执行:kubelet 默认要求关闭 swap
sudo swapoff -a
sudo sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
# 所有节点执行:安装并配置 containerd
sudo apt-get update
sudo apt-get install -y ca-certificates curl gpg containerd
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl enable --now containerd
添加 Kubernetes 软件源并安装指定小版本的工具。版本号应在控制面和工作节点保持一致;升级时遵循后文的集群生命周期管理,不要直接升级生产节点。
# 所有节点执行:Kubernetes v1.34 软件源
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key \
| sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /' \
| sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
安装后,在每台节点确认运行时和 kubelet 已启动。此时 kubelet 可能反复重启,因为它还没有收到 kubeadm 生成的配置,这是正常现象。
sudo systemctl status containerd --no-pager
sudo systemctl status kubelet --no-pager
3.3 初始化控制面
仅在控制面节点执行。将 CONTROL_PLANE_IP 改为该节点可被其他节点访问的内网 IP;不要填写 Pod CIDR 中的地址。
# 仅控制面节点执行
CONTROL_PLANE_IP=192.168.56.10
sudo kubeadm init \
--apiserver-advertise-address="${CONTROL_PLANE_IP}" \
--pod-network-cidr=192.168.0.0/16
# 让当前普通用户可以访问新集群
mkdir -p "$HOME/.kube"
sudo cp -i /etc/kubernetes/admin.conf "$HOME/.kube/config"
sudo chown "$(id -u):$(id -g)" "$HOME/.kube/config"
kubectl get nodes
kubeadm init 最后的输出包含 kubeadm join 命令。它带有短期令牌,应妥善保存,仅在可信节点上使用。令牌默认 24 小时过期;过期后可在控制面重新生成:
sudo kubeadm token create --print-join-command
3.4 安装 Pod 网络插件
控制面就绪不代表 Pod 网络已经可用。下面以 Calico 为例,安装完成前 CoreDNS 处于 Pending 是预期现象。Calico 的发布版本需要与 Kubernetes 版本兼容;创建固定版本的实验环境时,应把版本同时记录在变更或实验笔记中。
# 仅控制面节点执行
CALICO_VERSION=v3.31.0
kubectl apply -f "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/calico.yaml"
# 等待网络组件和 CoreDNS 就绪
kubectl get pods -n kube-system -w
若使用其他 CNI,必须按其官方安装文档设置对应的 Pod CIDR 和网络策略能力;不要同时安装多个 CNI。
3.5 加入工作节点
在控制面执行前一节保存的 kubeadm join 命令,或重新生成一条命令。然后在每一台工作节点粘贴并以 sudo 执行,例如:
# 仅工作节点执行;此命令以控制面实际输出为准
sudo kubeadm join 192.168.56.10:6443 \
--token TOKEN_VALUE \
--discovery-token-ca-cert-hash sha256:HASH_VALUE
回到控制面验证节点和系统组件。所有节点显示 Ready 后,再继续后续工作负载练习。
kubectl get nodes -o wide
kubectl get pods -n kube-system
kubectl cluster-info
如果只准备了一台实验机,可以移除控制面的调度污点,让业务 Pod 也能调度到该节点。这个设置仅适合单节点实验环境,生产控制面通常不应承载普通业务工作负载。
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
3.6 重置 kubeadm 实验环境
先在控制面驱逐工作节点的业务,再在各节点执行重置。kubeadm reset 不会删除 CNI 创建的网络规则或当前用户的 kubeconfig;以下清理命令会删除本机的集群配置,只能用于明确不再需要的实验集群。
# 控制面执行:先移除每个工作节点,替换为实际节点名
kubectl drain k8s-worker-01 --ignore-daemonsets --delete-emptydir-data
kubectl delete node k8s-worker-01
# 所有节点执行:重置 kubeadm 状态
sudo kubeadm reset -f
sudo rm -rf /etc/cni/net.d
# 控制面执行:若确认不再使用该 kubeconfig,再删除它
rm -rf "$HOME/.kube"
4. 建立自己的 Namespace
不要把练习资源堆在 default 或 kube-system。创建独立 Namespace,后续命令始终显式指定它:
kubectl create namespace learning
kubectl get namespace learning
# 创建一个只在当前终端生效的快捷 Namespace
kubectl config set-context --current --namespace=learning
kubectl config view --minify --output 'jsonpath={..namespace}{"\n"}'
最后一条命令应输出 learning。本系列示例默认使用此 Namespace;如果不设置默认值,请在每条命令中加入 -n learning。
5. 连接检查
# 控制面 API 是否可用
kubectl cluster-info
# 当前身份可以做什么;生产环境不应拥有 * 权限
kubectl auth can-i create deployments -n learning
kubectl auth can-i delete namespaces
# 查看核心系统组件所在 Namespace,不要在这里练习删除操作
kubectl get pods -n kube-system
kubectl auth can-i 是排查权限问题的第一步。若创建 Deployment 的结果为 no,应申请测试 Namespace 的最小权限,不要借用管理员 kubeconfig。
6. 清理 kind 练习环境
练习结束后可删除整个 kind 集群:
kind delete cluster --name k8s-lab
这会删除本地节点容器及其内部资源。真实集群绝不能使用类似“删除整个 Namespace / 集群”的方式清理,必须按变更流程逐项确认数据和依赖。
验收清单
-
kubectl version --client正常输出 -
kubectl config current-context指向练习集群 -
kubectl get nodes至少有一个Ready节点 - 已创建
learningNamespace - 会用
kubectl auth can-i检查权限 - 使用 kubeadm 时,所有节点均为
Ready,且kube-system中的 CNI 与 CoreDNS 已就绪
下一篇:看懂集群与核心资源。