亚洲熟女综合色一区二区三区,亚洲精品中文字幕无码蜜桃,亚洲va欧美va日韩va成人网,亚洲av无码国产一区二区三区,亚洲精品无码久久久久久久

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

最近排查了一個(gè) kubernetes 中使用了 hostport 后遇到比較坑的問題,奇怪的知識(shí)又增加了。

問題背景

集群環(huán)境為 K8s v1.15.9,cni 指定了 flannel-vxlan 跟 portmap, kube-proxy 使用 mode 為 ipvs,集群 3 臺(tái) master,同時(shí)也是 node,這里以 node-1,node-2,node-3 來表示。
集群中有 2 個(gè) mysql, 部署在兩個(gè) ns 下,mysql 本身不是問題重點(diǎn),這里就不細(xì)說,這里以 mysql-A,mysql-B 來表示。
mysql-A 落在 node-1 上,mysql-B 落在 node-2 上, 兩個(gè)數(shù)據(jù)庫 svc 名跟用戶、密碼完全不相同
出現(xiàn)詭異的現(xiàn)象這里以一張圖來說明會(huì)比較清楚一些:
記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南
其中綠線的表示訪問沒有問題,紅線表示連接 Mysql-A 提示用戶名密碼錯(cuò)誤
特別詭異的是,當(dāng)在 Node-2 上通過 svc 訪問 Mysql-A 時(shí),輸入 Mysql-A 的用戶名跟密碼提示密碼錯(cuò)誤,密碼確認(rèn)無疑,但當(dāng)輸入 Mysql-B 的用戶名跟密碼,居然能夠連接上,看了下數(shù)據(jù),連上的是 Mysql-B 的數(shù)據(jù)庫,給人的感覺就是請(qǐng)求轉(zhuǎn)到了 Mysql-A, 最后又轉(zhuǎn)到了 Mysql-B,當(dāng)時(shí)讓人大跌眼鏡
碰到詭異的問題那就排查吧,排查的過程倒是不費(fèi)什么事,最主要的是要通過這次踩坑機(jī)會(huì)挖掘一些奇怪的知識(shí)出來。

排查過程

既然在 Node-1 上連接 Mysql-A/Mysql-B 都沒有問題,那基本可以排查是 Mysql-A 的問題
經(jīng)實(shí)驗(yàn),在 Node-2 上所有的服務(wù)想要連 Mysql-A 時(shí),都有這個(gè)問題,但是訪問其它的服務(wù)又都沒有問題,說明要么是 mysql-A 的 3306 這個(gè)端口有問題,通過上一步應(yīng)該排查了 mysql-A 的問題,那問題只能出在 Node-2 上
k8s 中像這樣的請(qǐng)求轉(zhuǎn)發(fā)出現(xiàn)詭異現(xiàn)象,當(dāng)排除了一些常見的原因之外,最大的嫌疑就是 iptables 了,作者遇到過多次
這次也不例外,雖然當(dāng)前集群使用的 ipvs, 但還是照例看下 iptables 規(guī)則,查看 Node-2 上的 iptables 與 Node-1 的 iptables 比對(duì),結(jié)果有蹊蹺, 在 Node-2 上發(fā)現(xiàn)有以下的規(guī)則在其它節(jié)點(diǎn)上沒有
記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南
其中 10.224.0.222 為 Mysql-B 的 pod ip, xxxxxxxxxxxxx 經(jīng)查實(shí)為 Mysql-B 對(duì)應(yīng)的 pause 容器的 id
從上面的規(guī)則總結(jié)一下就是目的為 3306 端口的請(qǐng)求都會(huì)轉(zhuǎn)發(fā)到 10.224.0.222 這個(gè)地址,即 Mysql-B
看到這里,作者明白了為什么在 Node-2 上去訪問 Node-1 上 Mysql-A 的 3306 會(huì)提示密碼錯(cuò)誤而輸入 Mysql-B 的密碼卻可以正常訪問
雖然兩個(gè) mysql 的 svc 名不一樣,但上面的 iptables 只要目的端口是 3306 就轉(zhuǎn)發(fā)到 Mysql-B 了,當(dāng)請(qǐng)求到達(dá) mysql 后,使用正確的用戶名密碼自然可以登錄成功
原因是找到了,但是又引出來了更多的問題?
  1. 這幾條規(guī)則是誰入到 iptables 中的?
  2. 怎么解決呢,是不是刪掉就可以?

