☰
Kubernetes架构拆解与集群搭建实战:从控制平面到工作节点
2026/10/22 3:12:34 网站建设 项目流程

1. 从零吃透 Kubernetes:架构拆解与集群搭建实战手记

搞容器编排这些年,被问得最多的问题就是“Kubernetes 到底怎么入门”。网上资料一抓一大把,但要么是官方文档那种冷冰冰的规格说明书,要么是培训机构拼凑的速成讲义,真正能从架构原理讲到集群落地、还把踩坑经验说明白的并不多。我自己从单机 Docker 一路折腾到多节点集群,中间经历过证书过期、网络插件冲突、etcd 性能瓶颈这些经典问题,也帮不少团队做过集群规划和故障排查。这篇内容就是把这些年积累的架构理解和搭建经验完整梳理出来,从控制平面到工作节点、从容器运行时到网络方案选型、从 kubeadm 初始化到集群验证,每一步都讲清楚“为什么这么做”而不只是“怎么做”。

Kubernetes 本质上是一个声明式的容器编排系统,你告诉它“我要什么状态”,它负责把实际状态调整过来。这个核心理念贯穿整个架构设计。它解决的问题很明确:当你有几十上百个容器需要调度、扩缩、自愈、滚动更新的时候,手动管理完全不现实。适合谁来参考?如果你已经会用 Docker 跑单个容器,但对多节点编排、服务发现、持久化存储这些概念还比较模糊,那这篇内容就是为你准备的。如果你已经在用 Kubernetes 但想深入理解控制平面的工作机制,里面关于各组件协作流程的拆解同样有参考价值。

2. Kubernetes 架构核心组件拆解

2.1 控制平面:集群的大脑

控制平面是整个集群的决策中心,所有调度指令、状态变更、配置下发都从这里发出。它由四个核心组件构成,每个组件各司其职又紧密协作。

kube-apiserver是所有操作的唯一入口。无论你是用 kubectl 敲命令、还是 Dashboard 点按钮、还是 CI/CD 流水线调 API,最终都是打到 apiserver 上。它负责认证、授权、准入控制、请求校验,然后把合法的请求写入 etcd。可以把它理解成集群的“前台接待加保安”,所有进出都得经过它。apiserver 本身是无状态的,可以水平扩展多个实例,前面挂负载均衡就能扛住高并发场景。

etcd是集群的唯一数据源,所有集群状态——包括节点信息、Pod 规格、Service 配置、Secret 数据——全部存在这里。etcd 基于 Raft 一致性算法,保证分布式环境下的数据强一致。生产环境至少部署三个节点组成集群,因为 Raft 需要多数派存活才能写入。三个节点容忍一个挂掉,五个节点容忍两个挂掉。etcd 的性能直接决定整个集群的响应速度,磁盘 I/O 是关键瓶颈,强烈建议用 SSD。

kube-scheduler负责决定 Pod 跑在哪个节点上。它监听 apiserver,发现有新 Pod 创建但还没绑定节点时,就启动调度流程。调度分两个阶段:过滤和打分。过滤阶段排除不满足条件的节点(比如资源不够、端口冲突、亲和性不匹配),打分阶段对剩余节点按优先级排序,选最高分的。调度策略可以通过亲和性、污点容忍、拓扑分布约束等精细控制。

kube-controller-manager是一堆控制器的集合,每个控制器负责一种资源的状态协调。比如 Deployment 控制器确保实际副本数等于期望副本数,Node 控制器监测节点健康状态,Endpoint 控制器维护 Service 和后端 Pod 的映射关系。这些控制器本质上就是“观察-对比-调整”的循环,不断把实际状态往期望状态推。

2.2 工作节点:干活的肌肉

工作节点是实际运行容器的地方,核心组件有三个。

kubelet是节点上的“监工”,负责跟 apiserver 通信,接收分配给本节点的 Pod 规格,然后调用容器运行时去创建、启动、监控容器。它还负责上报节点状态和 Pod 状态。kubelet 不管理非 Kubernetes 创建的容器,只管自己负责的那些。

