☰
K8s集群搭建全流程清单:从环境准备到高并发运维实战
2026/9/26 5:23:47 网站建设 项目流程

1. 先把场景说清楚:为什么需要这份流程清单

搞过k8s的人都清楚,集群搭建这件事,十次有九次不是挂在技术上,而是挂在自己都没想到的细节上。我记得之前带一个项目时,部署环境是ubuntu 20.04,硬件还算充裕,三台控制节点,心想这配置足够了。结果一折腾就花了一整周,最后排查出来的原因居然是证书签发时间不对、容器运行时版本不匹配。这种问题你查文档基本查不出来,只能靠现场一点点翻日志。

也就是从那一次起,我开始整理自己的k8s流程创建清单,从环境准备、集群初始化、控制面高可用、存储与监控配套,一直覆盖到日常排障。现在每次新接项目,我都会先把这份清单过一遍,能省掉很多不必要的折腾。

这份清单主要解决三类问题。第一,明确每个阶段该交付什么东西、怎么验证,不依赖“感觉好像装好了”这种错觉。第二,沉淀版本、参数、网络规划这些容易踩坑的细节,让同一个坑不要被连续踩。第三,为后续扩容、升级、证书轮换、监控接入这些动作预留好接口,而不是等出了问题才临时补。

适合谁参考呢?如果你是刚入门k8s,准备在虚拟机或物理机上搭建集群的运维工程师,可以把它当作一份checklist来用。如果你已经有一定基础,想梳理一套标准化交付流程,里面很多细节也可以直接借鉴。即使你平时主要用kubectl管理应用,了解一下集群是怎么被创建和校验的,对定位问题也有帮助。

2. 环境与前置条件:把地基打牢再动手

2.1 硬件、操作系统与内核模块

k8s对硬件的要求并不苛刻,但也不能太随意。生产级配置我一般按控制面节点2核4GB起步来评估,工作节点根据业务负载决定。如果你要跑GPU工作负载,还得单独预留GPU资源,这个放到后面细说。

操作系统层面,我推荐Ubuntu LTS版本,比如20.04或22.04。原因有两个:一是内核版本适中,对overlay、br_netfilter这些容器相关模块支持友好;二是社区案例多,遇到问题能快速找到答案。CentOS虽然很多老项目在用,但大版本已经走向维护尾声,新项目我不建议再往里搭。如果公司内部已经有统一的操作系统基线,那就按基线走,但必须在动手之前确认内核模块、iptables、IPVS这些底层依赖是否就绪。

这里有一个很多人忽略的经验:不要在系统刚装完、还没处理内核模块的时候就急着跑kubeadm init。先把overlay和br_netfilter的自动加载确认掉,不然很多看起来像flannel或calico引发的报错,底层其实是模块没加载。检查方式很简单:

cat /proc/modules | grep br_netfilter cat /etc/modules-load.d/k8s.conf

如果输出为空,就手动创建modules-load.d配置,把overlay、br_netfilter写进去,然后重启或modprobe加载。这一步放进流程清单的最前面,能避免后面大量的网络类报错。

2.2 网络规划与网段划分

网络方面,我强烈建议先规划再动手。k8s集群里三个网段特别容易混淆:宿主机网络、Pod网络、Service网络。

  • 宿主机网络是节点自身的IP地址,由现有网络架构决定,可能是公司内网或云VPC。
  • Pod网络分配给每个Pod,主要由CNI插件管理,Calico场景下一般配置成192.168.0.0/16这类网段。
  • Service网络在kube-apiserver启动参数中用--service-cluster-ip-range定义,常见配置是10.96.0.0/12。

三个网段绝对不能重叠,否则路由会乱,排查起来非常痛苦。我踩过一次坑,机房内网段正好是10.96.0.0/16,我却把Service网络也配成了10.96.0.0/12,结果集群怎么装都不通,最后发现是网段冲突,一个下午就这么搭进去了。从那以后,我在流程清单里把网段规划设成硬性步骤,必须填表确认签字那种。

2.3 版本选型与容器运行时

版本选择上我不追最新,只追稳定。新版本往往伴随新的API特性和兼容性变化,对大多数项目来说,选择一个已发布三个月以上的版本更合理。当前来看,1.28、1.29、1.30这几个系列都算主流,具体要根据你使用的部署工具和厂商支持范围来定。

