第278篇:K8s Ingress 与 Service Mesh 网络
关键词:Ingress、Ingress Controller、Service Mesh、Istio、Envoy、侧车代理、L7路由
一、引言
在Kubernetes集群中,Service提供了Pod间的基本负载均衡和服务发现能力,但对于外部流量的管理和微服务间的精细流量控制,需要更高级的网络抽象:Ingress和Service Mesh。
Ingress是Kubernetes原生的L7入口控制器,负责将外部流量路由到集群内的Service。Service Mesh则通过在应用中注入侧车代理(Sidecar),实现了微服务间的流量管理、安全通信和可观测性。
二、核心概念
2.1 Ingress 资源
Ingress是Kubernetes的原生API资源,定义了L7层的路由规则:
Ingress的核心能力:
| 能力 | 说明 |
|---|---|
| 基于Host的路由 | 根据HTTP Host头路由到不同Service |
| 基于Path的路由 | 根据URL路径路由到不同Service |
| TLS终止 | 在Ingress层处理HTTPS解密 |
| 负载均衡 | 后端Service的多Pod负载均衡 |

2.2 Ingress Controller
Ingress Controller是实现Ingress路由规则的控制器:
| Controller | 特点 | 适用场景 |
|---|---|---|
| Nginx Ingress | 成熟稳定, 功能丰富 | 通用场景 |
| Traefik | 自动发现, 云原生友好 | 动态环境 |
| HAProxy Ingress | 高性能, TCP/HTTP | 高性能需求 |
| AWS ALB Ingress | AWS集成 | AWS环境 |
| Cilium Ingress | eBPF加速 | Cilium环境 |
2.3 Service Mesh 架构
Service Mesh通过侧车代理(Sidecar)实现微服务间通信的管理:
Service Mesh的核心组件:
| 组件 | 说明 | 示例 |
|---|---|---|
| 数据面(Data Plane) | 侧车代理, 处理服务间流量 | Envoy, Linkerd-proxy |
| 控制面(Control Plane) | 配置管理, 证书分发 | Istio Pilot, Linkerd Control |
| 侧车(Sidecar) | 与业务容器同Pod部署 | Envoy Sidecar |
| 网关(Gateway) | 入口/出口流量管理 | Istio Gateway |
2.4 Service Mesh vs Ingress
| 维度 | Ingress | Service Mesh |
|---|---|---|
| 作用域 | 集群入口(南北向) | 服务间(东西向) |
| L7路由 | ✓ | ✓ |
| 流量分割 | 有限 | 金丝雀/蓝绿/AB测试 |
| 安全(mTLS) | TLS终止 | 全链路mTLS |
| 可观测性 | 入口日志 | 全链路追踪 |
| 性能开销 | 低 | 中(Sidecar代理) |
| 复杂度 | 低 | 高 |
| 部署方式 | 独立Pod | Sidecar注入 |
三、技术细节
3.1 Ingress 路由规则
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: tls-secret
rules:
- host: api.example.com
http:
paths:
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
- path: /orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-frontend
port:
number: 80
3.2 Istio 流量管理
Istio VirtualService(流量路由):
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-app-vs
spec:
hosts:
- my-app
http:
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: my-app
subset: canary
weight: 100
- route:
- destination:
host: my-app
subset: v1
weight: 90
- destination:
host: my-app
subset: v2
weight: 10
Istio DestinationRule(子集定义):
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: my-app-dr
spec:
host: my-app
trafficPolicy:
connectionPool:
http:
h2UpgradePolicy: DEFAULT
maxRequestsPerConnection: 100
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
subsets:
- name: v1
labels:
version: v1
- name: canary
labels:
version: canary
3.3 Istio mTLS 安全通信

