结论: 部署一套生产可用的 Kubernetes 集群,最短路径是 kubeadm + containerd + CNI 插件三件套:先按角色规划节点并做好 swap/内核参数/时间同步三项前置,再用 kubeadm init 初始化控制平面、kubeadm join 加入工作节点,最后安装 Calico 或 Flannel 让 Pod 网络打通。生产环境控制平面节点至少 3 个,这是 etcd 多数派选举(quorum)的硬性要求,不是冗余建议。
Kubernetes(常简称 K8s)把服务器抽象成了一个资源池:你不关心任务跑在哪台机器上,只声明"要几个副本、要多少 CPU 和内存"。这个抽象很有价值,但它也是部署复杂度的来源——控制平面、容器运行时、CNI 网络、存储、负载均衡这五层,任何一层没配好,集群都会处于"能起来但不能用"的状态。
本文以 Ubuntu 24.04 LTS + Kubernetes 1.33 为例(截至 2026 年,请按 kubeadm 官方支持矩阵选择仍在维护的版本),给出可直接复制执行的完整流程。
集群规划:节点数量、硬件配置与"为什么至少 3 个 master"
结论前置:生产环境控制平面至少 3 个节点,因为 etcd 采用 Raft 一致性算法,需要多数派(n/2+1)存活才能对外提供写入;2 个节点与 1 个节点在容错能力上没有本质区别(都是不容错)。
| 角色 | 最小生产配置 | CPU / 内存建议 | 数量建议 | 说明 |
|---|---|---|---|---|
| control-plane(master) | 2 核 / 2 GB,推荐 4 核 / 8 GB | 与节点数同步扩展,节点越多 apiserver 压力越大 | ≥ 3(奇数) | 承载 kube-apiserver、etcd、kube-scheduler、kube-controller-manager |
| worker | 2 核 / 2 GB,推荐 4 核 / 16 GB 起 | 按业务 Pod 的 requests 总量上浮 20%~30% | ≥ 2 | 承载 kubelet、容器运行时与业务 Pod |
| etcd(独立部署时) | 4 核 / 8 GB,SSD/NVMe | IOPS 是关键指标 | 3 或 5 | 大规模集群通常与 control-plane 分离部署 |
| 负载均衡器 | — | — | 1(VIP)或云 LB | 对外暴露 apiserver 的 6443,实现控制平面高可用 |
关于节点数量,还有三条实操建议:
- 控制平面节点必须是奇数:3 节点容忍 1 台故障,5 节点容忍 2 台;4 节点同样只能容忍 1 台,还多耗一台机器。
- worker 至少 2 个:不是为了高可用,而是为了验证调度、网络跨节点连通与滚动更新是否正常。
- 磁盘要给足:worker 上镜像层与容器层会持续增长,建议 200 GB 以上并单独挂载
/var/lib/containerd;磁盘写满是 Node NotReady 最常见的原因之一。
前置准备:swap、内核参数与时间同步三件套
结论前置:跳过这三项直接跑 kubeadm,是最常见的失败原因。 以下步骤需要在所有节点(control-plane 与 worker)上执行。
# 1) 关闭 swap 并取消开机挂载(kubelet 默认拒绝在开启 swap 的节点上工作)
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
swapon --show # 无输出即表示已关闭
# 2) 加载 overlay 与 br_netfilter 内核模块
cat <<'EOF' | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 3) 让 iptables 能够过滤桥接流量,这是 Service 转发与 NetworkPolicy 生效的前提
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
# 4) 时间同步:证书校验、日志排序、调度器判定都依赖一致的时钟
sudo apt update && sudo apt install -y chrony
sudo systemctl enable --now chrony
chronyc sources
timedatectl status另外两项容易被忽略的检查:所有节点的主机名必须唯一且能被 DNS 或 /etc/hosts 解析(否则 apiserver 证书 SAN 校验会失败);确认 SELinux 处于关闭或 permissive 模式(Ubuntu 默认不启用,CentOS/RHEL 系需检查)。
安装容器运行时 containerd 与 kubeadm 三件套
结论前置:containerd 是当前推荐的容器运行时;它的 cgroup driver 必须配置为 systemd,否则 kubelet 与运行时的资源限制口径不一致,会出现节点频繁驱逐 Pod 甚至 NotReady。
# 安装 containerd.io(来自 Docker 官方仓库,版本号以实际仓库为准)
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update
sudo apt-get install -y containerd.io
# 生成默认配置并改用 systemd cgroup driver
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl daemon-reload
sudo systemctl enable --now containerd
sudo ctr version接着安装 kubeadm、kubelet、kubectl。注意三者的版本要严格一致,且要锁定(hold)防止意外升级:
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/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.33/deb/ /' \
| sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl cri-tools
sudo apt-mark hold kubelet kubeadm kubectl
# 让 crictl 指向 containerd 套接字(否则排查容器时会连不上运行时)
sudo crictl config runtime-endpoint unix:///var/run/containerd/containerd.sock
sudo crictl ps -a如果要使用国内镜像代替 registry.k8s.io,可以在 kubeadm init 时用 --image-repository 指定,或在 containerd 配置里设置 registry mirror。不要混用多种镜像源配置,那会导致拉取失败时无法判断到底用的哪个源。
初始化控制平面:kubeadm init 完整命令
结论前置:kubeadm init 的关键参数有三个——--pod-network-cidr(必须与你后面要装的 CNI 插件默认值一致)、--control-plane-endpoint(多 master 时必须配负载均衡入口)、--apiserver-advertise-address(多网卡时必须显式指定)。
# 单控制平面(测试环境)示例
sudo kubeadm init \
--apiserver-advertise-address=10.0.0.10 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--kubernetes-version=v1.33.0
# 多控制平面(生产)示例:务必加 control-plane-endpoint 指向负载均衡 VIP
sudo kubeadm init \
--control-plane-endpoint="k8s-api.example.com:6443" \
--apiserver-advertise-address=10.0.0.10 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--kubernetes-version=v1.33.0 \
--upload-certs初始化完成后按提示配置 kubeconfig,并把 join 命令保存好(24 小时后会过期):
mkdir -p "$HOME"/.kube
sudo cp /etc/kubernetes/admin.conf "$HOME"/.kube/config
sudo chown "$(id -u)":"$(id -g)" "$HOME"/.kube/config
kubectl get nodes
# worker 节点加入集群
sudo kubeadm join 10.0.0.10:6443 --token \
--discovery-token-ca-cert-hash sha256:
# 令牌过期也不怕,随时重新生成
kubeadm token create --print-join-command 校验健康的快速清单:kubectl get cs 看组件状态、kubectl -n kube-system get pod -o wide 确认 coreDNS 以外的系统 Pod 全部 Running、确认 coreDNS 的 Pod 已就绪(CNI 没装好时它们会一直 Pending)。
CNI 插件:Calico 与 Flannel 怎么选
结论前置:CNI(Container Network Interface,容器网络接口)插件负责 Pod 之间跨节点通信。没有 CNI,节点永远是 NotReady。 小集群和学习环境用 Flannel 图个省事;需要网络策略与更大规模时用 Calico。
| 对比项 | Flannel | Calico |
|---|---|---|
| 网络模型 | overlay 封装(VXLAN 为主,也支持 host-gw) | 支持 VXLAN / IPIP / BGP 直连路由多种模式 |
| 默认 Pod CIDR | 10.244.0.0/16 | 10.244.0.0/16(可在 Installation CR 中修改) |
| 网络策略 | 不支持 NetworkPolicy | 原生支持丰富的 NetworkPolicy |
| 简易度 | 部署一条命令,配置极少 | 组件较多(operator + calico-node + typha 等),可配置项丰富 |
| 性能 | VXLAN 模式有封装开销 | BGP 直连模式接近物理网络性能 |
| 适用规模 | 中小集群、边缘场景 | 中大型集群、要求网络隔离与安全策略的场景 |
安装 Flannel(要求 init 时使用默认的 10.244.0.0/16):
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
kubectl -n kube-flannel get pod -o wide安装 Calico(Operator 方式,版本需与 Kubernetes 版本匹配,请查官方兼容矩阵后替换版本号):
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.0/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.0/manifests/custom-resources.yaml
kubectl get tigerastatus如果需要自定义 Pod 网段,在安装前确认 Installation 资源的 spec.calicoNetwork.ipPools[0].cidr 与 kubeadm 的 --pod-network-cidr 完全一致;网上很多人只剩一行 kubectl get po 就以为装好了,其实网段对不上时 Pod 能 Running 但跨节点 ping 不通。
部署第一个应用:Deployment、Service 与 Ingress
结论前置:Kubernetes 里跑应用的三层分别是 Deployment(管副本与滚动更新)、Service(提供稳定的访问入口与负载均衡)、Ingress(按域名/路径把外部 HTTP(S) 流量引入集群)。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
readinessProbe: # 未就绪的 Pod 不会进入 Service 转发列表
httpGet: { path: /, port: 80 }
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests: { cpu: "100m", memory: "128Mi" }
limits: { cpu: "500m", memory: "256Mi" }
---
apiVersion: v1
kind: Service
metadata:
name: web-svc
spec:
type: NodePort # 生产建议改为 LoadBalancer 或由 Ingress 承接
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
spec:
ingressClassName: nginx # 需先安装对应 Ingress Controller
rules:
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-svc
port:
number: 80kubectl apply -f web.yaml
kubectl rollout status deployment/web
kubectl get pod,svc,ingress -o wide
# 集群内快速联通测试(临时Pod,测完即删)
kubectl run curl-test --rm -it --image=curlimages/curl:8.10.1 -- \
curl -sS -o /dev/null -w '%{http_code}\n' http://web-svc.default.svc.cluster.localIngress 本身只是一组规则,真正干活的是 Ingress Controller(如 ingress-nginx、Traefik、APISIX Ingress),需要单独安装并以 DaemonSet/Deployment + Service 暴露 80/443。常见做法是把它做成 DaemonSet 并配合 hostNetwork 或 NodePort + 外部负载均衡器,避免多一层 NAT 导致源 IP 丢失。
kubectl 常用命令速查表
结论前置:这张表覆盖日常 80% 的操作,建议贴在终端旁边。
| 命令 | 作用 |
|---|---|
kubectl get node -o wide | 查看节点状态、内网 IP 与 kubelet 版本 |
kubectl describe node | 查看节点资源分配、污点(Taint)与事件 |
kubectl -n kube-system get pod -o wide | 检查系统组件是否全部就绪 |
kubectl get pod -A -o wide | 跨命名空间查看所有 Pod 落点与 IP |
kubectl describe pod | 排查 Pending/ImagePullBackOff 的第一手信息 |
kubectl logs | 查看上一次崩溃容器的日志 |
kubectl exec -it | 进入容器排查(生产慎用) |
kubectl scale deployment/web --replicas=5 | 手动扩缩容 |
kubectl rollout undo deployment/web | 回滚到上一个版本 |
kubectl top pod -A | 查看实际资源占用(需 metrics-server) |
kubectl cordon / drain | 停止调度 / 驱逐节点上的 Pod(维护前必做) |
kubectl get events -A --sort-by=.metadata.creationTimestamp | 按时间查看集群事件,排障通用入口 |
企业QQ咨询




