简介:《Kubernetes部署指南.pdf》是一份面向容器运维人员、系统管理员及云原生开发者的实操型部署手册,聚焦如何在不同环境下快速搭建高可用Kubernetes集群。文档围绕单机部署与集群部署两条主线,系统讲解kubeadm、kops、Kubespray、kubeasz等工具在Azure、Windows、LinuxKit等平台上的操作要点,并给出GCE虚拟机中Kubernetes-The-Hard-Way的逐级实践路径,覆盖创建计算资源、配置证书、生成密钥、部署Etcd群集、初始化控制节点与计算节点、配置网络路由和DNS等完整步骤,适合正在规划生产环境、希望离线对照实施的工程师参考。资源包为单个PDF文件,大小3.91MB,便于本地查阅,目前已有178人学习下载。内容还整理了依赖组件的版本兼容对照(Etcd、Docker、Go、CNI、CSI等)、kubectl客户端安装、Sonobuoy烟雾测试以及国内镜像加速等实用经验,同时描述单机选择、公有云和裸机集群的不同校验方法,用户可按目录快速定位到自身场景,减少部署与排障过程中的摸索时间。
1. Kubernetes 部署指南:从单机 Docker 到多节点集群,中间卡住的不是概念
手里有一批物理机或云服务器,想在它们之上跑起一套 Kubernetes 集群,这大概是每位运维和后端工程师都绕不过去的一道坎。网上的教程一搜一大把,但真正落到自己环境里,问题往往不是“Kubernetes 是什么”,而是“这套部署流程为什么在我这里跑不通”。版本选型、容器运行时、网络插件、证书有效期,任何一个环节没对齐,初始化就会莫名其妙地失败。《Kubernetes部署指南.pdf》这份资料的核心价值,恰好就是把散落在官方文档和社区帖子里的部署经验收敛成一套可直接复现的操作路径。它不负责解释 Kubernetes 的架构哲学,而是解决一个更现实的问题:照着做,集群能起来,业务能跑上去。适合手里有测试机或者生产服务器、正要动手从零搭建集群的工程师,也适合集群已经Exists但想要梳理一遍部署合理性的人。
2. 动手前先定盘子:集群规模、版本选型与部署工具怎么选
2.1 部署工具选型:kubeadm、二进制还是发行版自带方案
第一次看到kubeadm init觉得简单,真正部署完才发现,工具只解决了控制平面初始化的问题,离“整个集群可运维”还很远。在考虑用什么工具之前,先想清楚一个更基本的问题:这套集群是给测试用的,还是给线上业务用的,还是给边缘节点用的。三种场景对部署工具的容忍度完全不同。
常见做法是先用 kubeadm,因为对于大多数中小规模集群,kubeadm 已经能把 etcd、API Server、Controller Manager、Scheduler 这些控制平面组件打包成静态 Pod 管理起来,升级和证书续期都有官方命令支撑。二进制部署的灵活性最大,可以自定义每个组件的启动参数,还可以把 etcd 单独拆到独立节点上,适合对控制平面有特殊要求或者需要离线交付的环境,但维护成本也最高。发行版自带方案,比如 RKE2、K3s 这类,封装程度高,部署速度快,但当集群出现诡异问题需要翻日志定位时,多出来的一层封装可能会成为排查时的黑匣子。
我个人的习惯是:测试环境直接 kubeadm,生产环境优先看团队有没有现成的运维体系,如果是从零开始且服务器数量在几十台以内,kubeadm 加少量脚本也能撑住。这个选择决定了后面每一步的排错路径,别在工具选型上花太多时间纠结,但要明确一点:无论选哪种方式,部署出来的集群都必须具备“坏了能修、升级能回滚、出问题能看日志”的基本能力。
2.2 集群规划:先算资源,再定角色
部署集群最忌讳的事情是边装边想,我见过不少翻车现场都是因为节点角色没有提前规划。一个标准的高可用集群至少需要三台控制平面节点,因为 etcd 需要奇数节点来保证选主可用性,三台是最低配。如果只有一台控制平面节点,那部署的是教学环境,不是生产环境,API Server 一挂整个集群就瘫痪了。
硬件规划上,控制平面节点对 CPU 和内存的敏感度远超工作节点。etcd 是磁盘敏感型应用,它的写入性能直接决定整个集群的响应速度,建议 SSD 起步,机械硬盘在节点数量多了以后会明显拖慢 watch 事件的推送。工作节点则根据业务类型区分:CPU 密集型的业务选高主频机型,内存密集型的业务重视内存大小,涉及模型推理或大数据计算的场景需要额外考虑 GPU 和本地盘。
下表是一个常见的资源建议,实际配置可以按业务压力浮动,但不建议低于这个基线:
| 节点角色 | CPU 建议 | 内存建议 | 磁盘建议 | 节点数量 |
|---|---|---|---|---|
| 控制平面(单节点测试) | 2 核 | 4 GB | 40 GB SSD | 1 |
| 控制平面(高可用) | 4 核 | 8 GB | 100 GB SSD | 3 |
| 工作节点(轻量业务) | 4 核 | 8 GB | 100 GB 以上 | 按需 |
| 工作节点(数据密集型) | 8 核以上 | 16 GB 以上 | SSD + 独立数据盘 | 按需 |
版本选型同样要提前锁定。Kubernetes 的版本迭代节奏很快,每个版本会同时维护多个 minor release,但并非所有版本都适合直接用。我的经验是选当前最新稳定版往前推一到两个 minor 版本,等待社区反馈充分之后再用。同时还要核对容器运行时和网络插件的兼容矩阵,Kubernetes 版本、containerd 版本、Calico/Cilium 版本三者之间任何一个不匹配,都会在初始化或运行时报出非常难排查的错误。
2.3 网络模型与存储方案:部署前必须敲定的两个决策
网络方案是整个部署过程中最容易让新手迷惑的部分。Kubernetes 自己不做网络实现,它只定义了 CNI 接口,具体的数据包转发由插件完成。Calico 是基于三层 BGP 路由的方案,性能好、排错直观,适合大多数传统运维团队;Cilium 基于 eBPF,功能更丰富,可观测性好,但对内核版本有要求,旧版本内核可能需要先升级再部署。如果集群工作节点都在一起且网络简单,Calico 的 IPIP 模式足够用;如果对性能敏感且内核版本够新,Cilium 值得投入。
存储方案也一样,需要在部署工作节点之前想清楚。集群跑起来以后,有状态服务早晚会出现在业务清单里,比如数据库、消息队列、对象存储网关。如果只打算跑无状态应用,那存储可以先不部署;但只要有持久化需求,就得从本地卷、NFS、Ceph 这类方案里挑一个提前准备。部署指南里反复强调存储前置,是因为 PVC 创建失败这个问题的表象极多,但根源往往只有一个:存储插件根本没装。
3. 按顺序搭控制平面与工作节点:节点准备到 Ingress 落地的完整部署步骤
3.1 节点初始化:主机名、内核参数与容器运行时
集群节点的系统准备有一套固定动作,在任何部署工具之前完成。第一步是设置主机名并写入/etc/hosts,确保节点之间能通过主机名互相解析。这一步看起来简单,但确实遇到过因为主机名带下划线或者大写字母导致 kubelet 证书生成异常的案例,主机名一律使用小写字母加连字符,不要包含特殊符号。
第二步是内核参数调整。Kubernetes 要求开启net.bridge.bridge-nf-call-iptables和net.ipv4.ip_forward,同时在有大量并发连接的场景下调整net.core.somaxconn和文件句柄限制。常见的做法是直接写入/etc/sysctl.d/k8s.conf,然后执行sysctl --system使其生效。还需要关闭交换分区,swapoff -a之后再从/etc/fstab里注释掉 swap 行,这一步不做,kubelet 会拒绝启动。
第三步是安装容器运行时。当前主流选择是 containerd,它比 dockershim 时代更轻量,也是 Kubernetes 官方推荐的方向。安装完成后需要修改默认配置,把SystemdCgroup设置为true,否则 kubelet 与容器运行时的 cgroup 驱动不一致,节点会一直处于 NotReady 状态。配置修改完毕后重启 containerd,用ctr version确认运行时可用。
3.2 初始化控制平面:初始化参数、Pod 网段与证书有效期
节点准备完成后,在控制平面节点上执行初始化命令。初始化参数里最需要注意的是--apiserver-advertise-address和--pod-network-cidr。前者决定 API Server 对外通信的地址,在有多个网卡的服务器上必须显式指定,否则 kubeadm 会自动抓取默认路由对应的 IP,可能抓到的是内网管理地址,导致其他节点无法访问 API Server。后者是 Pod 网段,需要和网络插件保持一 致,比如 Calico 默认使用的192.168.0.0/16就需要在初始化时配上。
常见的初始化命令如下:
kubeadm init \ --apiserver-advertise-address=192.168.10.10 \ --pod-network-cidr=192.168.0.0/16 \ --kubernetes-version=v1.28.2 \ --control-plane-endpoint=192.168.10.10:6443命令里的--kubernetes-version需要指定一个实际存在的版本,否则 kubeadm 会尝试从网上拉取最新版本信息,离线环境下这一步会直接卡住。--control-plane-endpoint在高可用场景下应该指向负载均衡器的地址,而不是某一台控制平面节点,这样才能保证 API Server 入口的高可用。
初始化完成后会在终端打印两段关键信息:一段是加入集群的命令,另一段是 kubeconfig 文件的拷贝命令。把这两段内容保存下来,后面加入工作节点和控制平面节点都靠它们。然后执行mkdir -p $HOME/.kube && cp -i /etc/kubernetes/admin.conf $HOME/.kube/config,让kubectl命令可用。
3.3 安装网络插件:Calico 部署的最小操作集
控制平面初始化完成后,集群里的节点还处于 NotReady 状态,因为没有网络插件。Calico 的部署在官方文档里有完整命令,但实际执行中按照固定的操作顺序来做比较稳妥。先创建 Calico 的配置目录,再用 kubectl 应用其 manifest 文件:
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/tigera-operator.yaml kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/custom-resources.yaml这里有个细节值得注意:custom-resources.yaml中默认的cidr字段是192.168.0.0/16,如果初始化时设置的 Pod 网段不是这个值,需要先编辑文件再提交。网络插件安装后,kubectl get pods -n calico-system观察 Pod 状态,等所有 Pod 进入 Running,控制平面节点会先变为 Ready,工作节点加入后再逐步 Ready。
3.4 工作节点加入集群:token 过期怎么办
工作节点的加入命令就是初始化时打印出来的那条kubeadm join,在每台工作节点上执行。如果当时没保存下来,或者 token 已经过期,可以在控制平面节点上重新生成:
kubeadm token create --print-join-command执行完 join 命令后,回到控制平面节点执行kubectl get nodes查看节点状态。工作节点变为 Ready 需要等待一会儿,因为要拉取镜像并启动 kubelet。如果节点长时间处于 NotReady,优先查看 kubelet 日志,journalctl -u kubelet是最直接的排查入口。大多数情况是容器运行时配置不一致,或者网络插件没有就绪,日志里通常会有明确的错误线索。
3.5 最后一段:Ingress Controller 的部署
集群基础就绪后,业务流量怎么进来,是让整套部署方案真正完整的关键。有两种常见做法:一是直接使用云平台提供的负载均衡器,配合 Service 的 LoadBalancer 类型暴露服务;二是在自建机房或没有云负载均衡的环境里部署 Ingress Controller。指南里推荐后者,因为不依赖特定云厂商,而且在裸金属和虚拟机环境里都能用。
Ingress Controller 以 Deployment 方式运行,配合 Service 对外暴露入口。如果在裸金属环境,常见做法是用 hostNetwork 方式让 Ingress Controller 直接占用宿主机端口,再在前面配一个 HAProxy 或 Nginx 做流量分发。部署完成后需要确认 IngressClass 资源是否存在,否则创建 Ingress 时会把所有流量导向默认的 nil class,导致后端规则一直不生效。检查命令是kubectl get ingressclass,如果为空,需要手动创建并标记为默认。
4. 生产级高可用与安全加固:etcd、证书与资源隔离的部署参数设计
4.1 高可用架构:控制平面负载均衡与 etcd 集群
单控制平面集群适合开发和测试,生产环境不推荐。把控制平面扩展成三节点,首先需要一个负载均衡器把外部流量分发到三台 API Server 上。自建环境里用 HAProxy 或 Nginx 都行,配置核心就一条:把 6443 端口代理到三台控制平面节点的 6443 端口,开启健康检查,后端节点异常时自动摘除。
etcd 的部署方式也要重新考虑。kubeadm 默认把 etcd 以静态 Pod 形式部署在控制平面节点上,三台控制平面节点就组成一个三节点的 etcd 集群。这种部署方式简单,但有个隐患:控制平面节点的磁盘压力和 etcd 的性能会互相影响。更大规模的集群通常把 etcd 单独部署到专用节点上,减少干扰,但这意味着要放弃 kubeadm 的默认编排,改用手动方式部署 etcd,复杂度明显上升。对于大多数规模在几十台节点以内的集群,控制平面和 etcd 共用节点是合理选择,关键是磁盘别用机械盘。
Etcd 的参数有几个关键项需要确认:--listen-client-urls和--listen-peer-urls要监听在正确的网卡上,--initial-cluster里的成员列表要写对,--quota-backend-bytes默认 2GB 建议调整到 8GB 防止 etcd 空间耗尽。执行etcdctl endpoint health --cluster可以验证 etcd 集群的健康状态,成员列表异常时会直接暴露出来。
4.2 证书体系:有效期查看与自动续期
Kubernetes 集群内部的证书体系由 PKI 构成,kubeadm 生成的证书有效期默认是一年。集群运行时间一旦超过这个期限,API Server 和 kubelet 之间的通信就会中断。如果业务不敏感,最简单的方案是每年手动执行一次kubeadm certs renew all,然后逐个重启控制平面组件。但手册化的部署流程更推荐直接加一个定时任务。
kubeadm certs renew all --config=/etc/kubernetes/kubeadm-config.yaml systemctl restart kubelet证书续期后需要重启相关 Pod 才能生效,常见做法是直接rm -rf /etc/kubernetes/manifests/下的静态 Pod 定义再恢复,或者通过逐台滚动重启控制平面节点实现。这里有个血泪教训:证书续期后如果不同步重启 kubelet,节点会陷入证书轮换的循环报错。记住这个顺序——先续期,再重启 kubelet,再检查 Node 状态。
4.3 资源隔离:Namespace 配额与 LimitRange
控制平面稳定后,业务侧的规范化也要在部署阶段就位。Namespace 配额是资源管控的第一道闸门,没有配额的集群会出现某个业务把资源占满、其他业务无法调度的情况。针对命名空间配置 ResourceQuota,再配合 LimitRange 约束单个 Pod 的资源上下限。
一个最小配置看起来像这样:
apiVersion: v1 kind: ResourceQuota metadata: name: quota spec: hard: requests.cpu: "8" requests.memory: 16Gi limits.cpu: "16" limits.memory: 32Gi没有设置 requests 和 limits 的 Pod 在高水位下会直接触发驱逐机制,业务出现无规律重启。这个参数层面的内容在部署新业务时非常容易被忽略 :YAML 只写镜像不写资源限制,等集群 OOM 时才开始补课,不如在部署阶段就把这些约束固化到流程里。
4.4 审计日志与资源请求规范
生产集群需要开启审计日志,记录 API Server 收到的所有请求。kubeadm 方式部署时,默认审计策略未配置,需要手动添加--audit-log-path和--audit-policy-file参数。审计日志有助于回答两个问题:谁在什么时间改了什么资源,以及某个异常状态是哪个组件触发的。输出到标准输出的审计日志没有价值,落盘加定期清理才是可用的方案。
资源请求规范则应落实到模板或脚手架上,所有新增服务一律要求写清 requests 和 limits。没有资源限制的服务在节点高负载时,被 OOM Kill 的对象可能不是业务进程本身,而是 kubelet 或系统关键进程。这一步不需要额外组件,纯靠部署时的模板约束和 review 习惯,但收益非常明显。
5. 部署避坑指南:初始化失败、被覆写的 Pod 与被“节点 NotReady”折磨的五个常见问题
5.1 现象:kubeadm init报错,提示端口被占用
现象:初始化执行到一半失败,提示[ERROR Port-6443]: Port 6443 is in use或类似信息,检查端口后确认没有其他进程占用,但 kubeadm 依旧拒绝继续。原因:最隐蔽的一种情况是 before 初始化尝试过其他方式部署,残留的 kubelet 服务或 etcd 静态 Pod 还挂在系统里;另一种是 Docker 或 containerd 中的历史容器占用了端口。解决:先彻底清理残留环境,执行kubeadm reset并删除/etc/kubernetes/、/var/lib/etcd等目录,再用ss -lntp确认端口真正释放。如果环境中存在容器运行时,需要把残留容器一并删掉,然后重新执行初始化。
5.2 现象:工作节点加入后一直 NotReady
现象:kubectl get nodes能看到节点,但状态为NotReady,等多久都不变。原因:kubelet 无法连接到 API Server,或者无法拉取必要的系统镜像;也有可能是容器运行时的 cgroup 驱动和 kubelet 不一致,这是最普遍的翻车原因。解决:先执行journalctl -u kubelet -f查看日志,如果日志中反复出现failed to get cgroup stats之类的内容,修改 containerd 的/etc/containerd/config.toml,把SystemdCgroup置为true,重启 containerd,再重启 kubelet。如果日志里报镜像拉取失败,检查节点能否访问镜像仓库,离线环境则需要提前导入镜像。
5.3 现象:集群运行一段时间后突然逐台失联
现象:节点全部 Ready,但每隔一段时间某台工作节点上的 Pod 被重新调度,节点状态在 Ready 和 NotReady 之间徘徊。原因:常见诱因是 etcd 集群性能劣化,导致控制平面的 watch 事件推送超时,kubelet 的心跳上报没有被及时处理。或者节点的系统盘空间被镜像和日志占满,kubelet 无法正常写状态文件。解决:这条坑很隐蔽,因为节点表面看是健康状态。先登录出问题的节点执行df -h检查磁盘余量,再在控制平面节点上执行etcdctl endpoint status查看 etcd 的延迟指标。如果确认是磁盘问题,清理/var/lib/containerd下的无用镜像层,配置镜像 GC 策略,给系统盘留出至少 20% 的余量。
5.4 现象:kubelet 反复重启,日志里报证书过期
现象:节点状态异常,kubelet 日志里出现certificate has expired or is not yet valid,即使重启节点也没有改善。原因:kubeadm 生成的证书默认为一年有效期,集群运行超过一年,kubelet 的客户端证书失效。部分场景下是集群运行期间做过主机的迁移或复制,导致/etc/kubernetes/pki中的证书与新主机信息不匹配。解决:在控制平面节点执行kubeadm certs renew all,然后在所有节点上重启 kubelet。如果证书文件本身损坏,需要在控制平面节点重新生成并分发到各个节点。这里给个后续部署时的建议:集群证书有效期可以单独建立一个告警项,别等到真断了才去排查,续期操作非常简单,但发现问题的过程会消耗大量时间。
5.5 现象:Ingress 规则配置正确但请求 404
现象:Ingress 的 rules 路径、后端 Service 和端口都确认没问题,但访问时还是 404。原因:大概率是 IngressClass 没有指定。集群里同时存在多个 Ingress Controller 时,Ingress 对象不知道要挂到哪个 Controller 上,流量被默认控制器接收,但规则没有匹配到。解决:执行kubectl get ingressclass确认默认 IngressClass 是否存在,如果没有,创建一个并加上ingressclass.kubernetes.io/is-default-class: "true"注解。同时检查 Ingress 的 YAML 声明里是否写了ingressClassName字段,确保指向正确的 Controller。还有一个不太容易想到的点:Ingress Controller 本身是通过 Service 暴露的,如果 Service 的 selector 和 Controller 的 Pod 标签不匹配,整个流量入口就是断的,用kubectl get endpoints -n ingress-nginx检查后端的 IP 列表是否存在即可验证。
6. 部署完成不等于能用:验证链路与巡检化的最终收尾
6.1 从 Pod 到域名:一条完整的验证链路
集群部署完,第一件事不是立刻迁移业务,而是验证整个数据链路是否真的通了。最快的验证方式:创建一个测试 Deployment,写一个 Service,再配上 Ingress,然后从集群外访问域名。
kubectl create deployment nginx --image=nginx kubectl expose deployment nginx --port=80 --target-port=80 --type=ClusterIP创建 Ingress 时,host 先用test.example.local代替,在客户端机器上解析到 Ingress Controller 所在节点的 IP。浏览器访问后能出现 Nginx 欢迎页,说明从域名解析、Ingress Controller、Service 到后端 Pod 的整条链路没有问题。逐层排查的顺序是:先看 Pod 是否 Running,再看 Service 的 Endpoints 是否有 IP,最后看 Ingress 是否绑定到了正确的 IngressClass。
6.2 故障演练:混沌工程式的验证方法
链路通了只代表正向流程正常,还要验证故障场景下的恢复能力。最常见的演练方法:逐台重启控制平面节点,观察集群是否还能正常服务;逐台驱逐工作节点上的 Pod,确认业务能调度到其他节点;手动 kill 掉一个关键 Pod,验证 ReplicaSet 能自动拉起新的副本。
这套验证要验证的不是“kubectl get nodes”是否正常,而是“业务是否真的不受影响”。重启控制平面节点时,如果负载均衡的健康检查没有配合好,API Server 的 VIP 会漂移,半天才恢复。这类问题光靠观看节点状态发现不了,必须实际访问一次业务域名才能暴露。
6.3 巡检脚本:把部署经验固化成可重复的动作
部署完成不是终点,而是运维周期的起点。我通常会把部署和巡检这两件事绑定到一起,把常见的检查项写成一个脚本,放到 cron 里定期执行。脚本的核心检查项包含:节点状态、etcd 集群健康、证书过期时间、磁盘余量、API Server 的响应延迟。遇到异常直接输出到日志并触发告警,这样就不用每天手动敲命令。
检查证书过期时间用一行 openssl 命令即可,配合定时任务实现自动化提醒。巡检的覆盖范围不需要一开始就追求全面,把部署过程中遇到过的坑逐步沉淀成检查项,是最实用的迭代路径。这套脚本的维护成本很低,但对长期运行的集群来说,它相当于一份会持续更新的部署手册。
6.4 版本升级:最后的常规操作
部署完成三个月后,大概率会面临版本升级。无论是大版本跳跃还是小版本迭代,升级前先做一件事:查看官方发布的版本差异和废弃 API 列表。Kubernetes 的 API 组有时会在某一版本被移除,如果业务里的 YAML 还在用旧版本 API,升级后可能会出现配置无法下发的问题。通常推荐用工具扫描一遍集群里已有的资源,找出使用废弃 API 的对象,提前修改。
升级过程中,优先升级控制平面节点,再逐批升级工作节点。控制平面升级到一半发现异常,至少可以先暂停,保住业务的稳定。如果一切都验证过了,整个集群就具备了持续演进的能力,后续再聊扩节点、混部、GPU 调度,都是顺手的事情。这套部署方案是否值得投入,用上面这四条验证路径跑一遍,答案自然就清楚了。希望帮到你。
本文还有配套的精品资源,点击获取