Istio 服务网格
Istio 服务网格
什么是服务网格
服务网格(Service Mesh)是一个专用的基础设施层,用于处理服务间的通信,使其可靠、快速和安全。
核心功能:
- 流量管理:路由、负载均衡、熔断
- 安全:mTLS、认证、授权
- 可观测性:指标、日志、追踪
- 策略执行:限流、配额、黑白名单
为什么需要 Istio
传统微服务架构的痛点:
┌──────────────────────────────────────┐
│ 应用代码 = 业务逻辑 + 基础设施代码 │
│ │
│ - 服务发现 │
│ - 负载均衡 │
│ - 熔断降级 │
│ - 重试超时 │
│ - 监控追踪 │
│ - 安全认证 │
└──────────────────────────────────────┘
使用 Istio 后:
┌──────────────────────────────────────┐
│ 应用代码 = 业务逻辑 │
└──────────────────────────────────────┘
↓
┌──────────────────────────────────────┐
│ Istio (Sidecar) = 基础设施代码 │
│ 自动注入,无需修改应用 │
└──────────────────────────────────────┘
Istio 架构
┌─────────────────┐
│ Control Plane │
│ (istiod) │
└────────┬────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Service │ │ Service │ │ Service │
│ A │ │ B │ │ C │
├─────────┤ ├─────────┤ ├─────────┤
│ Envoy │ │ Envoy │ │ Envoy │
│ Sidecar │ │ Sidecar │ │ Sidecar │
└─────────┘ └─────────┘ └─────────┘
Data Plane
组件:
- istiod:控制平面,统一管理配置
- Envoy Sidecar:数据平面,拦截所有流量
- Ingress Gateway:入口网关
- Egress Gateway:出口网关
安装 Istio
1. 下载 Istio
# 下载最新版本
curl -L https://istio.io/downloadIstio | sh -
# 进入目录
cd istio-1.20.0
# 添加到 PATH
export PATH=$PWD/bin:$PATH
2. 安装 Istio
# 使用 demo 配置(学习环境)
istioctl install --set profile=demo -y
# 生产环境使用
istioctl install --set profile=production -y
# 验证安装
kubectl get pods -n istio-system
3. 启用自动注入
# 为命名空间启用自动 Sidecar 注入
kubectl label namespace default istio-injection=enabled
# 验证标签
kubectl get namespace -L istio-injection
部署示例应用
1. Bookinfo 示例
# 部署 Bookinfo 应用
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
# 验证 Pod(每个 Pod 有 2 个容器:app + envoy)
kubectl get pods
# 验证服务
kubectl get services
2. 应用架构
┌──────────────┐
│ productpage │ (Python)
└──────┬───────┘
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ details │ │ reviews │ │ ratings │
└─────────┘ └────┬────┘ └─────────┘
│
┌────┴────┐
│ │
v1 (无星) v2 (黑星) v3 (红星)
3. 创建 Gateway
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
4. 创建 VirtualService
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
5. 访问应用
# 获取 Ingress Gateway 地址
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
# 访问应用
echo "http://$GATEWAY_URL/productpage"
流量管理
1. 按权重分配流量
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 50 # 50% 流量到 v1
- destination:
host: reviews
subset: v3
weight: 50 # 50% 流量到 v3
2. 定义 DestinationRule
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
3. 基于请求头路由
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
# 特定用户看到 v2
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
# 其他用户看到 v1
- route:
- destination:
host: reviews
subset: v1
4. 超时配置
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
timeout: 2s # 2 秒超时
5. 重试策略
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
retries:
attempts: 3 # 重试 3 次
perTryTimeout: 2s
retryOn: gateway-error,connect-failure,refused-stream
熔断和故障注入
1. 熔断配置
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 10
http2MaxRequests: 100
maxRequestsPerConnection: 2
outlierDetection:
consecutiveErrors: 5 # 连续 5 次错误
interval: 30s
baseEjectionTime: 30s # 隔离 30 秒
maxEjectionPercent: 50 # 最多隔离 50% 实例
2. 故障注入(测试)
注入延迟
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
delay:
percentage:
value: 10.0 # 10% 请求
fixedDelay: 5s # 延迟 5 秒
route:
- destination:
host: ratings
subset: v1
注入错误
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
abort:
percentage:
value: 10.0 # 10% 请求
httpStatus: 500 # 返回 500 错误
route:
- destination:
host: ratings
subset: v1
安全:mTLS
1. 启用 mTLS
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: STRICT # 强制 mTLS
模式:
- PERMISSIVE:允许明文和 mTLS(过渡期)
- STRICT:仅允许 mTLS
- DISABLE:禁用 mTLS
2. 验证 mTLS
# 检查证书
istioctl proxy-config secret <pod-name> -n default
# 测试连接
kubectl exec <pod-name> -c istio-proxy -- curl -s http://httpbin:8000/headers
3. 授权策略
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: productpage-viewer
namespace: default
spec:
selector:
matchLabels:
app: productpage
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/bookinfo-reviews"]
to:
- operation:
methods: ["GET"]
paths: ["/productpage"]
可观测性
1. 安装 Prometheus
kubectl apply -f samples/addons/prometheus.yaml
2. 安装 Grafana
kubectl apply -f samples/addons/grafana.yaml
# 访问 Grafana
istioctl dashboard grafana
3. 安装 Kiali
kubectl apply -f samples/addons/kiali.yaml
# 访问 Kiali(服务拓扑图)
istioctl dashboard kiali
4. 查看指标
# 查看服务指标
kubectl exec <pod-name> -c istio-proxy -- curl localhost:15000/stats/prometheus
5. Envoy 日志
# 查看 Sidecar 日志
kubectl logs <pod-name> -c istio-proxy
# 动态调整日志级别
istioctl proxy-config log <pod-name> --level debug
金丝雀发布(Istio 方式)
1. 部署两个版本
# v1 版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: v1
template:
metadata:
labels:
app: myapp
version: v1
spec:
containers:
- name: myapp
image: myapp:v1.0
---
# v2 版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v2
spec:
replicas: 1
selector:
matchLabels:
app: myapp
version: v2
template:
metadata:
labels:
app: myapp
version: v2
spec:
containers:
- name: myapp
image: myapp:v2.0
2. 流量分配
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: myapp
subset: v2
- route:
- destination:
host: myapp
subset: v1
weight: 90 # 90% 流量
- destination:
host: myapp
subset: v2
weight: 10 # 10% 流量
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
3. 逐步增加流量
# 增加到 50%
kubectl patch virtualservice myapp --type merge -p '
{
"spec": {
"http": [{
"route": [
{"destination": {"host": "myapp", "subset": "v1"}, "weight": 50},
{"destination": {"host": "myapp", "subset": "v2"}, "weight": 50}
]
}]
}
}'
# 全量切换到 v2
kubectl patch virtualservice myapp --type merge -p '
{
"spec": {
"http": [{
"route": [
{"destination": {"host": "myapp", "subset": "v2"}, "weight": 100}
]
}]
}
}'
Ingress Gateway 高级配置
1. HTTPS 配置
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: myapp-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: myapp-tls # Secret 名称
hosts:
- myapp.example.com
创建 TLS Secret:
kubectl create -n istio-system secret tls myapp-tls \
--cert=myapp.crt \
--key=myapp.key
2. 多域名配置
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: multi-host-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "app1.example.com"
- "app2.example.com"
- "*.example.com"
最佳实践
1. 资源配置
# 为 Sidecar 设置合理的资源
apiVersion: v1
kind: ConfigMap
metadata:
name: istio-sidecar-injector
namespace: istio-system
data:
values: |
sidecarInjectorWebhook:
rewriteAppHTTPProbe: true
global:
proxy:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 2000m
memory: 1024Mi
2. 性能优化
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1000
http:
http2MaxRequests: 1000
maxRequestsPerConnection: 10
loadBalancer:
consistentHash:
httpCookie:
name: user
ttl: 3600s # Session 粘性
3. 多集群配置
# 安装主集群
istioctl install --set profile=demo \
--set values.global.multiCluster.clusterName=cluster1
# 安装远程集群
istioctl install --set profile=remote \
--set values.global.multiCluster.clusterName=cluster2 \
--set values.global.remotePilotAddress=<cluster1-pilot-address>
故障排查
1. 检查 Sidecar 注入
# 检查 Pod 是否有 Sidecar
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[*].name}'
# 应该看到:myapp istio-proxy
# 查看 Sidecar 状态
kubectl describe pod <pod-name>
2. 配置不生效
# 同步配置到 Envoy
istioctl proxy-config routes <pod-name>
istioctl proxy-config clusters <pod-name>
istioctl proxy-config endpoints <pod-name>
# 验证 VirtualService
istioctl analyze
3. mTLS 问题
# 检查 mTLS 状态
istioctl authn tls-check <pod-name> <service-name>
# 查看证书
istioctl proxy-config secret <pod-name>
4. 网关问题
# 检查 Gateway 状态
kubectl get gateway -n default
# 查看 Ingress Gateway 日志
kubectl logs -n istio-system -l app=istio-ingressgateway
# 测试连接
kubectl exec <pod-name> -c istio-proxy -- curl -v http://productpage:9080
卸载 Istio
# 删除示例应用
kubectl delete -f samples/bookinfo/platform/kube/bookinfo.yaml
# 卸载 Istio
istioctl uninstall --purge -y
# 删除命名空间
kubectl delete namespace istio-system
# 删除标签
kubectl label namespace default istio-injection-
总结
Istio 核心能力:
| 功能 | 说明 | 使用场景 |
|---|---|---|
| 流量管理 | 智能路由、金丝雀发布 | 灰度发布、A/B 测试 |
| 安全 | mTLS、认证授权 | 零信任网络 |
| 可观测性 | 指标、日志、追踪 | 问题诊断 |
| 弹性 | 超时、重试、熔断 | 提高可靠性 |
选择建议:
- 小型应用:不需要 Istio,使用原生 K8s 资源
- 中型应用:使用 Istio 核心功能(流量管理)
- 大型应用:完整使用 Istio(流量+安全+可观测)
- 多集群:Istio 是最佳选择