Istio 日志
支持的版本: Istio 1.28 最后更新: February 19, 2026
Istio 的日志功能可让您记录并分析服务网格中的所有活动。使用 Access Log(访问日志)、Envoy 日志和 structured logs(结构化日志)进行流量分析、调试和安全审计。
目录
- 日志概览
- Access Log 配置
- 使用 Telemetry API 自定义日志
- 日志过滤与采样
- 调整 Envoy 日志级别
- Promtail + Loki 集成
- Grafana 日志仪表板
- 日志与指标/追踪集成
- 性能优化
- 故障排除
日志概览
Istio 日志层
日志类型
- Access Log(访问日志):记录所有 HTTP/TCP 请求/响应
- Envoy Proxy 日志:Envoy 内部操作日志
- Istiod 日志:控制平面日志
- 应用日志:应用自身的日志
Access Log 配置
1. 使用 MeshConfig 启用全局 Access Log
基本文本格式
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: istio
namespace: istio-system
data:
mesh: |
accessLogFile: /dev/stdout
accessLogFormat: |
[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%"
%RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION%
"%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%"
"%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"应用:
bash
kubectl rollout restart deployment -n istio-system istiod
# Or restart existing pods
kubectl rollout restart deployment -n <namespace> <deployment-name>JSON 格式(结构化日志)
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: istio
namespace: istio-system
data:
mesh: |
accessLogFile: /dev/stdout
accessLogEncoding: JSON
accessLogFormat: |
{
"start_time": "%START_TIME%",
"method": "%REQ(:METHOD)%",
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%",
"protocol": "%PROTOCOL%",
"response_code": "%RESPONSE_CODE%",
"response_flags": "%RESPONSE_FLAGS%",
"bytes_received": "%BYTES_RECEIVED%",
"bytes_sent": "%BYTES_SENT%",
"duration": "%DURATION%",
"upstream_service_time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%",
"x_forwarded_for": "%REQ(X-FORWARDED-FOR)%",
"user_agent": "%REQ(USER-AGENT)%",
"request_id": "%REQ(X-REQUEST-ID)%",
"authority": "%REQ(:AUTHORITY)%",
"upstream_host": "%UPSTREAM_HOST%",
"upstream_cluster": "%UPSTREAM_CLUSTER%",
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%",
"downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%",
"downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%",
"requested_server_name": "%REQUESTED_SERVER_NAME%",
"route_name": "%ROUTE_NAME%"
}2. 使用 Telemetry API 进行精细控制
Telemetry API 允许您按 namespace 或 workload 控制日志。
为整个网格启用 JSON Access Log
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: mesh-logging
namespace: istio-system
spec:
accessLogging:
- providers:
- name: envoy
# JSON format with all fields
filter:
expression: "true" # Log all requests按 namespace 配置日志
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: production-logging
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
# Log only errors and slow requests
filter:
expression: |
response.code >= 400 ||
duration > 1000按 workload 记录详细日志
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: payment-service-logging
namespace: production
spec:
selector:
matchLabels:
app: payment-service
accessLogging:
- providers:
- name: envoy
# Log all requests + additional custom fields
filter:
expression: "true"使用 Telemetry API 自定义日志
自定义日志提供程序
1. 通过 OpenTelemetry 发送日志
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: istio
namespace: istio-system
data:
mesh: |
extensionProviders:
- name: otel-logging
envoyOtelAls:
service: opentelemetry-collector.observability.svc.cluster.local
port: 4317
logFormat:
labels:
start_time: "%START_TIME%"
method: "%REQ(:METHOD)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
protocol: "%PROTOCOL%"
response_code: "%RESPONSE_CODE%"
response_flags: "%RESPONSE_FLAGS%"
duration: "%DURATION%"
upstream_host: "%UPSTREAM_HOST%"
user_agent: "%REQ(USER-AGENT)%"
request_id: "%REQ(X-REQUEST-ID)%"
---
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: otel-access-logging
namespace: istio-system
spec:
accessLogging:
- providers:
- name: otel-logging2. 将日志保存到文件(Sidecar 卷共享)
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: file-logging
namespace: production
spec:
accessLogging:
- providers:
- name: envoy-file-logger
---
apiVersion: v1
kind: ConfigMap
metadata:
name: istio
namespace: istio-system
data:
mesh: |
extensionProviders:
- name: envoy-file-logger
envoyFileAccessLog:
path: /var/log/istio/access.log
logFormat:
labels:
timestamp: "%START_TIME%"
method: "%REQ(:METHOD)%"
path: "%REQ(:PATH)%"
status: "%RESPONSE_CODE%"日志格式自定义
使用 CEL 表达式的动态字段
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: custom-log-format
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: "true"可用变量:
| 变量 | 描述 | 示例 |
|---|---|---|
request.method | HTTP 方法 | GET, POST |
request.path | 请求路径 | /api/v1/users |
request.url_path | URL 路径(不含查询参数) | /api/v1/users |
request.headers | 请求头 | request.headers['user-agent'] |
response.code | HTTP 状态码 | 200, 404, 500 |
response.headers | 响应头 | response.headers['content-type'] |
response.flags | Envoy 响应标志 | UH, UF, URX |
duration | 请求时长(ms) | 123 |
connection.mtls | mTLS 使用情况 | true, false |
source.principal | 源服务账户 | spiffe://... |
destination.principal | 目标服务账户 | spiffe://... |
日志过滤与采样
1. 条件日志记录
仅记录错误和慢请求
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: error-slow-logging
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: |
response.code >= 400 ||
response.code == 0 ||
duration > 1000排除特定路径
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: filter-health-checks
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: |
!(request.url_path.startsWith('/health') ||
request.url_path.startsWith('/ready') ||
request.url_path.startsWith('/live') ||
request.url_path == '/metrics')HTTP 方法过滤
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: critical-methods-only
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: |
request.method in ['POST', 'PUT', 'DELETE', 'PATCH']仅记录非 mTLS 流量(安全审计)
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: non-mtls-logging
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: |
!connection.mtls2. 采样
概率采样(记录 10%)
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: sampled-logging
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: |
random() < 0.1 # 10% sampling条件 + 采样(错误 100%,正常请求 1%)
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: smart-sampling
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: |
response.code >= 400 ||
duration > 2000 ||
random() < 0.013. 按 namespace 区分日志记录
yaml
# Production: Log only errors
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: production-logging
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: "response.code >= 400"
---
# Staging: Log all requests
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: staging-logging
namespace: staging
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: "true"
---
# Development: Disable logging
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: dev-logging
namespace: development
spec:
accessLogging:
- disabled: true调整 Envoy 日志级别
动态更改日志级别
整体 Envoy 日志级别
bash
# Change to Debug level
istioctl proxy-config log <pod-name> -n <namespace> --level debug
# Restore to Info level
istioctl proxy-config log <pod-name> -n <namespace> --level info
# Change to Warning level
istioctl proxy-config log <pod-name> -n <namespace> --level warning按组件设置日志级别
bash
# Debug HTTP connections only
istioctl proxy-config log <pod-name> -n <namespace> --level http:debug
# Debug Router and Connection components only
istioctl proxy-config log <pod-name> -n <namespace> --level router:debug,connection:debug
# Multiple component combinations
istioctl proxy-config log <pod-name> -n <namespace> \
--level http:debug,router:info,upstream:debug,connection:trace关键 Envoy 日志组件
| 组件 | 描述 | 使用场景 |
|---|---|---|
admin | 管理接口 | 管理 API 调试 |
aws | AWS 集成 | AWS 服务问题 |
connection | TCP 连接 | 连接问题调试 |
filter | HTTP 过滤器 | 过滤器链分析 |
forward_proxy | 正向代理 | 代理行为跟踪 |
grpc | gRPC | gRPC 通信问题 |
hc | 健康检查 | 健康检查失败 |
http | HTTP | HTTP 请求/响应跟踪 |
http2 | HTTP/2 | HTTP/2 协议问题 |
jwt | JWT 身份验证 | JWT token 验证 |
lua | Lua 脚本 | Lua 过滤器调试 |
main | 主逻辑 | 一般 Envoy 操作 |
router | 路由 | 路由决策跟踪 |
runtime | 运行时配置 | 动态配置变更 |
upstream | 上游 cluster | 后端连接问题 |
client | HTTP 客户端 | 出站请求 |
pool | 连接池 | 连接池管理 |
rbac | RBAC 过滤器 | 权限问题调试 |
持久化日志级别配置
yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
defaultConfig:
proxyLogLevel: "info" # Default level
componentLogLevel: "http:debug,router:info,upstream:debug"仅向特定 workload 应用调试日志
yaml
apiVersion: v1
kind: Pod
metadata:
name: my-app
annotations:
sidecar.istio.io/componentLogLevel: "http:debug,router:debug"
sidecar.istio.io/logLevel: "debug"
spec:
containers:
- name: app
image: my-app:latestPromtail + Loki 集成
1. 安装 Grafana Loki
Loki Deployment(简单可扩展模式)
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: loki-config
namespace: observability
data:
loki.yaml: |
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2024-01-01
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
retention_period: 168h # 7 days
ingestion_rate_mb: 16
ingestion_burst_size_mb: 32
max_query_length: 721h
max_query_lookback: 721h
max_streams_per_user: 10000
max_global_streams_per_user: 0
reject_old_samples: true
reject_old_samples_max_age: 168h
compactor:
working_directory: /loki/compactor
compaction_interval: 10m
retention_enabled: true
retention_delete_delay: 2h
retention_delete_worker_count: 150
querier:
max_concurrent: 4
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: loki
namespace: observability
spec:
serviceName: loki
replicas: 1
selector:
matchLabels:
app: loki
template:
metadata:
labels:
app: loki
spec:
containers:
- name: loki
image: grafana/loki:2.9.4
args:
- -config.file=/etc/loki/loki.yaml
ports:
- containerPort: 3100
name: http
- containerPort: 9096
name: grpc
volumeMounts:
- name: config
mountPath: /etc/loki
- name: storage
mountPath: /loki
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 2000m
memory: 4Gi
volumes:
- name: config
configMap:
name: loki-config
volumeClaimTemplates:
- metadata:
name: storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: gp3
---
apiVersion: v1
kind: Service
metadata:
name: loki
namespace: observability
spec:
selector:
app: loki
ports:
- name: http
port: 3100
targetPort: 3100
- name: grpc
port: 9096
targetPort: 9096
type: ClusterIP2. 安装 Promtail(Istio Access Log 收集)
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: promtail-config
namespace: observability
data:
promtail.yaml: |
server:
http_listen_port: 3101
clients:
- url: http://loki:3100/loki/api/v1/push
backoff_config:
min_period: 1s
max_period: 5m
max_retries: 10
positions:
filename: /tmp/positions.yaml
scrape_configs:
# Istio Envoy Access Logs
- job_name: istio-accesslog
pipeline_stages:
# JSON parsing
- json:
expressions:
start_time: start_time
method: method
path: path
protocol: protocol
response_code: response_code
response_flags: response_flags
duration: duration
bytes_received: bytes_received
bytes_sent: bytes_sent
upstream_host: upstream_host
user_agent: user_agent
request_id: request_id
# Timestamp parsing
- timestamp:
source: start_time
format: "2006-01-02T15:04:05.000Z"
# Add labels
- labels:
method:
path:
response_code:
response_flags:
# Convert duration to number
- metrics:
request_duration_ms:
type: Histogram
description: "HTTP request duration"
source: duration
config:
buckets: [10, 50, 100, 500, 1000, 5000]
kubernetes_sd_configs:
- role: pod
relabel_configs:
# Select only Istio proxy containers
- source_labels: [__meta_kubernetes_pod_container_name]
action: keep
regex: istio-proxy
# Namespace label
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace
# Pod name label
- source_labels: [__meta_kubernetes_pod_name]
target_label: pod
# Service label
- source_labels: [__meta_kubernetes_pod_label_app]
target_label: app
# Version label
- source_labels: [__meta_kubernetes_pod_label_version]
target_label: version
# Istio Pilot/Istiod Logs
- job_name: istio-control-plane
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- istio-system
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
action: keep
regex: istiod
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace
- source_labels: [__meta_kubernetes_pod_name]
target_label: pod
- source_labels: [__meta_kubernetes_pod_container_name]
target_label: container
# Application Logs
- job_name: kubernetes-pods
pipeline_stages:
# Try parsing JSON logs
- json:
expressions:
level: level
timestamp: timestamp
logger: logger
message: message
- labels:
level:
logger:
kubernetes_sd_configs:
- role: pod
relabel_configs:
# Exclude Istio proxy
- source_labels: [__meta_kubernetes_pod_container_name]
action: drop
regex: istio-proxy
# Exclude Istio init
- source_labels: [__meta_kubernetes_pod_container_name]
action: drop
regex: istio-init
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace
- source_labels: [__meta_kubernetes_pod_name]
target_label: pod
- source_labels: [__meta_kubernetes_pod_container_name]
target_label: container
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: promtail
namespace: observability
spec:
selector:
matchLabels:
app: promtail
template:
metadata:
labels:
app: promtail
spec:
serviceAccountName: promtail
containers:
- name: promtail
image: grafana/promtail:2.9.4
args:
- -config.file=/etc/promtail/promtail.yaml
volumeMounts:
- name: config
mountPath: /etc/promtail
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
ports:
- containerPort: 3101
name: http-metrics
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: config
configMap:
name: promtail-config
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: promtail
namespace: observability
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: promtail
rules:
- apiGroups: [""]
resources:
- nodes
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: promtail
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: promtail
subjects:
- kind: ServiceAccount
name: promtail
namespace: observability3. LogQL 查询示例
基础查询
logql
# All logs from a specific namespace
{namespace="production"}
# Logs from a specific app
{app="payment-service"}
# Only Istio access logs
{container="istio-proxy"}
# Only error logs
{namespace="production"} |= "error" or "ERROR"
# Only 5xx responses
{namespace="production"} | json | response_code >= "500"高级过滤
logql
# Only HTTP POST requests
{container="istio-proxy"}
| json
| method="POST"
# Slow requests (> 1 second)
{container="istio-proxy"}
| json
| duration > 1000
# Detect circuit breaker activation
{container="istio-proxy"}
| json
| response_flags =~ ".*UO.*|.*URX.*"
# Traffic not using mTLS
{container="istio-proxy"}
| json
| connection_security_policy="none"
# Specific path pattern
{container="istio-proxy"}
| json
| path =~ "/api/v1/.*"聚合与统计
logql
# Request rate by service (RPS)
sum(rate({container="istio-proxy"} | json [1m])) by (app)
# Response code distribution
sum(count_over_time({container="istio-proxy"} | json [5m])) by (response_code)
# P95 latency
quantile_over_time(0.95, {container="istio-proxy"} | json | unwrap duration [5m])
# Error rate
sum(rate({container="istio-proxy"} | json | response_code >= "500" [5m]))
/
sum(rate({container="istio-proxy"} | json [5m]))
# Average response time
avg_over_time({container="istio-proxy"} | json | unwrap duration [5m])Grafana 日志仪表板
1. 添加 Loki 数据源
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-datasources
namespace: observability
data:
loki.yaml: |
apiVersion: 1
datasources:
- name: Loki
type: loki
access: proxy
url: http://loki:3100
jsonData:
maxLines: 1000
derivedFields:
# Extract Trace ID
- datasourceUid: tempo
matcherRegex: "request_id\":\"([^\"]+)"
name: TraceID
url: '$${__value.raw}'
# Metric integration
- datasourceUid: prometheus
matcherRegex: "app\":\"([^\"]+)"
name: Metrics
url: '/d/istio-service?var-service=$${__value.raw}'2. Istio Access Log 仪表板
仪表板 JSON
json
{
"dashboard": {
"title": "Istio Access Logs",
"tags": ["istio", "logs"],
"timezone": "browser",
"panels": [
{
"title": "Request Rate by Service",
"type": "timeseries",
"targets": [
{
"expr": "sum(rate({container=\"istio-proxy\"} | json [1m])) by (app)",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 0}
},
{
"title": "Response Code Distribution",
"type": "piechart",
"targets": [
{
"expr": "sum(count_over_time({container=\"istio-proxy\"} | json [5m])) by (response_code)",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}
},
{
"title": "P50/P95/P99 Latency",
"type": "timeseries",
"targets": [
{
"expr": "quantile_over_time(0.50, {container=\"istio-proxy\", app=\"$service\"} | json | unwrap duration [1m])",
"legendFormat": "P50",
"refId": "A"
},
{
"expr": "quantile_over_time(0.95, {container=\"istio-proxy\", app=\"$service\"} | json | unwrap duration [1m])",
"legendFormat": "P95",
"refId": "B"
},
{
"expr": "quantile_over_time(0.99, {container=\"istio-proxy\", app=\"$service\"} | json | unwrap duration [1m])",
"legendFormat": "P99",
"refId": "C"
}
],
"gridPos": {"h": 8, "w": 24, "x": 0, "y": 8}
},
{
"title": "Error Rate",
"type": "stat",
"targets": [
{
"expr": "sum(rate({container=\"istio-proxy\"} | json | response_code >= \"500\" [5m])) / sum(rate({container=\"istio-proxy\"} | json [5m]))",
"refId": "A"
}
],
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 16}
},
{
"title": "Top 10 Slowest Requests",
"type": "table",
"targets": [
{
"expr": "topk(10, avg_over_time({container=\"istio-proxy\", app=\"$service\"} | json | unwrap duration [5m])) by (path, method)",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 20}
},
{
"title": "Error Logs",
"type": "logs",
"targets": [
{
"expr": "{container=\"istio-proxy\", app=\"$service\"} | json | response_code >= \"400\"",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 20}
},
{
"title": "Circuit Breaker Events",
"type": "logs",
"targets": [
{
"expr": "{container=\"istio-proxy\"} | json | response_flags =~ \".*UO.*|.*URX.*\"",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 24, "x": 0, "y": 28}
},
{
"title": "Request Duration Heatmap",
"type": "heatmap",
"targets": [
{
"expr": "sum(rate({container=\"istio-proxy\", app=\"$service\"} | json | unwrap duration [1m])) by (le)",
"format": "heatmap",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 24, "x": 0, "y": 36}
}
],
"templating": {
"list": [
{
"name": "namespace",
"type": "query",
"query": "label_values({container=\"istio-proxy\"}, namespace)",
"datasource": "Loki"
},
{
"name": "service",
"type": "query",
"query": "label_values({container=\"istio-proxy\", namespace=\"$namespace\"}, app)",
"datasource": "Loki"
}
]
}
}
}3. Grafana 告警配置
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-alerting
namespace: observability
data:
alerting.yaml: |
groups:
- name: istio-logging-alerts
interval: 1m
rules:
# High error rate
- alert: HighErrorRate
expr: |
sum(rate({container="istio-proxy"} | json | response_code >= "500" [5m]))
/
sum(rate({container="istio-proxy"} | json [5m]))
> 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate detected"
description: "Error rate is {{ $value | humanizePercentage }}"
# Circuit Breaker triggered
- alert: CircuitBreakerTriggered
expr: |
count_over_time({container="istio-proxy"}
| json
| response_flags =~ ".*UO.*|.*URX.*" [1m])
> 10
for: 1m
labels:
severity: warning
annotations:
summary: "Circuit breaker triggered"
description: "Circuit breaker has been triggered {{ $value }} times"
# Slow requests
- alert: SlowRequests
expr: |
quantile_over_time(0.95,
{container="istio-proxy"}
| json
| unwrap duration [5m])
> 2000
for: 5m
labels:
severity: warning
annotations:
summary: "P95 latency too high"
description: "P95 latency is {{ $value }}ms"
# Non-mTLS traffic
- alert: NonMTLSTraffic
expr: |
count_over_time({container="istio-proxy"}
| json
| connection_security_policy="none" [5m])
> 0
for: 1m
labels:
severity: warning
annotations:
summary: "Non-mTLS traffic detected"
description: "{{ $value }} requests without mTLS in the last 5 minutes"日志与指标/追踪集成
1. 从日志跳转到追踪
在 Grafana 中,您可以直接从 Loki 日志跳转,以查看特定请求的追踪。
yaml
# Loki datasource configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-datasources
namespace: observability
data:
loki.yaml: |
apiVersion: 1
datasources:
- name: Loki
type: loki
jsonData:
derivedFields:
- datasourceUid: tempo
matcherRegex: '"request_id":"([^"]+)"'
name: TraceID
url: '$${__value.raw}'
urlDisplayLabel: 'View Trace'使用方法:
- 在 Grafana Explore 中查看 Loki 日志
- 单击日志条目中的 “View Trace” 链接
- 自动跳转到 Tempo 以查看相应的追踪
2. 从指标深入查看日志
yaml
# Prometheus datasource configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-datasources
namespace: observability
data:
prometheus.yaml: |
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
jsonData:
exemplarTraceIdDestinations:
- datasourceUid: tempo
name: TraceID3. 集成仪表板示例
json
{
"panels": [
{
"title": "Request Rate (Metric)",
"type": "timeseries",
"datasource": "Prometheus",
"targets": [
{
"expr": "rate(istio_requests_total{app=\"$service\"}[1m])"
}
],
"links": [
{
"title": "View Logs",
"url": "/explore?left={\"datasource\":\"Loki\",\"queries\":[{\"expr\":\"{app=\\\"${service}\\\"}\"}]}"
}
]
},
{
"title": "Recent Logs",
"type": "logs",
"datasource": "Loki",
"targets": [
{
"expr": "{container=\"istio-proxy\", app=\"$service\"} | json"
}
]
}
]
}性能优化
1. 减少日志量
使用条件日志记录减少 50-90%
yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: optimized-logging
namespace: production
spec:
accessLogging:
- providers:
- name: envoy
filter:
expression: |
response.code >= 400 ||
duration > 1000 ||
random() < 0.01 # Sample only 1% of normal requests通过排除健康检查减少 30-50%
yaml
filter:
expression: |
!(request.url_path.startsWith('/health') ||
request.url_path.startsWith('/ready') ||
request.url_path.startsWith('/live') ||
request.url_path == '/metrics' ||
request.url_path == '/favicon.ico')2. Loki 性能调优
yaml
limits_config:
# Chunk size optimization
ingestion_rate_strategy: global
ingestion_rate_mb: 32 # Default: 4
ingestion_burst_size_mb: 64 # Default: 6
# Query performance
max_query_parallelism: 32
max_query_series: 10000
max_query_lookback: 720h
# Stream limits
max_streams_per_user: 10000
max_global_streams_per_user: 0
# Label cardinality limits
max_label_names_per_series: 30
max_label_value_length: 20483. Promtail 优化
yaml
# Batching configuration
clients:
- url: http://loki:3100/loki/api/v1/push
batchwait: 1s
batchsize: 1048576 # 1MB
# Retry configuration
backoff_config:
min_period: 500ms
max_period: 5m
max_retries: 10
# Timeout
timeout: 10s故障排除
Access Log 不可见
bash
# 1. Check MeshConfig
kubectl get configmap istio -n istio-system -o yaml | grep -A 5 accessLog
# 2. Check Telemetry resources
kubectl get telemetry -A
# 3. Verify log generation in Envoy
kubectl logs -n <namespace> <pod-name> -c istio-proxy | head -20
# 4. Check Envoy configuration
istioctl proxy-config bootstrap <pod-name> -n <namespace> -o json | \
jq '.bootstrap.staticResources.listeners[].accessLog'JSON 解析失败
bash
# 1. Check log format
kubectl logs -n <namespace> <pod-name> -c istio-proxy | head -1
# 2. Check accessLogEncoding
kubectl get configmap istio -n istio-system -o yaml | grep accessLogEncoding
# 3. Manually test JSON parsing
kubectl logs -n <namespace> <pod-name> -c istio-proxy | head -1 | jq .Promtail 未收集日志
bash
# 1. Check Promtail logs
kubectl logs -n observability daemonset/promtail
# 2. Check Promtail metrics
kubectl port-forward -n observability daemonset/promtail 3101:3101
curl http://localhost:3101/metrics | grep promtail_
# 3. Verify data is reaching Loki
kubectl port-forward -n observability svc/loki 3100:3100
curl -G -s "http://localhost:3100/loki/api/v1/query" --data-urlencode 'query={job="istio-accesslog"}' | jq .日志量过大
bash
# 1. Check log volume by namespace
kubectl top pods -n <namespace> --containers | grep istio-proxy
# 2. Check number of log streams
curl -G -s "http://localhost:3100/loki/api/v1/labels" | jq '.data | length'
# 3. Find services generating the most logs
# LogQL:
topk(10, sum(count_over_time({container="istio-proxy"} [1h])) by (app))