3.4 金丝雀发布与灰度发布
Service Mesh支持精细化的流量分割,实现金丝雀发布:
# 金丝雀发布配置
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-app-canary
spec:
hosts:
- my-app
http:
# 规则1: 内部测试用户走金丝雀版本
- match:
- headers:
x-user-type:
exact: "tester"
route:
- destination:
host: my-app
subset: canary
weight: 100
# 规则2: 5%的随机流量走金丝雀
- route:
- destination:
host: my-app
subset: stable
weight: 95
- destination:
host: my-app
subset: canary
weight: 5
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: my-app-subsets
spec:
host: my-app
subsets:
- name: stable
labels:
version: v1
- name: canary
labels:
version: v2
| 发布策略 | 流量分配 | 适用场景 |
|---|---|---|
| 全量发布 | 100%→新版本 | 非关键变更 |
| 金丝雀发布 | 5%→金丝雀, 95%→稳定 | 新功能验证 |
| 灰度发布 | 按用户分群路由 | 面向特定用户群测试 |
| A/B测试 | 按特征分流 | 功能对比实验 |
| 蓝绿发布 | 0%→100%原子切换 | 快速回滚需求 |
3.5 熔断与限流策略
熔断(Circuit Breaker):
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: my-app-circuit-breaker
spec:
host: my-app
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
connectTimeout: 30ms
http:
h2UpgradePolicy: DEFAULT
maxRequestsPerConnection: 10
maxPendingRequests: 1000
maxRetries: 3
outlierDetection:
consecutive5xxErrors: 5 # 连续5次5xx错误
interval: 10s # 检测间隔
baseEjectionTime: 30s # 基础熔断时间
maxEjectionPercent: 50 # 最大熔断比例
限流(Rate Limiting):
| 限流维度 | 说明 | Istio实现 |
|---|---|---|
| 全局限流 | 整个服务的请求速率 | Envoy external rate limit |
| 用户限流 | 每个用户的请求速率 | Envoy local rate limit |
| 路径限流 | 每个API路径的请求速率 | VirtualService + RateLimit |
| 集群限流 | 每个后端集群的请求速率 | DestinationRule连接池 |
3.6 Service Mesh 性能开销分析
| 开销维度 | 无Sidecar | 有Sidecar(Envoy) | 开销比例 |
|---|---|---|---|
| 延迟增加 | 基线 | +50-200μs | 5-20% |
| 内存占用 | 应用内存 | +50-100MB/Sidecar | 20-50% |
| CPU占用 | 应用CPU | +5-15%/Sidecar | 10-30% |
| 启动时间 | 应用启动 | +2-5秒(Sidecar启动) | 显著 |
| Pod规模 | 1容器 | 2容器(应用+Sidecar) | 翻倍 |
降低Sidecar开销的方法:
| 方法 | 说明 | 效果 |
|---|---|---|
| 资源限制优化 | 调低Sidecar的CPU/内存请求 | 减少资源预留 |
| 延迟注入关闭 | 生产环境关闭故障注入 | 消除额外延迟 |
| mTLS优化 | 使用会话复用(TLS Session Resumption) | 降低握手开销 |
| eBPF Service Mesh | 使用Cilium等eBPF方案替代Sidecar | 消除Sidecar开销 |
| 选择性注入 | 仅关键服务注入Sidecar | 按需启用 |
四、实战配置/案例分析
4.1 Nginx Ingress Controller 部署
# Nginx Ingress Controller (Deploy模式)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx-ingress
template:
metadata:
labels:
app: nginx-ingress
spec:
containers:
- name: nginx-ingress
image: registry.k8s.io/ingress-nginx/controller:v1.9.0
args:
- /nginx-ingress-controller
- --publish-service=ingress-nginx/ingress-nginx
- --election-id=ingress-nginx-leader
ports:
- containerPort: 80
- containerPort: 443
- containerPort: 10254
name: metrics
---
# Service (LoadBalancer模式)
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
spec:
type: LoadBalancer
selector:
app: nginx-ingress
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
4.2 故障案例:Ingress TLS证书过期导致502
现象:某生产环境Ingress配置的HTTPS站点返回502 Bad Gateway错误,HTTP站点正常。
排查过程:
# 1. 检查Ingress状态
kubectl get ingress
# Ingress状态正常, 外部IP已分配
# 2. 检查TLS Secret
kubectl get secret tls-secret -o yaml
# 解码certificate字段
kubectl get secret tls-secret -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -dates -noout
# notBefore=Jan 1 00:00:00 2024 GMT
# notAfter=Jan 1 00:00:00 2025 GMT
# 证书已过期!
# 3. 检查Ingress Controller日志
kubectl logs -n ingress-nginx nginx-ingress-controller-xxx
# 错误: SSL certificate has expired
根因:Ingress引用的TLS证书已过期,Nginx Ingress Controller拒绝使用过期证书处理HTTPS请求,返回502错误。
解决: 1. 使用cert-manager自动化证书管理:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: app-tls
spec:
secretName: tls-secret
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- app.example.com
- 立即更新证书解决当前问题
- 部署cert-manager实现证书自动续期
4.3 故障案例:Istio Sidecar注入失败
现象:命名空间已启用Istio自动注入,但新创建的Pod中Sidecar容器启动失败。
排查过程:
# 1. 检查Pod状态
kubectl get pods
# istio-proxy容器状态为CrashLoopBackOff
# 2. 检查Sidecar日志
kubectl logs my-app-pod -c istio-proxy
# 错误: Envoy configuration NACKed
# 具体: cluster "xds-grpc": xds_cluster: xds_cluster connects to non-ipv4/ipv6
# 3. 检查Istio配置
kubectl get configmap -n istio-system istio -o yaml
# meshConfig中proxyMetadata配置错误
# 4. 检查命名空间标签
kubectl get namespace my-namespace --show-labels
# istio-injection=enabled 标签存在
根因:Istio Control Plane的ConfigMap配置中,xds-grpc集群的地址格式不正确(使用了主机名而非IP),导致Envoy Sidecar无法连接到控制面获取配置。
解决: 1. 修正Istio ConfigMap中的meshConfig配置 2. 重启受影响的Pod使其重新注入正确的Sidecar配置 3. 在Istio升级或配置变更时,先在测试命名空间验证
五、总结
| 组件 | 层次 | 功能 | 性能开销 |
|---|---|---|---|
| Service | L4 | Pod负载均衡 | 低 |
| Ingress | L7 | 入口路由,TLS终止 | 低 |
| Service Mesh | L7 | 流量管理,mTLS,可观测性 | 中(Sidecar) |
| Service Mesh方案 | 代理 | 控制面 | 特点 |
|---|---|---|---|
| Istio | Envoy | Istiod | 功能最全, 社区活跃 |
| Linkerd | linkerd-proxy(Rust) | linkerd-control | 轻量, 安全 |
| Consul Connect | Envoy | Consul | 与Consul集成 |
| Cilium Service Mesh | eBPF | Cilium Operator | 无Sidecar, 高性能 |
| 流量管理能力 | Ingress | Service Mesh |
|---|---|---|
| 基于Host路由 | ✓ | ✓ |
| 基于Path路由 | ✓ | ✓ |
| 金丝雀发布 | 有限 | ✓(精细化) |
| 熔断/限流 | 有限 | ✓ |
| mTLS | 入口TLS | 全链路mTLS |
| 全链路追踪 | ✗ | ✓ |
思考
- Service Mesh通过Sidecar代理拦截所有服务间流量,这种架构对业务应用的性能有什么影响?
- Ingress Controller和Service Mesh Gateway在功能上是否有重叠?什么场景下需要同时部署?
- Istio的mTLS是自动双向认证,业务应用需要做哪些改动才能支持mTLS?
- 金丝雀发布中如何确定金丝雀版本的流量比例应该从多少开始?如何逐步放量?
- Service Mesh的熔断机制如何工作?熔断后如何自动恢复?
下篇预告:第279篇:容器网络的多租户隔离方案