Istio 调用链追踪与指标收集

引言

Mixer组件 提供策略控制遥测收集功能,我在Istio架构那篇文章有写,但是从Istio 1.5开始Istio标准指标Envoy代理直接导出遥测组件被实现为Proxy-wasm插件。
由于看的书对应的Istio版本比较老了,王夕宁《Istio 服务网格技术解析与实战》,让我非常折磨的点在于很多东西我需要去istio.io官网文档对比。

那么这到底能用来干嘛呢,如果想了解就继续往下看。顺便说一下从现在开始已经开始偏向运维的东西了。写这类文章不容易,请赞一个吧。

调用链追踪

在学习spring-cloud的时候调用链追踪我们是将它集成在项目代码中的,但使用istio后我们将它移到了基础架构中。

文章中只写一个Zipkin,使用都差不多,如果想使用jaeger,请参考官方文档,都差不多,链接: 使用 jaeger

安装Zipkin

注意:如果使用过下面这个命令,会自动安装prometheus,grafana和zipkin

kubectl apply -f samples/addons
kubectl apply -f samples/addons/extras

手动安装步骤:

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/extras/zipkin.yaml

如果您无法访问github,我这里提供资源清单

apiVersion: apps/v1
kind: Deployment
metadata:
  name: zipkin
  namespace: istio-system
  labels:
    app: zipkin
spec:
  selector:
    matchLabels:
      app: zipkin
  template:
    metadata:
      labels:
        app: zipkin
      annotations:
        sidecar.istio.io/inject: "false"
    spec:
      containers:
        - name: zipkin
          image: openzipkin/zipkin-slim:2.21.0
          env:
            - name: STORAGE_METHOD
              value: "mem"
          readinessProbe: # 就绪探针 
            httpGet:
              path: /health
              port: 9411
            initialDelaySeconds: 5
            periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: tracing
  namespace: istio-system
  labels:
    app: zipkin
spec:
  type: ClusterIP
  ports:
    - name: http-query
      port: 80
      protocol: TCP
      targetPort: 9411
  selector:
    app: zipkin
---
apiVersion: v1
kind: Service
metadata:
  labels:
    name: zipkin
  name: zipkin
  namespace: istio-system
spec:
  ports:
    - port: 9411
      targetPort: 9411
      name: http-query
  selector:
    app: zipkin

Istio 启用调用链追踪

istio install的时候添加配置项,让其使用调用链追踪功能,在install时添加--set values.global.tracer.zipkin.address=zipkin.istio-system:9411(如果您没有DNS服务发现可以使用ip:port形式)。

如果您已经安装了Istio,那么可以使用istioctl profile dump demo > demo.yaml,然后修改yaml,使用istioctl upgrade命令进行更新。

暴露zipkin服务

如果您已将zipkin部署到istio-system命名空间,执行下面的命令可以暴露服务:

istioctl dashboard zipkin

自定义采样率

使用全局配置

可以通过全局配置所有跟踪选项MeshConfig。为了简化配置,建议创建一个YAML文件,您可以将其传递给istioctl install -f命令。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    defaultConfig:
      tracing:
        sampling: 10 # 采样率
        custom_tags: # 自定义标签 zipkin体现在span
          my_tag_header:
            header:
              name: host

针对Deployment设置

Deploymentspec.template.metadata加入proxy.istio.io/config设置

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sleep
spec:
  ...
  template:
    metadata:
      ...
      proxy.istio.io/config: |
        tracing:
          sampling: 10 # 采样率
          custom_tags: # 自定义标签 zipkin体现在span
            my_tag_header:
              header:
                name: host
    spec:
      ...

指标收集

在以前有些人可能会通过ElasticsearchKibana+MetricbeatFilebeat等来实现指标和日志采集,有些人使用Prometheus + Grafana + Alertmanager + node_exporter来进行报警+监控+可视化,实际上在Istio中我们也可以使用Prometheus+Grafana

dashboard-metrics-scraper

这是istio插件中就有的,如果您选择了安装,在(minikube + istio部署demo)那篇文章有写如何安装额外插件,这里面也可以收集到一些指标。

CEXL表达式

我们先讲讲Mixer configuration expression language(CEXL),它用来指定Mixer遥测策略配置匹配表达式映射表达式。这个玩意会用在我们需要自定义收集某些指标的时候。

操作符/函数定义示例说明
==相等request.size == 200请求体大小等于200
!=不相等request.auth.principal != “admin”请求认证的主要信息不等于admin
||逻辑或request.size == 200 || request.auth.principal != “admin”
&&逻辑与request.size == 200 && request.auth.principal != “admin”
[ ]访问字典request.headers[“X-Forwarded-For”]
+request.host + request.path
|默认值request.size|0如果a存在返回a,否则返回b
隐式三元表达式
编程语言中体现为 a?a:b
python理解为 a and a or b 或 a if a else b
php/c#理解为 a??b
match全局匹配match(source.labels[“app”],“myapp-*”)匹配所有来源的标签app值为myapp-* ,*为通配符
email将email字符串转为EMAIL_ADDRESS 类型email(“awersome@istio.io”)使用email函数创建一个EMAIL_ADDRESS类型的字面量
dnsName将域名字符串转为DNS_NAME类型dnsName(“www.istio.io”)使用dnsName函数创建一个DNS_NAME类型的字面量
ip将IPv4地址字符串转换为IP_ADDRESS类型destination.ip == ip(“10.20.11.11”)使用IP创建一个IP_ADDRESS类型的字面量
timestamp将RFC 3339格式的时间字符串转为TIMESTAMP类型timestamp(“2020-12-18T00:00:00Z” )使用timestamp函数创建一个TIMESTAMP类型的字面量
uri将一个URI字符串转为一个URI类型uri(“http://istio.io”)使用uri函数创建一个URI类型的字面量
.matches正则表达式匹配“myapp-+”.matches(source.labels[“app”])用正则表达式 “myapp-+” 匹配source.labels[“app”]
.startsWith匹配字符串前缀destination.service.startsWith(“myapp”)匹配目标服务名以myapp开头
.endsWith匹配字符串后缀destination.service.endsWith(“nginx”)匹配目标服务名以nginx结尾
emptyStringMap创建一个空字符串字典request.headers | emptyStringMap()如果request的headers为空就返回一个空的字符串字典,否则返回本身内容
conditional模拟三元表达式conditionnal(request.headers[“token”] === “123456789”,“authenticated”,“unauthorized”)如果请求头中的token值等于123456789 返回authenticated否则返回unauthorized
toLower将字符串转换为小写toLower(“User-Agent”)返回user-agent

使用Prometheus+Grafana

1.5之前版本

1.5之前的版本参考王夕宁书中所写.

配置模型

控制策略和遥测功能涉及配置3种类型资源

  • 处理程序(Handler),用于确定正在使用的适配器组及其操作方式。
  • 实例(Instance),描述如何将请求属性映射到适配器输入。实例表示一个或多个适配器将操作的各种数据,资源清单对应的kindmetric
  • 规则(Rule),这些规则描述了合适调用特定的适配器及哪些实例,kind对应为rule

下面会分别讲解这3个玩意并且给出小栗子,演示如何使用它们

处理程序

处理程序用于处理实例传回来的指标

{metadata.name}.{kind}.{metadata.namespace}是处理程序的全限定名
举个栗子:

apiVersion: config.istio.io/v1alpha2
kind: listchecker
metadata:
  name: staticversion
  namespace: istio-system
spec:
  providerUrl: http://white_list/ # 指定URL
  blacklist: false # 是否为黑名单模式

上面对应的全限定名(FQDN)就是staticversion.listchecker.isitio-system,这个listchecker适配器的作用是,如果URL在白名单中(因为我们不是黑名单模式),就会返回成功的结果。

再给一个prometheus的栗子:
关于实例instance会在下面写出来。

apiVersion: config.istio.io/v1alpha2
kind: prometheus
metadata:
  name: handler
  namespace: istio-system
spec:
  metrics:
  - name: my_request_count# 请求数
    instance_name: myrequestcount.metric.istio-system # 实例的全限定名
    kind: COUNTER # 这里指定为计数器 就是将实例返回的内容每次递增,递增数值为实例中spec.value的值
    label_names: # 对应实例的dimensions
    - destination_service
    - destination_version
    - response_code
  - name: request_duration # 请求持续时间
    instance_name: requestduration.metric.istio-system # 实例的全限定名
    label_names: # 对应实例的dimensions
    - destination_service
    - destination_version
    - response_code
    buckets: # 对应实例的spec.value
      explicit_buckets:
        bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]
