線上 K8s Ingress 訪問(wèn)故障排查思路
原文鏈接:https://corvo.myseu.cn/archives/
此次排查發(fā)生在 2021-02 月份.
具體現(xiàn)象
應(yīng)用遷移至我們的PaaS平臺(tái)后會(huì)出現(xiàn)偶發(fā)性的502問(wèn)題, 錯(cuò)誤見(jiàn)圖片:

相比于程序的請(qǐng)求量, 錯(cuò)誤肯定是比較少的, 但是錯(cuò)誤一直在發(fā)生, 會(huì)影響調(diào)用方的代碼, 需要檢查下問(wèn)題原因.
為啥我們只看到了POST請(qǐng)求
讀者肯定會(huì)說(shuō), 你們elk過(guò)濾字段里面寫(xiě)的是POST, 所以肯定只有POST請(qǐng)求, hah. 其實(shí)不是這樣的, GET請(qǐng)求也會(huì)有502, 只是Nginx會(huì)對(duì)GET請(qǐng)求進(jìn)行重試, 產(chǎn)生類似如下的日志:

重試機(jī)制是Nginx默認(rèn)的: proxy_next_upstream
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream
因?yàn)镚ET方法會(huì)被認(rèn)為是冪等的, 所以當(dāng)一個(gè)upstream出現(xiàn)502的時(shí)候, nginx會(huì)再次嘗試. 對(duì)于我們的問(wèn)題, 主要想確認(rèn)為什么有502, 只看POST請(qǐng)求就足夠了, 兩者的原因應(yīng)該是一致的.
網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)
網(wǎng)絡(luò)請(qǐng)求流入集群時(shí), 對(duì)于我們集群的結(jié)構(gòu):
1 | 用戶請(qǐng)求=>Nginx=>Ingress =>uwsgi |
不要問(wèn)為什么有了 Ingress 還有 Nginx. 這是歷史原因, 有些工作暫時(shí)需要由 Nginx 承擔(dān).
統(tǒng)計(jì)排查
基于我們對(duì)于Nginx和Ingress的錯(cuò)誤請(qǐng)求統(tǒng)計(jì), 發(fā)現(xiàn)兩者中的502錯(cuò)誤是想等的, 說(shuō)明問(wèn)題一定是出現(xiàn)在Ingress<=>uwsgi之中.
抓包
這個(gè)并不是最先想到的方案, 因?yàn)槲覀冇昧撕芏嘟y(tǒng)計(jì)方法也沒(méi)總結(jié)出來(lái)規(guī)律, 最后只能寄希望于抓包了…
該請(qǐng)求日志如下:

抓包結(jié)果如下:

從抓包情況來(lái)看, 當(dāng)前的tcp連接被復(fù)用了, 由于Ingress中使用了HTTP1.1協(xié)議, 會(huì)在一次tcp連接中嘗試發(fā)送第二個(gè)HTTP請(qǐng)求, 但是uwsgi沒(méi)有支持http1.1, 所以在第二個(gè)請(qǐng)求根本不會(huì)被處理, 直接拒絕了. 所以在Ingress看來(lái), 這個(gè)請(qǐng)求失敗了, 因此返回了502. 由于GET請(qǐng)求會(huì)重試, 但POST請(qǐng)求無(wú)法重試, 所以訪問(wèn)統(tǒng)計(jì)中出現(xiàn)了POST請(qǐng)求502的問(wèn)題.
Ingress配置學(xué)習(xí)
Ingress中, 默認(rèn)對(duì)upstream使用的http版本為1.1, 但是我們的uwsgi使用的是http-socket, 而非http11-socket, 我們Ingress中使用了與后端不同的協(xié)議, 出現(xiàn)了意料之外的502錯(cuò)誤.

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#proxy-http-version
因?yàn)镹ginx默認(rèn)是1.0, 但是切換到Ingress中默認(rèn)變成了1.1, 而我們沒(méi)有統(tǒng)一, 解決方案是強(qiáng)制指定Ingress中使用的http協(xié)議版本.
{% if keepalive_enable is sameas true %}nginx.ingress.kubernetes.io/proxy-http-version: "1.1"{% else %}nginx.ingress.kubernetes.io/proxy-http-version: "1.0"{% endif %}
如果有大佬看到了, 可以簡(jiǎn)單講講Ingress會(huì)在什么時(shí)候復(fù)用http1.1的連接, 以及為什么Ingress不復(fù)用每一個(gè)連接, 這樣問(wèn)題會(huì)盡快的暴露, 這些問(wèn)題我沒(méi)有繼續(xù)深究了. 畢竟你換個(gè)語(yǔ)言比如Golang就沒(méi)有這個(gè)問(wèn)題了, 這個(gè)是uwsgi專屬錯(cuò)誤.
總結(jié)
有關(guān)這個(gè)502問(wèn)題的排查, 我個(gè)人覺(jué)得, 最后抓包一次性解決問(wèn)題其實(shí)沒(méi)什么特別的, 抓了就能發(fā)現(xiàn)問(wèn)題, 不抓就發(fā)現(xiàn)不了.
我是希望給大家一個(gè)啟發(fā), 對(duì)于一整條鏈路, 如何來(lái)排查故障: 我們這里既使用了Nginx, 又使用了Ingress, 在排查時(shí), 需要首先檢查兩者的錯(cuò)誤數(shù)量, 如果確認(rèn)錯(cuò)誤基本一致, 那就說(shuō)明錯(cuò)誤與Nginx沒(méi)有關(guān)系, 需要檢查Ingres上的錯(cuò)誤, 對(duì)于多個(gè)中轉(zhuǎn)的請(qǐng)求, 這樣的排查能比較快的確定鏈路的錯(cuò)誤位置.
- END -
?推薦閱讀? 31天拿下K8S含金量最高的CKA+CKS證書(shū)! ?
Kubernetes 生態(tài)架構(gòu)圖 Prometheus Thanos 多集群監(jiān)控 20張最全的DevOps架構(gòu)師技術(shù)棧圖譜 Linux Shell 腳本編程最佳實(shí)踐 我的云服務(wù)器被植入挖礦木馬,CPU飆升200% 做了這么多年運(yùn)維工作,現(xiàn)在才看清職業(yè)方向 一篇文章講清楚云原生圖景及發(fā)展路線 K8s kubectl 常用命令總結(jié)(建議收藏) 一名運(yùn)維小哥對(duì)運(yùn)維規(guī)則的10個(gè)總結(jié) K8s運(yùn)維錦囊,19個(gè)常見(jiàn)故障解決方法 編寫(xiě) Dockerfile 最佳實(shí)踐 搭建一套完整的企業(yè)級(jí) K8s 集群(kubeadm方式)
點(diǎn)亮,服務(wù)器三年不宕機(jī)


