Istio 的功能与作用在之前的文章中已经向大家展示了,基于 Istio 的微服务治理也必将登上广大云服务供应商的舞台。本文中,我们将会为您重点介绍一下 Istio 的核心组件 Mixer 与 adapter 适配器的关系,并且从代码层面向您展示如何去开发配置 Mixer 中的 adapter 适配器。在文章最后还将介绍Mixer是怎样集成部署到当今主流的 K8S 环境中工作。
Istio 内置的部分适配器以及相应功能举例如下:
- circonus:微服务监控分析平台。
- cloudwatch:针对AWS云资源监控的工具。
- fluentd:开源的日志采集工具。
- prometheus:开源的时序数据库,非常适合用来存储监控指标数据。
- statsd:采集汇总应用指标的工具。
- stdio:使Istio能将日志和 metrics 输出到本地,结合内置的ES、Grafana就可以查看相应的日志或指标了。
现在我们将**逐步向您介绍如何在 Mixer 中开发、测试和集成一个简单的适配器。该适配器可以支持 Mixer 附带的 metric 模板,**并且对于每一个请求,在请求时将从 Mixer 接收的数据打印到文件中去。 完成本次实例的开发部署与编译运行总共只需要几步,大约需时30分钟。所以通过本实例,您只需要短短半个小时就可以掌握一个 adpater 适配器的开发运行过程,是不是很 easy?那我们现在就开始吧!
因篇幅有限,只截取关键代码(后续代码模块皆为关键代码)如下所示,它定义了适配器Builder和Handler类型以及处理metric的业务逻辑接口。虽然还没有实现业务处理,但我们不妨通过下图先了解一下adapter的代码结构。
var _ metric.HandlerBuilder = &builder{}
var _ metric.Handler = &handler{}
func (b *builder) Build(ctx context.Context, env adapter.Env) (adapter.Handler, error) {
return &handler{}, nil
}
func (h *handler) HandleMetric(ctx context.Context, insts []*metric.Instance) error {
return nil
}
但是二者必不可少。Builder 的功能类似于构造器,可以通过加载相关参数(比如从配置文件中直接读取)生成一个 Handler,而 Handler 是配置好的 Adapter 的实例。后者可以参与处理metric业务。
如上所示现在我们有了一个适配器的基本框架,其中包含 HandleMetric 接口的空实现。HandlerMetric 是适配器中处理业务逻辑的实现方法也是核心方法,在该方法中我们可以将收集到的 metric进行数据处理然后上报出去,后台的程序接收到这些处理后的 metric 数据就可以进行相应数据监控和分析了。在后面的步骤中将添加此适配器的核心代码。
适配器配置
适配器要发挥特定的作用,必须要对其做相应的配置处理。由于在本次实践中我们只是将通过将从 Mixer 接收的数据打印到文件中来演示一下 adapter 的功能。因此适配器需要将文件的路径作为配置字段,在 config 目录下创建配置 proto 文件。
config.proto 文件是一个专门用来配置适配器参数的文件,在该文件中我们可以设置testAdapter.go
中需要用到的所有配置信息比如缓存大小、发生计时器大小等,但是一定要注意 proto 中每行代码都需要注释,后面的 yaml 文件也可以从该文件中读取参数。编写完成后,用go generate ./ …
指令可以进行编译并生成相应go文件。现在让我们将 config.proto 文件生成相应的 go 文件。然后我们可以输入如下指令来编译调试 proto 文件。
go generate ./...
go build ./...
配置完 proto 文件,咱们还需要配置 yaml 文件。不同的 adapter 具有不同的 attributes,yaml 用模板的形式定义了 attributes 到 adapter 输入数据映射的 schema,一个适配器可以支持多个模板。而 Mixer 的 yaml 配置可以看成是三种模型的模板集成到一个文件下,分别是 Handler、Instance 和 Rule。
这三种模型分别具有什么样的功能呢?
Handler 是配置好的 Adpater 的实例,它从 yaml 配置文件中取出 adapter 需要的配置数据。
Instance 定义了 attributes 到 adapter 输入的映射。
Rule 定义了一个特定的 Instance 何时调用一个特定的 Handler。
三种模型通过 yaml 中的 kind 进行区分。要让适配器工作起来,我们必然需要配置 yaml 来将 attributes 映射到 adapter 里面。所以,让我们给 Mixer 编写一个简单的 yaml 配置,以便将数据发送到您的适配器。我们需要将实例,处理程序和规则配置传递给 Mixer 服务器。当然我们本次实践主要是为了进行一个 adapter 端到端的演示,所以一个完整的输出到文件中的 metric 应该还需要指定它的输出路径。
通过配置文件在对应的文件中打印实例和关联的类型信息,这需要在配置时存储metric标准类型信息并在请求时使用它。要添加此功能,需要在文件testAdapter.go中加入相应业务逻辑处理的代码。如下所示:
func (h *handler) HandleMetric(ctx context.Context, insts []*metric.Instance) error {
for _, inst := range insts {
if _, ok := h.metricTypes[inst.Name]; !ok {
h.env.Logger().Errorf("Cannot find type %s",inst.Name)
continue
}
h.f.WriteString(fmt.Sprintf(`HandleMetric invoke for :
Instance Name :'%s'
Instance Value : %v,
Type : %v`, inst.Name, *inst, *h.metricTypes[inst.Name]))
}
return nil
}
然后编译就可以了,这样就完成了适配器代码的实现部分。那么适配器是如何在 Mixer 中进行工作以及我们如何验证所编写的代码做了哪些事呢?下面的步骤将告诉你答案。
将适配器插入 Mixer 中
适配器开发完以后,我们还需要将适配器插入进 Mixer 中,首先要更新inventory.yaml
文件并且将新的适配器添加到 Mixer 的适配器注册列表中。通过 go generate 命令在/adapter
目录中运行来重新生成库存代码。到这里您的适配器已经插入到 Mixer 中并已经准备好接收数据。
本地验证适配器
以上工作做完以后,我们就可以在本地进行端到端的验证了。启动 Mixer 终端将会输出相应信息,并处于等待服务请求状态。
现在让我们使用 Mixer 客户端调用 report 请求。在这里我们需要 Mixer 服务器使用 yaml 构造的实例对象调用样例 adapter。并启动一个新的终端窗口。在新窗口中调用命令:
tail $ ISTIO /istio/cloud.txttail $ ISTIO /istio/cloud.txt
如何将Mixer集成到K8S环境中运行调试
在上面我们仅向大家演示了如何在本地测试自己开发的 adapter。我想大家对于 Istio 充满热情的很大原因都是因为其可以部署集成到 Kubernates(K8S)环境中运行。那么今天正好可以向您介绍如何将 Mixer 打包成镜像在 K8S 集群节点上运行调试。
在这里我们需要再回顾一下 yaml 文件,yaml 文件可以完美的将我们需要上报的参数传递给 k8s,在这里我们以一个流量监控的案例来简单描述一下 adapter 怎样与 K8S 协作运行。如下图所示:
首先定义一个用来计数的 metric,它会根据我们定义的参数去采集相应数据,例如命名空间等,这些都将会传递到 K8S 中,还会将自己的 value 属性传递进 HandlerMetric 业务逻辑中,在 HandlerMetric 中我们就可以通过它的属性“1”来进行一个请求计数,从而实现流量监控的功能。
定义完了metric,我们还需要定义一个Handler来处理这个metric,如下所示:
在这个 handler 中我们将去处理 COUTER 类型的 metric 并获取其上报上来的参数,然后上报到指定的 ip 地址(自己根据需要设置)、集群等等。最后我们还需要在 yaml 中定义一个规则去调度使用你的 handler,如下所示:
通过以上我们可以很清晰的看到。Mixer 与 K8S 直接是通过上述 yaml 文件定义的参数来实现无缝衔接的集成部署。定义完 yaml,我们还需要将其部署到 heml 文件夹下,如下图所示的目录中:
并且将上述 yaml 中的内容配置到该文件夹下的 config.yaml
中,这样当在界面上安装 Istio 控制面的时候,适配器上报过来的环境变量就会自动注入 K8S 的环境中。进而可以实现 Mixer 在 K8S 环境中的集成部署。接下来我们就可以将 Mixer 下的文件编译成二进制文件,然后制作成镜像,将镜像输出为 tar 包。通过远程登录命令 ssh 到自己的集群节点上,然后将镜像拷贝到环境上。到这里,如果你在 pod 列表中看到我们刚刚自己创建的镜像名,那么就表示我们的适配器已经成功部署到 K8S 环境中了。然后可以通过 kubectl 来查看日志了解自己的适配器工作情况。