kube-proxy负责实现 Service 的网络代理和负载均衡。它监听 apiserver 中 Service 和 Endpoint 的变化,然后在本节点上维护 iptables 或 IPVS 规则,把发往 Service ClusterIP 的流量转发到后端 Pod。iptables 模式在服务数量少时没问题,但上千个 Service 时规则链会非常长,性能下降明显,这时候就该换 IPVS 模式了。

容器运行时是真正跑容器的组件。早期 Kubernetes 直接用 Docker,后来为了解耦,引入了 CRI(容器运行时接口),只要实现了 CRI 的运行时都能用。现在主流选择是 containerd 和 CRI-O,Docker 本身因为架构原因在较新版本中不再被直接支持。containerd 相对轻量、稳定,是目前大多数发行版和托管集群的默认选择。

2.3 核心资源对象与协作流程

理解架构不能只看组件,还得看它们怎么围绕资源对象协作。最核心的资源对象包括 Pod、Deployment、Service、ConfigMap、Secret、PersistentVolume 等。

拿一个典型的部署流程举例:你用 kubectl 提交一个 Deployment 资源,请求打到 apiserver,apiserver 校验通过后写入 etcd。Deployment 控制器监听到新对象,创建一个 ReplicaSet,ReplicaSet 控制器再创建对应数量的 Pod 对象。调度器发现有 Pod 没有绑定节点,经过过滤打分后把 Pod 绑定到某个节点。目标节点的 kubelet 监听到有 Pod 分配给自己,调用容器运行时拉镜像、起容器。同时 kube-proxy 更新规则,让 Service 能把流量导到这个新 Pod。整个过程是异步的、最终一致的,每个组件只关心自己那部分逻辑。

这种解耦设计的好处是扩展性强、容错性好。某个组件短暂挂掉,恢复后会自动追上进度。但也带来一个副作用:排查问题时需要沿着整条链路逐段检查,不能只看一个地方。

3. 集群搭建前的规划与准备

3.1 节点规划与资源评估

搭建集群第一步不是敲命令,而是做规划。我见过太多人上来就装,结果跑了一段时间发现资源不够、网络冲突、证书过期,返工成本极高。

节点数量方面,学习环境一台控制平面加两台工作节点就够了。生产环境控制平面至少三台(保证 etcd 高可用),工作节点按业务负载定。控制平面节点建议 4 核 8G 起步,工作节点按 Pod 密度算,一般来说 8 核 16G 能跑几十个中等负载的 Pod。

操作系统选择上,Ubuntu 和 CentOS 系都常见。关键是要关闭 Swap,因为 kubelet 默认要求禁用交换分区,否则调度和内存管理会出问题。内核参数也要调,比如开启网桥转发、调整连接跟踪表大小,这些在后续步骤里会具体说。

网络规划是最容易出问题的环节。你需要提前确定几个网段:节点物理网络、Pod 网段、Service 网段。这三个网段不能重叠,否则路由会乱。Pod 网段和 Service 网段用私有地址段就行,比如 Pod 用 10.244.0.0/16,Service 用 10.96.0.0/12。如果集群要跟外部网络互通,还得规划好路由或者 NAT 策略。

3.2 容器运行时选型对比

前面提到容器运行时现在主流是 containerd 和 CRI-O。我两个都用过,说下实际感受。

containerd 的优势是生态成熟、社区活跃、跟 Docker 镜像格式完全兼容,调试工具也多。它的架构相对简单,资源占用低,稳定性经过大规模验证。CRI-O 是专门为 Kubernetes 设计的,更轻量,但生态工具链相对少一些,遇到问题查资料不如 containerd 方便。

对于大多数场景,我建议直接用 containerd。安装配置都不复杂,跟 Kubernetes 的集成也很顺。下面搭建步骤里就以 containerd 为例。