問題復(fù)現(xiàn)

同樣是 Mysql,為何 Mysql-A 沒有呢? 那么比對(duì)一下這兩個(gè) Mysql 的部署差異

比對(duì)發(fā)現(xiàn), 除了用戶名密碼,ns 不一樣外,Mysql-B 部署時(shí)使用了 hostPort=3306, 其它的并無異常

難道是因?yàn)?hostPort?

作者日常會(huì)使用 NodePort,倒卻是沒怎么在意 hostPort,也就停留在 hostPort 跟 NodePort 的差別在于 NodePort 是所有 Node 上都會(huì)開啟端口,而 hostPort 只會(huì)在運(yùn)行機(jī)器上開啟端口,由于 hostPort 使用的也少,也就沒太多關(guān)注,網(wǎng)上短暫搜了一番,描述的也不是很多,看起來大家也用的不多

那到底是不是因?yàn)?hostPort 呢?

Talk is cheap, show me the code

通過實(shí)驗(yàn)來驗(yàn)證,這里簡(jiǎn)單使用了三個(gè) nginx 來說明問題, 其中兩個(gè)使用了 hostPort,這里特意指定了不同的端口,其它的都完全一樣,發(fā)布到集群中,yaml 文件如下

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

Finally,問題復(fù)現(xiàn):

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

可以肯定,這些規(guī)則就是因?yàn)槭褂昧?hostPort 而寫入的,但是由誰寫入的這個(gè)問題還是沒有解決?

罪魁禍?zhǔn)?/span>

作者開始以為這些 iptables 規(guī)則是由 kube-proxy 寫入的, 但是查看 kubelet 的源碼并未發(fā)現(xiàn)上述規(guī)則的關(guān)鍵字

再次實(shí)驗(yàn)及結(jié)合網(wǎng)上的探索,可以得到以下結(jié)論:

首先從 kubernetes 的官方發(fā)現(xiàn)以下描述:

The CNI networking plugin supports hostPort. You can use the official portmap[1] plugin offered by the CNI plugin team or use your own plugin with portMapping functionality.

If you want to enable hostPort support, you must specify portMappings capability in your cni-conf-dir. For example:

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

也就是如果使用了 hostPort, 是由 portmap 這個(gè) cni 提供 portMapping 能力,同時(shí),如果想使用這個(gè)能力,在配置文件中一定需要開啟 portmap,這個(gè)在作者的集群中也開啟了,這點(diǎn)對(duì)應(yīng)上了

另外一個(gè)比較重要的結(jié)論是:

The CNI ‘portmap’ plugin, used to setup HostPorts for CNI, inserts rules at the front of the iptables nat chains; which take precedence over the KUBE- SERVICES chain. Because of this, the HostPort/portmap rule could match incoming traffic even if there were better fitting, more specific service definition rules like NodePorts later in the chain

參考:?https://ubuntu.com/security/CVE-2019-9946

翻譯過來就是使用 hostPort 后,會(huì)在 iptables 的 nat 鏈中插入相應(yīng)的規(guī)則,而且這些規(guī)則是在 KUBE- SERVICES 規(guī)則之前插入的,也就是說會(huì)優(yōu)先匹配 hostPort 的規(guī)則,我們常用的 NodePort 規(guī)則其實(shí)是在 KUBE- SERVICES 之中,也排在其后

從 portmap 的源碼中果然是可以看到相應(yīng)的代碼

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

所以,最終是調(diào)用 portmap 寫入的這些規(guī)則。

端口占用

進(jìn)一步實(shí)驗(yàn)發(fā)現(xiàn),hostport 可以通過 iptables 命令查看到, 但是無法在 ipvsadm 中查看到

使用 lsof/netstat 也查看不到這個(gè)端口,這是因?yàn)?hostport 是通過 iptables 對(duì)請(qǐng)求中的目的端口進(jìn)行轉(zhuǎn)發(fā)的,并不是在主機(jī)上通過端口監(jiān)聽

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