容器运行时方面,最常见的选择是containerd和Docker。这里有一个老生常谈的话题:k8s和docker的区别到底是什么?我的理解是,Docker是一套容器管理工具,负责构建镜像、运行容器、管理镜像生命周期;k8s是一个容器编排平台,负责调度、伸缩、服务发现、故障恢复。两者本身不在同一层。换句话说,k8s完全可以不依赖Docker,借助containerd就能完成运行时层面的工作。

在流程清单里,我统一推荐containerd。原因很直接:kubelet通过CRI对接containerd,配置链短,排查看日志更清晰。自Kubernetes 1.24之后,dockershim已经被移除,再强行用Docker作为kubelet运行时需要额外适配层,纯属给自己添堵。如果团队里还有人问docker和k8s是什么关系,可以顺手解释一句:docker管单机上的容器,k8s管整个集群里的容器,前者是工具,后者是平台。

3. 集群创建的核心阶段:控制面立起来才算开始

3.1 初始化准备与镜像处理

在正式执行kubeadm init之前,有两件事必须先做:确认kubeadm、kubelet、kubectl三个组件版本一致;提前处理镜像拉取问题。

版本不一致是我见过最多的低级翻车点。kubeadm、kubelet、kubectl必须在同一个minor版本内,否则初始化时kubelet和apiserver之间的通信会产生版本不匹配报错。这类报错往往藏得很深,表面看起来是token失效或TLS握手失败,实际查版本才发现对不上。

镜像处理上,如果你在默认网络环境下直接用registry.k8s.io,大概率会卡住。更稳妥的方案是先把镜像清单拉出来,换到可用镜像源再导入。用kubeadm config images list能看到所需镜像,通过--image-repository参数指定替代仓库。这一步我在清单里标记为“必做”,否则初始化卡在拉镜像这一个环节就能耗掉大半天。

3.2 三台master的高可用方案选型

所谓高可用,核心是避免控制面单点故障。最常见的方案有两种:kubeadm自带的stacked etcd模式,以及外部etcd集群模式。对大多数中小型集群,stacked etcd就够用。它把etcd和控制面组件放在同一批master节点上,部署简单,维护成本低,推荐优先考虑。

三台master如何保证高可用?简单说需要两个层面的配合。

控制面组件层面,kube-apiserver是无状态的,可以多副本运行,通过负载均衡对外提供服务;kube-controller-manager和kube-scheduler通过leader election机制选主,同一时刻只有一个实例真正工作。

流量入口层面,需要一个虚拟IP或负载均衡器把请求转发到多个apiserver。常见的组合是keepalived加haproxy,也可以用云厂商SLB,或者用kubekey这类工具做自动化部署。

我之前在ubuntu上做高可用k8s部署,用的就是三台master加keepalived加haproxy的组合。haproxy负责反向代理6443端口的apiserver流量,keepalived负责提供虚拟IP漂移。只要任意一台master挂掉,流量会自动切到健康节点,对上层用户无感知。

有一点必须提醒:kubeadm join其他master节点时,一定要用负载均衡地址,而不是某台master的单独IP。很多人初始化时把apiserver-endpoint写成了第一台master的IP,后面第三台master加入时,它只连那一台。一旦第一台挂了,整个控制面入口就断了。这个细节我在清单里会用高亮标出来。

如果你不想手动拼接这些组件,kubekey是另一个不错的选择。它能比较顺滑地编排多master配置,对国内环境也更友好。但无论用什么工具,高可用的本质逻辑是一样的:apiserver必须多副本加统一入口,etcd数据必须冗余且保持一致。

3.3 工作节点加入与集群自检

控制面起来后,工作节点加入反而简单。核心就是拿到token和证书哈希,执行kubeadm join。但有两个点容易被忽略:

  • token默认有效期是24小时,如果隔几天再扩容,需要重新生成token。
  • 加入指令里的--discovery-token-ca-cert-hash要用kubeadm token create --print-join-command打印出来,不要复制网上的示例。

节点加入后,自检我从三个维度来看:

kubectl get nodes kubectl get pods -n kube-system -o wide kubectl get cs

第一看节点状态是否Ready,第二看coredns、flannel或calico等核心Pod是否Running,第三看controller-manager和scheduler是否healthy。这三个命令基本覆盖80%的初始化问题。

有一点要注意,新版k8s里kubectl get cs可能显示为legacy或不准确,因为它读的是ComponentStatus接口,实际意义有限。我更建议把多个维度结合起来判断,重点还是看核心Pod的状态和节点条件。

3.4 GPU资源接入要点

GPU接入是AI项目里最常见的硬需求。声明GPU资源的正确方式是在容器资源限制里加nvidia.com/gpu字段:

resources: limits: nvidia.com/gpu: 1

但加上这个并不代表就能直接用,整个链路涉及三个环节:

  • 节点上安装NVIDIA驱动和CUDA,保证nvidia-smi能正常输出。
  • 部署NVIDIA Container Toolkit,让容器运行时能感知GPU设备。
  • 在集群中启用NVIDIA Device Plugin,把GPU资源暴露给kubelet。

如果集群用containerd,需要修改/etc/containerd/config.toml,在plugins配置里加入nvidia runtime配置,然后重启containerd。我第一次做k8s与GPU安装时漏了这一步,GPU资源始终显示不出来,排查一圈才发现是containerd没有感知到nvidia runtime。从此这份流程清单里,“containerd GPU runtime配置”就成了必检项。

4. 存储、监控与控制器:让应用跑得稳

4.1 持久化存储方案

生产环境中大多数应用都需要持久化数据,存储方案不能等到部署应用时再临时抱佛脚。

本地卷适合单机验证,但生产环境我更推荐网络存储,比如NFS、Ceph或云厂商的存储卷。k8s通过StorageClass管理动态供应,应用只需要声明PVC,系统会自动创建PV并绑定,省去手动创建PV的麻烦。

如果你的硬件条件一般,NFS是成本最低的入门方案。部署一个NFS服务端,然后装nfs-subdir-external-provisioner这个StorageClass Provider,之后创建PVC时就会自动在NFS上分配目录。这个方案对中小型项目够用,唯一要注意的是NFS服务端的性能和稳定性。NFS自身一旦挂掉,所有依赖它的Pod都可能异常,所以至少要做服务端监控。

4.2 Prometheus监控部署

监控这一环,我见过太多项目装完集群就不管了,全靠肉眼发现问题。实际上,部署prometheus监控k8s并不复杂:kube-state-metrics暴露集群对象的状态指标,node-exporter采集节点指标,Prometheus负责抓取和存储,Grafana负责展示,一套基础监控栈就起来了。

如果你不想每个组件单独配置,kube-prometheus-stack这个Helm Chart把Prometheus、Alertmanager、Grafana、node-exporter都打包好了,一条命令就能部署。部署时核心要改的是serviceMonitor的selector,确保命名空间标签和实际业务命名空间对得上,否则指标抓不到,Grafana面板上一片空白。

还有一点经常被忽略:监控账号的RBAC权限。默认Helm Chart一般会带上ClusterRole,但如果你自定义了配置文件,务必确认监控账号有足够的get/list/watch权限。我最开始部署prometheus监控k8s时只顾着serviceMonitor,忘了鉴权这一层,结果大部分指标能拉到,资源相关指标却一直403。这个点,清单里必须写。

4.3 控制器类型的选型逻辑

k8s的控制器很多,Deployment、StatefulSet、DaemonSet、Job、CronJob等。不少人一开始只认识Deployment,所有工作负载都往里塞,但选错控制器会给后续维护埋坑。

  • Deployment适合无状态应用,比如Web服务、API服务,可以随意替换Pod,支持滚动更新和回滚。
  • StatefulSet适合有状态应用,比如数据库、缓存中间件,每个Pod有稳定的网络标识和存储声明。
  • DaemonSet适合每个节点都要跑一个实例的场景,比如日志采集、监控采集Agent、CNI组件本身。

举个小例子,Deployment这个术语在中文环境里通常就直接叫“部署”或“工作负载”。它做的事情很朴素:声明你要的Pod副本数,并自动维持这个数量。如果Pod挂了,它再拉起一个;如果流量大了,它配合HPA扩容。而StatefulSet和Deployment的核心差异在于身份和存储的稳定性,所以数据库这类应用天生应该用StatefulSet,而不是Deployment。

5. 常用命令、证书生命周期与高并发落地

5.1 高频命令速查

命令这块,我平时用得最多的整理如下:

用途命令
查看节点状态kubectl get nodes
查看所有Podkubectl get pods -A
查看Pod详细日志kubectl logs -f -n
进入Pod调试kubectl exec -it -n -- /bin/sh
查看资源明细kubectl describe pod -n
查看集群事件kubectl get events --sort-by=.lastTimestamp
临时启动调试Podkubectl run -it --rm --restart=Never test --image=busybox -- /bin/sh
端口转发调试kubectl port-forward svc/my-service 8080:80

很多问题排查的第一步,我就直接看events。这个命令能把集群里的异常事件一次性列出来,比如镜像拉取失败、探针失败、磁盘压力等,比对着单个Pod反复describe高效得多。我见过太多人一遇到问题就describe Pod,却忘了先看events,白白浪费不少时间。

还有一个我常用的组合是kubectl get pod -n某个命名空间 -o wide加kubectl describe node节点名。节点级别的问题,比如内存不足、磁盘压力,用describe node能看到Conditions里的压力状态,再配合kubectl top nodes看实时占用,基本能快速定位。

5.2 证书过期与自动续签

证书过期是k8s运维中的经典定时炸弹。默认情况下,集群各组件证书有效期是一年。一年内你可能没什么感觉,一旦过期,kubelet与apiserver之间的TLS握手直接失败,整个集群像被按了暂停键。

kubeadm部署的集群,证书续签命令是kubeadm certs renew。流程大致是:

  • 备份旧证书目录,比如/etc/kubernetes。
  • 执行kubeadm certs renew all。
  • 重启控制面组件容器或更新kubeconfig。
  • 验证apiserver、controller-manager、scheduler及所有节点的证书是否更新。

但这里有个细节很多人忽略:kubeadm管理的证书会续签,但如果你手动调整过组件启动参数,或者证书结构有特殊情况,自动续签可能不完整。更省心的方案是上证书自动续签机制。我见过团队用cert-manager结合kubeadm,也有人写一个cronjob定时执行检查与续签。无论哪种方案,核心原则都是一致的:证书续签不是一次性动作,必须纳入日常巡检。

我在流程清单里会写一行:每个月跑一次kubeadm certs check-expiration,看看证书状态,这比任何警报都直接。

5.3 高并发组件优化

k8s本身的设计能处理高并发,但“能处理高并发”不等于“默认配置就能扛住高并发”。比较典型的优化点在三个位置:

  • kube-apiserver是集群所有请求的入口,高并发下需要调大内存和限流参数,比如--max-requests-inflight和--max-mutating-requests-inflight。
  • kube-scheduler在Pod频繁创建销毁时会成为瓶颈,需要根据Pod数量评估调度性能。
  • HPA是k8s处理高并发的核心组件之一,基于CPU、内存或自定义指标自动扩缩容,配合ingress-nginx或云负载均衡,把流量分发到多个副本上。

高并发场景里有几个特别容易踩的坑。HPA的指标采集存在延迟,业务流量瞬间暴增时,Pod扩容会有滞后。如果想快速扩容,得提前配置HPA的behavior参数,设置较大的scaleUp速率,甚至加一层基于自定义指标的触发机制,才能应对突刺流量。

apiserver限流参数也是重点。如果集群里有大量定时任务或批处理脚本,在高峰期频繁创建、删除Pod,默认限流很容易触发,最终表现为kubectl命令大量超时。这类问题不会直接在业务日志里体现,而是在集群元数据层面积累。

5.4 管理工具选型

kubectl是基础,但长时间在终端里敲命令效率还是不够高。这里分享几个我用过的工具。

  • k9s:终端UI,能直接看Pod、Service、日志、事件,不用每次敲一长串命令,适合日常巡检。
  • Lens:桌面客户端,图形化操作,多集群管理方便。
  • Kuboard:有中文界面,适合让开发人员也能看到集群状态。
  • kubekey:既能部署也支持管理,对国内环境比较友好。

工具不是越多越好,选一个用得顺手的就行。我个人是k9s加kubectl并行,k9s负责快速看状态,kubectl负责精细操作。多集群场景下,注意context切换,可以在~/.kube/config里配置多个集群context,然后kubectl config use-context切换。

6. 常见问题与排障实录

6.1 节点NotReady的最常见原因

节点变成NotReady,排第一的原因基本是CNI网络插件没有正常工作。比如flannel或calico的Pod没有Running状态,节点之间的网络隧道没建立,kubelet上报时就会带NetworkPluginNotReady。

遇到NotReady,我先看这组命令:

kubectl get pods -n kube-system -o wide kubectl describe node <node>

先确认kube-system里有没有大量CrashLoopBackOff的Pod,再看node的Conditions输出。Ready状态里如果reason是KubeletNotReady,通常message里会写具体原因,指向容器运行时或网络插件。

