线上生产环境envoy网关崩溃处理
如上两个根据官方提供的命令测试均未模拟出故障期间的崩溃问题,在设置limit后只出现了413状态码,已经显示出上传文件过大。某线上生产环境反馈部分业务功能不可用了,通过登录环境排查,发现envoy网关pod全部状态异常,通过重启pod无法拉起。如上根据模拟租户侧相同的请求,能复现出当时的故障,而创建envoyfilter后就返回413,并没有崩溃。当时根据日志,当时创建envoyfilter设置m
背景
某线上生产环境反馈部分业务功能不可用了,通过登录环境排查,发现envoy网关pod全部状态异常,通过重启pod无法拉起。
网关崩溃处理过程
当时第一次重启网关pod无法拉起的情况下,查看了相关网关日志,发现网关日志报健康检查通不过,后来尝试进入网关pod控制器,删除对应服务控制器的探针配置,重启pod,pod可以正常running一会,还是再会挂掉,在查看网关日志,发现网关存在崩溃,崩溃日志只展示部分如下:
StreamInfoImpl 0x566959139990, protocol_: 1, response_code_: null, response_code_details_: null, attempt_count_: null, health_check_request_: 0, route_name_: upstream_info_:
UpstreamInfoImpl 0x5669748a6600, upstream_connection_id_: null
OverridableRemoteConnectionInfoSetterStreamInfo 0x566959139990, remoteAddress(): x.x.x.x:62534, directRemoteAddress(): x.x.x.x:62534, localAddress(): x.x.x.x:8080
Http1::ConnectionImpl 0x56695ab9c008, dispatching_: 1, dispatching_slice_already_drained_: 1, reset_stream_called_: 0, handling_upgrade_: 0, deferred_end_stream_headers_: 0, require_strict_1xx_and_204_headers_: 0, send_strict_1xx_and_204_headers_: 1, processing_trailers_: 0, no_chunked_encoding_header_for_304_: 1, buffered_body_.length(): 1300, header_parsing_state_: Done, current_header_field_: , current_header_value_:
active_request_:
, request_url_: null, response_encoder_.local_end_stream_: 0
absl::get<RequestHeaderMapPtr>(headers_or_trailers_): null
, current_dispatching_buffer_: nullConnectionImpl 0x56695ab0e000, connecting_: 0, bind_error_: 0, state(): Open, read_buffer_limit_: 1048576
socket_:
ListenSocketImpl 0x56695aa7b800, transport_protocol_: raw_buffer
connection_info_provider_:
ConnectionInfoSetterImpl 0x56695ab25eb0, remote_address_: x.x.x.x:62534, direct_remote_address_: x.x.x.x:62534, local_address_: x.x.x.x:8080, server_name_:
2025-06-13T00:55:23.713609Z info ads ADS: "@" sino-nginx-prod-7cc5c4887d-2l86k.cms-v6-prod-1 terminated
2025-06-13T00:55:23.713676Z info ads ADS: "@" sino-nginx-prod-7cc5c4887d-2l86k.cms-v6-prod-2 terminated
2025-06-13T00:55:23.715081Z error failed scraping envoy metrics: error scraping http://localhost:15090/stats/prometheus: Get "http://localhost:15090/stats/prometheus": read tcp [::1]:41584->[::1]:15090: read: connection reset by peer
2025-06-13T00:55:23.715860Z error Epoch 0 exited with error: signal: segmentation fault (core dumped)
2025-06-13T00:55:23.715924Z info No more active epochs, terminating
当时根据日志,当时创建envoyfilter设置max_request_bytes的大小,进行恢复。
网关崩溃问题分析
1、部署模拟测试场景,根据报错日志进行故障模拟。
根据envoy官方提供的文件上传模拟最大请求字节数案例进行部署测试场景,相关地址如下:
https://github.com/jewertow/istio-playground/tree/master/issues/ext-authz-max-requests-bytes-413-payload-too-large
1.1、官方测试场景:
测试场景一 没有创建envoyfilter,默认request大小10M,buffer大小默认1M,模拟100M大文件上传
测试命令如下(官方提供的命令):
curl -v POST -H “x-ext-authz: allow” -F ‘data=@test.txt’
http://10.10.10.10:3000/file-upload/upload?key=TESTUSER
测试结果如下:
测试场景二 创建envoyfilter设置request值为12M,模拟100M大文件上传
测试命令如下(官方提供命令):
curl -v POST -H “x-ext-authz: allow” -F ‘data=@test.txt’
http://10.10.10.10:3000/file-upload/upload?key=TESTUSER
测试结果如下:
如上两个根据官方提供的命令测试均未模拟出故障期间的崩溃问题,在设置limit后只出现了413状态码,已经显示出上传文件过大。
1.2、根据租户侧请求进行模拟请求场景
通过网关崩溃日志发现,存在两处崩溃的日志都有相同的特征
'authorization', '' 'content-type', 'multipart/form-data' 'user-agent', 'okhttp/4.7.2'
崩溃发生在处理分块请求体时:
#1: Envoy::Router::Function::FcpFilter::decodeData() [0xaaaade927e24] #4: Envoy::Http::Http1::ServerConnectionImpl::onBody() #5: Envoy::Http::Http1::ConnectionImpl::dispatchBufferedBody()
崩溃可能当空认证头 + okhttp/4.7.2时特定分块大小组合时,根据这两点, 开始准备进行模拟租户侧的请求。
测试场景一、 未创建envoyfilter,模拟请求头包含空的请求头+okhttp/4.7.2
测试命令如下:
curl -v POST -H "authorization: " -H “user-agent:okhttp/4.7.2” -F
‘data=@minio-helm.tar.gz’
http://10.228.38.83:12356/file-upload/upload?key=TESTUSER
测试结果如下,跟当时网关崩溃报错日志吻合:
测试场景二、 创建envoyfilter,模拟请求头包含空的请求头+okhttp/4.7.2
测试命令如下:
curl -v POST -H "authorization: " -H “user-agent:okhttp/4.7.2” -F ‘data=@minio-helm.tar.gz’ http://10.228.38.83:12356/file-upload/upload?key=TESTUSER
测试结果,会反馈413,如下:

如上根据模拟租户侧相同的请求,能复现出当时的故障,而创建envoyfilter后就返回413,并没有崩溃。
2、问题总结

OkHttp使用8KB(8192字节)的缓冲区,当数据块0<size<8192时使用特殊处理进行分块,放入缓冲区,1300字节正好落入到这个危险区间,大量文件上传时,envoy没有对request的大小做任何限制 ( 我们当时认为这个request的默认大小是10M,还在模拟期间产生了疑问,为什么超过10M的文件上传,不会触发envoy的413,看了代码才知道根本没做限制 ) ,触发envoy的缓冲过滤器内存错误如越界访问导致的崩溃,而对网关添加了envoyfilter的request的大小限制,相当于给网关加了一个过载的保护,当上传的文件太大,会触发这个保护机制,拒绝大文件上传,网关不会崩溃掉。
envoy的max_request_bytes部分代码如下:
更多推荐


所有评论(0)