既然 lsof 跟 netstat 都查不到端口信息,那這個(gè)端口相當(dāng)于沒有處于 listen 狀態(tài)?

如果這時(shí)再部署一個(gè) hostport 提定相同端口的應(yīng)用會(huì)怎么樣呢?

結(jié)論是: 使用 hostPort 的應(yīng)用在調(diào)度時(shí)無法調(diào)度在已經(jīng)使用過相同 hostPort 的主機(jī)上,也就是說,在調(diào)度時(shí)會(huì)考慮 hostport

如果強(qiáng)行讓其調(diào)度在同一臺(tái)機(jī)器上,那么就會(huì)出現(xiàn)以下錯(cuò)誤,如果不刪除的話,這樣的錯(cuò)誤會(huì)越來越多,嚇的作者趕緊刪了.

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

如果這個(gè)時(shí)候創(chuàng)建一個(gè) nodePort 類型的 svc, 端口也為 31123,結(jié)果會(huì)怎么樣呢?

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

可以發(fā)現(xiàn),NodePort 是可以成功創(chuàng)建的,同時(shí)監(jiān)聽的端口也出現(xiàn)了.

從這也可以說明使用 hostposrt 指定的端口并沒有 listen 主機(jī)的端口,要不然這里就會(huì)提示端口重復(fù)之類

那么問題又來了,同一臺(tái)機(jī)器上同時(shí)存在有 hostPort 跟 nodePort 的端口,這個(gè)時(shí)候如果 curl 31123 時(shí), 訪問的是哪一個(gè)呢?

經(jīng)多次使用 curl 請(qǐng)求后,均是使用了 hostport 那個(gè) nginx pod 收到請(qǐng)求

原因還是因?yàn)?KUBE-NODE-PORT 規(guī)則在 KUBE-SERVICE 的鏈中是處于最后位置,而 hostPort 通過 portmap 寫入的規(guī)則排在其之前

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

因此會(huì)先匹配到 hostport 的規(guī)則,自然請(qǐng)求就被轉(zhuǎn)到 hostport 所在的 pod 中,這兩者的順序是沒辦法改變的,因此無論是 hostport 的應(yīng)用發(fā)布在前還是在后都無法影響請(qǐng)求轉(zhuǎn)發(fā)

另外再提一下,hostport 的規(guī)則在 ipvsadm 中是查詢不到的,而 nodePort 的規(guī)則則是可以使用 ipvsadm 查詢得到

問題解決

要想把這些規(guī)則刪除,可以直接將 hostport 去掉,那么規(guī)則就會(huì)隨著刪除,比如下圖中去掉了一個(gè) nginx 的 hostport

記一次 K8S HostPort 引發(fā)的服務(wù)故障排錯(cuò)指南

另外使用較多的 port-forward 也是可以進(jìn)行端口轉(zhuǎn)發(fā)的,它又是個(gè)什么情況呢? 它其實(shí)使用的是 socat 及 netenter 工具,網(wǎng)上看到一篇文章,原理寫的挺好的,感興趣的可以看一看

參考:?https://vflong.github.io/sre/k8s/2020/03/15/how-the-kubectl-port-forward-command-works.html

生產(chǎn)建議

一句話,生產(chǎn)環(huán)境除非是必要且無他法,不然一定不要使用 hostport,除了會(huì)影響調(diào)度結(jié)果之外,還會(huì)出現(xiàn)上述問題,可能造成的后果是非常嚴(yán)重的

來源:https://izsk.me/2021/08/01/Kubernetes-hostport/

文章轉(zhuǎn)載:高效運(yùn)維
(版權(quán)歸原作者所有,侵刪)

相關(guān)新聞

歷經(jīng)多年發(fā)展,已成為國(guó)內(nèi)好評(píng)如潮的Linux云計(jì)算運(yùn)維、SRE、Devops、網(wǎng)絡(luò)安全、云原生、Go、Python開發(fā)專業(yè)人才培訓(xùn)機(jī)構(gòu)!