一、Kubernetes 集群搭建全流程讲解
理解了"为什么",这些命令就不用死记硬背了。
环境:Ubuntu 26.04 + Kubernetes v1.30.14 + containerd + Calico,1 个 master + 1 个 worker。
1、整体认知:k8s 集群长什么样
javascript
┌─────────────┐
kubectl ────▶│ Master │ 大脑:管调度、存数据、发指令
(管理命令) │ apiserver │ 唯一入口
│ etcd │ 数据库(存集群状态)
│ scheduler │ 调度器:决定 Pod 去哪台机器
│ controller │ 控制器:维持期望状态
└──────┬──────┘
│ 6443 端口
┌─────────┴─────────┐
▼ ▼
┌──────────┐ ┌──────────┐
│ Worker 1 │ │ Worker 2 │ 手脚:真正跑应用容器
│ kubelet │ │ kubelet │ 每节点一个"代理人"
│containerd│ │containerd│ 容器引擎
└──────────┘ └──────────┘
本次搭建:1 个 master + 1 个 worker,最小可用集群。
2、流程回顾:为什么按这个顺序做
阶段 1:节点准备(检查 + 修改系统)
k8s 对运行环境有一堆硬性要求,不满足就会在某个环节报莫名其妙的错。先做 7 项检查:
| 检查项 | 不满足的后果 | 实际情况 |
|---|---|---|
| 系统版本 | 安装命令不兼容 | Ubuntu 26.04 ✅ |
| CPU≥2核、内存≥2G | kubeadm 预检直接拒绝 | 3.3G 勉强过(建议 4G+) |
| hostname 全小写 | k8s 节点名规范,大写会被拒 | 已改 ✅ |
| 单网卡/确定用哪块 | kubelet 选错 IP,节点互相找不到 | ens33 ✅ |
| 节点互通、防火墙关闭 | 6443 等端口被拦,join 失败 | ufw 已关 ✅ |
| 不直接用 docker | 概念性要求 | ✅ |
另外三件"提前修"的事:
- 关 swap:k8s 调度器需要根据内存精确决定 Pod 放哪台机器,swap 会让内存数据不准,所以强制要求关
- /etc/hosts 互写:内网主机名没有 DNS 解析,k8s 组件按名字找对方,必须手动告诉每台机器"谁是谁"
- 关防火墙:master/worker 之间要开十几个端口通信,学习阶段直接全关最省事
阶段 2:安装三大组件(每个节点都装)
text
kubelet → k8s 在每个节点上的"代理人",负责创建/管理 Pod
containerd → 容器引擎,真正拉起容器(k8s 1.24 后官方不再支持 Docker,这是行业标准)
kubeadm → 集群安装工具,master 用它 init,worker 用它 join
kubectl → 管理命令行(只有操作集群的地方需要)
为什么 containerd 要改 SystemdCgroup = true :
cgroup 是 Linux 限制进程资源(CPU/内存)的机制,有两套驱动(cgroupfs 和 systemd)。
kubelet 用 systemd 驱动,containerd 默认用 cgroupfs,两边不一致会导致资源限制失效、节点状态异常------这是必须对齐的配置。
为什么要开 br_netfilter、ip_forward :
Pod 网络依赖 Linux 网桥和 IP 转发,默认没开,Calico 的虚拟网络会不通。
阶段 3:初始化 master(kubeadm init)
这一步做的事,用大白话说:
- 预检:把阶段 1 的所有条件再检查一遍
- 拉镜像 :apiserver、etcd、scheduler 等以容器形式运行(k8s 用容器管自己),从阿里云镜像站拉(默认地址国内拉不动)
- 发证书:集群内所有通信都要 TLS 加密,生成一整套 CA 和证书
- 写配置 :在
/etc/kubernetes/manifests/生成几个"静态 Pod 清单"------这是特殊机制:kubelet 启动时自动读取这个目录,把 apiserver、etcd 等拉起来。先有 kubelet 照清单拉容器,才有 apiserver,之后 kubelet 再听命于 apiserver - 生成 join 门票:token + 证书哈希,worker 凭它加入集群
踩坑实录 ① :kubelet 拉 apiserver 容器前需要基础镜像 pause (每个 Pod 的"地基"),它写死了去
registry.k8s.io拉------国内连不通。解法:给镜像"换马甲"------从阿里云拉下来,tag 成官方地址,让 kubelet 误以为"本地已有"。
阶段 4:配置 kubectl + 安装网络插件
bash
cp /etc/kubernetes/admin.conf ~/.kube/config # 告诉 kubectl:集群地址+管理员凭据
为什么装完 Calico 节点才 Ready :
k8s 只负责"调度 Pod 到某台机器",Pod 之间的虚拟网络是另一层(CNI 插件)负责的。
没装网络插件时,节点网络状态未就绪,所以一直 NotReady。
Calico 就是给所有 Pod 发虚拟 IP、打通跨节点通信的"交换机系统"。
为什么 Pod 网段必须是 10.100.0.0/16 :
物理网络是 192.168.152.x,Calico 默认的 192.168.0.0/16 会和它重叠------路由表分不清"去物理机的 192.168.152.5"还是"去 Pod 的 192.168.x.x",网络直接瘫痪。
所以必须改成不冲突的网段,并且 kubeadm 和 Calico 配置两边要一致。
踩坑实录 ② :Calico 镜像在 docker.io,国内拉不动。
解法 :给 containerd 配镜像加速(
/etc/containerd/certs.d/docker.io/hosts.toml),相当于给它一个"国内中转站"地址。
阶段 5:worker 加入(kubeadm join)
text
worker: "我要加入"(出示 token 门票)
↓
master 的 apiserver 验证门票 → 批准
↓
worker 的 kubelet 自动向 master 申请正式证书(TLS Bootstrap)
↓
worker 成为集群一员,master 开始给它派活
worker 上为什么不用配 kubectl :它只是干活的,管理权在 master。
在 worker 上执行 kubectl 报错连 localhost:8080,就是因为它压根没有管理员凭据。
阶段 6:验证
部署一个 nginx,本质是验证三层:
- 调度:scheduler 把 Pod 放到某台节点
- 网络:浏览器 → master IP:NodePort → kube-proxy 转发 → Pod(跨节点则验证了 Calico 隧道)
- 生态:镜像拉取(daocloud 加速)、DNS(coredns)都工作
三、一句话总结整个流程
备好环境(主机名/IP/网络)→ 每台装 kubelet+containerd → master 上 init 建集群 → 装 Calico 让 Pod 通网 → worker 拿 token join → 部署应用验证。
二、Kubernetes 集群搭建命令手册(Ubuntu 26.04 + k8s 1.30.14)
环境约定
- Master: 192.168.152.135 (chn-k8s-master)
- Worker: 192.168.152.136 (chn-k8s-worker)
- k8s 版本: v1.30.14
- Pod 网段: 10.100.0.0/16
- 标注【双节点】= master 和 worker 都执行
阶段 1:节点准备【双节点】
bash
# 1.1 修改主机名(两台分别执行,改完 exec bash 刷新)
sudo hostnamectl set-hostname chn-k8s-master # master
sudo hostnamectl set-hostname chn-k8s-worker # worker
exec bash
# 1.2 静态 IP(worker 换成 192.168.152.136)
sudo nmcli con mod "netplan-ens33" ipv4.method manual ipv4.addresses 192.168.152.135/24 ipv4.gateway 192.168.152.2 ipv4.dns "114.114.114.114 8.8.8.8"
sudo nmcli con down "netplan-ens33" && sudo nmcli con up "netplan-ens33"
# 1.3 关防火墙 / 1.4 关 swap
sudo ufw disable
sudo swapoff -a
sudo sed -i '/swap/s/^/#/' /etc/fstab
# 1.5 hosts 互解析(双节点都执行;先替换旧主机名)
sudo sed -i 's/chn-k8s-master-VMware-Virtual-Platform/chn-k8s-master/' /etc/hosts
sudo sed -i 's/chn-k8s-worker-VMware-Virtual-Platform/chn-k8s-worker/' /etc/hosts
echo -e "192.168.152.135 chn-k8s-master\n192.168.152.136 chn-k8s-worker" | sudo tee -a /etc/hosts
# 1.6 验证: hostname / ip a (无dynamic) / ping 对端主机名
阶段 2:安装组件【双节点】
bash
# 2.1 containerd
sudo apt update && sudo apt install -y containerd
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd && sudo systemctl enable containerd
# 2.2 内核模块与参数
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay && sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
# 2.3 kubelet/kubeadm/kubectl(阿里云源)
sudo apt install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/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://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable kubelet
# 2.4 镜像预处理(国内防坑)
sudo ctr -n k8s.io images pull registry.aliyuncs.com/google_containers/pause:3.10.1
sudo ctr -n k8s.io images tag registry.aliyuncs.com/google_containers/pause:3.10.1 registry.k8s.io/pause:3.10.1
sudo mkdir -p /etc/containerd/certs.d/docker.io
sudo tee /etc/containerd/certs.d/docker.io/hosts.toml <<'EOF'
server = "https://docker.io"
[host."https://docker.m.daocloud.io"]
capabilities = ["pull", "resolve"]
EOF
sudo sed -i "s#config_path = ''#config_path = '/etc/containerd/certs.d'#" /etc/containerd/config.toml
sudo systemctl restart containerd
阶段 3:初始化 Master【仅 master】
bash
sudo kubeadm init \
--kubernetes-version=v1.30.14 \
--image-repository registry.aliyuncs.com/google_containers \
--apiserver-advertise-address=192.168.152.135 \
--pod-network-cidr=10.100.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
阶段 4:Calico 网络插件【仅 master】
bash
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/calico.yaml
sed -i -e 's/^ # - name: CALICO_IPV4POOL_CIDR/ - name: CALICO_IPV4POOL_CIDR/' \
-e 's/^ # value: "192.168.0.0\/16"/ value: "10.100.0.0\/16"/' calico.yaml
grep -A1 CALICO_IPV4POOL_CIDR calico.yaml
kubectl apply -f calico.yaml
watch kubectl get pods -n kube-system
kubectl get nodes # Ready
阶段 5:Worker 加入【仅 worker】
bash
sudo kubeadm join 192.168.152.135:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
# 重新生成: master 上执行 kubeadm token create --print-join-command
阶段 6:验证【master】
bash
kubectl get nodes
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get svc nginx
curl http://192.168.152.135:3xxxx
kubectl delete deployment nginx && kubectl delete svc nginx
维护与排错
bash
sudo kubeadm reset -f && rm -rf $HOME/.kube # 重置集群
kubectl get pods -A # 谁不正常
kubectl describe pod <pod> -n <ns> | tail -20 # 看 Events
kubectl logs <pod> -n <ns> # 看日志