实例

实例用于描述收集哪些指标

apiVersion: config.istio.io/v1alpha2
kind: metric
metadata:
  name: myrequestcount
  namespace: istio-system
spec:
  value: "1" # 返回处理程序需要处理的值
  dimensions:
    destination_service: destination.service | "unknown"
    destination_version: destination.labels["version"] | "unknown"
    response_code: response.code | 501
  monitored_resource_type: '"UNSPECIFIED"' # 监视资源类型为不明确的
---
apiVersion: config.istio.io/v1alpha2
kind: metric
metadata:
  name: requestduration
  namespace: istio-system
spec:
  value: response.duration|"0ms" # 返回处理程序需要处理的值 持续时间
  dimensions:
    destination_service: destination.service | "unknown"
    destination_version: destination.labels["version"] | "unknown"
    response_code: response.code | 501
  monitored_resource_type: '"UNSPECIFIED"' # 监视资源类型为不明确的
规则

规则指定什么时候使用实例调用特定的处理程序。您可以理解为将实例和处理程序进行绑定,并加了一个条件。

apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: promhttp
  namespace: istio-system
spec:
  match: destination.service == "httpbin.ns.svc.cluster.local" && request.headers["token"] == "123456789"
  actions:
  - handler: handler.prometheus # 指定处理程序
    instances: # 指定有哪些实例
    - requestduration.metric.istio-system
    - myrequestcount.metric.istio-system

kubectl apply/create -f 这几个yaml
此时就会自动收集这些指标了。

1.5之后版本

安装prometheus

注意:如果使用过下面这个命令,会自动安装prometheus,grafana和zipkin

kubectl apply -f samples/addons
kubectl apply -f samples/addons/extras

手动安装:

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/prometheus.yaml

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/extras/prometheus-operator.yaml

如果您安装好了prometheus,那么可以使用如下命令暴露服务:

 istioctl dashboard prometheus
安装grafana
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/grafana.yaml

之后可以在http://grafana的ip:端口/dashboard/db/istio-mesh-dashboard进行查看

验证是否开始生成和收集TCP指标值

Prometheus内选择Graph,输入istio_tcp_connections_opened_total 或者 istio_tcp_connections_closed_total ,看看是否能显示一些信息。

资源清单详解
  • prometheus.yaml中配置的是关于prometheusDeployment(其中有prometheus的job_name配置)Service,ServiceAccount等等。
  • prometheus-operator.yaml 中是PodMonitorServiceMonitor资源(下面自定义的scraping配置会讲)。
自定义的scraping配置

默认情况下是开启的(默认就支持prometheus收集各种指标),您也可以通过使用注解将它关闭。或者在istio install时使用全局配置关闭,--set meshConfig.enablePrometheusMerge=false

这是为了简化配置Istio能够完全通过annotations[].prometheus.io来单独控制scraping (抓取)。如果没有使用注解也会使用默认配置进行scraping,这样Istio既可以使用标准配置scraping(开箱即用,默认是开启的),也可以单独配置。

如下资源是放在Deployment中的,表明该Deployment需要被promethues发现并采集数据。

spec:
  template:
    metadata:
      annotations:
        prometheus.io/scrape: true   # 确定pod是否应scraping。设置true为启用。
        prometheus.io/path: /metrics # 确定从中获取指标的路径。默认为/metrics.
        prometheus.io/port: 80       # 确定从中获取指标的端口。默认为80.

举个栗子:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
  labels:
    app: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-deployment
  template:
    metadata:
      labels:
        app: nginx-deployment
      annotations: # 通过注解指定prometheus自定义抓取的端口
        prometheus.io/scrape: true
        prometheus.io/port: 9999
    spec:
      serviceAccountName: prometheus
      containers:
      - image: "nginx"
        name: nginx
        imagePullPolicy: "IfNotPresent"
        ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
        - name: prometheus
          containerPort: 9999

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: default
  labels:
    app: nginx-service
