Istio 1.1 中的 Handler

一直觉得 Mixer 的功能会比较不稳定,这次在《深入浅出 Istio》一书的的验证过程中发现,Prometheus 的部分无法工作了,因此今天排查一下,也因此有了些收获,这里做一个简单的记录。

首先我发现,istio-system 中系统默认安装的 Prometheus 资源不见了

$ kubectl get prometheus --all-namespaces
No resources found.

但是好在相关的 Rule 还在,写法有了一些变化,例如 istio-system 中的 promtcp 的定义:

apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
...
  name: promtcp
  namespace: istio-system
spec:
  actions:
  - handler: prometheus
    instances:
    - tcpbytesent.metric
    - tcpbytereceived.metric
  match: context.protocol == "tcp"

过去我们习惯的 Handler 填写一般会是 handler.prometheus,也就是名为 handler 的 prometheus 资源。例如官方文档中的写法:

# Rule to send metric instances to a Prometheus handler
apiVersion: "config.istio.io/v1alpha2"
kind: rule
metadata:
  name: doubleprom
  namespace: istio-system
spec:
  actions:
  - handler: doublehandler.prometheus
    instances:
    - doublerequestcount.metric

很明显的,1.1 的用法发生了变更,这个新用法中并没有提及对象名称,只知道名字是 prometheus。在 Istio 1.1 的 Helm 源码中搜索一下 name: prometheus 就会看到,在 helm/istio/charts/mixer/templates/config.yaml 中定义了一个对象,一个 handler 类型的对象:

apiVersion: "config.istio.io/v1alpha2"
kind: handler
metadata:
  name: prometheus

这样就可以查查他的定义了,运行 kubectl get -n istio-system handler prometheus -o yaml

apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
...
  name: prometheus
  namespace: istio-system
...
spec:
  compiledAdapter: prometheus
  params:
    metrics:
    - instance_name: requestcount.metric.istio-system
...

是的,这个名为 prometheushandler 对象和以前几乎一毛一样。现在有两种定义 Prometheus 的 Handler 了,对此开发给出的解释是,并非所有 Adapter 都会创建自己的 CRD,因此推荐共用的 Handler 类型来进行定义。

Reference 中对这一对象做了个大概的讲解。需要注意其中的 compiledAdapter: prometheus,用于指定 Adapter 类型。其中使用 compiledAdapteradapter 两个字段分别用于描述进程内外的两种适配器类型。

因此在 1.1 中,Handler 真正的成为了 Handler,下面给出一个简单的定义,来讲解一下自定义指标中,新 Handler 的定义方法,其中给指标定义名称为 cxl_counter

apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
  labels:
    app: mixer
    chart: mixer
    heritage: Tiller
    release: istio
  name: prometheus
spec:
  compiledAdapter: prometheus
  params:
    metrics:
      - instance_name: cxl.metric.default
        kind: COUNTER
        label_names:
          - source_app
          - source_workload
          - source_workload_namespace
          - source_version
          - destination_app
          - destination_workload
          - destination_workload_namespace
          - destination_version
          - destination_service
          - destination_service_name
          - destination_service_namespace
          - reporter
          - response_code
        name: cxl_counter
    metricsExpirationPolicy:
      metricsExpiryDuration: 10m

原有 Handler 的定义方式,同样的指标,定义为 double_counter

apiVersion: config.istio.io/v1alpha2
kind: prometheus
metadata:
  name: handler
spec:
  metrics:
    - instance_name: cxl.metric.default
      kind: COUNTER
      label_names:
        - source_app
        - source_workload
        - source_workload_namespace
        - source_version
        - destination_app
        - destination_workload
        - destination_workload_namespace
        - destination_version
        - destination_service
        - destination_service_name
        - destination_service_namespace
        - reporter
        - response_code
      name: double_counter
  metricsExpirationPolicy:
    metricsExpiryDuration: 10m

用一个 Rule,将同样的指标分别输出到两个 Handler 之中:

apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: prom-http
spec:
  actions:
    - handler: prometheus
      instances:
        - cxl.metric
    - handler: handler.prometheus
      instances:
        - cxl.metric
  match: context.protocol == "http" || context.protocol == "grpc"

而指标的定义不变:

apiVersion: config.istio.io/v1alpha2
kind: metric
metadata:
  name: cxl
spec:
  dimensions:
    destination_app: destination.labels["app"] | "unknown"
    destination_service: destination.service.host | "unknown"
    destination_service_name: destination.service.name | "unknown"
    destination_service_namespace: destination.service.namespace | "unknown"
    destination_version: destination.labels["version"] | "unknown"
    destination_workload: destination.workload.name | "unknown"
    destination_workload_namespace: destination.workload.namespace | "unknown"
    source_app: source.labels["app"] | "unknown"
    source_version: source.labels["version"] | "unknown"
    source_workload: source.workload.name | "unknown"
    source_workload_namespace: source.workload.namespace | "unknown"
    reporter:
      conditional((context.reporter.kind | "inbound") == "outbound", "source",
      "destination")
    response_code: response.code | 200
  monitored_resource_type: '"UNSPECIFIED"'
  value: "2"

制造请求之后,会发现新旧 Handler 同时工作,并用各自的名字写入了指标。在 Prometheus 中即可查看。

这里真的要吐槽一句,Metric 定义中的所有 Label 需要照抄到 Handler 定义中,映射关系出错的时候,出的不是 Warning,而是 Panic。

涉及到的代码已经更新到版本库的 1.1 分支的第八章内容里。

Avatar
崔秀龙

简单,是大师的责任;我们凡夫俗子,能做到清楚就很不容易了。

comments powered by Disqus
下一页
上一页

相关