ARTICLE DETAIL

资讯详情

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

容器十年:Kelsey Hightower退休,容器为何仍霸占热搜?

容器十年:Kelsey Hightower退休,容器为何仍霸占热搜? 2023年初Kelsey Hightower在Twitter上宣布从Google退休。这条消息刷屏了云原生圈很多人说“一个时代结束了”。但真正让我停下来想了很久的是同一周里某个技术群里闪过的一个问题——“docker容器怎么赋予目录读写权限”。一边是容器领域最著名的布道者功成身退一边是新手还在为一道再基础不过的权限问题挣扎。Kelsey本人离开了容器话题的中心可“容器”这个词却依然在热搜榜上、技术群聊里、招聘JD中反复出现。为什么十年过去了我们还在谈论容器这篇文章不打算讲Docker命令、也不打算复盘Kubernetes架构我想认真聊聊这件事本身。1. Kelsey Hightower退休了容器话题却还在热搜榜上没有走1.1 Kelsey Hightower是谁Kubernetes的“人肉翻译机”先对齐一个背景。Kelsey Hightower不是Kubernetes源代码提交量最大的工程师也不是CNCF的理事但他可能是让地球上最多人理解“Kubernetes是什么”的那一个人。他的职业身份是Google Cloud的开发者关系工程师常被戏称为“社区布道者”但这个称呼太小看他了。他做的事情是把一套极其复杂的分布式系统调度框架拆成一个个能让人听懂、能动手复现的Demo。看过他演讲的人大概都记得那种风格——没有夸张的PPT没有晦涩的架构图他就在一台机器前现场敲命令把一个服务从零部署进集群失败了他就当场排查一边查一边解释。台下的观众会有一种很强烈的错觉这东西我也能搞定。这种“让我来你没问题的”的传播力比任何一份官方文档都有效。Kelsey在Kubernetes生态里的位置很像早期Linux社区里那些写文档、做培训、跑展会的人。他不负责发明轮子他负责让所有人都相信轮子是圆的、是能转的、是自己也能造一个的。对一个尚在早期、被怀疑“是不是厂商炒作”的项目来说这种信任比功能本身更值钱。1.2 退休不是终点而是容器叙事的一个注脚他宣布退休的时候云原生社区的反应大致分成两派一派是伤感觉得技术偶像离开了舞台另一派是释然因为Kelsey本人传递出来的信号一直很清楚——容器和Kubernetes已经成熟了成熟到不再需要那么多聚光灯下的布道他可以退场了。我曾经看过一段他接受访谈的内容大意是技术已经走到一个“无聊”的阶段云原生已经从新奇事物变成了默认基础设施剩下的问题更多是工程执行而非方向探索。这里的“无聊”不是一个贬义词恰恰是对技术生命周期最精准的判断。人会在什么情况下退休手头的事情已经稳定到不需要他盯着了。服务器集群跑得挺好的监控告警都静默了交接文档写完了新人已经能值班了。Kelsey对Kubernetes做的事情本质上是同一个逻辑。但问题在于他解决的是“怎么迈出容器化第一步”的问题而后来者面对的是“怎么和容器一起生活十年”的漫长日常。这两件事之间隔着数不清的权限报错、内存泄漏、镜像安全扫描、跨部门扯皮。这就是为什么他退休了容器这个词却还在热搜榜上反复出现。2. 一个词承载三个世界操作系统容器、Java容器、数据结构容器2.1 在搜索框里输入“容器”你会得到一份错位清单我特意去看过那些围绕“容器”的网络热搜词越看越觉得有意思。排在前面的是“docker容器怎么赋予目录读写权限”“容器资源隔离”往下翻会出现“spring容器启动流程”“stl容器”“vector容器”“容器list/dict”再往后还有“西门子授权提示密钥容器损坏”“uos系统wine容器软件缓存清理”。这些词根本不是在讨论同一个东西。“docker容器”属于操作系统层的隔离技术“spring ioc容器”指的是Java框架运行时管理对象生命周期的机制“stl容器”则是C标准库里用来存数据的集合类“西门子授权提示密钥容器损坏”里的“容器”多半是Windows操作系统的密钥存储容器。它们唯一的共同点就是都翻译成了“容器”这两个汉字。这一发现其实解释了很多无效沟通的来源。两个工程师在同一个群里争论“要不要上容器”一个人脑子里是Docker镜像和编排集群另一个人脑子里是Spring的BeanFactory和ApplicationContext他们说了十分钟之后发现彼此根本不是同一个话题但谁也不愿意承认浪费了时间。这种场景在中文技术圈每天都在上演。2.2 三种容器三种含义三层技术栈为了方便理解我通常会给团队里的新人做一张“容器分层辨析表”把经常被混为一谈的三种“容器”放进去容器类型所处层级典型代表典型讨论问题OS级容器操作系统虚拟化层Docker、Kubernetes、containerd镜像构建、容器编排、资源隔离、权限挂载、容器逃逸防护应用运行时容器语言运行环境Spring IOC容器、Servlet容器Tomcat、EJB容器Bean生命周期、启动流程、依赖注入、连接池管理数据结构容器编程语言抽象层C STL的vector/list/map、Python的dict/list内存分配策略、迭代器失效、遍历性能三者唯一的相似点是“装东西”这个语义隐喻。OS级容器装的是进程和它们的文件系统视图Java容器装的是类实例和依赖关系STL容器装的是数据元素。底层实现、技术栈、解决问题的维度完全不一样。2.3 歧义带来的真实乌龙一群后端工程师开会讨论“把系统容器化改造一下”架构师说的是把服务重构成Docker镜像再部署到KubernetesJava开发理解的是调整Spring Bean的作用域和对象生命周期还有一位来自嵌入式背景的同事以为是在讨论如何把UI模块塞进一个轻量级图形容器。这种错位不是段子是我在多个团队里见过的真实状况。所以我现在养成了一个习惯听到“容器”两个字先确认上下文。讨论基础设施的时候默认它是Docker/Kubernetes阵营讨论Java应用性能的时候默认是Spring或者Tomcat讨论算法题和数据结构的时候再回到STL容器。这个小小的确认动作能省掉一整场“鸡同鸭讲”的会议。3. 容器十年的三个拐点从神器到默认设置3.1 2013年的Docker它没有发明容器只发明了“把容器变成日常用品”的方式很多人以为Docker是容器的发明者其实不是。Linux的namespace、cgroups、rootfs切换这些内核机制早就在那里了LXC也早在2008年前后就在做类似的事情。真正让这一切被大众使用起来的是Docker在2013年的开源。Docker做的事情本质上是一次产品化和工具链革命。它把“通过内核特性构建隔离环境”这件事封装成了一条docker run命令又配套了镜像分层、UnionFS、Docker Hub分发仓库。以前你要折腾数小时来配置一个隔离环境现在一个文件加一条命令就够了。它把容器从系统工程师的玩具变成了所有开发者的日常用品。这个转变的意义怎么强调都不过分。镜像这一交付格式让“本地能跑”终于变成了“处处能跑”。过去交付软件是丢一个安装包再附带三页环境要求说明对方环境稍有偏差就崩现在交付的是一个包含全部运行时依赖的镜像走到哪都是一样的行为。3.2 2014到2017年的Kubernetes容器从“运行环境”变成“计算资源调度系统”但单机Docker撑不起大规模业务。2014年前后容器的编排问题逐渐成为主角而恰好这时Google开源了Kubernetes把内部系统Borg的管理理念带了出来。这不是一个简单的编排轮子它建立了一套关于“容器如何被当作资源调度”的完整哲学——声明式API、控制器循环、Service负载均衡、自动扩缩容。2015年CNCF成立KubeCon的规模逐年翻几倍。到2017年容器编排这个赛道基本已经分出胜负了Swarm和Mesos先后退出主流语境Kubernetes成为唯一被大规模验证的编排标准。回过头看这是一个相当典型的技术霸权路线Docker定义了容器的交付格式Kubernetes定义了容器的调度语义两者叠起来几乎关死了开箱方式的其他可能。3.3 2018年以后的“无聊”恰恰说明它成了土地2018年之后“Kubernetes is boring”这句话开始流行源头之一就是Kelsey Hightower的表达。这句话被很多人误解为“没意思了”实际上它的意思更接近“它终于稳定到可以托付业务了”。真正成熟的技术的标志不是天天让人惊讶而是变成默认背景。就像你现在不会每天感叹“哇服务器居然连上网络了”就像你写代码时根本不会感谢操作系统帮你管理了虚拟内存。容器在2018年之后也跨过了这个门槛——不再有人惊讶于“Docker跑起来了”更常见的话题变成“为什么我的Java应用在容器里内存占用这么高”“容器里的时区怎么不对”“如何给容器目录配权限”。看看那些热搜词——大部分已经不是“要不要用容器”而是“在容器里怎么处理某个具体问题”。这几乎就是底色技术才能享有的待遇你已经在地上建楼了不再关注土地本身。4. 拆热搜词当代容器焦虑都在哪几层4.1 权限和隔离容器内的边界不等于安全边界“docker容器怎么赋予目录读写权限”“容器资源隔离”“无法枚举容器中的对象访问被拒绝”——这一类搜索词长期霸榜。权限焦虑确实是容器落地最常见的头号痛点。容器的隔离不是一个整块的黑箱。文件系统挂载涉及Uid/Gid映射和用户命名空间进程操作受Capabilities限制宿主机的SELinux或者AppArmor策略又可能拦截容器行为。这么多层叠在一起用户通常需要在宿主机权限、容器内账号、挂载卷属主、安全策略四个维度同时对齐才能解决一个看似简单的“没有写权限”问题。实际排查路径大概是先确认挂载路径的属主和组成员再检查容器进程运行的是不是root再尝试调整宿主机SELinux布尔值最后才轮到考虑用户命名空间映射。这个顺序搞反了很容易陷入“改了一个东西、冒出新问题”的死循环。4.2 资源和性能容器不是一个轻量虚拟机“java docker容器占用内存特别高怎么排查”这种问题是另一个常青树。很多人天然以为容器比虚拟机轻所以内存占用也该更小但事实没那么简单。JVM在容器里很容易基于物理机总内存算堆大小而不是基于cgroup的限额所以一个限制512MB的容器可能申请到2GB的堆空间。排查思路通常是从几个方向同步进行先看docker stats确认容器的实际用量和限制再进容器用free看PageCache再分析JVM启动参数确认-XX:MaxRAMPercentage和-XX:InitialRAMPercentage是否针对容器环境做了调整最后用jcmd或者GC日志排除堆外内存泄漏。前段时间我们一个服务反复在深夜OOM Kill用这个流程查下来发现罪魁祸首既不是堆内内存也不是GC压力而是Netty的Direct Buffer碎片化这类问题不看实测数据只靠猜基本浪费时间。4.3 部署和交付容器化不再只是某类人的独门手艺“容器化部署datax与datax-web”“蜜罐hfish容器部署”“青龙容器公益版”“多容器部署hermes webui”——这些词指向一个非常明显的趋势容器已经从互联网大厂的基建赛道渗透到了中长尾工具和垂直场景。数据同步工具、安全蜜罐、自动化脚本、甚至嵌入式UI组件都要容器化交付说明这套机制已经超越了“微服务立面”的范畴变成了一种通用的软件分发手段。研究这些工具的容器化部署时真正有价值的不再是“这功能怎么用”而是如何把别人的镜像拉进来、把端口和数据卷理清楚、再配合外部依赖完成联调。4.4 概念混用和跨行业误伤剩下的那些搜热词——“西门子授权提示密钥容器损坏”“uos系统wine容器软件缓存清理”“lvgl容器”——就很值得玩味。他们完全不是Docker/Kubernetes语境下的容器但同样被“容器”这个前缀吞没。这其实说明一个现实“容器”这个词已经成为一块通用的语义橡皮泥不同行业的人往里填充了各自的形状。这也带来一种隐性成本——当你搜某类容器问题时你判断不了搜出来的结果到底跟你是不是同一个技术栈。我的建议是搜问题的时候一定要带上下文词比如“docker容器权限”“spring容器启动流程”“STL容器vector”把命名空间明确到无法误解。防止用C的语法去查Windows证书存储容器的故障这种错乱能让一个高级工程师撞上完全陌生的墙。5. 容器落地中的三个反直觉误区与排查心得5.1 把容器当虚拟机内核共享带来的一连串误解容器最容易被新手误读的地方在于“它是一个隔离的环境”于是天然会去套虚拟机的心智模型。虚拟机里你能跑多个服务、能登录上去改各种环境配置、能装systemd但容器里最好一个进程一个职责业务进程就是PID 1别再给它配一堆守护进程。还有一个容易被忽视的点容器共享宿主机内核。这意味着你没法在容器里换内核、改内核参数、加载内核模块那些“进容器改sysctl”的操作要么没效果要么被宿主机的安全机制拦下。如果你的业务确实需要更彻底的内核级隔离需要考虑gVisor或者Kata Containers这类安全运行时而不是寄希望于加几个权限标志就能消除逃逸风险。5.2 镜像瘦身不是唯一的KPI安全、启动速度、兼容性同样重要基础镜像用Alpine还是Debian很多团队吵了很久。Alpine确实小但MUSL libc和glibc并不完全等价一些预编译二进制在Alpine里会踩到莫名其妙的雷。我见过一个项目为省磁盘空间硬上Alpine结果Java应用在容器里遇到DNS解析超时的问题折腾了两天才定位到MUSL和glibc的行为差异。省下来的几十MB换成了两个工程师两天半的时间。更合理的做法是优先选择一个你熟悉、有安全更新承诺、且能稳定复现问题的基础镜像。把镜像做小确实重要但“构建出来能稳定运行”永远排在更前面。5.3 权限问题挂载、属主、用户命名空间三者的三角恋回到那个热搜词“docker容器怎么赋予目录读写权限”。这个问题看起来简单实际上牵涉三个层面挂载volume时宿主机目录的属主和权限容器内进程的实际用户以及宿主机SELinux/AppArmor策略是否允许容器访问该路径。我通常建议的一个收敛方案是在镜像里显式创建专用运行用户并固定Uid比如USER 10001宿主机挂载目录的属主也设为10001启动时不额外加--privileged让SELinux保持Enforcing模式。这样做可以把权限问题从“不断试错”变成“按设计对齐”。得益于用户命名空间宿主机上看起来是10001的账号在容器里可以变成管理员而不会越过安全边界。6. 我们还在谈论容器但容器真正成熟的那天我们会谈论别的东西6.1 “K8s is boring”的含义不是技术无用而是技术退入了日常如果Kelsey Hightower的思想有内核我会把它概括为一个技术栈最成功的状态就是它不再需要专门的话题热度。TCP/IP不再上热搜Linux内核也不再被互联网社区天天挂在嘴边因为它们已经彻底变成基础设施。Kubernetes正走在这条路上。今天你用Kubernetes部署一个应用就像你从前用systemd起服务一样稀松平常没人会多看一眼。当“容器”这个词不再被单独拎出来讨论时恰恰说明它已经完全渗入工程实践。构建镜像、编排调度、配额管理成为不同岗位的默认能力就像写代码的人不觉得自己在“使用文本编辑器”市场也不再单独为“会用Kubernetes”设置一个高薪岗位这反而是岗位本身变得更有价值的表现。6.2 容器话题会往哪里去平台工程、WebAssembly、Serverless那么容器话题会彻底消失吗我觉得不会忽然消失而是会分流。一部分人继续往平台工程方向走把容器、网络、可观测性打包成内部开发者平台抽象成一套自助服务另一部分人转向更轻的运行时形态比如WebAssembly组件用更小的体积和更快的冷启动承担某些场景的负载还有一部分人被Serverless接走不再感知底层是不是容器。但其中“镜像作为交付格式”这件事的生命力会非常长。就算未来硬件异构、边缘节点、Serverless函数全都算进来镜像仍然是最通用的交付载体。只是到那一天大家对它的称呼未必还是“容器”而是“标准制品”“OCI工件”之类更具体的名词。6.3 我的建议认真建设自己的“容器消化层”复盘这几年给团队做容器化的经验最有价值的项目从来不是把某个服务塞进Docker然后部署上集群而是建设一层“容器消化层”——统一基础镜像规范、统一资源配额和LimitRange、统一镜像仓库和扫描策略、统一发布流水线和回滚机制。消化层建好之后团队里的应用开发只管提交代码和看发布结果容器里的权限、内存、网络策略这些问题直接在平台层就帮你拦掉了一大半。真正消化掉容器技术的团队日常讨论里“容器”这个词的出现频率会显著下降取而代之的是“上线”“回滚”“配额”“告警”这类业务语言。结尾想聊一点个人的体会。退役了Kelsey Hightower还能把一句话说进我心里“Kubernetes is boring”。换个角度想“我们还在谈论容器”这件事并不是技术没有成熟的证明而是容器已经像空气一样进入了每个工程师的呼吸。总有一天它会彻底退入背景色就像现在的进程和网络栈一样没有人再追问它是什么。真的到了那一天欢迎你继续讨论的是容器之上那些真正影响业务的分布式复杂性问题——那才是下一个十年里真正值得花时间的热词。
返回列表