注意:如果你之前装过 Docker,它可能已经自带了 containerd,但版本和配置不一定符合 Kubernetes 要求。建议单独安装官方推荐的 containerd 版本,避免版本冲突。

3.3 网络插件方案选择

网络插件是集群搭建里另一个关键决策。Kubernetes 本身不提供网络实现,只定义了 CNI 接口,具体网络功能由插件提供。常见选择有 Flannel、Calico、Cilium 等。

Flannel 最简单,配置少,适合学习和中小规模集群。它主要解决 Pod 跨节点通信问题,网络策略支持较弱。Calico 功能更全,支持网络策略、BGP 路由、IP 池管理,性能也好,是中大型集群的主流选择。Cilium 基于 eBPF 技术,性能和可观测性都很强,但学习曲线陡一些,对内核版本有要求。

我的建议是:学习环境用 Flannel 快速跑通,生产环境用 Calico。下面实操部分我会以 Calico 为例,因为它的配置更能体现生产环境的真实需求。

4. 基于 kubeadm 的集群搭建实操

4.1 基础环境配置

假设你有三台机器,一台做控制平面,两台做工作节点,操作系统是 Ubuntu 22.04。以下操作在三台机器上都执行。

先设置主机名和 hosts 解析,方便节点间通信:

# 在每台机器上分别设置 hostnamectl set-hostname k8s-master hostnamectl set-hostname k8s-node1 hostnamectl set-hostname k8s-node2 # 三台机器都加上 hosts 解析 cat >> /etc/hosts << EOF 192.168.1.10 k8s-master 192.168.1.11 k8s-node1 192.168.1.12 k8s-node2 EOF

关闭 Swap 并禁用开机自动挂载:

swapoff -a sed -i '/swap/s/^/#/' /etc/fstab

加载内核模块并调整内核参数:

cat > /etc/modules-load.d/k8s.conf << EOF overlay br_netfilter EOF modprobe overlay modprobe br_netfilter cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system

这几步的原因:overlay 模块是 containerd 存储驱动需要的,br_netfilter 让网桥流量能走 iptables 规则,ip_forward 开启 IP 转发。不配这些,后面 Pod 网络不通是必然的。

4.2 安装 containerd 运行时

安装 containerd 并生成默认配置:

apt update apt install -y containerd mkdir -p /etc/containerd containerd config default > /etc/containerd/config.toml

关键一步:修改配置让 containerd 使用 systemd cgroup 驱动,这跟 kubelet 的 cgroup 驱动保持一致,否则会出现资源管理异常:

sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

同时建议把 pause 镜像地址改成国内可访问的地址,避免初始化时拉取超时。找到sandbox_image那一行,改成你环境里能访问的镜像仓库地址。

重启并设置开机自启:

systemctl restart containerd systemctl enable containerd

验证 containerd 状态:

systemctl status containerd ctr version

4.3 安装 kubeadm、kubelet、kubectl

添加软件源并安装:

apt install -y apt-transport-https ca-certificates curl curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | 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.29/deb/ /' > /etc/apt/sources.list.d/kubernetes.list apt update apt install -y kubelet kubeadm kubectl apt-mark hold kubelet kubeadm kubectl

apt-mark hold是防止这三个包被自动升级,因为版本不匹配会导致集群异常。这个坑我踩过,某次自动升级后 kubelet 起不来,排查半天才发现是版本问题。

4.4 初始化控制平面

在 master 节点上执行初始化。这里需要指定 Pod 网段,要跟后面网络插件的配置一致:

kubeadm init \ --apiserver-advertise-address=192.168.1.10 \ --pod-network-cidr=10.244.0.0/16 \ --kubernetes-version=v1.29.0

初始化过程会做一系列检查,包括系统配置、端口占用、镜像拉取等。如果卡在拉镜像,多半是网络问题,可以提前用kubeadm config images pull手动拉取。

初始化成功后,按照提示配置 kubectl:

mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config

