ARTICLE DETAIL

资讯详情

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

Kubernetes版本演进全解析:从1.0到1.31的升级避坑指南

Kubernetes版本演进全解析:从1.0到1.31的升级避坑指南 从2015年v1.0正式发布算起Kubernetes已经更了三十多个大版本。如果你跟我一样是从v1.7、v1.8开始用kubeadm搭集群或者干脆一上来就直接上手1.24会发现一个很有意思的现象版本变更记录里的条目越来越密但真正让你半夜被电话叫醒的翻车点往往就集中在那么几个。这篇就着k8s版本变更记录的主线把影响至今的关键变更、生产升级时必然要面对的坑以及选型和面试里到底该怎么理解版本演进一次性梳理清楚。适合正在维护集群、准备升级或者刚把k8s捡起来准备系统学习的读者。1. 版本演进的主线从1.0到1.31K8s经历了三个阶段1.1 初创期1.0-1.5先解决能跑很多人以为Kubernetes生来就是今天这种完整模样其实早期版本相当朴素。v1.0在2015年7月发布继承了Borg论文的核心思路API Server、Scheduler、Kubelet、etcd这些骨架早已定下但控制器、存储、网络都还没形成后来的生态。v1.2到v1.3期间Deployment和ReplicaSet开始成为主流工作负载抽象v1.5加入StatefulSet的beta版本也正是这个版本让有状态应用第一次有了像样的编排入口。这个阶段的最大价值是证明了一条路径可行用声明式API管理容器通过控制器不断收敛到期望状态。但说实话那会儿的生产环境更多是科技公司内部的尝试踩坑成本极高。比如早期etcd还是v2存储集群规模稍微上来一点watch性能就开始出问题RBAC还没影儿权限全靠ABAC配置文件堆维护起来相当痛苦。如果你现在学k8s是从1.25开始学的回头翻这一段会觉得很多东西怎么这么原始但正是这个阶段确定了Pod、Service、Deployment这些最核心的抽象后面所有版本变更都是在给这套底座打补丁。1.2 成长期1.6-1.15从能跑到能安全地大规模跑v1.6是一个真正改写历史的版本。它引入了RBACbeta级别把权限模型从一个配置文件管全部变成了角色绑定到用户或服务账号同时支持etcd v3watch和存储性能有了本质改善。从那以后多团队共享集群、精细授权成为可能云厂商也开始放心地把托管集群推给企业客户。v1.13则是另一个分水岭。kubeadm在这个版本正式GACoreDNS成为默认DNS组件。可以说在这之前搭一个高可用集群基本靠博客和运维的命在这之后一条kubeadm init加一条kubeadm join集群就能按标准流程拉起来。同一时期CSI存储标准逐渐成熟并在v1.13/1.15之间成为生产推荐容器运行时接口CRI也把Docker的绑定关系慢慢拆开。到了v1.15CRD自定义资源定义基本GA为后来遍地开花的Operator模式埋下了最关键的地基。这个阶段整体的主题是标准化权限标准、存储标准、运行时标准、集群初始化标准。很多老玩家怀念这个时期因为功能增长迅猛每个版本都有大新闻但也正因为功能堆得太快留下了大量的v1beta1、v1beta2这种过渡API给后面的版本埋了一颗大雷。1.3 成熟期1.16-1.31稳定、清理、抠细节v1.16开始Kubernetes的画风明显变了。社区不再疯狂堆新功能而是开始大规模清理beta API、缩短支持周期、把那些测试了很久但一直没转正的特性要么转stable要么直接砍掉。extensions/v1beta1、apps/v1beta1这类老API大批退役很多老集群从1.13跨到1.16的时候直接起不来原因就是manifest里的apiVersion已经不认识了。之后几年社区把注意力转向了生命周期管理v1.20宣布Dockershim弃用v1.24正式移除v1.21宣布PodSecurityPolicy弃用v1.25正式移除同时Pod Security Admission转正。到v1.28、v1.30、v1.31这几个版本功能层面的亮点变成了Sidecar容器、In-place Pod Resize、更细粒度的调度门控这类体验优化型特性。成熟期的K8s不再需要证明自己能不能跑而是要证明自己跑得稳、管得住、升级得起。2. 五个里程碑版本这些变更至今影响生产环境2.1 v1.6RBAC与etcd v3权限和存储的底子v1.6是生产级别权限管理的开端。RBAC刚出来时大家没什么感觉也觉得配置serviceaccount、Role、RoleBinding很麻烦但回头看没有RBAC后面所有多租户、审计、安全策略都无从谈起。直到今天面试里问你怎么限制某个namespace下的Pod只能访问特定API资源答案依然是RBAC这套东西。etcd v3的影响同样深远。v2时代大集群频繁list-watch很容易把etcd拖垮版本变更记录里v1.6对etcd v3的支持相当于把控制面存储从玩具换成了数据库。你现在排查集群性能问题第一反应是看etcd的慢请求和日志压缩策略这个习惯就是从那个版本开始养成的。如果你的集群还是很老的1.5以下升级时这部分基本等于重搭而不是平滑升级。2.2 v1.13kubeadm和CoreDNS成熟部署从玄学变标准在v1.13之前用kubeadm搭集群经常被吐槽视频对着录都搭不出来——镜像拉不下来、证书过期、token对不上各种莫名其妙。v1.13把kubeadm从beta推到GA同时把CoreDNS设成默认DNS这才有了后来各个教程里一键初始化的标准化体验。现在网上大量k8s安装部署教程基本都基于kubeadm包括很多人在热搜里搜的k8s控制节点master初始化显示the api server is not healthy after 4m0.00747357s也是在kubeadm init这个环节炸出来的问题。这个我后面专门展开。可以这么理解v1.13之前的集群搭建考验的是运维的个人经验v1.13之后考验的是你对配置文件的理解难度不是一个量级。2.3 v1.16API大清理老集群升级的分水岭v1.16是无数运维的噩梦也是后来所有升级前记得看deprecated API说法的源头。这个版本把extensions/v1beta1下的Deployment、DaemonSet、Ingress以及apps/v1beta1、apps/v1beta2这些过渡版本成批移除。很多老项目的YAML文件只要apiVersion写得稍微旧一点apply上去就是“no matches for kind”。我见过一个生产环境集群版本还停在1.13里面几百个Deployment用的全是extensions/v1beta1的旧API升级的时候不动manifest根本起不来。那一次的教训让人印象很深版本变更记录不只是新闻而是升级前要对着自己存量资源逐一检查的清单。Ingress资源也在这个时期大规模切换后来Ingress GA版本networking.k8s.io/v1在v1.19落地再到v1.22把v1beta1的Ingress也淘汰掉整个过程都是在为集群可以稳定升级这个目标服务。2.4 v1.24与v1.25告别Dockershim告别PodSecurityPolicyv1.24移除Dockershim是近几年最轰动的一次变更。很多人以为只是kubelet不再直接管理Docker容器这么简单实际上它意味着所有节点都必须走CRI要么containerd、要么CRI-O。升级前如果节点上还在用Docker配合kubelet节点会直接失联。这一步其实从v1.20宣布弃用开始就给足了缓冲期但很多公司是等到v1.24出来才被迫行动。v1.25移除PodSecurityPolicy同样是个大事件。PSP的语法复杂、容易被绕过实际落地效果很一般社区最终用更简单直接的Pod Security Admission替代。这意味着升级到1.25之后你的pod-security行为需要重新设计一遍。对老集群来说从1.22跨到1.25算一次大手术运行时要换安全策略要改API兼容要查。很多生产环境至今还停在1.20、1.22不是没有原因的。2.5 v1.28之后从大爆炸转向细节体验v1.28、v1.29、v1.30、v1.31这几个版本放在五年前就是平平无奇的节奏。Sidecar容器从alpha走向beta可以让日志采集、流量代理这类辅助容器具备自己的生命周期管理而不被主容器退出拖累In-place Pod Resize允许在不重建Pod的情况下调整CPU、内存资源对在线业务非常友好kubelet的seccomp默认配置也逐步收紧安全基线在提高。这些变更单独看都不是革命性的但合起来反映了一个趋势Kubernetes的核心问题早已不是能不能跑而是跑得是否细腻。对使用方来说最新版本当然香但也意味着你要花更多精力跟踪每一个alpha、beta特性的进度而不是无脑追新。3. 升级和安装中比版本号更值得关注的三类变更3.1 支持周期官方只维护最近三个小版本首先得先把生命周期这件事说清楚。Kubernetes社区目前一个minor版本大约支持14个月实际策略是维护最近的三个minor版本。举例来说当v1.31发布时v1.28就可能已经过了安全维护期。这个窗口比很多企业想象的短得多如果你还在跑一个两年前的版本说明它大概率已经收不到安全补丁了。这对生产环境的直接建议是升级节奏尽量控制在一年一次到两次不要跨太多版本。K8s虽然设计上允许跳版本升级但每跳过一个大版本中间堆叠的API弃用和配置迁移就会全部压到你身上。很多团队从1.16直接跳到1.24结果Dockershim、API版本、PSP全部赶在一起那种酸爽经历过一次就再也不想经历第二次。3.2 API Server与Kubelet的版本差异失联的隐形原因Kubernetes对组件版本偏差其实是有约束的最核心的一条是kubelet的版本不能高于kube-apiserver同时官方建议两者的差距尽量控制在一个小版本以内。不少集群升级时习惯先升master再升node这没问题但如果master升完后某台节点的kubelet长期不升而它又恰好执行了某些新版kubelet才能支持的配置很可能出现API Server可以通、但节点调度和状态上报异常的情况。我排过最诡异的一个故障升级到1.26后某些老节点的kubelet还是1.24Pod能创建但一直ContainerCreatingkubectl describe看到的事件是failed to generate container config。查到最后就是因为kubelet和API Server之间对某些字段的序列化处理不一致。所以升级前先检查每个节点上的kubelet版本把版本差先补齐比直接一窝蜂跑upgrade命令稳妥得多。3.3 排查the api server is not healthy after 4m0.00747357s的完整链路这个热搜词几乎是每个kubeadm玩家都见过的报错。kubeadm init初始化到尾声控制面组件一直在等API Server健康检查通过等了4分钟后放弃给你留下这句看着像定时炸弹的日志。很多人第一反应是重新init一遍但问题通常出在下面几个环节不解决重来多少次都一样。第一步看kubelet是不是活着systemctl status kubelet和journalctl -u kubelet -f是必查项。最常见的死法是swap没关干净kubelet起不来或者/etc/containerd/config.toml里的SystemdCgroup没有设成truecgroup驱动和kubelet对不上。第二步检查镜像能不能拉。kubeadm config images pull先把pause、etcd、apiserver这些镜像拉一遍如果你在离线环境或网络慢的环境sandbox_image一般是pause镜像拉不下来会直接导致kubelet创建Sandbox失败。第三步看静态Pod。/etc/kubernetes/manifests目录下的四个静态Pod特别是etcd经常因为证书路径、文件权限或者磁盘满而一直CrashLoopBackOff。用crictl ps -a能看到容器状态如果etcd容器一直重启基本是etcd的健康检查挂了。第四步查网络和内核参数。6443端口不能占、net.ipv4.ip_forward要打开、Pod网段不能和节点网段冲突这些听着基础但真的一踩一个准。4. 容易被热搜点名的实战变更externalIPs、Operator与GPU调度4.1 externalIPs核心API没大改但踩的人一直很多Service的externalIPs字段从很早就存在于v1核心API中版本变更记录里几乎看不到它的身影但搜这个问题的人一直没断过。它做的事情很简单把Service通过一个自定义IP暴露出去这个IP不属于Kubernetes自动管理的对象需要你自己保证它路由到节点网络。实际用起来坑就多了。首先externalIPs不会自动在节点上建出网卡地址你要么在节点上手动配IP要么靠上层交换机路由否则流量到了节点也进不了iptables规则。其次它和NodePort、LoadBalancer同时存在时如果externalIPs填了云负载均衡器的IP很容易出现路由冲突表现为Service的Endpoints都正常但外部访问时通时不通。另一个高频坑是容器网络策略Calico或者Cilium默认可能对非集群来源的流量做了隔离导致externalIPs看起来配了没用。给现在的建议是对于简单的开发环境可以用externalIPs快速暴露服务生产环境优先考虑LoadBalancer或者Ingress别用一个历史遗留字段撑核心链路。4.2 Operator模式为什么在v1.16之后爆发CRD版本是关键市面上大量Operator案例都建立在CRDCustomResourceDefinition之上。CRD不是刚开始就能直接用于生产的它在v1.7附近出现到v1.16才GA。同时apiextensions.k8s.io/v1beta1版本的CRD在v1.16被弃用、v1.22被移除。所以你会发现一个现象很多老教程里的operator安装YAML还是v1beta1的apiVersion拿到1.25的集群上apply会直接报错。理解这个版本门槛再看现在operator生态的繁荣就很顺理成章了。CRD的schema校验、pruning、subresource都是在GA之后才逐渐完善。到后面Controller-Runtime和Operator-SDK的版本兼容矩阵也会明确写出支持Kubernetes 1.2x到1.3x这样的范围。如果你在生产环境维护一堆operator升级集群之前一定要把每个operator的CRD apiVersion列出来别让旧版CRD文件成为升级后的第一批炸弹。4.3 GPU调度的版本台阶device plugin与Extended Resourcek8s调用GPU如今看起来是个常规操作但它的门槛也是跟着版本走的。设备插件Device Plugin机制从v1.8开始提供alpha预告v1.10附近进入betaNVIDIA官方device plugin也逐渐成为主流方案。如果你在非常老的版本上尝试gpu调度大概率根本找不到nvidia.com/gpu这个资源不是因为镜像问题而是版本根本不支持。到了现在新版集群里GPU调度已经不算什么稀奇事更前沿的是Dynamic Resource AllocationDRA提供比Extended Resource更灵活的分配方式支持按设备属性做更细粒度的选择大概从v1.26开始以alpha形式出现。做GPU集群规划时建议把device plugin版本和K8s版本看成一个整体来核对NVIDIA维护的兼容性列表比任何博客都更值得信。这个细节也可以回答很多人疑惑的为什么照着网上教程在某个版本上就是调不通GPU。5. 用版本变更记录做决策选型与面试的思路5.1 生产环境选型别最新也别太旧看了这么多版本变更落到选型上其实可以总结成一句话生产环境选一个发布超过半年的GA版本同时它的下一个版本已经出来做缓冲。比如某个版本发布三个月内patch版本可能还没补齐各种稳定性修复至少等到x.3或x.5再上生产。太旧的版本则面临支持窗口逼近的问题以及和当前CNI、CSI、runtime生态的兼容性越来越差。具体判断维度我一般列三个一是自己的CRI和CNI是否跟目标版本测试过特别是containerd的版本和kubelet的cgroup驱动二是存量API清单是否在目标版本被弃用用kubectl convert或kubeconform提前校验一遍三是operator和GPU之类的专用组件是否在兼容矩阵里。这三关都过了再谈要不要升级。5.2 面试怎么答版本题从背特性到讲趋势k8s面试题里版本相关的问题频率一直不低很多人喜欢背1.24移除Docker1.25移除PSP这种结论但面试官真正想听的是你有没有理解背后的脉络。比如被问到升级注意什么别只罗列命令而是能说清先查deprecated API再核对kubelet版本差最后确认运行时和CNI兼容矩阵这个顺序以及为什么。被问到PSP为什么被移除要能讲出它配置复杂、难以覆盖真实运行时场景所以被Pod Security Admission替代。我自己的习惯是拿到一个新版本先看三样东西Deprecated API清单、kubelet和运行时变更、feature gate变化。这三个点基本决定了一次升级疼不疼。等积累多了你会发现所谓版本知识不是背出来的是踩出来的。最后分享一个实操小技巧每次升级前把当前集群的所有YAML用新版本的kubeconform跑一遍它会用新版本的OpenAPI schema帮你找出所有不兼容的资源定义这一步能挡住至少一半的升级事故。
返回列表