在 Kubernetes 中,Pod 和 Service 的代理主要通过三种方式配置:用环境变量处理出站(egress)流量、用 sidecar 容器实现精细控制并与 service mesh 集成、以及用 Ingress 资源或 Service 类型管理入站(ingress)流量。本文详细介绍在 Kubernetes 环境中实现代理配置的各种机制。
Pod 的出站代理配置
Pod 常常需要出站代理来访问外部网络、执行安全策略或管理出集群的流量路由。
环境变量
为 Pod 内的应用配置出站代理,最直接的方法是使用标准的 HTTP/HTTPS 代理环境变量。许多应用和客户端库会自动遵循这些变量。
HTTP_PROXY:指定用于 HTTP 请求的代理服务器。HTTPS_PROXY:指定用于 HTTPS 请求的代理服务器。NO_PROXY:以逗号分隔的主机名、域名或 IP 地址列表,这些目标将绕过代理。这对集群内部通信至关重要(例如kubernetes.default.svc、10.0.0.0/8、*.svc.cluster.local)。
这些变量在 Pod 的容器规格中定义。
apiVersion: v1
kind: Pod
metadata:
name: my-app-with-proxy
spec:
containers:
- name: my-app
image: my-application-image:latest
env:
- name: HTTP_PROXY
value: "http://proxy.internal.domain:3128"
- name: HTTPS_PROXY
value: "http://proxy.internal.domain:3128"
- name: NO_PROXY
value: "localhost,127.0.0.1,.svc,.cluster.local,10.0.0.0/8" # 示例:请按您的集群 CIDR 调整
用 Init 容器实现动态代理配置
在更复杂的场景中,可以用 Init 容器在主应用容器启动前准备代理配置或注入证书。这适用于:
- 从配置服务获取代理信息。
- 基于集群内部 IP 段生成
NO_PROXY列表。 - 注入代理所需的自定义 CA 证书。
apiVersion: v1
kind: Pod
metadata:
name: my-app-init-proxy
spec:
initContainers:
- name: init-proxy-config
image: alpine/git # 示例:一个用于拉取配置的简单镜像
command: ["sh", "-c", "echo 'HTTP_PROXY=http://dynamic-proxy:3128' > /mnt/proxy/config"]
volumeMounts:
- name: proxy-config-volume
mountPath: /mnt/proxy
containers:
- name: my-app
image: my-application-image:latest
command: ["sh", "-c", ". /mnt/proxy/config && exec my-app-binary"] # 加载配置
volumeMounts:
- name: proxy-config-volume
mountPath: /mnt/proxy
volumes:
- name: proxy-config-volume
emptyDir: {}
用于出站的 sidecar 代理
sidecar 代理与应用容器运行在同一个 Pod 中。它拦截应用容器的全部出站流量并经代理转发。这种模式带来:
- 网络透明:应用容器无需感知代理,代理逻辑由 sidecar 负责。
- 集中策略:出站策略(例如允许/拒绝名单、限流、认证)可在 sidecar 层面统一执行,与应用无关。
- 可观测性:sidecar 可为全部出站流量输出指标、日志和链路追踪。
常见的 sidecar 代理包括 Envoy(Istio 使用)和 Linkerd 的代理。
apiVersion: v1
kind: Pod
metadata:
name: my-app-with-sidecar-egress
spec:
containers:
- name: my-app
image: my-application-image:latest
# 应用流量通过 iptables 规则重定向到 sidecar
- name: egress-proxy-sidecar
image: envoyproxy/envoy:v1.28.0 # Envoy 镜像示例
ports:
- containerPort: 15001 # 应用发送流量所使用的端口
volumeMounts:
- name: envoy-config
mountPath: /etc/envoy
# Envoy 的配置:将流量转发到外部代理或直接转发
#(通常由 service mesh 控制平面管理)
volumes:
- name: envoy-config
configMap:
name: egress-envoy-config
Service 的入站代理配置
对于进入 Service 的流量,Kubernetes 提供了若干本身就包含代理机制的方式。
Kubernetes Service(kube-proxy)
运行在每个节点上的 kube-proxy 组件负责处理 Kubernetes Service 的虚拟 IP(VIP)。当集群内外的客户端尝试连接某个 Service 的 ClusterIP 时,kube-proxy 会拦截流量并转发给支撑该 Service 的某个 Pod。它相当于四层(TCP/UDP)代理和负载均衡器。
- 模式:
kube-proxy运行在iptables(默认)或ipvs模式下。- iptables:使用
iptables规则完成 NAT 和负载均衡。 - ipvs:使用 IP Virtual Server(IPVS),提供更完善的负载均衡算法,在 service 数量很多时性能更好。
- iptables:使用
这种代理是自动的,除了定义 Service 本身之外,不需要在 Pod 或 Service 中做任何显式配置。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP # 由 kube-proxy 完成的内部代理
Ingress 资源与 Ingress Controller
要让 Service 支持外部 HTTP/HTTPS 访问,需要把 Ingress 资源与 Ingress Controller 配合使用。Ingress Controller 本身就是运行在集群内的专用代理。
- Ingress Controller:运行 NGINX、HAProxy、Traefik 或 AWS ALB/GCE L7 负载均衡器控制器等代理的一个 Pod(或一组 Pod)。它监听 Ingress 资源并动态配置自己的代理规则。
- Ingress 资源:定义把外部 HTTP/HTTPS 流量路由到 Service 的规则,包括基于主机的路由、基于路径的路由和 TLS 终止。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
tls: # 可选:在 Ingress Controller 上进行 TLS 终止
- hosts:
- api.example.com
secretName: my-tls-secret
LoadBalancer 类型的 Service
创建 LoadBalancer 类型的 Service 时,会自动开通一个外部负载均衡器(通常由云服务商提供)。该外部负载均衡器充当代理,把流量转发到 Service 的 NodePort,再由 kube-proxy 路由到后端 Pod。
apiVersion: v1
kind: Service
metadata:
name: my-external-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer # 由云服务商 LB 完成的外部代理
用于入站的 sidecar 代理(Service Mesh)
在 service mesh(例如 Istio、Linkerd)中,sidecar 代理会被注入到 Pod 内,同时处理应用容器的入站和出站流量。对于入站流量,sidecar 会拦截发往应用的流量,先应用 mesh 策略(例如认证、鉴权、流量切换、重试、熔断),再转发给应用容器。
这带来:
- 策略执行:对服务之间如何通信实现细粒度控制。
- 可观测性:对所有服务间通信自动提供指标、日志和分布式追踪。
- 流量管理:高级路由能力(例如金丝雀发布、A/B 测试)。
- 安全性:服务之间的双向 TLS(mTLS)。
sidecar 的注入和配置通常由 service mesh 的控制平面自动完成。
apiVersion: v1
kind: Pod
metadata:
name: my-app-with-mesh-sidecar
labels:
app: my-app
# Istio 示例:触发自动 sidecar 注入
istio-injection: enabled
spec:
containers:
- name: my-app
image: my-application-image:latest
ports:
- containerPort: 8080
# Istio 控制平面会自动添加一个 'istio-proxy' sidecar 容器
# 并配置 iptables 规则来重定向流量。
各种代理方案对比
| 特性 | 环境变量 | sidecar 代理(手动) | sidecar 代理(service mesh) | Ingress Controller | LoadBalancer Service |
|---|---|---|---|---|---|
| 作用范围 | 特定容器的出站流量 | 特定 Pod 的出站/入站流量 | 所有启用 mesh 的 Pod 的出站/入站流量 | 到 Service 的外部入站流量 | 到 Service 的外部入站流量 |
| 层级 | L7(HTTP/S) | L4/L7 | L4/L7 | L7(HTTP/S) | L4(TCP/UDP) |
| 配置方式 | Pod env |
Pod containers、volumes、iptables(手动) |
由控制平面自动完成 | Ingress 资源、控制器配置 | Service 类型、云服务商 |
| 复杂度 | 低 | 高(手动 iptables 与配置) | 中(初期 mesh 搭建) | 中(Ingress 规则、控制器) | 低(Service 定义) |
| 能力 | 基础出站代理 | 精细流量控制、可观测性、安全 | 高级流量管理、mTLS、可观测性、安全 | 路径/主机路由、TLS 终止、L7 特性 | 基础 L4 负载均衡、外部 IP |
| 主要适用场景 | 简单的外部代理需求 | 每个应用自定义、精细的代理 | 微服务通信、策略、可观测性 | 外部 HTTP/S 访问、L7 路由 | 外部 L4 访问、云集成 |
| 对应用的影响 | 应用必须遵循环境变量 | 应用无感知(透明) | 应用无感知(透明) | 应用无感知(目标为 Service) | 应用无感知(目标为 Service) |
实践注意事项
证书管理
代理往往会终止或发起 TLS 连接。
- Ingress Controller:通常通过 Kubernetes Secret 管理 TLS 证书,从而在集群边缘完成 TLS 终止。
- sidecar 代理:在 service mesh 中,sidecar 会自动处理 mTLS,通常使用由 mesh 的证书颁发机构签发的短期证书。对于出站流量,它们可能需要信任自定义 CA,以便检查加密流量或连接内部服务。
性能与开销
每增加一个代理,就在网络路径上多一跳,可能增加延迟。
kube-proxy:已高度优化。service 数量较多时,ipvs模式性能更好。- sidecar:每个 Pod 都会带来 CPU、内存和网络开销。这一开销是 service mesh 部署时必须考虑的设计因素。
- Ingress Controller:如果没有针对大流量做好扩容,可能成为瓶颈。
可观测性
代理是采集遥测数据的集中点。
- 日志:代理可以记录连接详情、请求/响应头以及错误。
- 指标:可以抓取请求速率、延迟、错误率等标准指标。
- 追踪:service mesh 中的 sidecar 代理无需修改应用代码即可实现分布式追踪。
安全
代理是执行安全策略的关键节点。
- 访问控制:代理可以对进出流量执行认证和鉴权策略。
- 网络分段:代理可以隔离应用流量,阻止本不应通信的服务之间建立直接连接。
- DDoS 防护:外部代理(如 Ingress Controller 或云负载均衡器)可以提供 DDoS 缓解能力。
