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 协议》,转载必须注明作者和本文链接
Was mich nicht umbringt, macht mich stärker
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!