spec:
  externalTrafficPolicy: Local
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  - port: 443
    targetPort: 443
    protocol: TCP
    name: https
  - port: 9999
    targetPort: 9999
    protocol: TCP
    name: prometheus
  selector:
    app: nginx-deployment
---
# 使用PodMonitor
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  labels:
    app: nginx-podmonitor
  name: nginx-podmonitor
  namespace: default
spec:
  podMetricsEndpoints:
  - interval: 10s #每10秒一次
    path: /metrics
    port: prometheus
  namespaceSelector:
    matchNames:
    - default
      # any: true 也可以使用不限制命名空间
  selector:
    matchLabels:
      app: nginx-deployment
---
#### PodMonitor和ServiceMonitor选择需要的使用
# 对于上面的资源来说 这两个其实是一个效果
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  labels:
    app: nginx-servicemonitor
  name: nginx-servicemonitor
  namespace: default
spec:
  endpoints:
  - interval: 10s
    port: prometheus
  namespaceSelector:
    matchNames:
    - default
  selector:
    matchLabels:
      app: nginx-service

PodMonitor资源的作用,是Prometheus Operator会将PodMonitor解析为prometheus的配置。
配置完成后我们可以在http://prometheus:端口/config中查找对应的job_name,其格式为命名空间/podmonitor名

自定义指标

为了简化配置,建议创建一个YAML文件,您可以将其传递给istioctl install -f命令。telemetry.v2默认EnvoyFilter配置等效于以下安装选项。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    telemetry:
      v2:
        prometheus:
          configOverride:
            inboundSidecar: # 网格入站
              disable_host_header_fallback: false
            outboundSidecar: # 网格出站
              disable_host_header_fallback: false
            gateway: # 网关
              disable_host_header_fallback: true

比如我们想在指标中加入request_hostdestination_portrequest_host_port

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    telemetry:
      v2:
        prometheus:
          configOverride:
            inboundSidecar:
              metrics:
                - name: requests_total
                  dimensions:
                    destination_port: string(destination.port)
                    request_host: request.host
                    request_host_port: request.host + string(destination.port)
            outboundSidecar:
              metrics:
                - name: requests_total
                  dimensions:
                    destination_port: string(destination.port)
                    request_host: request.host
                    request_host_port: request.host + string(destination.port)
            gateway:
              metrics:
                - name: requests_total
                  dimensions:
                    destination_port: string(destination.port)
                    request_host: request.host
                    request_host_port: request.host + string(destination.port)

如果需要收集的指标标签不在DefaultStatTags中,需要在Deployment中额外定义sidecar.istio.io/extraStatTags,或者在meshConfig设置全局默认配置。
源码里DefaultStatTags有下面这些:

var (
	// DefaultStatTags for telemetry v2 tag extraction.
	DefaultStatTags = []string{
		"reporter",
		"source_namespace",
		"source_workload",
		"source_workload_namespace",
		"source_principal",
		"source_app",
		"source_version",
		"source_cluster",
		"destination_namespace",
		"destination_workload",
		"destination_workload_namespace",
		"destination_principal",
		"destination_app",
		"destination_version",
		"destination_service",
		"destination_service_name",
		"destination_service_namespace",
		"destination_port",
		"destination_cluster",
		"request_protocol",
		"request_operation",
		"request_host",
		"response_flags",
		"grpc_response_status",
		"connection_security_policy",
		"permissive_response_code",
		"permissive_response_policyid",
		"source_canonical_service",
		"destination_canonical_service",
		"source_canonical_revision",
		"destination_canonical_revision",
	}
)

request_host_port不在DefaultStatTags中,所以Deployment中需要额外定义

apiVersion: apps/v1
kind: Deployment
spec:
  template: # pod template
    metadata:
      annotations:
        sidecar.istio.io/extraStatTags: destination_port,request_host,request_host_port

或者在meshConfig中设置全局默认配置

meshConfig:
  defaultConfig:
    extraStatTags:
     - destination_port
     - request_host
     - request_host_port
官方最佳实践

链接:Observability Best Practices

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没事干写博客玩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值