Istio技术与实践04:最佳实践之教你写一个完整的Mixer Adapter

765 阅读8分钟

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 来查看日志了解自己的适配器工作情况。