验证控制平面状态:

kubectl get nodes kubectl get pods -n kube-system

这时候 master 节点应该是 NotReady 状态,因为网络插件还没装。这是正常的。

4.5 部署网络插件

以 Calico 为例,部署方式现在推荐用 operator:

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/tigera-operator.yaml

然后创建自定义资源,指定 Pod 网段:

cat > calico-custom.yaml << EOF apiVersion: operator.tigera.io/v1 kind: Installation metadata: name: default spec: calicoNetwork: ipPools: - blockSize: 26 cidr: 10.244.0.0/16 encapsulation: VXLANCrossSubnet natOutgoing: Enabled nodeSelector: all() EOF kubectl apply -f calico-custom.yaml

等几分钟,检查 Calico Pod 是否全部 Running:

kubectl get pods -n calico-system

网络插件跑起来后,master 节点会变成 Ready。

4.6 加入工作节点

在 master 上生成加入令牌:

kubeadm token create --print-join-command

复制输出的命令,在两个工作节点上分别执行。执行完后回到 master 查看节点状态:

kubectl get nodes -o wide

三个节点都 Ready 就说明集群基本搭建完成。

5. 集群验证与核心功能测试

5.1 部署测试应用验证调度

光看节点 Ready 不够,得实际跑个应用验证调度、网络、服务发现都正常。

创建一个 Deployment:

kubectl create deployment nginx-test --image=nginx:alpine --replicas=3

查看 Pod 分布:

kubectl get pods -o wide

三个 Pod 应该分散在不同节点上(或者至少不是全挤在一个节点)。如果全在一个节点,检查调度器配置和节点资源。

暴露为 Service:

kubectl expose deployment nginx-test --port=80 --type=NodePort

查看 Service:

kubectl get svc nginx-test

拿到 NodePort 后,用任意节点的 IP 加端口访问,能返回 nginx 欢迎页就说明 Service 和网络都正常。

5.2 验证跨节点 Pod 通信

跨节点通信是集群网络的核心能力。可以起两个测试 Pod 互相 ping:

kubectl run test-pod1 --image=busybox --restart=Never -- sleep 3600 kubectl run test-pod2 --image=busybox --restart=Never -- sleep 3600

拿到两个 Pod 的 IP 后,从一个 Pod 里 ping 另一个:

kubectl exec -it test-pod1 -- ping <test-pod2-ip>

能通说明 CNI 工作正常。如果不通,检查 Calico 的 IP 池配置、节点路由表、iptables 规则。

5.3 验证 DNS 解析

Kubernetes 集群内 DNS 由 CoreDNS 提供。测试一下:

kubectl exec -it test-pod1 -- nslookup nginx-test

应该能解析出 Service 的 ClusterIP。如果解析失败,检查 CoreDNS Pod 状态和 Service 配置。

5.4 验证持久化存储

存储是另一个容易出问题的环节。简单测试可以用 hostPath,但生产环境要用网络存储。这里演示用 local PV 的方式:

apiVersion: v1 kind: PersistentVolume metadata: name: test-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: local-storage local: path: /mnt/data nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - k8s-node1

创建 PVC 绑定这个 PV,然后挂载到 Pod 里写入数据,验证持久化是否生效。

6. 常见故障排查与避坑指南

6.1 节点 NotReady 排查思路

节点 NotReady 是最常见的故障。排查顺序建议这样走:

先看 kubelet 状态和日志:

systemctl status kubelet journalctl -u kubelet -f --no-pager | tail -100

常见原因有几个:容器运行时没起来、cgroup 驱动不匹配、证书过期、网络插件没装好。日志里一般会有明确报错,比如failed to run Kubelet: misconfiguration: kubelet cgroup driver: "cgroupfs" is different from docker cgroup driver: "systemd",这就是 cgroup 驱动不一致,改 containerd 配置就行。

如果 kubelet 正常但节点还是 NotReady,检查网络插件 Pod 是否 Running,以及节点到 apiserver 的网络是否通。

