Istio Proxy Access日志

开启 Access 日志

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: v1
kind: ConfigMap
metadata:
  name: istio
  namespace: istio-system
data:
  mesh: |
    accessLogEncoding: JSON
    accessLogFile: /dev/stdout
    accessLogFormat: ""

格式化 Access 日志

1
2
3
4
5
6
apiVersion: v1
data:
  mesh: |-
    accessLogEncoding: JSON
    accessLogFile: /dev/stdout
    accessLogFormat: "{\"authority\":\"%REQ(:AUTHORITY)%\",\"bytes_received\":\"%BYTES_RECEIVED%\",\"bytes_sent\":\"%BYTES_SENT%\",\"downstream_local_address\":\"%DOWNSTREAM_LOCAL_ADDRESS%\",\"downstream_remote_address\":\"%DOWNSTREAM_REMOTE_ADDRESS%\",\"duration\":\"%DURATION%\",\"istio_policy_status\":\"%DYNAMIC_METADATA(istio.mixer:status)%\",\"method\":\"%REQ(:METHOD)%\",\"path\":\"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%\",\"protocol\":\"%PROTOCOL%\",\"request_id\":\"%REQ(X-REQUEST-ID)%\",\"requested_server_name\":\"%REQUESTED_SERVER_NAME%\",\"response_code\":\"%RESPONSE_CODE%\",\"response_flags\":\"%RESPONSE_FLAGS%\",\"response_code_details\":\"%RESPONSE_CODE_DETAILS%\",\"connection_termination_details\":\"%CONNECTION_TERMINATION_DETAILS%\",\"route_name\":\"%ROUTE_NAME%\",\"start_time\":\"%START_TIME%\",\"upstream_cluster\":\"%UPSTREAM_CLUSTER%\",\"upstream_host\":\"%UPSTREAM_HOST%\",\"upstream_local_address\":\"%UPSTREAM_LOCAL_ADDRESS%\",\"upstream_service_time\":\"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%\",\"upstream_transport_failure_reason\":\"%UPSTREAM_TRANSPORT_FAILURE_REASON%\",\"user_agent\":\"%REQ(USER-AGENT)%\",\"x_forwarded_for\":\"%REQ(X-FORWARDED-FOR)%\"}"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
  "authority": "%REQ(:AUTHORITY)%",
  "bytes_received": "%BYTES_RECEIVED%",
  "bytes_sent": "%BYTES_SENT%",
  "downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%",
  "downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%",
  "duration": "%DURATION%",
  "istio_policy_status": "%DYNAMIC_METADATA(istio.mixer:status)%",
  "method": "%REQ(:METHOD)%",
  "path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%",
  "protocol": "%PROTOCOL%",
  "request_id": "%REQ(X-REQUEST-ID)%",
  "requested_server_name": "%REQUESTED_SERVER_NAME%",
  "response_code": "%RESPONSE_CODE%",
  "response_flags": "%RESPONSE_FLAGS%",
  "route_name": "%ROUTE_NAME%",
  "start_time": "%START_TIME%",
  "upstream_cluster": "%UPSTREAM_CLUSTER%",
  "upstream_host": "%UPSTREAM_HOST%",
  "upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%",
  "upstream_service_time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%",
  "upstream_transport_failure_reason": "%UPSTREAM_TRANSPORT_FAILURE_REASON%",
  "user_agent": "%REQ(USER-AGENT)%",
  "x_forwarded_for": "%REQ(X-FORWARDED-FOR)%"
}

访问日志格式化变量

变量描述
%REQ(:AUTHORITY)%请求的 authority
%BYTES_RECEIVED%请求体大小
%BYTES_SENT%响应体大小
%DOWNSTREAM_LOCAL_ADDRESS%下游本地地址
%DOWNSTREAM_REMOTE_ADDRESS%下游远程地址
%DURATION%请求持续时间
%DYNAMIC_METADATA(istio.mixer:status)%Istio Mixer 状态
%REQ(:METHOD)%请求方法
%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%请求路径
%PROTOCOL%请求协议
%REQ(X-REQUEST-ID)%请求 ID
%REQUESTED_SERVER_NAME%请求的服务器名称
%RESPONSE_CODE%响应状态码
%RESPONSE_FLAGS%响应标志
%RESPONSE_CODE_DETAILS%响应状态码详情
%CONNECTION_TERMINATION_DETAILS%连接终止详情
%ROUTE_NAME%路由名称
%START_TIME%请求开始时间
%UPSTREAM_CLUSTER%上游集群
%UPSTREAM_HOST%上游主机
%UPSTREAM_LOCAL_ADDRESS%上游本地地址
%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%上游服务时间
%UPSTREAM_TRANSPORT_FAILURE_REASON%上游传输失败原因
%REQ(USER-AGENT)%请求的用户代理
%REQ(X-FORWARDED-FOR)%请求的 X-Forwarded-For 头
%DYNAMIC_METADATA(istio.mixer:status)%Istio Mixer 状态

响应标识详情

响应标识完整名称描述
UHNoHealthyUpstream除了 503 响应代码之外,上游集群中没有健康的上游主机
UFUpstreamConnectionFailure除 503 响应代码外,上游连接失败
UOUpstreamOverflow除了 503 响应码之外,还有上游溢出(断路)
NRNoRouteFound除了 404 响应代码之外,没有为给定请求配置路由,或者下游连接没有匹配的过滤器链
URXUpstreamRetryLimitExceeded由于达到了上游重试限制 (HTTP)或最大连接尝试次数 (TCP),请求被拒绝
NCNoClusterFound未找到上游(Upstream)集群
DTDurationTimeout当请求或连接超过max_connection_duration或max_downstream_connection_duration时
DCDownstreamConnectionTermination下游连接终止,响应代码为0
UTUpstreamRequestTimeout除了 504 响应代码之外,上游请求超时
LHFailedLocalHealthCheck除了 503 响应代码之外,本地服务运行状况检查请求也失败
LRLocalReset除了 503 响应代码之外,连接本地重置
URUpstreamRemoteReset除了 503 响应代码之外,上游远程重置
UCUpstreamConnectionTermination除了 503 响应代码之外,上游连接终止
DIDelayInjected请求处理延迟了通过故障注入指定的时间
FIFaultInjected请求被中止,并通过故障注入指定了响应代码
RLRateLimited请求被速率限制器拒绝
UAEXUnauthorizedExternalService该请求被外部授权服务拒绝
RLSERateLimitServiceError该请求被拒绝,因为利率限制服务存在误差
IHInvalidEnvoyRequestHeaders该请求被拒绝,因为除了400个响应代码外,它设定了严格检查标头的无效值
SIStreamIdleTimeout除了408或504响应代码外,流闲置超时
DPEDownstreamProtocolError下游请求有HTTP协议错误
UPEUpstreamProtocolError上游响应具有HTTP协议错误
UMSDRUpstreamMaxStreamDurationReached上游请求达到了最大流持续时间
RFCFResponseFromCacheFilter该响应是从特使缓存过滤器提供的
NFCFNoFilterConfigFound该请求被终止,因为在允许的变暖截止日期内未收到过滤器配置
OMOverloadManagerTerminated超载管理器终止了请求
DFDnsResolutionFailed该请求由于DNS分辨率故障而终止
DODropOverload由于Drop_overloads,该请求还终止了503个响应代码
DRDownstreamRemoteReset响应详细信息是http2.remote_reset或http2.remote_refuse
UDOUnconditionalDropOverload由于 drop_overloads 设置为 100%,因此除了 503 响应代码之外,请求还被终止

前面7个(UH, UF, UO, NR, URX, NC, DT)是HTTP和TCP都支持的响应标识,其他的都是HTTP的响应标识。

查看 response_flags 非空的服务和请求目标地址

1
sort_desc(sum(changes(istio_requests_total{response_flags!="-",}[24h])>0) by (source_app, reporter,destination_service,response_flags))

自定义日志文件路径

1
accessLogFile: /var/log/envoy/envoy.log

局部启用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
cat << EOF | kubectl apply -f -
---
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: enable-accesslog
spec:
  workloadSelector:
    labels:
      app: details
  configPatches:
  - applyTo: NETWORK_FILTER
    match:
      context: ANY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
    patch:
      operation: MERGE
      value:
        typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
          access_log:
          - name: envoy.access_loggers.file
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
              path: "/var/log/istio/access.log"
              log_format:
                json_format:
                  authority: "%REQ(:AUTHORITY)%"
                  bytes_received: "%BYTES_RECEIVED%"
                  bytes_sent: "%BYTES_SENT%"
                  downstream_local_address: "%DOWNSTREAM_LOCAL_ADDRESS%"
                  downstream_remote_address: "%DOWNSTREAM_REMOTE_ADDRESS%"
                  duration: "%DURATION%"
                  method: "%REQ(:METHOD)%"
                  path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
                  protocol: "%PROTOCOL%"
                  connection_termination_details: "%CONNECTION_TERMINATION_DETAILS%"
                  request_id: "%REQ(X-REQUEST-ID)%"
                  requested_server_name: "%REQUESTED_SERVER_NAME%"
                  response_code: "%RESPONSE_CODE%"
                  response_flags: "%RESPONSE_FLAGS%"
                  response_code_detail: "%RESPONSE_CODE_DETAILS%",
                  route_name: "%ROUTE_NAME%"
                  start_time: "%START_TIME%"
                  upstream_cluster: "%UPSTREAM_CLUSTER%"
                  upstream_host: "%UPSTREAM_HOST%"
                  upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
                  upstream_service_time: "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%"
                  upstream_transport_failure_reason: "%UPSTREAM_TRANSPORT_FAILURE_REASON%"
                  user_agent: "%REQ(USER-AGENT)%"
                  x_forwarded_for: "%REQ(X-FORWARDED-FOR)%"
EOF

日志滚动

当输出到独立文件时,存在一个问题,日志不断增长导致磁盘空间不足,需要针对落盘文件进行滚动处理;

在这里采用社区提供的 logrotate 镜像,具体介绍可以参考【2】,通过 Istio 注入模板增加 Container 来实现日志滚动;当然也可以在这个基础上拓展采集对应的日志,但是sidecar形式资源成本较多,可以以 Daemonset 形式部署采集端。

修改Istio 注入模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
apiVersion: v1
data:
  config: |-
    ...
    templates:
      sidecar: |
        spec:
        ...
          containers:
          {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/logrotate` .Values.global.logrotate.enable) }}
          - name: logrotate
          {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/logrotateImage` .Values.global.logrotate.image) }}
            image: "{{ annotation .ObjectMeta `sidecar.istio.io/logrotateImage` .Values.global.logrotate.image }}"
          {{- else }}
            image: "realz/logrotate"
          {{- end }}
            imagePullPolicy: IfNotPresent
            - env:
              - name: CRON_EXPR
                value: {{ .Values.global.logrotate.cronexpr | default "*/30 * * * *" | quote }}
              - name: LOGROTATE_LOGFILES
                value: /data/log/ingress/*.log
              - name: LOGROTATE_FILESIZE
                value: {{ .Values.global.logrotate.filesize | default 100M | quote }}
              - name: LOGROTATE_FILENUM
                value: {{ .Values.global.logrotate.filenum | default "5" | quote }}
            volumeMounts:
            - mountPath: /data/log/ingress
              name: log
            resources:
              limits:
                cpu: 200m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
          {{end}}
          - name: istio-proxy
          ...
          volumes:
          {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/logrotate` .Values.global.logrotate.enable )}}
          - hostPath:
              path: /data/log/ingress
              type: ""
            name: log
          {{end}}
          - emptyDir:
            name: workload-socket
          ...
  values: |-
    {
      "global": {
        "logrotate": {
          "enable": true,
          "cronexpr": "*/30 * * * *",
          "filesize": "100M",
          "filenum": "5"
        }
      }
    }

参考资料

  1. istio 官方文档给出的常见变量

  2. docker-logrotate

  3. Istio: 503’s with UC’s and TCP Fun Times

  4. 基于实际案例解析Istio访问日志ResponseFlag系列

  5. Envoy ResponseFlagUtils 源代码

0%