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 是最佳选择