6.2 Pod 一直 Pending 的原因分析

Pod Pending 说明调度器找不到合适的节点。用kubectl describe pod看 Events 部分,通常会有明确原因。

资源不足是最常见的,Events 里会写Insufficient cpu或Insufficient memory。这时候要么加节点,要么调低 Pod 的资源请求。

节点亲和性或污点问题也会导致 Pending。比如 master 节点默认有污点,普通 Pod 不会调度上去。如果想让 master 也跑 Pod,得去掉污点:

kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane:NoSchedule-

PVC 绑定失败也会导致 Pending,Events 里会显示pod has unbound immediate PersistentVolumeClaims,这时候要检查 PV 和 PVC 的匹配情况。

6.3 证书过期导致集群不可用

kubeadm 默认生成的证书有效期是一年。到期后 apiserver 无法启动,整个集群瘫痪。查看证书有效期:

kubeadm certs check-expiration

续期命令:

kubeadm certs renew all

续期后需要重启控制平面组件。更稳妥的做法是提前监控证书有效期,在到期前主动续期。我一般会在集群里跑一个定时任务,每周检查一次证书剩余天数,少于 30 天就告警。

6.4 常见问题速查表

现象可能原因排查命令解决方向
节点 NotReady运行时异常/cgroup 不匹配journalctl -u kubelet检查 containerd 配置
Pod Pending资源不足/污点/亲和性kubectl describe pod调整资源或调度策略
Pod CrashLoopBackOff应用启动失败/配置错误kubectl logs检查应用日志和配置
Service 无法访问网络插件异常/规则未生效kubectl get endpoints检查 CNI 和 kube-proxy
DNS 解析失败CoreDNS 异常kubectl logs -n kube-system检查 CoreDNS 配置
证书过期超过一年有效期kubeadm certs check-expiration执行续期操作
etcd 性能下降磁盘 I/O 瓶颈etcdctl endpoint status换 SSD 或优化参数

6.5 实操心得与避坑建议

关于版本选择,我的建议是不要追最新版。Kubernetes 每个版本迭代很快,新版本可能有未暴露的 bug。选一个稳定版本,比如 1.28 或 1.29,等社区验证充分了再升级。升级也要一个版本一个版本升,不能跨版本。

关于资源预留,生产环境一定要给系统组件预留资源。kubelet 有--system-reserved和--kube-reserved参数,不预留的话,业务 Pod 可能把节点资源吃光,导致 kubelet 自己都起不来。

关于备份,etcd 数据是集群的命根子,必须定期备份。备份命令很简单:

ETCDCTL_API=3 etcdctl snapshot save backup.db \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key

建议做成定时任务,每天备份一次,保留最近七天的。恢复的时候用etcdctl snapshot restore,然后改 etcd 配置指向恢复的数据目录。

关于监控,集群搭好只是开始,后续要上监控。Prometheus 加 Grafana 是标配,重点监控 apiserver 延迟、etcd 写入延迟、节点资源使用率、Pod 重启次数这些指标。没有监控的集群就是盲人骑瞎马。

关于日志,容器日志默认存在节点本地,不清理会把磁盘撑满。kubelet 有日志轮转配置,但默认值可能不够。建议在 containerd 配置里调整日志大小和保留数量,同时上集中式日志方案,比如 Loki 或者 Elasticsearch。

最后说一个我踩过的坑:有次集群跑得好好的,突然所有节点 NotReady。排查发现是 etcd 所在磁盘满了,导致 etcd 无法写入,apiserver 跟着挂掉。后来加了磁盘监控和自动清理才解决。所以磁盘空间一定要盯紧,尤其是 etcd 和容器运行时所在的分区。

集群搭建本身不难,难的是稳定运行和故障处理。把架构理解透,知道每个组件干什么、怎么协作,遇到问题就能沿着链路定位。多动手、多踩坑、多总结,慢慢就有感觉了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询