名称: istio 描述: 使用 Istio 实现服务网格,用于微服务的流量管理、安全和可观察性。适用于实现服务网格、mTLS、流量路由、负载均衡、熔断器、重试、超时、金丝雀部署、A/B 测试或服务间通信。触发词: istio, 服务网格, envoy, 边车, virtualservice, destinationrule, gateway, mtls, peerauthentication, authorizationpolicy, serviceentry, 流量管理, 流量分割, 金丝雀, 蓝绿部署, 熔断器, 重试, 超时, 负载均衡, 入口, 出口, 可观察性, 追踪, 遥测。 允许工具: Read, Grep, Glob, Edit, Write, Bash
Istio 服务网格
概述
Istio 是一个开源服务网格,为微服务架构提供流量管理、安全和可观察性。它使用 Envoy 代理作为边车模式,拦截和控制所有服务间的网络通信。
核心能力
流量管理:负载均衡、流量分割、金丝雀部署、蓝绿部署、A/B 测试、重试、超时、熔断器、故障注入。
安全:mTLS 加密、证书管理、认证、授权策略、RBAC、JWT 验证、服务间安全。
可观察性:分布式追踪、指标收集、访问日志、服务拓扑可视化、黄金信号监控。
快速参考:常见任务
| 任务 | 资源 | 部分 |
|---|---|---|
| 启用服务间 mTLS | PeerAuthentication | mTLS PeerAuthentication |
| 路由流量到新版本 | VirtualService + DestinationRule | 金丝雀的流量分割 |
| 添加熔断器 | DestinationRule (outlierDetection) | 熔断器和重试 |
| 配置重试/超时 | VirtualService (retries, timeout) | 熔断器和重试 |
| 暴露服务到互联网 | Gateway + VirtualService | Gateway 和 VirtualService |
| 控制出口流量 | Sidecar + ServiceEntry | Sidecar 资源用于出口 |
| 添加授权规则 | AuthorizationPolicy | AuthorizationPolicy 用于 RBAC |
| 配置负载均衡 | DestinationRule (loadBalancer) | DestinationRule 带流量策略 |
| 测试韧性 | VirtualService (fault injection) | 用于测试的故障注入 |
架构组件
控制平面 (istiod)
- 服务发现和配置分发
- mTLS 的证书颁发机构
- Pilot 用于流量管理
- Galley 用于配置验证
- Citadel 用于安全
数据平面
- Envoy 代理部署为边车
- 拦截所有入站和出站流量
- 执行策略和收集遥测
- 处理流量路由、负载均衡和重试
关键资源
Gateway:配置 HTTP/TCP 流量进入网格的负载均衡器VirtualService:定义流量路由规则DestinationRule:配置路由后的策略(负载均衡、连接池、熔断器)ServiceEntry:将外部服务添加到网格PeerAuthentication:配置服务间 mTLSAuthorizationPolicy:定义访问控制策略Sidecar:控制边车代理配置和出口流量
安装和配置
使用 istioctl 安装 Istio
# 下载并安装 istioctl
curl -L https://istio.io/downloadIstio | sh -
cd istio-*
export PATH=$PWD/bin:$PATH
# 使用生产配置文件安装 Istio
istioctl install --set profile=production -y
# 验证安装
kubectl get pods -n istio-system
istioctl verify-install
# 为命名空间启用自动边车注入
kubectl label namespace default istio-injection=enabled
配置配置文件
# 最小:仅控制平面,无入口/出口
istioctl install --set profile=minimal
# 默认:推荐用于生产
istioctl install --set profile=default
# 生产:高可用控制平面
istioctl install --set profile=production
# 自定义配置
istioctl install --set profile=default \
--set meshConfig.accessLogFile=/dev/stdout \
--set meshConfig.enableTracing=true \
--set meshConfig.defaultConfig.proxyMetadata.ISTIO_META_DNS_CAPTURE=true
验证边车注入
# 检查命名空间是否启用了注入
kubectl get namespace -L istio-injection
# 验证 Pod 是否有边车
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[*].name}'
# 应显示:app-container istio-proxy
# 查看边车配置
istioctl proxy-config all <pod-name>.<namespace>
最佳实践
Gateway 配置
指南
- 为每个域或协议使用专用 Gateway 资源
- 使用正确的 TLS 证书配置 HTTPS
- 实现健康检查和超时
- 谨慎使用通配符域以提高安全性
- 将网关放在专用命名空间(如 istio-system 或 istio-ingress)
反模式
- 避免多个 Gateway 绑定到同一端口/主机组合
- 不要在没有认证的情况下直接暴露内部服务
- 切勿在 Gateway 规格中硬编码凭据
流量管理模式
渐进式交付
- 使用加权路由进行金丝雀部署
- 通过即时流量切换实现蓝绿部署
- 应用基于头部的路由来测试新版本
- 在推广金丝雀之前监控指标
韧性
- 配置带指数退避的重试
- 实现熔断器以防止级联故障
- 设置连接池限制以保护服务
- 使用异常检测移除不健康的实例
路由策略
- 基于头部、URI 路径或查询参数路由
- 使用基于子集的路由进行版本管理
- 实现故障注入进行混沌测试
- 在每个服务边界应用超时
安全策略
mTLS 配置
- 在生产中为所有服务启用 STRICT 模式
- 仅在迁移期间使用 PERMISSIVE 模式
- 将 PeerAuthentication 范围限定到特定命名空间或工作负载
- 使用
istioctl authn tls-check验证 mTLS 状态
授权
- 默认拒绝所有流量,然后明确允许
- 使用命名空间级策略进行广泛规则
- 应用工作负载特定策略进行细粒度控制
- 利用 JWT 认证获取最终用户身份
- 定期审计授权策略
证书管理
- 自动轮换证书(默认 90 天)
- 在生产中使用外部 CA(如 cert-manager、Vault)
- 监控证书过期时间
- 测试证书续订过程
可观察性集成
指标
- 部署 Prometheus 进行指标收集
- 使用 Grafana 仪表板进行可视化
- 监控黄金信号:延迟、流量、错误、饱和度
- 为 SLO 违规设置警报
追踪
- 与 Jaeger、Zipkin 或 Datadog 集成
- 在应用代码中传播追踪头部
- 智能采样追踪(生产环境中不要 100%)
- 使用追踪调试延迟问题
日志
- 选择性启用访问日志(影响性能)
- 以 JSON 格式结构化日志
- 发送日志到集中式日志系统(如 ELK、Splunk)
- 在应用日志中包含追踪 ID
生产就绪示例
Gateway 和 VirtualService
# gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: public-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
# HTTPS 配置
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: tls-cert-secret # istio-system 命名空间中的 Secret
hosts:
- "api.example.com"
- "app.example.com"
# HTTP 到 HTTPS 重定向
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "api.example.com"
- "app.example.com"
tls:
httpsRedirect: true
---
# virtualservice.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api-routes
namespace: default
spec:
hosts:
- "api.example.com"
gateways:
- istio-system/public-gateway
http:
# 路由 /v2 到新服务
- match:
- uri:
prefix: "/v2/"
rewrite:
uri: "/"
route:
- destination:
host: api-v2.default.svc.cluster.local
port:
number: 8080
timeout: 30s
retries:
attempts: 3
perTryTimeout: 10s
retryOn: 5xx,reset,connect-failure,refused-stream
# 路由 /v1 到旧服务
- match:
- uri:
prefix: "/v1/"
route:
- destination:
host: api-v1.default.svc.cluster.local
port:
number: 8080
timeout: 60s
# 默认路由
- route:
- destination:
host: api-v2.default.svc.cluster.local
port:
number: 8080
DestinationRule 带流量策略
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: api-destination
namespace: default
spec:
host: api.default.svc.cluster.local
trafficPolicy:
# 负载均衡
loadBalancer:
consistentHash:
httpHeaderName: x-user-id # 会话亲和性
# 连接池设置
connectionPool:
tcp:
maxConnections: 100
connectTimeout: 30ms
tcpKeepalive:
time: 7200s
interval: 75s
http:
http1MaxPendingRequests: 50
http2MaxRequests: 100
maxRequestsPerConnection: 2
maxRetries: 3
# 异常检测(熔断器)
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
minHealthPercent: 40
# 上游的 TLS 设置
tls:
mode: ISTIO_MUTUAL # 使用 Istio mTLS
# 定义用于基于版本路由的子集
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
- name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: LEAST_REQUEST
金丝雀部署的流量分割
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: canary-rollout
namespace: default
spec:
hosts:
- reviews.default.svc.cluster.local
http:
# 发送 10% 流量到金丝雀
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: reviews.default.svc.cluster.local
subset: v2
- route:
- destination:
host: reviews.default.svc.cluster.local
subset: v1
weight: 90
- destination:
host: reviews.default.svc.cluster.local
subset: v2
weight: 10
---
# 蓝绿部署(即时切换)
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: blue-green
namespace: default
spec:
hosts:
- orders.default.svc.cluster.local
http:
- route:
# 通过将权重改为 100 切换到绿色
- destination:
host: orders.default.svc.cluster.local
subset: blue
weight: 100
- destination:
host: orders.default.svc.cluster.local
subset: green
weight: 0
熔断器和重试配置
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: circuit-breaker
namespace: default
spec:
host: backend.default.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 10
http:
http1MaxPendingRequests: 1
http2MaxRequests: 10
maxRequestsPerConnection: 1
outlierDetection:
# 在 5 个连续错误后移除实例
consecutive5xxErrors: 5
consecutiveGatewayErrors: 5
# 每秒检查一次
interval: 1s
# 保持实例移除 30 秒
baseEjectionTime: 30s
# 最多 100% 的实例可以被移除
maxEjectionPercent: 100
# 最小 0% 必须健康(允许完全移除用于测试)
minHealthPercent: 0
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: retry-policy
namespace: default
spec:
hosts:
- payment.default.svc.cluster.local
http:
- route:
- destination:
host: payment.default.svc.cluster.local
timeout: 10s
retries:
attempts: 3
perTryTimeout: 3s
# 在这些条件下重试
retryOn: 5xx,reset,connect-failure,refused-stream,retriable-4xx
# 仅在幂等方法上重试
retryRemoteLocalities: true
mTLS PeerAuthentication
# 命名空间范围的 STRICT mTLS
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default-mtls
namespace: production
spec:
mtls:
mode: STRICT
---
# 网格范围的 mTLS(应用到 istio-system)
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: mesh-mtls
namespace: istio-system
spec:
mtls:
mode: STRICT
---
# 工作负载特定的 PERMISSIVE(迁移)
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: legacy-service
namespace: default
spec:
selector:
matchLabels:
app: legacy-app
mtls:
mode: PERMISSIVE # 接受 mTLS 和明文
# 端口级覆盖
portLevelMtls:
8080:
mode: DISABLE # 健康检查端口
---
# 验证 mTLS 状态
# istioctl authn tls-check <pod-name>.<namespace> <service-name>.<namespace>.svc.cluster.local
AuthorizationPolicy 用于 RBAC
# 默认拒绝所有
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: production
spec: {} # 空规格拒绝所有请求
---
# 允许特定服务间通信
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
selector:
matchLabels:
app: backend
action: ALLOW
rules:
# 允许来自前端服务
- from:
- source:
principals:
- "cluster.local/ns/production/sa/frontend"
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/*"]
---
# JWT 认证和授权
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-jwt
namespace: default
spec:
selector:
matchLabels:
app: api
action: ALLOW
rules:
- from:
- source:
requestPrincipals: ["*"] # 需要有效的 JWT
when:
- key: request.auth.claims[role]
values: ["admin", "user"]
---
# 基于 IP 的允许列表
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-internal-ips
namespace: default
spec:
selector:
matchLabels:
app: admin-panel
action: ALLOW
rules:
- from:
- source:
ipBlocks: ["10.0.0.0/8", "172.16.0.0/12"]
---
# 基于方法和路径的限制
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: read-only-access
namespace: default
spec:
selector:
matchLabels:
app: database-api
action: ALLOW
rules:
- to:
- operation:
methods: ["GET", "HEAD"]
# DENY 优先于 ALLOW
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-delete
namespace: default
spec:
selector:
matchLabels:
app: database-api
action: DENY
rules:
- to:
- operation:
methods: ["DELETE"]
Sidecar 资源用于出口控制
# 命名空间的默认边车(限制出口)
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: default-sidecar
namespace: production
spec:
# 应用到命名空间中的所有工作负载
egress:
# 允许访问同一命名空间中的服务
- hosts:
- "./*"
# 允许访问 istio-system
- hosts:
- "istio-system/*"
# 允许特定外部服务
- hosts:
- "*/external-api.external.svc.cluster.local"
---
# 工作负载特定的边车
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: frontend-sidecar
namespace: default
spec:
workloadSelector:
labels:
app: frontend
ingress:
- port:
number: 8080
protocol: HTTP
name: http
defaultEndpoint: 127.0.0.1:8080
egress:
# 仅允许访问后端服务
- hosts:
- "./backend.default.svc.cluster.local"
# 允许访问外部 API
- hosts:
- "*/api.external.com"
---
# 优化边车以访问外部服务
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-api
namespace: default
spec:
hosts:
- api.external.com
ports:
- number: 443
name: https
protocol: HTTPS
location: MESH_EXTERNAL
resolution: DNS
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: external-egress
namespace: default
spec:
workloadSelector:
labels:
app: worker
outboundTrafficPolicy:
mode: REGISTRY_ONLY # 仅允许注册的 ServiceEntry
egress:
- hosts:
- "*/api.external.com"
高级模式
用于测试的故障注入
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: fault-injection
namespace: default
spec:
hosts:
- ratings.default.svc.cluster.local
http:
- match:
- headers:
x-test:
exact: "chaos"
fault:
# 为 50% 的请求注入 5 秒延迟
delay:
percentage:
value: 50.0
fixedDelay: 5s
# 中断 10% 的请求并返回 HTTP 500
abort:
percentage:
value: 10.0
httpStatus: 500
route:
- destination:
host: ratings.default.svc.cluster.local
- route:
- destination:
host: ratings.default.svc.cluster.local
多集群服务网格
# 主集群配置
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: primary-cluster
spec:
values:
global:
meshID: mesh1
multiCluster:
clusterName: primary
network: network1
---
# 远程集群配置
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: remote-cluster
spec:
values:
global:
meshID: mesh1
multiCluster:
clusterName: remote
network: network2
remotePilotAddress: istiod.istio-system.svc.cluster.local
基于位置的负载均衡
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: locality-lb
namespace: default
spec:
host: service.default.svc.cluster.local
trafficPolicy:
loadBalancer:
localityLbSetting:
enabled: true
# 优先相同区域/可用区
distribute:
- from: us-west/zone1/*
to:
"us-west/zone1/*": 80
"us-west/zone2/*": 20
# 故障转移配置
failover:
- from: us-west
to: us-east
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
故障排除命令
# 检查 Istio 安装
istioctl verify-install
# 分析配置问题
istioctl analyze --all-namespaces
# 检查代理配置
istioctl proxy-config cluster <pod-name>.<namespace>
istioctl proxy-config route <pod-name>.<namespace>
istioctl proxy-config listener <pod-name>.<namespace>
istioctl proxy-config endpoint <pod-name>.<namespace>
# 检查 mTLS 状态
istioctl authn tls-check <pod-name>.<namespace> <service-name>.<namespace>.svc.cluster.local
# 查看代理日志
kubectl logs <pod-name> -c istio-proxy -n <namespace>
# 调试路由
istioctl experimental describe pod <pod-name> -n <namespace>
# 检查证书过期时间
istioctl proxy-config secret <pod-name>.<namespace> -o json | jq '.dynamicActiveSecrets[0].secret.tlsCertificate.certificateChain.inlineBytes' -r | base64 -d | openssl x509 -text -noout
# 测试流量路由
kubectl exec <pod-name> -c istio-proxy -- curl -v http://service:port/path
# 导出代理配置用于调试
istioctl proxy-config all <pod-name>.<namespace> -o json > proxy-config.json
性能调优
资源请求和限制
# 边车代理资源
apiVersion: v1
kind: Namespace
metadata:
name: production
annotations:
# 设置默认边车资源
sidecar.istio.io/proxyCPU: "100m"
sidecar.istio.io/proxyCPULimit: "2000m"
sidecar.istio.io/proxyMemory: "128Mi"
sidecar.istio.io/proxyMemoryLimit: "1024Mi"
控制平面调优
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
# 减少配置推送时间
defaultConfig:
holdApplicationUntilProxyStarts: true
proxyMetadata:
ISTIO_META_DNS_CAPTURE: "true"
ISTIO_META_DNS_AUTO_ALLOCATE: "true"
components:
pilot:
k8s:
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
cpu: 2000m
memory: 4Gi
env:
- name: PILOT_PUSH_THROTTLE
value: "100"
- name: PILOT_ENABLE_WORKLOAD_ENTRY_HEALTH_CHECKS
value: "true"
安全加固
禁用特权容器
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
defaultConfig:
# 以非 root 用户运行
runAsUser: 1337
runAsGroup: 1337
# 丢弃所有权限
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
出口流量控制
# 默认阻止所有出口
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
outboundTrafficPolicy:
mode: REGISTRY_ONLY # 仅允许注册的 ServiceEntry
迁移策略
阶段 1:安装 Istio(无注入)
istioctl install --set profile=default
# 暂时不启用自动注入
阶段 2:按工作负载启用注入
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
template:
metadata:
annotations:
sidecar.istio.io/inject: "true"
阶段 3:启用 PERMISSIVE mTLS
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: PERMISSIVE
阶段 4:验证所有服务使用 mTLS
# 检查每个服务
for pod in $(kubectl get pods -n production -o name); do
istioctl authn tls-check $pod
done
阶段 5:启用 STRICT mTLS
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT