k8s環境,假設呼叫鏈路是A呼叫B。
- A呼叫B報超時錯誤
- 服務B介面監控發現延遲正常(就好像A並沒有呼叫B一樣)
- B是
php
服務,階段性出現php_network_getaddresses: getaddrinfo failed
報錯
DNS問題?
先從這個報錯查起php_network_getaddresses: getaddrinfo failed
搜尋這個錯誤,谷歌、百度會告訴你dns
解析的問題,解析失敗會報這個錯。
但實際上,我們不論在pod
裡面還是在node
機器上ping
對應訪問的域名,都是可以成功解析的。
排查陷入尷尬的境地,感覺是網路問題,為什麼呢?
- 上游請求下游,大量超時,但是下游卻響應正常,感覺因為網路有問題,請求沒有到達下游,或者下游返回的時候上游沒有收到。
getaddrinfo failed
表示有時候dns
解析有問題,但是能排除dns
本身的問題,可能還是網路的問題,但是請求或者響應有問題。
網路問題?
網路問題可能是哪些問題呢?
頻寬滿了?
不是,檢查過
node
的頻寬,雖然頻寬佔用挺高的,但是遠沒有達到上限
LB
超載了?不是,雖然問題期間連結數上升了不少,但是還是沒有到達上限。目前主要問題是請求超時,因為請求不能快速結束,所以需要更多的連結,連結數上升也說得通。
機器問題?
CPU、記憶體、負載高了?
不是,指標正常
看看
node
主機有沒有報錯?demsg
,看到有如下報錯:dropping packet
不就是丟包的意思麼?
現在定位的問題是conntrack table
滿了,導致丟包。那conntrack
是什麼呢?
conntrack
即連線跟蹤,大概意思是Linux為每一個經過網路堆疊的資料包,生成一個新的連線記錄項 (Connection entry)。此後,所有屬於此連線的資料包都被唯一地分配給這個連線,並標識連線的狀態。
檢視conntrack
的上限和當前值,上線是52.4w,當前已經是52.2w
,已經接近上限了。
執行命令sysctl -w net.netfilter.nf_conntrack_max=2310720
,提高上限,此時問題收斂。
問題覆盤期間,運維同學提到net.netfilter.nf_conntrack_max
這個值在去年的時候已經調整到231w
了,為啥現在又變回來了?
考慮到k8s
的kube_proxy
元件和conntrack
有絕對關係,然後谷歌了下,看到kube-proxy
有幾個相關的引數。
看了下我們kube-proxy
的啟動命令/usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf --hostname-override=cn-beijing-xxx
,配置檔案是空的,也就是都是使用這些引數的預設值,--conntrack-max-per-core
代表每個cpu核跟蹤的最大NAT數量,預設值是32768
。我們是16核
的機器,16*32768=524288,524288
和系統中的net.netfilter.nf_conntrack_max
值是一致的。
net.netfilter.nf_conntrack_max為啥變化了呢
運維同學很確定這個引數值在去年就修改過,這個事情我也有印象。繼續谷歌,看到了這邊文章《kube-proxy conntracker設定》,大概意思是,kube-proxy
的啟動引數中如果沒有設定–conntrack-max引數,則對比–conntrack-min
和–conntrack-max-per-core的值與cpu
核數的大小取其大者返回max
值,預設值是32768 * CPU
核數,最後呼叫SetMax設定conntrack-max的值。
所以是kube-proxy
重啟的時候修改了系統的net.netfilter.nf_conntrack_max
值。這是一個坑,不踩真的不知道。
再回想,昨天運維確實升級重啟過kube-proxy
….
上游請求下游,上游超時,下游響應正常,大機率是網路的問題。
網路的問題,是
node
主機conntrack達到上限,導致丟包,丟包導致微服務請求超時。net.netfilter.nf_conntrack_max
這個引數在kube-proxy啟動的時候會重新設定,所以要設定好kube-proxy啟動引數。再看到
php_network_getaddresses: getaddrinfo failed
報錯,排除dns
本省的問題,很可能就是網路丟包導致的阿里雲已經有相關監控和告警了
# 現象
k8s環境,假設呼叫鏈路是A呼叫B。
- A呼叫B報超時錯誤
- 服務B介面監控發現延遲正常(就好像A並沒有呼叫B一樣)
- B是
php
服務,階段性出現php_network_getaddresses: getaddrinfo failed
報錯
DNS問題?
先從這個報錯查起php_network_getaddresses: getaddrinfo failed
搜尋這個錯誤,谷歌、百度會告訴你dns
解析的問題,解析失敗會報這個錯。
但實際上,我們不論在pod
裡面還是在node
機器上ping
對應訪問的域名,都是可以成功解析的。
排查陷入尷尬的境地,感覺是網路問題,為什麼呢?
- 上游請求下游,大量超時,但是下游卻響應正常,感覺因為網路有問題,請求沒有到達下游,或者下游返回的時候上游沒有收到。
getaddrinfo failed
表示有時候dns
解析有問題,但是能排除dns
本身的問題,可能還是網路的問題,但是請求或者響應有問題。
網路問題?
網路問題可能是哪些問題呢?
頻寬滿了?
不是,檢查過
node
的頻寬,雖然頻寬佔用挺高的,但是遠沒有達到上限
LB
超載了?不是,雖然問題期間連結數上升了不少,但是還是沒有到達上限。目前主要問題是請求超時,因為請求不能快速結束,所以需要更多的連結,連結數上升也說得通。
機器問題?
CPU、記憶體、負載高了?
不是,指標正常
看看
node
主機有沒有報錯?demsg
,看到有如下報錯:dropping packet
不就是丟包的意思麼?
現在定位的問題是conntrack table
滿了,導致丟包。那conntrack
是什麼呢?
conntrack
即連線跟蹤,大概意思是Linux為每一個經過網路堆疊的資料包,生成一個新的連線記錄項 (Connection entry)。此後,所有屬於此連線的資料包都被唯一地分配給這個連線,並標識連線的狀態。
檢視conntrack
的上限和當前值,上線是52.4w,當前已經是52.2w
,已經接近上限了。
執行命令sysctl -w net.netfilter.nf_conntrack_max=2310720
,提高上限,此時問題收斂。
問題覆盤期間,運維同學提到net.netfilter.nf_conntrack_max
這個值在去年的時候已經調整到231w
了,為啥現在又變回來了?
考慮到k8s
的kube_proxy
元件和conntrack
有絕對關係,然後谷歌了下,看到kube-proxy
有幾個相關的引數。
看了下我們kube-proxy
的啟動命令/usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf --hostname-override=cn-beijing-xxx
,配置檔案是空的,也就是都是使用這些引數的預設值,--conntrack-max-per-core
代表每個cpu核跟蹤的最大NAT數量,預設值是32768
。我們是16核
的機器,16*32768=524288,524288
和系統中的net.netfilter.nf_conntrack_max
值是一致的。
net.netfilter.nf_conntrack_max為啥變化了呢
運維同學很確定這個引數值在去年就修改過,這個事情我也有印象。繼續谷歌,看到了這邊文章《kube-proxy conntracker設定》,大概意思是,kube-proxy
的啟動引數中如果沒有設定–conntrack-max引數,則對比–conntrack-min
和–conntrack-max-per-core的值與cpu
核數的大小取其大者返回max
值,預設值是32768 * CPU
核數,最後呼叫SetMax設定conntrack-max的值。
所以是kube-proxy
重啟的時候修改了系統的net.netfilter.nf_conntrack_max
值。這是一個坑,不踩真的不知道。
再回想,昨天運維確實升級重啟過kube-proxy
….
上游請求下游,上游超時,下游響應正常,大機率是網路的問題。
網路的問題,是
node
主機conntrack達到上限,導致丟包,丟包導致微服務請求超時。net.netfilter.nf_conntrack_max
這個引數在kube-proxy啟動的時候會重新設定,所以要設定好kube-proxy啟動引數。再看到
php_network_getaddresses: getaddrinfo failed
報錯,排除dns
本省的問題,很可能就是網路丟包導致的阿里雲已經有相關監控和告警了
本作品採用《CC 協議》,轉載必須註明作者和本文連結