k8s 環境下Cannot assign requested address問題解決

tsin發表於2021-12-11

問題

最近生產環境有個介面每過一段時間就會出現報錯,重啟服務又能恢復,經排查,該介面相關的日誌有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

相關文章