再往下排查可能是磁盘满了,也可能是运行时挂了。这里有个很现实的点:小容量磁盘集群,长期不清理,/var/lib/containerd会涨得很快,kubelet因为磁盘压力把节点标记为NotReady。所以日常巡检里,磁盘空间监控和日志清理要放在前面。我在流程清单里专门加了一步:给containerd配置镜像垃圾回收,同时把系统目录独立挂盘,避免根分区被塞满。

6.2 Pod卡在Pending或CrashLoopBackOff

Pod一直Pending,最常见的原因是资源不足,其次是调度约束不满足。最快的方法还是看describe Pod的Events部分。

如果Events提示0/3 nodes are available,说明节点资源不够,要么扩容,要么降低Pod的requests。如果提示node affinity或taint相关消息,就得确认节点标签和污点配置是否符合预期。

Pod处于CrashLoopBackOff时,思路也直接:先看日志,再看退出码。退出码137代表被OOM杀掉,退出码1通常是应用自己崩溃,退出码127是命令找不到。很多情况下,问题出在镜像启动命令与容器配置不一致,比如镜像里没有entrypoint,你在yaml里指定了不存在的参数。这类问题靠单纯重启Pod没用,必须改配置源头。

6.3 DNS解析与网络策略问题

集群内服务互相访问,最常遇到的是CoreDNS相关问题。现象就是Pod之间通过Service名解析不通,或跨namespace访问失败。

先检查CoreDNS Pod是否在跑,再看CoreDNS配置里的forward是否正常。如果只影响某个命名空间,多半是Service的metadata.name和实际服务名不一致。还有一点容易被忽略:Pod里的/etc/resolv.conf是否正确注入了kube-dns的ClusterIP。如果没用上,检查Pod的dnsPolicy配置。

网络策略方面,默认是“允许所有”,可一旦引入NetworkPolicy并且配置不当,服务间通信会被静默丢弃。排查时先用kubectl get networkpolicy -A看有哪些策略,必要时临时调整策略做对比测试。这类问题通常不会在日志里直接报错,需要结合抓包或策略配置来定位,但大多数场景下,确认策略是否一致已经能解决问题。

6.4 真实案例:一场高并发下的apiserver抖动

最后分享一个真实案例。某次业务反馈,应用访问数据库偶发性超时,持续时间不长但频率很高。一开始怀疑数据库压力,后来看数据库集群一切正常,SLA指标也没问题。

后来我们把视角转到k8s层面,发现apiserver在高峰期出现慢请求,导致大量Pod在创建或更新时延迟明显。进一步排查时定位到某个团队写了大量短时任务,一直在用kubectl创建和删除Pod,apiserver默认限流参数被顶到了上限。

处理办法其实不复杂:调整apiserver的--max-requests-inflight和--max-mutating-requests-inflight,同时给不同用户配置ResourceQuota和LimitRange,限制单个命名空间的Pod数量上限。

这个案例给我的启发是:k8s的问题往往是系统性的,单点排查可能很长时间找不到源头,把视角拉高到整个集群的请求链路,才能逐步定位。也正因如此,流程清单里不能只写“怎么建集群”,还得写清“建完后怎么长线观察”。

7. 写在最后:我的清单迭代体会

很多人在做完一次集群搭建后就把文档封存了,等到半年后再扩容或升级,发现一切都变了,又要从零摸索。我的做法是,每次项目结束后都把流程清单更新一遍,记录踩过的坑、用过的参数、耗时情况,以及验证通过的环境。

这么做最直接的好处是,同一个坑我不会踩第二次。比如本文写到的网段冲突、证书过期、containerd的GPU runtime配置,几乎都是团队新人最容易碰到的。而一份真正好用的k8s流程创建清单,从来不是从网上复制下来的,而是从自己的实践里长出来的。

我的建议是,先按这套框架搭一份最小可用的清单,跑通一个简单项目,把环境差异补进去,再在后续项目中逐步打磨。它会慢慢变成团队内部真正有价值的运维沉淀,比任何现成模板都靠谱。

最后再分享一个小技巧:把这份清单做成集群交付时的验收依据,不管是内部同事还是外部实施方,都按清单逐项签字确认。你会发现,很多潜在风险在交付阶段就被拦下来了,而不是等业务上线后变成故障再补救。

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

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

立即咨询