
简介Kubernetes 部署指南.pdf 以 PDF 文档形式提供了一份系统化的 Kubernetes 集群部署教程适合需要落地单机或生产级集群的运维、开发及架构师阅读。文档涵盖 kubeadm、kops、Kubespray、Kubernetes-The-Hard-Way 等多种主流部署方式并详细说明 Etcd、Docker、Go、CNI、CSI 等组件的版本依赖此外还包括 kubectl 安装、控制节点与计算节点部署、DNS、附加组件配置等实操步骤能帮助读者根据自身环境选择并完成集群构建。资源包内为 1 个 PDF 文件整体大小约 3.91MB内容结构清晰既有目录导航也有配置示例。针对国内环境文档也整理了使用国内镜像、解决镜像拉取慢等常见部署问题并在最后给出基于 Sonobuoy 的验证与烟雾测试思路。目前已有 178 人学习该资源可作为 Kubernetes 部署从入门到排错的参考手册。 最近整理团队内部的部署文档时我把这份《Kubernetes部署指南》PDF重新翻了出来结合前前后后部署过测试环境和生产环境的经验把里面一些关键步骤重新梳理了一遍。说实话Kubernetes的部署网络上教程一抓一大把但绝大多数都卡在“能装起来”这个层面真正到了生产环境会发现各种小问题不断。这篇博客就是基于这份指南的实操记录把部署过程中的核心细节、选型逻辑和踩坑经验都摊开来讲适合刚接触Kubernetes想动手搭一套环境的人也适合搭完以后被各种诡异问题折腾得睡不着觉的运维同学。整个指南围绕一条主线用kubeadm在物理机或虚拟机上搭建一套多节点Kubernetes集群部署配套的Dashboard和轻量级日志系统最后通过一系列检查项确认集群健康。下面按我实际操作的顺序把每一阶段的思路、动作和注意事项完整过一遍。1. 部署前的整体设计与方案选型1.1 先想清楚集群规模和用途做任何部署之前第一步永远是确认你要的到底是什么。Kubernetes集群按用途大概分三类本地开发环境、测试验证环境、生产环境。三者的部署侧重点完全不同直接决定了后面每一步怎么做。本地开发一般直接上minikube或Kind单节点、资源占用小、装完即用。测试环境建议用kubeadm搭一套1主2从的小集群既能验证多节点调度、网络插件行为又不会占用太多机器资源。生产环境则要考虑高可用至少3个控制平面节点加多个工作节点etcd建议独立部署或至少不和业务Pod混部还要规划好证书有效期、备份策略、镜像仓库等。我在指南里用的是kubeadm方案目标是一套测试环境。原因是kubeadm是目前官方主推的部署工具它把etcd、kube-apiserver、kube-controller-manager、kube-scheduler这些核心组件全部容器化通过静态Pod的方式管理升级和回滚都方便。相比纯二进制部署kubeadm屏蔽了大量底层细节但对网络插件、运行时配置仍然保留了足够的灵活性非常适合作为从入门到进阶的桥梁。1.2 版本选型与镜像源规划版本选型是个容易被忽略但极其重要的点。Kubernetes的版本迭代非常快社区一般同时维护最近三个minor版本。选版本时要注意两点一是不要追最新等发布一两个patch版本后再上二是注意kubeadm、kubelet、kubectl三个组件的版本差异不能超过一个minor版本。另一个现实问题是镜像拉取。Kubernetes核心组件镜像默认从registry.k8s.io拉取在国内网络环境下经常超时。我的做法是配置镜像加速或使用代理具体来讲kubeadm支持通过kubeadm init的--image-repository参数指定镜像仓库也可以提前用kubeadm config images pull验证能否拉取成功。生产环境如果有私有镜像仓库强烈建议把需要的镜像提前推到私有仓库里部署时直接指定既快又稳。2. 环境准备与核心依赖配置2.1 操作系统与基础配置节点操作系统我建议用Ubuntu 22.04 LTS或CentOS/Rocky Linux 9.x内核版本不要太老。Kubernetes对内核有最低版本要求比如iptables、ipvs等模块都要内核支持。节点的基础配置包括关闭swap、加载内核模块、调整sysctl参数这些在官方文档里都有但有几个细节容易被忽略。首先是主机名和/etc/hosts。所有节点的hostname必须唯一且不能包含下划线等特殊字符。推荐规划好主机名规范比如k8s-master01、k8s-node01这种同时把所有节点的IP和主机名映射写进/etc/hosts。如果你有内部DNS这一步可以省略但没有DNS的小集群强烈建议加上避免后续证书和节点通信出幺蛾子。其次是时间同步。Kubernetes集群对时间偏差比较敏感尤其是证书校验和etcd选举。我在部署前习惯先确认chrony或ntp服务在跑并且时钟偏差控制在几十毫秒以内。曾经遇到过一个节点时钟慢了2分钟导致kubelet和apiserver通信频繁报证书错误排查了半天才定位到是时间问题这个坑后面细说。2.2 容器运行时现在都推荐containerd容器运行时的选择经历了docker → containerd的迁移过程。Kubernetes从1.24开始彻底移除了对Docker的直接支持所以新部署的集群直接用containerd就好。很多刚从Docker迁移过来的同学会不适应其实containerd的命令行工具crictl和ctr用起来并不复杂日常排障够用。containerd安装完成后最关键的一步是修改配置文件/etc/containerd/config.toml。默认配置下需要调整两个地方一是SystemdCgroup参数Kubernetes官方要求运行时使用cgroupfs还是systemd必须与kubelet保持一致现在主流做法都是cgroupdriverssystemd所以必须把SystemdCgroup改成true二是沙箱镜像地址默认的pause镜像地址在国外拉取经常失败需要改成国内镜像源或私有仓库地址。改完配置后重启containerd然后用crictl version验证一下客户端和服务端都能正常响应。这一步做扎实了后面kubeadm init的时候会非常顺畅。2.3 网络插件的选择逻辑网络插件是整个集群的“任督二脉”选不好后面全是坑。主流选择是Calico和Flannel也有用Cilium、Weave的。我的建议是追求性能和NetworkPolicy能力选Calico追求极简和低资源占用选Flannel想上eBPF技术栈就选Cilium。我在这套环境里默认用Calico。原因是Calico基于BGP路由协议在三层实现网络互联性能好对底层网络环境要求不高而且天然支持NetworkPolicy。Flannel虽然简单但它的VXLAN模式在跨网段场景下存在一定的封装开销且不支持NetworkPolicy。Cilium功能最强但引入了eBPF依赖对内核版本有要求排障门槛也更高。网络插件的部署顺序有讲究一定要在kubeadm init完成之后、工作节点join之前部署或者至少在第一个工作节点join之前部署。因为CNI插件的DaemonSet会在节点上创建虚拟网卡并分配Pod网段如果你先把节点全部join进来再装CNI节点会一直处于NotReady状态虽然最终也能恢复但会给排障带来不必要的干扰。3. 部署实操kubeadm init到节点接入3.1 控制平面初始化完整步骤环境准备好之后正式开始初始化。我习惯把整个流程分成几个阶段每个阶段都做一个验证这样可以快速定位问题出在哪个环节。第一个阶段是预检。直接执行kubeadm initkubeadm会自动做一整套前置检查包括内核模块、swap、端口占用、CRI连接等。如果哪一项不满足它会明确报出来。这一步我的经验是别跳过也别直接用--ignore-preflight-errors硬闯因为很多报错背后是系统配置的真实问题比如某个内核模块没加载、某个端口被占用这种问题现在不解决后面早晚以更诡异的方式冒出来。第二个阶段是真正的初始化。执行命令时我会带上几个关键参数kubeadm init \ --apiserver-advertise-address192.168.10.10 \ --pod-network-cidr10.244.0.0/16 \ --image-repositoryregistry.aliyuncs.com/google_containers \ --kubernetes-versionv1.28.2这里--pod-network-cidr的取值很关键它必须和你选的网络插件期望的网段一致。比如Flannel默认用10.244.0.0/16Calico默认用192.168.0.0/16。你可以在init之后手动改CNI配置但完全没有必要给自己找麻烦初始化时直接对齐是最省事的。初始化成功后终端会输出三样东西一是kubectl的配置文件路径二是控制平面节点如何访问集群三是工作节点join的命令包括token和CA哈希。这三样东西一定要保存好尤其是join命令如果token过期了后面要重新生成。3.2 Worker节点接入与验证控制平面初始化完成后先别急着join工作节点第一件事是配置kubectl并确认控制平面组件全部正常运行。mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config kubectl get pods -n kube-system正常情况下etcd、kube-apiserver、kube-controller-manager、kube-scheduler这几个核心Pod会陆续进入Running状态。这里有个小细节如果某个Pod一直Pending或CrashLoopBackOff先别慌用kubectl describe pod查看事件信息大部分情况下是镜像拉取失败、配置错误或资源不足三个原因之一。接下来在工作节点上执行join命令。join之前确保工作节点的containerd已经配置好并且和主节点使用相同的sandbox镜像。如果join时遇到token过期可以用下面的命令重新获取kubeadm token create --print-join-command所有节点join完成后在控制平面节点执行kubectl get nodes如果看到所有节点都是NotReady不要意外因为CNI还没装。这正好接上前面说的CNI是让节点Ready的关键一步。部署Calico后等一两分钟节点状态就会变成Ready。3.3 验证集群健康状态集群看似起来了但“起来”和“健康”是两回事。我有一套固定的验收流程每次部署完都会完整走一遍。先看节点状态kubectl get nodes -o wide确认所有节点都是Ready并且显示正确的内部IP、内核版本、容器运行时版本。然后看核心组件kubectl get pods -n kube-system除了CNI的Pod外其他Pod都应该稳定在Running状态Restart次数尽量是0。再看DNS和调度功能创建一个临时Deployment比如运行nginx验证Pod能正常调度到工作节点Service能通过ClusterIP访问DNS能正确解析Service名称。这一步能同时验证CNI、kube-proxy、CoreDNS是否协同工作。我在指南里专门列了一个“最小验收清单”包括Pod调度、Service访问、DNS解析、跨节点通信四项每一项都有对应的测试命令。这套清单后来被团队其他人拿去当模板用反馈说省了不少事。4. 配套组件Dashboard和日志系统4.1 Kubernetes Dashboard安装与访问集群装好之后最直观的配套组件就是Dashboard。虽然很多老手习惯用命令行但对于团队协作来说有一个可视化界面还是很有价值的。安装Dashboard很简单直接应用官方YAML即可。麻烦的是访问方式的配置。Dashboard默认只允许通过HTTPS访问并且默认用Token登录。我踩过的坑是忘记创建管理员账号导致登录时没有可用的Token。正确做法是先创建一个ServiceAccount绑定cluster-admin权限然后获取Tokenkubectl create serviceaccount admin-user -n kubernetes-dashboard kubectl create clusterrolebinding admin-user-binding \ --clusterrolecluster-admin \ --serviceaccountkubernetes-dashboard:admin-user kubectl get secret -n kubernetes-dashboard \ $(kubectl get serviceaccount admin-user -n kubernetes-dashboard -o jsonpath{.secrets[0].name}) \ -o jsonpath{.data.token} | base64 -d访问模式上最简单的是使用kubectl proxy在本机开一个代理通道访问Dashboard。如果是多台机器要访问建议用NodePort方式暴露服务或者通过ingress配置域名访问。这里要注意NodePort暴露的端口范围是30000-32767而且Dashboard默认带有RBAC权限控制给不同的团队成员分配不同的ServiceAccount和权限不要所有人共享管理员Token这个习惯得从第一天养成。4.2 轻量级日志收集Grafana Loki日志系统是生产集群的刚需但有些团队一上来就上ELK把Elasticsearch、Logstash、Kibana三件套全铺开中小规模团队往往吃不消。我在指南里推荐的是Grafana Loki它的设计理念和ELK完全不同只索引日志的元数据不索引日志全量内容这意味着存储占用低得多部署也轻量得多。Loki的部署方式有两种单机模式和微服务模式。测试环境用单机模式就够了一个二进制文件就能跑起来。配合Promtail作为日志采集器把节点上/var/log/containers目录下的容器日志实际是软链接到/var/lib/docker/containers或/var/lib/containerd下的JSON日志采集到Loki中再用Grafana做可视化。我在这套环境里用Helm安装loki-stack一条命令就能把Loki、Promtail、Grafana一起装好。装完以后有个使用习惯建议Grafana的Explore页面里用LogQL语法去筛选日志比如通过label如namespace、pod、container快速定位某个应用的日志流再配合关键字过滤。第一次用的人可能觉得LogQL有点难但只要记住几个关键语法比如{namespacedefault}和| ERROR这种管道操作日常排查效率会瞬间提升好几倍。5. 常见问题排查与经验心得5.1 镜像拉取失败的几种处理方式镜像问题可以说是Kubernetes部署中概率最高的报错。kubeadm init时报“failed to pull image”或者Pod一直ImagePullBackOff都指向同一个根源镜像拉不到。我总结了三层递进的解决思路。第一层确认镜像地址和仓库。如果用了私有仓库先手工在节点上crictl pull测试一下能否拉取。第二层检查网络和镜像加速配置。containerd的config.toml里可以配置registry镜像加速但注意containerd的加速配置和Docker的daemon.json格式不一样网上很多教程直接把Docker的配置搬过来结果完全不起作用。第三层如果是离线环境可以在一台有网的机器上先把所有镜像导出为tar包再传到目标节点用ctr -n k8s.io images import导入。这里尤其要注意containerd导入镜像时必须指定命名空间为k8s.io否则kubelet无法识别。5.2 节点NotReady和CoreDNS CrashLoopBackOff节点NotReady的原因排行第一是CNI没装好第二是网络插件Pod异常。如果是Calico的Pod一直CrashLoopBackOff查看日志后往往会发现IP自动检测失败。Calico默认使用节点上第一个可用网卡作为对外通信的IP如果你有多个网卡比如VMware虚拟机常见的ens160和docker0Calico可能选错网卡导致BGP会话建立失败。解决办法是在Calico的DaemonSet环境变量里手动指定网卡env: - name: IP_AUTODETECTION_METHOD value: interfaceens.*CoreDNS的CrashLoopBackOff也值得单独说。最常见的原因是CoreDNS Pod调度到了某个节点但该节点无法访问集群DNS所需的网络。另一个原因可能是coredns的configmap被改坏或者loop插件检测到上游DNS循环转发。排查时先看日志kubectl logs -n kube-system -l k8s-appkube-dns再看coredns配置里upstream的指向是否正确。5.3 证书过期的预防和处理Kubernetes的证书机制是很多人的噩梦。kubeadm默认签发的证书有效期是一年到期后kubelet和apiserver之间的通讯就会报x509证书过期错误。有人说那我每年重新部署一次集群算了这话半开玩笑但确实有不少人这么干过。预防方法有两个层面。一是运维层面在证书到期前几个月就规划好更新窗口使用kubeadm certs renew all命令来完成续期然后重启相关组件。二是自动化层面可以用定时任务检查证书有效期kubeadm certs check-expiration这条命令会列出所有证书的到期时间。生产环境建议加个监控告警在证书到期前30天就触发通知。我曾经遇到过一种情况证书明明续期了但节点仍然报证书错误最后发现是kubelet没有重启还在用内存里的旧证书。所以续期之后一定记得重启kubelet以及控制平面的静态Pod可以直接删除Pod让它重建这个细节很容易被忽略。5.4 最后分享几个部署实战心得整套部署走下来我最想强调的一点是Kubernetes部署不是一锤子买卖而是一套持续迭代的工程实践。不要指望照着教程敲一遍命令就完事真正的价值在于理解每个组件之间的关系。比如kubelet、containerd、CNI插件、kube-proxy这几层是如何协作把用户的一个Deployment变成实际运行的Pod的。理解了这条链路遇到问题你才知道该看哪个组件的日志。另一个实践层面非常实用的建议是把部署过程中的命令和配置整理成版本化的脚本放到团队的Git仓库里任何新环境都可以快速复现。我这份指南PDF后来就是直接基于这套脚本生成的每次有新同事入职直接照着文档走一遍半小时内就能把一套测试集群跑起来几乎没有需要求救的情况。这也是为什么我一直觉得与其收藏各种零散的教程不如花点时间沉淀一套真正属于自己团队的部署指南收益会远超预期。本文还有配套的精品资源点击获取