为Envoy上游gRPC集群启用TLS遇阻,寻求解决方案
解决Cloud Run上Envoy代理无法向上游gRPC后端发起TLS连接的问题
问题背景
我有一个grpc-web前端应用,通过Envoy代理与gRPC后端通信,本地环境(含容器化)运行完全正常。部署到Google Cloud Run后,前端和Envoy均可通过HTTPS访问,且用Postman或Golang gRPC客户端能直接调用Cloud Run上的gRPC后端(地址为my-grpc-server.a.run.app),但Envoy配置TLS连接上游后,无法正确转换grpc-web请求,直接转发HTTP/2请求导致Cloud Run返回路径不存在错误,gRPC状态码为12(UNIMPLEMENTED)。
核心解决方案
问题根源在于Envoy未正确识别并转换grpc-web请求,同时上游TLS配置需适配Cloud Run的公网可信证书环境,以下是关键配置要点和完整示例:
1. 必须启用grpc_web过滤器
在Envoy的HTTP过滤器链中加入grpc_web过滤器是核心,它负责将浏览器的grpc-web请求转换为标准gRPC请求,确保上游后端能识别。
2. 简化上游集群TLS配置
Cloud Run的服务证书由公网CA签发,Envoy默认信任系统根证书,无需手动指定CA文件,只需开启TLS传输并设置正确的SNI(即Cloud Run服务域名)。
3. 适配Cloud Run的HTTP/2要求
gRPC后端依赖HTTP/2协议,需在集群配置中开启http2_protocol_options。
完整Envoy配置示例
static_resources: listeners: - name: listener_0 address: socket_address: { address: 0.0.0.0, port_value: 8080 } filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager codec_type: AUTO stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: grpc_backend } http_filters: - name: envoy.filters.http.grpc_web typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb - name: envoy.filters.http.cors typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors allow_origin_string_match: - prefix: "*" allow_methods: GET, PUT, DELETE, POST, OPTIONS allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout expose_headers: grpc-status,grpc-message - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router upgrade_configs: - upgrade_type: h2c - upgrade_type: grpc-web clusters: - name: grpc_backend connect_timeout: 0.25s type: LOGICAL_DNS lb_policy: ROUND_ROBIN http2_protocol_options: {} load_assignment: cluster_name: grpc_backend endpoints: - lb_endpoints: - endpoint: address: socket_address: address: my-grpc-server.a.run.app port_value: 443 transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext sni: my-grpc-server.a.run.app
关键配置说明
grpc_web过滤器位置:必须放在router过滤器之前,确保请求先被转换为标准gRPC格式。- HTTP/2支持:集群配置中的
http2_protocol_options: {}开启HTTP/2,匹配gRPC后端的协议要求。 - TLS配置:仅需设置
sni和开启TLS传输,无需额外CA文件,Envoy默认信任系统根证书,可验证Cloud Run的公网证书。 - CORS规则:明确允许grpc-web所需的请求头(如
x-grpc-web、grpc-timeout),避免前端跨域拦截。
验证要点
- 查看Envoy日志,确认请求经过
grpc_web过滤器处理后,Content-Type被转换为application/grpc。 - 确认上游请求以HTTP/2协议发送到
my-grpc-server.a.run.app:443。 - 确保Cloud Run的gRPC后端已正确配置为接受HTTP/2请求(Cloud Run默认支持gRPC服务,只需镜像正确暴露gRPC端口)。
内容的提问来源于stack exchange,提问作者EmmanuelB
相关产品推荐
相关产品推荐

