ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Kubernetes Pod原理与Rancher实战:容器管理全解析

Kubernetes Pod原理与Rancher实战:容器管理全解析 像我们这种常年和Kubernetes打交道的人一听到“容器管理”四个字脑子里蹦出来的往往不是某个炫酷的UI而是Pod那点“剪不断理还乱”的关系。很多人上来就装个Rancher点几个按钮创建集群觉得K8s也不过如此。但真到了线上Pod疯狂重启、Sandbox创建失败、证书一夜之间全部过期的时候才发现自己连问题出在哪一层都说不清。这篇内容就是想把这两条线彻底打通一条是K8s最核心的Pod原理搞清楚它为什么长这样、调度器到底在忙什么、控制器和Pod之间是怎么“纠缠”的另一条是Rancher实战从集群部署、多集群管理到监控告警、证书续期把我在生产环境里踩过的坑和验证过有效的做法一次说透。无论你是刚入门想搭一套能用的K8s环境还是已经在维护生产集群想补上底层逻辑这篇文章都应该能给你一些实在的参考。1. 内容整体设计与思路拆解1.1 为什么说Pod才是K8s真正的灵魂很多人学K8s第一个接触的概念是Pod但真正理解Pod的分量往往是在排查问题的时候。K8s里有个非常经典的报错failed to create pod sandbox: rpc error: code unknown desc failed to create这个报错如果只看字面意思你只知道Pod的沙箱创建失败了但你不知道的是——这一步发生在kubelet调用容器运行时比如containerd创建Pod的“壳”时而这个“壳”才是Pod的灵魂所在。K8s之所以不直接调度容器而是在容器外面再包一层Pod是因为在很多业务场景里多个容器需要共享网络命名空间、共享存储卷、共享生命周期。比如一个日志采集容器sidecar要读取主容器的日志文件比如一个服务网格的envoy代理要和业务容器共用同一个网络栈这些场景如果各自调度独立的容器技术上会很别扭。Pod把一组容器绑成一个调度单元kubelet在创建Pod时首先拉起一个Pause容器也叫infra容器这个容器本身几乎不干活它的作用是把网络命名空间、IPC、PID等资源先建立起来其他业务容器启动时直接加入这个已存在的沙箱。这里有个非常关键的点Pause容器创建不成功后面的业务容器一概起不来。所以当你看到failed to create pod sandbox时本质上就是Pause容器这一步挂了。这就像合租一套房子你得先把客厅、厨房、卫生间这些公共空间打扫好室友们才能搬进来住公共空间没搞定室友住不进来不管你室友多优秀都没用。1.2 从Pod到Rancher为什么要学两套体系Rancher本身并不创造新的容器编排体系它的价值在于把K8s的复杂度封装起来。但这里有个容易让人误入歧途的点如果你完全不懂Pod的原理直接用Rancher建集群前期确实很爽因为Rancher把很多操作都图形化了但一旦遇到问题你会发现自己像拿着自动驾驶的车去跑越野——Rancher不会帮你在内核层面排障它只是把kubelet、containerd、etcd这些组件的状态暴露给你看。所以我一直建议Rancher的定位是“管理平面”而Pod原理是“数据平面”和“控制平面”的地基。Rancher管理的是多个K8s集群的总览、权限、应用目录、监控告警Pod原理解决的是某个工作负载为什么起不来、网络为什么不通、存储为什么挂载失败。两者是互补的不是替代关系。我见过不少团队把Rancher当成K8s的“一键部署工具”装完之后就只在Rancher界面里点来点去连kubectl get pods -o wide都不怎么用。结果集群出问题的时候连kubectl describe pod这个最基本的排查命令都想不起来。所以这篇内容我刻意把结构切成“原理—实战—排障”三个层次让读者既能站在Rancher的上帝视角看全局又能蹲在Pod旁边看细节。2. Pod核心原理与控制器机制解析2.1 Pod的完整生命周期和状态机Pod的生命周期看起来是Pending → Running → Succeeded/Failed但实际运维中你会看到更多中间状态比如ContainerCreating、CrashLoopBackOff、Terminating。这些状态之间不是简单地推进的kubelet会根据容器运行时反馈的事件来回跳转。我在实际运维里总结了一套判断Pod状态的“定位口诀”如果Pod长期处于Pending说明调度还没完成要么是节点资源不足要么是节点有污点taint导致没有匹配的容忍度toleration要么是PVC没法挂载。如果Pod处于ContainerCreating超过几分钟重点怀疑镜像拉取、存储卷挂载、Sandbox创建这三件事。如果Pod反复处于CrashLoopBackOff说明容器起来之后马上又退了这时候看日志kubectl logs比看事件kubectl describe pod更有价值。这个状态机背后有一个关键组件叫kubelet它是节点上的“房管员”负责跟API Server保持心跳、监听分配到本节点的Pod、调用运行时如containerd创建和销毁容器、定期上报节点状态和Pod状态。还有一个很多人不理解的点Pod的RestartPolicy只区分Always、OnFailure和Never。如果你用Deployment管理Pod重启策略默认是Always这意味着即使容器正常退出exit code 0kubelet也会把它拉起来。如果你想跑一个一次性任务比如数据迁移脚本应该用Job而不是Deployment否则你会发现任务跑完了Pod还在那反复重启。2.2 控制器如何“指挥”Pod工作Deployment是99%的场景会用到的控制器它管理的是无状态应用。Deployment下面挂着ReplicaSetReplicaSet负责维护指定数量的Pod副本。这里有一个容易忽略的细节Deployment的滚动更新RollingUpdate机制实际上是创建了一个新的ReplicaSet然后逐步调整新旧ReplicaSet的副本数来实现的。如果你手动kubectl scale某个Deployment可能不太容易发现这个细节但如果你用kubectl rollout history查看版本历史你会看到每一次更新都对应一个新的ReplicaSet版本。这个设计的好处是回滚非常方便一条kubectl rollout undo就能切回上一个ReplicaSet。与Deployment相对的是StatefulSet它适合有状态应用数据库、消息队列等。StatefulSet创建的Pod具有稳定的网络标识Pod名称固定序号从0开始和稳定的存储标识PVC也是按序号的但这也带来一个坑StatefulSet缩容时序号大的Pod会先被删除如果你没做好数据备份删掉之后PVC可能残留重新扩容时会重新绑定旧的PVC。这个行为在运维层面需要格外小心和Deployment随便删随便建的模式完全不同。DaemonSet则保证每个节点或满足条件的节点上运行一个Pod副本典型场景是日志采集Fluentd、Filebeat、指标采集Prometheus Node Exporter、网络插件Calico的calico-node。用Rancher部署集群时默认会装一些DaemonSet类型的组件比如rancher-vsphere之类的你看节点列表时留意一下DaemonSet状态是否健康很多集群问题的根因就是某个节点上的daemon pod没起来。2.3 调度器、etcd与API Server是如何协作的站在Pod的视角整个K8s控制平面的工作流程大概是你通过kubectl或Rancher发出一个创建Deployment的请求这个请求先到API ServerAPI Server会做认证、鉴权、准入控制Admission Control然后把Deployment资源写入etcd。随后Deployment控制器从API Server Watch到变化创建ReplicaSetReplicaSet控制器又创建Pod对象调度器kube-schedulerWatch到Pending状态的Pod根据节点资源、亲和性、污点容忍等条件选一个最合适的节点把Pod绑定到该节点。接着kubelet在该节点上创建Sandbox、启动容器。这个链路里最容易出问题的环节是etcd和API Server之间的交互。很多朋友在集群规模扩大后遇到“API Server响应变慢”一查发现etcd的磁盘IOPS瓶颈了。etcd是K8s的“数据库”所有的资源状态都存在这里它要求低延迟、高可靠但它不擅长处理大量的并发写请求。生产环境的etcd建议用SSD盘并且不要让etcd和其他高IO应用比如数据库容器共享同一块磁盘。Rancher在安装时会把K3s或RKE2所需的etcd一起装好如果你用Docker安装Rancher单机版Rancher本身的数据也存在一个容器的卷里。多集群生产环境下Rancher管理的每个下游K8s集群都会有自己独立的etcd而不是所有集群共用一份etcd这个架构设计比较清晰但你要注意给每个集群的etcd预留足够的磁盘空间和性能。3. Rancher实战从部署到多集群管理3.1 单节点Rancher快速部署选型Rancher有两大类部署形态一是单节点docker run起一个容器适合测试环境或小规模场景二是高可用部署用helm把Rancher装到某个K8s集群里。单节点部署非常简单但有两个需要注意的点第一Rancher容器本身会把K3s作为一个嵌入的K8s集群跑起来也就是说Rancher的控制面是跑在K8s之上的第二Rancher默认会自带一个local集群这个集群可以用来管理Rancher自身但你最好不要在上面跑业务工作负载因为一旦Rancher所在的节点挂了业务也一起没了这个耦合非常脆弱。如果做生产级部署我更推荐用RKE2Rancher Kubernetes Engine 2搭建一个底层K8s集群再用helm在集群里安装Rancher。这个方案的优点是可以把Rancher的etcd、API Server、控制器等组件按K8s原生方式管理还能借助Rancher自己的监控告警体系来监控Rancher本身。听起来有点“套娃”但实际用下来确实比单容器部署稳定很多尤其在证书轮转、版本升级这些操作上helm方式要优雅得多。生产RKE2搭建时组件的选择和版本对齐要特别注意。我一般建议把RKE2的版本和后续安装的K8s集群版本尽量对齐避免出现kubectl版本和API Server版本差异过大导致兼容性问题。Rancher对下游集群的版本管理是一大亮点它可以在UI上直接升级下游集群的K8s版本但升级前一定要确认集群里安装的CRDCustom Resource Definition和operator是否兼容新版K8s。3.2 在Rancher上导入和创建集群Rancher支持两种方式纳管集群一是直接用Rancher的UI创建一个全新的K8s集群RKE2或K3s二是把已有的K8s集群“导入”到Rancher里管理。第二种方式在企业里用得很频繁因为很多集群早就搭好了不可能推倒重来。导入集群的操作在UI里非常直观Rancher会给你一段kubectl apply的manifest你在目标集群上执行一下集群代理就装好了。这个代理组件叫cattle-cluster-agent它会主动连回Rancher ServerRancher通过它来下发指令。这里有个网络层面的细节如果Rancher Server和下游集群不在同一个网络比如一个在公网一个在内网你要确保cattle-cluster-agent能够访问Rancher Server的地址反之在注册时填写的server-url也要能被集群内的组件访问到。很多导入失败的案例都是这个网络方向没打通。创建新集群时Rancher会引导你配置节点角色。RKE2集群的节点角色分etcd、controlplane、worker三种你可以把三种角色都放在同一台机器上All-in-One也可以分离部署。对于生产环境我建议至少三台机器三台都同时承担etcd和controlplane角色worker角色单独扩展这样就实现了“三台master高可用”。Rancher底层用的是RKE2内置的etcd集群它天然支持多节点etcd选举少数节点故障不影响集群可用性。3.3 多集群管理中的认证授权与资源隔离Rancher一个很大的价值在于统一认证和RBAC管理。企业里可能有开发环境、预发环境、生产环境多个K8s集群如果每个集群单独维护一套kubeconfig权限管理会非常混乱。Rancher支持对接LDAP/AD、GitHub、SAML等外部认证源用户登录Rancher后按集群、按命名空间授权不需要接触底层kubeconfig就能操作。我在实际项目中喜欢把Rancher的权限模型设计成“项目Project”和“命名空间Namespace”两层一个项目对应一个业务线或一个团队项目里包含若干个命名空间。团队A的成员只能看到自己项目的资源无法越权查看其他项目的Deployment或Pod。这个隔离机制特别适合多团队共用一套K8s集群的场景也是Rancher相比原生K8s的一大体验提升。多集群的场景下还要注意Rancher的Cluster资源健康状态。Rancher UI里的集群列表会显示每个集群的“Active / Updating”状态如果某个集群一直处于Updating状态很可能是集群代理和Rancher Server的通信中断或者底层集群的证书出了状况。这时候先去检查cattle-cluster-agent或cattle-system命名空间里的Pod日志一般来说线索都在那。3.4 Rancher上的监控、告警与应用商店Rancher自带的Monitoring功能是基于Prometheus生态封装的开箱即用。你在Rancher的工具 → Monitoring里启用后它会自动部署Prometheus、Grafana、AlertManager等组件并提供一批预置的仪表盘比如集群CPU/内存使用率、Pod状态、API Server延迟等。这里我的建议是即使你已经有一套独立的Prometheus也可以让Rancher的监控跑一份作为“集群级体检”因为它的指标采集范围覆盖了控制面组件和节点的系统指标比自己手工拼装一堆exporter方便太多。Rancher的告警规则配置也很快比如CPU使用率超过80%持续5分钟就触发告警。告警可以发到企业微信、钉钉、Slack等渠道。但这里有个小坑告警通知里不能直接带上敏感的token把webhook地址配置在Rancher的“通知”里时要确保地址安全避免泄露到公共群。应用商店Apps则是Rancher另一个高频使用的功能。Rancher整合了HelmUI上可以直接搜索和部署应用比如部署Prometheus、Grafana、LonghornRancher自家的分布式存储等。实际使用中我建议对应用商店里的Chart版本保持谨慎不要盲目升级升级前最好在测试环境验证一遍因为有些Chart在升级时会修改CRD导致老资源兼容出问题。4. 从Pod原理看Rancher排障高频问题与操作实录4.1 Sandbox创建失败到底怎么查开篇提到的failed to create pod sandbox我在真实环境里遇到过好几次最常见的原因是容器运行时containerd和kubelet之间的状态不一致或者镜像仓库拉取Pause容器镜像失败。Pause容器镜像是Sandbox的“地基”如果你用的是私有镜像仓库仓库里没有同步pause镜像或者tag不对Sandbox就必然创建失败。排查方法很简单先kubectl describe pod pod-name看事件确认报错内容。在对应节点上执行crictl ps -a看容器状态确认Sandbox容器是否存在。检查/etc/containerd/config.toml里的sandbox_image配置确认镜像地址和tag是否正确。如果镜像没问题再看一下crictl pull sandbox-image能不能拉下来。另一个容易忽视的原因是节点磁盘空间不足尤其是inode耗尽。当docker或containerd的存储目录所在磁盘满的时候Sandbox创建会直接失败报错不是“磁盘满”而是“无法创建Sandbox”非常迷惑。我建议节点监控里必看df -iinode占用率和df -h磁盘占用率两个指标双管齐下。4.2 证书过期与自动续签的应对思路K8s证书过期是个经典问题涉及的面比较广kubelet的客户端证书、API Server的serving证书、etcd对等证书每一样过期都会引发各种匪夷所思的症状比如节点状态变成NotReady、API请求401、组件之间握不上手。Rancher在证书管理上做了一些自动化比如它自己生成的证书可以自动轮转但更底层的K8s组件证书是否自动续签取决于你用什么方式搭建集群。RKE2默认的证书有效期策略比较合理但也不是完全一劳永逸。我个人的建议是把“证书剩余有效期”纳入日常巡检指标用kubeadm alpha certs check-expiration如果用kubeadm或查看集群内部证书文件的有效期来判断剩余时间。生产环境建议配置证书监控告警至少在过期前30天提醒一次。如果你用Rancher管理集群Rancher会有一个rotate certificates的功能在UI里可以对下游集群执行证书轮转。但执行这个操作时要注意轮转过程中API Server和kubelet都会重启集群会产生短暂的不可用窗口要在维护窗口内执行并提前通知业务方。轮转后检查节点状态、CoreDNS、调度器是否恢复正常不要以为UI提示“成功”就万事大吉。4.3 Pod卡在Pending或CrashLoopBackOff的排查思路Pod卡在Pending时第一件事是看kubectl describe pod的Events。如果提示0/3 nodes are available说明所有节点都不满足调度条件常见原因有三个节点资源不足、节点标签选择器没匹配上、节点有污点但Pod没有对应容忍。资源不足的判断很简单kubectl top nodes看CPU/内存使用率。如果节点上有大量Evicted状态的Pod说明节点资源长期紧张触发过驱逐这时候应该扩容节点或清理无用Pod。CrashLoopBackOff则要看容器日志kubectl logs --tail50 pod-name定位进程退出原因。我见过最多的两类原因应用启动时依赖的数据库/配置中心连不上以及配置文件中某个环境变量没传入导致空指针。此类问题用Rancher的日志查看器也能排查但Rancher把kubectl logs封装成了界面操作原理其实完全一样。日志只能帮你看到应用层面的事如果应用日志显示正常但容器还是退出那就要怀疑健康检查配置有问题——探针livenessProbe/readinessProbe可能配置得太严格导致kubelet认为容器不健康而不断重启。4.4 GPU调度和其他高级调度策略的落地方案涉及AI训练的团队都绕不开K8s调用GPU这个问题。K8s调度GPU的方式一般有两种一种是直接声明nvidia.com/gpu资源通过NVIDIA Device Plugin另一种是用NVIDIA MIGMulti-Instance GPU把一张卡切成多个实例。配置NVIDIA Device Plugin的步骤通常很固定先在节点上装好NVIDIA驱动然后部署nvidia-device-plugin这个DaemonSet最后在Pod里resources.limits声明nvidia.com/gpu: 1。这里有一个常见坑宿主机上如果以Docker方式安装了NVIDIA Container Toolkit但K8s使用的是containerd运行时需要确保这个toolkit的hook对containerd也生效很多GPU调度不了的案例都是因为这个适配没做好。如果你想在多个GPU节点之间做更细粒度的调度建议用Node Label 亲和性来约束业务。比如给A组节点打gpu-typeA100给B组打gpu-type4090在Pod的nodeSelector或nodeAffinity里指定要调度到哪类GPU节点。Rancher的UI里虽然可以直接编辑工作负载的YAML但GPU资源这种定义还是建议直接在YAML里写清楚避免UI表单遗漏字段。4.5 高可用架构下必须注意的etcd和master角色前面提到“三台master高可用”这里再展开说一下。RKE2集群里每个master同时承担etcd和controlplane角色三台互为备份。etcd使用Raft协议选举leader只要多数节点3台中至少有2台存活集群就能继续工作。但正因为如此etcd集群里跑着敏感数据必须做好定期备份。Rancher本身就提供了etcd备份和恢复的功能在集群设置里可以配置备份到S3或本地路径。我的经验值是每天至少备份一次etcd并同样把备份文件复制到异地存储防止整个机房故障时连备份也一起丢了。另外这三个master节点的网络延迟要尽量低因为etcd的Raft协议对性能很敏感。如果三台机器分别在不同机房网络抖动会导致频繁leader切换严重时集群会进入只读状态。生产环境应该把etcd节点放在同一个可用区或同一个物理机房并使用低延迟网络。5. 实战补充Prometheus监控、常用命令与版本策略5.1 用Prometheus把集群监控指标补全Rancher内置监控能覆盖大部分场景但我还是会在集群里再部署一套社区版Prometheus用来采集更多自定义指标。kube-prometheus-stack这个Chart是很多人的首选它把Prometheus Operator、Grafana、AlertManager、节点exporter都整合到了一起。部署这套监控时最重要的是搞清楚ServiceMonitor和PodMonitor这两个CRD的作用。ServiceMonitor定义Prometheus如何抓取某个Service背后Pod的指标PodMonitor则直接抓取某一组Pod的指标。如果你在Rancher的应用商店里安装了某个Chart但Grafana里看不到指标大概率是ServiceMonitor没有创建成功或者selector没匹配到目标Service。实际告警规则里我个人最推荐这几条必配项节点CPU使用率持续过高、内存使用率过高、磁盘即将写满、Pod长时间Pending、API Server错误率上升、etcd leader变化频繁。这些规则在kube-prometheus-stack默认就有不少但需要你按业务需要取舍避免告警轰炸导致告警疲劳。5.2 高频kubectl命令速查在Rancher UI之下总有一些事情是UI做起来很别扭、必须上命令行的。我平时用得最多的几个命令场景查看所有命名空间的Pod状态kubectl get pods -A -o wide查看某个Pod详情的完整事件kubectl describe pod pod-name -n namespace实时跟踪Pod日志kubectl logs -f pod-name -n namespace进入容器调试kubectl exec -it pod-name -n namespace -- /bin/sh查看节点资源用量kubectl top nodes查看集群证书有效期kubectl get csr或直接查看证书文件路径Rancher的UI里其实也集成了“执行命令行”的功能但你在浏览器里执行kubectl和在自己终端执行kubectl心理安全感是完全不同的。尤其是在集群出问题、Rancher UI本身都打不开的时候你必须具备本地kubectl直连集群的能力。平时把kubeconfig文件备份到一个安全的地方是一件非常重要的事。5.3 K8s和Docker到底是什么关系别再搞混了“k8s和docker区别”这个话题经常被问到很多人以为K8s就是用来管理Docker容器的其实更准确的说法是Docker提供的是容器运行时和镜像格式而K8s在整个容器生命周期里扮演的是编排者。K8s默认的容器运行时在较新版本里已经是containerd了它直接管理容器不再依赖Docker Engine。这就解释了为什么很多排障场景里你会看到crictl而不是docker命令crictl是K8s生态的命令行工具专门和CRI兼容的容器运行时交互。在节点上执行crictl ps、crictl logs比docker ps更准确因为Docker命令看到的容器不一定就是K8s正在管理的那个容器特别是在 containerd 环境下Docker CLI甚至根本看不到。明白这个区别后你再看“部署K8s”和“部署Docker”就是两个完全不同的事情Docker负责“把容器跑起来”K8s负责“在成百上千台机器上决定容器该跑在哪里、跑几个、挂了怎么办”。Rancher则是在K8s之上再帮你加了一层“可视化管理”降低操作门槛但三者层层递进谁也替代不了谁。6. 一些很实用的细节经验与收尾6.1 Deployment的中文名与资源标识规范有一个很有意思的问题如果给K8s Deployment一个中文名字会发生什么K8s的元数据名称metadata.name必须符合DNS子域名的规范只能包含小写字母、数字和-不能直接使用中文。因为Pod的名称是基于Deployment名称生成的如果名称里包含中文Pod的主机名和DNS解析都会出问题。但你可以用metadata.labels或annotations来写中文备注比如app: 订单服务这样在Rancher UI里看到的列表名称可以展示中文同时底层资源名保持合法。这是一个容易被忽略的规范细节尤其是在国内团队协作时大家天然喜欢用中文描述业务但底层资源命名还是建议统一用英文加连字符风格并配好中文注解。6.2 版本升级前必须做的三件事不管你是升级Rancher版本还是升级下游集群的K8s版本我都建议在动任何版本升级之前完成这三件事第一备份etcd不只是Rancher自己的etcd还包括所有下游集群的etcd。备份后最好在测试环境验证一下能否恢复。第二检查所有CRD和operator的兼容性列表很多线上事故都是因为升级K8s后旧的CRD版本不再被API Server支持导致自定义资源全部不可用。第三确认第三方组件比如存储插件、CNI插件、监控组件的版本支持矩阵这类组件的适配滞后经常是升级的隐形炸弹。把这三件事做完再选一个维护窗口动版本心里会踏实很多。Rancher的升级页面上会把“当前版本”和“可升级版本”列得清清楚楚但它不会替你判断业务兼容性这个责任还是要运维自己扛。6.3 用Rancher管理多套环境的心得最后说一点个人体会。我自己维护着三套K8s环境开发、预发、生产。最初每套环境都是用不同的方式搭建的结果管理起来非常痛苦配置漂移严重同一个应用在每套环境里的行为都不一样。后来把三套环境全部纳入Rancher统一管理后至少获得了三个显著改善一是账号体系统一了不需要每套环境维护各自的kubeconfig二是应用发布流程可以在Rancher的“持续交付”里做成标准模板开发环境和生产环境共用一套Chart只是参数不同三是监控和日志入口一致出问题时能快速对比不同环境之间的差异。当然Rancher不是万能的它解决不了K8s底层架构设计本身的问题。如果你把Pod原理学透了再配合Rancher这个管理平面绝大多数生产问题都能在半小时内定位到组件级别。我觉得这才是“容器管理全解析”最值得掌握的能力不是记住某个按钮在哪儿而是当系统报错时你能下意识地判断出问题出在控制平面、数据平面还是运行时然后知道去哪一层、用什么工具排查。
返回列表