几乎是随着 Service Mesh 概念的普及,“sidecar”这个词被容器从业者提到的频率也越来越高。甚至可以说,sidecar proxy 已经是 Service Mesh 的第一技术特征。今天我们就和 Flomesh 团队负责人蔡书一起来聊聊为什么会出现 sidecar proxy,以及除了 proxy 还有哪些 sidecar,最后展望一下“理想化”的 sidecar 应该是什么样子。
Rethink 系列回顾: 《Istio 之外,我们需要什么样的服务网格?》
蔡书:Sidecar 本意是指三轮摩托旁边的那个挎斗。Kubernetes 在形成初期,就把“容器”这个模型演化成了“pod”模型。Pod 就是多个容器“编组使用”,或者简单地说,如果把一个“pod”类比成一个“虚拟机”,那么多个容器就是这个虚拟机里边的多个进程。这些进程里边,那些配合业务进程的其他进程我们一般就称为 sidecar。比如 pod 运行的是一个 Spring Boot 的进程,在这个 pod 里边我们部署了采集日志的 Filebeat 进程,部署了代理流量的 proxy 进程,那么这个采集日志和代理进程都叫做“sidecar”。
在 sidecar 这个说法被广泛使用之前,其实 sidecar 这种用法就已经被普遍使用了,比如上边例子说的有些容器玩家会在容器内部署采集日志的进程。但是 sidecar 这个叫法是随着 Service Mesh 出现而流行起来的。在几乎所有讨论 Serivce Mesh 的材料和文章中都会出现 sidecar 这个词,如果从自然语言分析角度看,“Service Mesh”和“sidecar”是关联度极高的两个词汇。事实上,和 Service Mesh 一起说的 sidecar,是“sidecar proxy”的一个简化说法。所以当讨论的上下文是“Service Mesh”的时候,说到“sidecar”,一般就是指“sidecar proxy”。
蔡书:虽然这个词汇是最近几年随着服务网格开始在容器圈流行,但是 sidecar 模式其实早就存在,甚至可以说从操作系统进入了“多任务”以后就出现了。
蔡书:这个话题非常有趣,我试着从三个方面聊下,一个是操作系统,一个是应用服务器,一个是容器时代的 pod,他们之间内在有时间上的先后顺序,逻辑上他们的模型也有共性之处。
这里先做一个假设,就是我的目标是运行一个“业务程序”,比如一个 SpringBoot 的 Java 程序,当启动这个 SpringBoot 程序的时候,我需要用 Java springboot.jar 之类的命令来启动这个进程。在典型的 Linux 上,通常我们会把这个命令包装到一个脚本里边,用类似 start-springboot.sh 之类的脚本来启动。事实上,在我们启动这个 Java 进程之前,就有很多进程在运行了,典型的比如说监控进程,比如 zabbix agent;还有比如日志收集的进程,比如 filebeat,等等。
其实除了这些大家常见的进程,还有一些大家可能未必留意的进程,也在运行了。典型的比如 crond,大家都用 crontab 做一些定时任务,crond 进程就是管理这个的。记得以前常常有用户问我们“能不能给我一个最小最干净的操作系统”,其实他指的就是在运行业务进程的时候,只有最少的其他进程在运行。这些“其他进程”,从逻辑模型看,都可以认为是业务进程的 sidecar。从功能的角度来说,我们会发现,这些 sidecar 进程可以分为几类,一类是辅助业务的,比如定时任务;一类是管理员需要的,比如日志采集、监控;一类是系统本身需要的,操作系统在启动内核后,会启动一个“超级进程”,称为 initd 进程,后来的 systemd 进程是 initd 的替代品,这个超级进程会启动一些进程用来辅助操作系统的功能,最典型的比如 kdump,用来在程序崩溃时候收集信息。概括地说,早期使用单机操作系统运行业务进程的时候,我们有三类“sidecar”,#1 是业务自身需要的,#2 是管理员需要的,#3 是操作系统需要的。
说完操作系统,我们再说应用服务器。千禧年之后,随着 Java 进入企业领域,也就是当时的 J2EE,应用服务器开始普及。以 Java 应用服务器来说(事实上几乎各种语言都有自己的“应用服务器”),应用服务器有自己的启动过程,在这个过程中,应用服务器会启动很多“线程”,这些线程也是辅助完成业务逻辑或者实现管理功能的,他们的本质也是 sidecar。
进入容器时代以后,尤其是 K8s 提出 pod 的概念,围绕业务进程的辅助进程模式更加清晰和明确,这些辅助进程就是 sidecar。同样,这些 sidecar 也还是完成着传统的三方面功能,一方面是辅助业务的;一方面是面向管理员的;一方面是面向系统的。容器环境是典型的云环境,所以这里的“面向管理员”和“面向系统”又有了新的含义和进一步的需求。
蔡书:说“没有 sidecar 不行”不如说“sidecar 的普遍使用是客观现实,是刚需”。这种刚需的产生我觉得有这么几个因素,一个是不同角色需要不同能力的进程协助完成工作,比如业务进程、应用运维、系统运维,彼此工作的和角色的差异,导致了每个角色用自己的 sidecar 辅助进程是一种分工,也是一种清晰的工作边界。
另一方面,有些需求是在业务上线后出现的,那么这个时候,用一个附加的 sidecar 进程完成管理工作就很顺理成章。还有一点,进程是现代 Unix 和类 Unix 系统的基本管理单位,进程级的管理是非常成熟的技术。作为一个对比,其实上一代应用服务器,比如 JEE 应用服务器,尝试把很多辅助管理能力放到线程级,但是后来又都逐渐分离到外部进程了。所谓“一个快速、简洁的 Java 进程”。这些客观的需求,使得 sidecar 辅助进程成为一种刚需。
蔡书:就像上一个问题里说到的,sidecar 辅助进程的出现很多时候是顺理成章、水到渠成的,是一种最佳选择。简单来说,sidecar 本质就是分而治之,并且天然具有“分工”的属性,还可以用来解决很多“上线时候还没有的管理需求”,扮演了管理上的补丁角色。从 sidecar proxy 的角度看,proxy 提供一种“切片管理”的能力,这个是非常经典的设计模式。
蔡书:容器和 K8s 的普及,使得“云”距离用户更近了一步,这里,我总结了一些和 sidecar 相关的技术变化,以及“云”本身带来的一些变化。很多时候,我认为这些变化和特征也是“云原生”的特征和驱动力的一部分。
具体包括这么几个部分:
容器启动的时候,有一个 PID=1 的进程。通常而言,这个进程就是“业务进程”(实际上 pod 启动还有个 init 进程,叫做 pause)。当我们想启动 sidecar 进程的时候,目前的做法是通过 hook,在启动过程中启动 sidecar。实际上,这个时候 K8s(或者具体的说 Kubelet)其实是一个超级进程,它负责启动业务进程和 sidecar。很多时候,sidecar 和业务进程,甚至是 sidecar 之间,是有启动顺序的。但是目前在 K8s 的体系内,缺少对这种依赖的管理。如果大家熟悉 Linux 的 initd 和 systemd,会知道系统的启动过程是由一堆脚本控制的,也包含了一些优先关系。在操作系统时代,这些 sidecar 的启动是个“准标准”,也是可以通过 Shell 脚本“定制化”的。总结来说:pod 的 init 过程在标准化、定制化、扩展方面比较简单,在一个 pod 内容器多且有依赖和关联的时候,当前的机制不够灵活。所以第一个“新”需求就是 pod 内多进程的启动依赖及顺序,目前容器平台没有提供相应的机制。
容器快速被认可,背后最主要的原因是容器“轻量化”,而轻量化是“敏捷”的前提。当我们需要通过 sidecar 进程来完成某一种辅助功能的时候,我们需要这个辅助进程尽可能轻量化,否则就会有一种头重脚轻的感觉。前几天有个技术分享,提到他们业务容器的资源配置是 4C8G,然后 sidecar 资源配置是 4C4G。对这种配置,我只能感慨“有钱真好”。大多数用户还是希望 sidecar 是很轻量化的。概括地说,第二个“进阶”需求是,pod 内的 sidecar 辅助进程需要比传统主机上更轻量化。
权限。当我们在虚拟机或者物理机上部署 sidecar 这些辅助进程的时候,有时候我们需要特权,因为读写一些系统信息需要高权限。在主机(虚拟机、物理机)时代,超级用户加上业务用户的两级权限很好地满足了不同用户运行不同进程权限管理的需求。但是在容器时代,这个事情变难了。容器环境里,除了宿主机的管理(通常是特权用户)和业务进程(通常是普通用户)之外,多了这些 sidecar 辅助进程。这些 sidecar 辅助进程,有些也需要特权、更多的最好是用普通用户。相当于在容器环境和 pod 里,其实出现了 3 个等级的权限需求:宿主机的 root、容器的“root”、容器的普通用户。这层权限的出现,本质上是云的多租户导致的。目前来看,这个中间层的权限比较难处理,因为业务进程和辅助 sidecar 进程是共享 namespace 的。概括起来,第三个“新”需求是 sidecar 辅助进程通常要求一种介于宿主机 root 和业务进程之间的权限能力。
扩展性。主机上传统的 sidecar 辅助进程,一般都有自己的配置方式(配置文件格式),以及一些扩展方式,比如 zabbix 可以运行脚本等。这些传统的辅助进程进入到容器后,管理其实更难了。之前积累的很多管理工具,可以通过配置工具如 ansible 之类下发,而容器一般提供的方式是 configMap,这种配置和扩展的变化导致了严重的碎片化,而且方式改变也带来了新的困难。Sidecar 辅助进程的功能,很多是需要这种客户化和现场定制化的,这部分需要通用、简单的扩展机制和方式。因此,第四个“进阶”需求是 sidecar 辅助进程通常需要比传统主机上更简单、易用、且强大的扩展能力。
大概总结这么几个,其实还有一些,以后想起来再讨论。
蔡书:这是个好问题,在我看来,整个行业都发现了这些新问题——就是说,pod 里正在被塞进越来越多的 sidecar。因此整个行业也都在探索可行的解决办法。这里介绍下我们开源项目 pipy 的探索:我们通过 infra container 的方式为每个容器提供了 PID=1 的 sidecar,这个 pipy 进程类似 Linux 中的 initd 或者 systemd,它的作用是根据需要引入和执行其他的功能;通过 pipy repo 和 pipy js 的能力,pipy 可以提供目前我们已经识别的各种 sidecar 所需要的功能,比如服务注册 / 注销、服务发现、日志采集、指标采集、主动健康检查、定时任务、提供网络代理(也就是 sidecar proxy 能力)等。这是一种尝试,也欢迎大家一起来探讨。
为了感谢老粉们一直以来对 InfoQ 的陪伴,InfoQ 又来给大家送福利啦!
超多好礼 0 元免费领取,达标即送~
华为 FreeBuds Pro、SKG 颈椎按摩器、小米小爱音箱 play、极客时间 GEEK 抱枕、“极客青年”马克杯
长按识别二维码,发送【十一】获得属于自己的专属海报以及活动参与方式!