k8s 环境下Cannot assign requested address问题解决
问题
最近生产环境有个接口每过一段时间就会出现报错,重启服务又能恢复,经排查,该接口相关的日志有Cannot assign requested address的错误
原因
“Cannot assign requested address”是由于linux分配的客户端连接端口用尽,无法建立socket连接所致,虽然socket正常关闭,但是端口不是立即释放,而是处于TIME_WAIT状态,默认等待60s后才释放。 生产环境中,该接口会调用另一个服务的接口,由于请求过于频繁,连接又不能很快释放,且默认的可用端口不够用,导致连接数满载,再也发不出请求。
解决方法
需要对Linux系统的以下参数进行优化:
// 表示开启重用。允许将 TIME-WAIT sockets 重新用于新的 TCP 连接,默认为 0,表示关闭
net.ipv4.tcp_tw_reuse=1
//修改系默认的 TIMEOUT 时间,默认为60s
net.ipv4.tcp_fin_timeout=15
// 表示用于向外连接的端口范围。设置为 1024 到 65535
net.ipv4.ip_local_port_range=1024 65535
由于是使用容器,所以把以上设置添加到Dockerfile脚本中,而且是添加到启动命令中,因为以上设置涉及到Linux系统的参数,需要在容器启动后才能进行设置。
// 示例,在dockerfile中,CMD命令做如下修改:
// 最后一段命令是原来容器启动需要的,前面的是修改Linux系统参数
CMD ["bash","-c","sysctl -w net.ipv4.tcp_tw_reuse=1 && sysctl -w net.ipv4.tcp_fin_timeout=10 && sysctl -w net.ipv4.ip_local_port_range='1024 65535' && sysctl -p && ./xxxx -c /path/to/cfg.yml"]
修改后,部署到测试环境,发现容器启动的时候报错,提示找不到相应的配置文件。这到底是是什么原因呢?经过一番追查,了解到,容器是可以修改这些参数的,但要给容器权限。于是在k8s的deployment文件中添加:
containers:
- name: container-app
image: 'xxxxx'
# 新添加的参数,给予容器启动时修改系统参数的权限
securityContext:
capabilities: {}
privileged: true
注意是在containers[]相应的容器下添加。 修改后重新部署应用,问题解决。
参考
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: