单体系统拆分成一堆微服务,服务治理和部署运维时会遇到很多挑战和问题,服务编排就是指如何把这些服务组织到一起,解决这些问题。
可以类比积木搭城堡。积木就是你的一大堆微服务、依赖的各个组件,城堡就是指整个微服务系统。搭城堡不是简单的把一堆积木哗啦啦倒一起,要考虑每个位置放什么积木,同样,微服务的编排也要考虑非常多的事情。
编排(Orchestration)这个词有点抽象,我们用一个实例来说明微服务编排到底指哪些事情: 假如现在准备用Kubernetes来编排一套微服务系统,要考虑哪些事情呢?
- 服务依赖的基础组件,比如数据库、缓存服务,这些组件如何部署,如何访问?
- 服务的配置,比如数据库账号、密钥等,这些放到哪里?
- 不同服务和组件之间的隔离策略如何配置,混合部署还是独占,混布策略是什么?
- 不同服务之间是否有依赖关系,如何处理?
- 服务之间通信,如何发现彼此,网络上如何隔离?
- 每个服务需要部署多少实例,资源配额分别是多少,负载均衡策略是什么?
- 需要自动扩缩容的服务,自动伸缩的策略如何配置?
- 服务如何暴露到外界,访问入口如何配置?
- 每个服务在健康时才能放行流量,服务健康检查要如何配置?
- 可观测性四连:日志、监控、告警、链路追踪,相关的基础设施组件怎么部署,服务如何接入?
- 每个服务在启动时和关闭时,是否需要执行额外的脚本,来做一些初始化或优雅退出的工作?
- 金丝雀发布如何实现,流量灰度的策略是什么?
这些全部都是编排相关的问题。要解决这些问题,需要创建Kubernetes抽象出来的资源(Deployment,ConfigMap,Persistent Volume,Volume,Secret,Service,Ingress,HPA,PVC,NetworkPolicy ...),以及一些内部细节(Pod Spec, Affinity,LifeCycle Hook、Probe ...),配合一些在Kubernetes生态下的组件(Prometheus Operator,istio,Jaeger,EFK ...)共同解决。
一边想这些问题,一边写Kubernetes Yaml、Kubernetes CRD Yaml,就是在做服务编排(如果不用Kubernetes,用Docker compose、Docker Swarm做编排也可以,但Kubernetes已经是事实标准,本文不讨论非Kubernetes的情况)。
Kubernetes中的微服务的容器化编排,狭义上可以认为就是给各个服务写好Deployment、Service、Ingress这几个资源定义的Yaml,就可以按照这些编排文件部署出来了。
然而,微服务的运维挑战,更多的在于服务治理、可观测性,以及基础设施组件如何管理。在做编排时要考虑的事情非常多,这些事情反映到声明式编排文件上会非常复杂。我个人理解的服务编排,是包括这些所有相关的事情的,不仅是狭义上的写几个简单的Yaml,那样是没法满足大规模系统的产线要求的。
延伸一下,既然编排一套微服务系统如此复杂,有没有简化的办法呢?
目前广泛使用的是Helm和Kustomize,通过把一些动态参数抽离和模板渲染,比直接写原生Yaml舒服很多,减少了重复性工作。另外,阿里云和微软云一起搞了个OAM[1],来简化编排过程、分离不同角色的关注点,用OAM定义的CRD可以让编排过程更加简单,其运行时CrossPlane[2]项目也已经在CNCF中,有兴趣可以了解一下。微服务架构中服务的编排