前言
本系列文章主要从源码(35e2b904)出发,对istio做深入剖析,让大家对istio有更深的认知,从而方便平时排查问题。不了解Service Mesh和Istio的同学请先阅读敖小剑老师如下文章进行概念上的理解:
本文主要对istio在ubuntu16.04下环境搭建做简单介绍,Mac用户和其他linux发行版用户请根据bash脚本做相应调整。
概念介绍
Mixer提供三个核心功能:
- 前置条件检查(Precondition Checking):某一服务响应外部请求前,通过Envoy向Mixer发送Check请求,检查该请求是否满足一定的前提条件,包括白名单检查、ACL检查等。
- 配额管理(Quota Management):当多个请求发生资源竞争时,通过配额管理机制可以实现对资源的有效管理。
- 要测报告上报(elemetry Reporting):该服务处理完请求后,通过Envoy向Mixer上报日志和监控等数据。
要深入了解Mixer,我们先对如下几个概念介绍:
attribute(属性)
大部分attributes由Envoy提供。Istio用attributes来控制服务在Service Mesh中运行时行为。attributes是有名称和类型的元数据,用来描述入口和出口流量和流量产生时的环境。attributes携带了一些具体信息,比如:API请求状态码、请求响应时间、TCP连接的原始地址等。
refrencedAttributes(被引用的属性)
refrencedAttributes是Mixer Check时进行条件匹配后被使用的属性的集合。Envoy向Mixer发送的Check请求中传递的是属性的全集,refrencedAttributes只是该全集中被应用的一个子集。
举个例子,Envoy某次发送的Check请求中发送的attributes为{request.path: xyz/abc, request.size: 234,source.ip: 192.168.0.1}
,如Mixer中调度到的多个adapters只用到了request.path
和request.size
这两个属性。那么Check后返回的refrencedAttributes为{request.path: xyz/abc, request.size: 234}
。
为防止每次请求时Envoy都向Mixer中发送Check请求,Mixer中建立了一套复杂的缓存机制,使得大部分请求不需要向Mixer发送Check请求。
1 | request.path: xyz/abc |
属性词汇由[_.a-z0-9]组成,其中”.”为命名空间分隔符,所有属性词汇可以查看这里,属性类型可以查看这里。
adapter(适配器)
Mixer是一个高度模块化、可扩展组件,内部提供了多个适配器(adapter)。
Envoy提供request级别的属性(attributes)数据。
adapters基于这些attributes来实现日志记录、监控指标采集展示、配额管理、ACL检查等功能。Istio内置的部分adapters举例如下:
- circonus:一个微服务监控分析平台。
- cloudwatch:一个针对AWS云资源监控的工具。
- fluentd:一款开源的日志采集工具。
- prometheus:一款开源的时序数据库,非常适合用来存储监控指标数据。
- statsd:一款采集汇总应用指标的工具。
- stdio:stdio适配器使Istio能将日志和metrics输出到本地,结合内置的ES、Grafana就可以查看相应的日志或指标了。
template(模板)
对于一个网络请求,Mixer通常会调用两个rpc:Check和Report。不同的adapter需要不同的attributes,template定义了attributes到adapter输入数据的映射的schema,一个适配器可以支持多个template。一个上报metric数据的模板如下所示:
1 | apiVersion: "config.istio.io/v1alpha2" |
模板字段的值可以是字面量或者表达式,如果时表达式,则表达式的值类型必须与字段的数据类型一致。
Mixer配置文件
Mixer的yaml配置可以抽象成下述三种类型:Handler、Instance、Rule
这三种类型主要通过yaml中的kind字段做区分,kind值有如下几种:
- adapter kind:表示配置段为Handler。
- template kind:表示配置段为Template。
- “rule”:表示配置段为Rule.
Handler(处理者)
一个handler是配置好的adpater的实例。handler从yaml配置文件中取出adapter需要的配置数据。一个典型的promethues handler配置如下所示:
1 | apiVersion: config.istio.io/v1alpha2 |
对于handler而言,{metadata.name}.{kind}.{metadata.namespace}
是其完全限定名(Fully Qualified name),上述handler的完全限定名是handler.prometheus.istio-system
,完全限定名是全局唯一的。
adapter的配置信息定义在spec段中,每个adapter配置的格式都有所区别,可以从[这里]查看(https://istio.io/docs/reference/config/adapters/)指定的adapter配置格式。
Instance(请求实例)
instance定义了attributes到adapter输入的映射,一个处理requestduration metric数据的实例配置如下所示:
1 | apiVersion: config.istio.io/v1alpha2 |
完全限定名(Full Qualified Name)上述instance的
Rule(规则)
Rule定义了什么instance生效的条件,一个简单的Rule配置如下所示:
1 | apiVersion: config.istio.io/v1alpha2 |
上述例子中,定义的Rule为:对目标服务为service1.ns.svc.cluster.local且request.headers[“x-user”] 为user1的请求,我们才应用requestduration.metric.istio-system
这个instance。
Mixer工作流程源码分析
上面简单介绍了Mixer相关概念,下面我们从源码出发来对Mixer工作流程做分析。
编译mixer二进制文件和docker镜像
先看Makfile:1
2
3
4
5
6
7
8
9···
MIXER_GO_BINS:=${ISTIO_OUT}/mixs ${ISTIO_OUT}/mixc
mixc: # Mixer客户端,通过mixc我们可以和运行的mixer进行交互。
bin/gobuild.sh ${ISTIO_OUT}/mixc istio.io/istio/pkg/version ./mixer/cmd/mixc
mixs: # Mixer服务端,和Envoy、adapter交互。部署Istio的时候随之启动。
bin/gobuild.sh ${ISTIO_OUT}/mixs istio.io/istio/pkg/version ./mixer/cmd/mixs
···
include tools/istio-docker.mk # 引入编译docker镜像的Makefile文件。
...
Makefile中定义了mixs(mixer server)和mixc(mixer client)的编译流程。使用指令make mixs mixc
编译好二进制文件后,再编译docker镜像。istio-docker.mk中编译mixer镜像相关指令如下:
1 | ... |
执行make docker.mixer
会在本地编译mixer镜像,依据的dockerfile是mixer/docker/Dockerfile.mixer,如下所示:
1 | FROM scratch |
可以知道容器启动时执行的mixs指令为/usr/local/bin/mixs server --configStoreURL=fs:///etc/opt/mixer/configroot --configStoreURL=k8s://
Mixer Server启动流程
mixs启动入口:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// supportedTemplates 从mixer/pkg/template包获取所有注册的模板信息。
func supportedTemplates() map[string]template.Info {
return generatedTmplRepo.SupportedTmplInfo
}
// supportedAdapters 从mixer/pkg/adapter包获取所有注册的适配器信息。
func supportedAdapters() []adptr.InfoFn {
return adapter.Inventory()
}
func main() {
// 构造cobra.Command实例,mixs server子命令设计在serverCmd中定义。
rootCmd := cmd.GetRootCmd(os.Args[1:], supportedTemplates(), supportedAdapters(), shared.Printf, shared.Fatalf)
if err := rootCmd.Execute(); err != nil {
os.Exit(-1)
}
}
mixs server子命令在istio/mixer/cmd/mixs/cmd/server.go#serverCmd中定义:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20func serverCmd(info map[string]template.Info, adapters []adapter.InfoFn, printf, fatalf shared.FormatFn) *cobra.Command {
...
serverCmd := &cobra.Command{
Use: "server",
Short: "Starts Mixer as a server",
Run: func(cmd *cobra.Command, args []string) {
// 用户执行mixs server命令时,启动mixer gRPC server
runServer(sa, printf, fatalf)
},
}
...
}
// runServer函数启动mixer gRPC server
func runServer(sa *server.Args, printf, fatalf shared.FormatFn) {
s, err := server.New(sa)
...
s.Run()
...
}
gRPC server启动主要逻辑在istio/mixer/pkg/server/server.go#newServer:
1 | func newServer(a *Args, p *patchTable) (*Server, error) { |
其中istio/mixer/pkg/api/grpcServer.go#NewGRPCServer函数中初始化了保存attributes的list和全局字典
1 | func NewGRPCServer(dispatcher dispatcher.Dispatcher, gp *pool.GoroutinePool) mixerpb.MixerServer { |
Mixer启动的gRPC server定义了两个rpc:Check、Report。
istio/vendor/istio.io/api/mixer/v1/service.proto#48行
1 | service Mixer { |
CheckRequest、CheckResponse结构如下所示:
1 | message CheckRequest { |
ReportRequest、ReportResponse结构如下所示:
1 | message ReportRequest { |
Check请求执行细节
1 | func (s *grpcServer) Check(legacyCtx legacyContext.Context, req *mixerpb.CheckRequest) (*mixerpb.CheckResponse, error) { |
Report请求执行整体逻辑和Check相似,本文暂不做解析。
Mixer适配器工作流程
- Mixer server启动。
- 初始化adapter worker线程池
- 初始化Mixer模板仓库。
- 初始化adapter builder表。
- 初始化runtime实例。
- 注册并启动gRPC server。
- 某一服务外部请求被envoy拦截,envoy根据请求生成指定的attributes,attributes作为参数之一向Mixer发起Check rpc请求。
- Mixer 进行前置条件检查和配额检查,调用相应的adapter做处理,并返回相应结果。
- Envoy分析结果,决定是否执行请求或拒绝请求。若可以执行请求则执行请求。请求完成后再向Mixer gRPC服务发起Report rpc请求,上报遥测数据。
- Mixer后端的adapter基于遥测数据做进一步处理。
作者
郑伟,小米信息技术部基础架构组
招聘
小米信息部武汉研发中心,信息部是小米公司整体系统规划建设的核心部门,支撑公司国内外的线上线下销售服务体系、供应链体系、ERP体系、内网OA体系、数据决策体系等精细化管控的执行落地工作,服务小米内部所有的业务部门以及 40 家生态链公司。
同时部门承担大数据基础平台研发和微服务体系建设落,语言涉及 Java、Go,长年虚位以待对大数据处理、大型电商后端系统、微服务落地有深入理解和实践的各路英雄。
欢迎投递简历:jin.zhang(a)xiaomi.com
更多技术文章:小米信息部技术团队
扫描二维码,分享此文章