k8s線上集群的機(jī)器,重啟iptables后,造成CI系統(tǒng)(drone)構(gòu)建偶發(fā)失敗,docker run容器無法訪問外網(wǎng)問題排查記錄

引子:

線上的k8s集群內(nèi)部,每一臺(tái)機(jī)器,都有2塊網(wǎng)卡,一塊兒em1(10網(wǎng)段),一個(gè) em2(192網(wǎng)段)。然后,線上的機(jī)器,通過iptables限制為:訪問192段的服務(wù)任意端口都是暢通的,而訪問10段的服務(wù)端口,只有333端口可以連通。333端口,是線上機(jī)器的ssh端口。

線上集群的k8s,使用的calico網(wǎng)絡(luò)。

線上有一個(gè)問題,就是容器訪問當(dāng)前宿主機(jī)192段IP的999端口不通,訪問其他機(jī)器192段IP的9999端口暢通。

我們知道,當(dāng)從容器訪問宿主機(jī)的應(yīng)用時(shí),會(huì)重新進(jìn)入iptables的INPUT鏈,而線上的iptables INPUT鏈如下:

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1    1477K 2519M cali-INPUT  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* cali:Cz_u1IQiXIMmKD4c */
2     272K   20M KUBE-SERVICES  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
3     273K   20M KUBE-FIREWALL  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
4     263K   20M ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
5        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
6      393 17292 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
7    11880 1019K ACCEPT     all  --  em2    *       0.0.0.0/0            0.0.0.0/0           
8        7   308 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:333
9     228 62052 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

意思是:

①:如果報(bào)文是途徑em2網(wǎng)卡,訪問任意其他網(wǎng)卡。則全部放行。(這就是為什么192段的訪問全部放行)

②:如果報(bào)文是tcp,不管報(bào)文從哪個(gè)網(wǎng)卡出來,去往哪個(gè)網(wǎng)卡,只要目的端口是333,就放行。(這就是為什么10段的訪問,只能訪問333)

我們?nèi)萜靼l(fā)出的報(bào)文,網(wǎng)卡是 cal 網(wǎng)卡(calico的網(wǎng)卡名稱),所以,容器只能訪問333。

錯(cuò)誤操作:

要把9999端口放開,意味著,我要添加開放9999端口到INPUT鏈路中,為了讓iptables再重啟后依然生效,我將規(guī)則,添加到

/etc/sysconfig/iptables

在添加完成后其實(shí)并未生效,然后,有2種方式,用于讓iptables生效:

①:手動(dòng)添加規(guī)則,比如 iptables -t filter -I INPUT 9 -s 172.20.0.0/14 -p tcp -m tcp --dport 9999 -j ACCEPT

②:重啟iptables(會(huì)自動(dòng)加載 /etc/sysconfig/iptables內(nèi)容 )

我選擇了后者,之所以選擇后者,其實(shí)是因?yàn)椋幢阒貑⒘薸ptables,加載了剛剛的規(guī)則,原來的k8s和calico的iptables會(huì)丟失,但是,k8s會(huì)重建自己的整套iptables規(guī)則的。

事實(shí)上,k8s確實(shí)也在我重啟iptables后,重建了iptables,但問題來了。

引發(fā)的2個(gè)網(wǎng)絡(luò)問題:

1、我們線上的CI系統(tǒng),是基于drone,做的二次開發(fā),改動(dòng)了很多的東西,添加了很多特性,結(jié)果上面一系列操作之后,我發(fā)現(xiàn),我們的CI系統(tǒng)中,個(gè)別鏡像的構(gòu)建(Dockerfile中的RUN操作,有網(wǎng)絡(luò)相關(guān)操作時(shí),比如yum)會(huì)失敗。

2、線上的機(jī)器,執(zhí)行 docker run,起來的容器,無法訪問外網(wǎng)了。然而,k8s起來的pod里的容器,卻可以訪問外網(wǎng)。

鏡像的構(gòu)建,其實(shí)本質(zhì)上,也是起容器來做事情,而且,你無法定制docker build操作時(shí),使用的網(wǎng)絡(luò)模式,只能是bridge模式。而 docker run 起來的容器,默認(rèn)也是 bridge 模式。結(jié)合上面2個(gè)內(nèi)容,基本上可以確定,此問題,和k8s無關(guān),而是純粹的docker的問題了。

排查:

①:一開始以為是k8s的iptables重建不完整,所以,多次用線上的機(jī)器的機(jī)器 nodeA(無人訪問的一臺(tái)),不斷嘗試清空iptables,等待k8s重建iptables,多次嘗試無效。

②:stop docker -> stop kubelet -> clean iptables -> start docker -> start kubelet。這個(gè)操作的意義是,以為重啟docker,重啟k8s,docker 和 k8s 都會(huì)重建自己的 iptables。多次嘗試無效。

③:使用現(xiàn)在的k8s安裝工具:kubespray,重新安裝 nodeA,并添加到k8s集群內(nèi)。寄希望于安裝工具重裝docker和k8s,結(jié)果依然無效。

④:回歸問題本身,問題一定出在iptables上。也是因?yàn)橐婚_始重啟了iptables導(dǎo)致此一系列問題。

解決過程:

既然問題出在iptables上,而我們要訪問外網(wǎng),那么,就得重iptables 報(bào)文轉(zhuǎn)出入手。好在線上的機(jī)器,并沒有都為了適配9999端口重啟iptables,有3臺(tái) k8s 的 master 節(jié)點(diǎn),并沒有重啟 iptables。

然后,對(duì)比有問題機(jī)器、沒有問題機(jī)器的 FORWARD、POSTROUTING 的規(guī)則。發(fā)現(xiàn),缺少DOCKER相關(guān)的規(guī)則,這些規(guī)則,本來是安裝docker之后,由docker創(chuàng)建的。那么,解決此問題,就需要重建docker的iptables。

①:找一臺(tái)干凈的機(jī)器(只安裝了docker,未啟動(dòng)容器,為安裝k8s),然后從中提取docker相關(guān)的規(guī)則

②:將提取的規(guī)則,與出問題的機(jī)器的iptables默認(rèn)規(guī)則融合。

③:執(zhí)行 iptables-restore 恢復(fù)規(guī)則。

后續(xù)驗(yàn)證:

在問題機(jī)器上,docker run centos 容器,然后ping qq.com,鏈路暢通。有一個(gè)小問題,就是如果你先啟動(dòng)的容器執(zhí)行 ping 外網(wǎng)操作。然后才再目的機(jī)器上執(zhí)行 iptables-restore 的話,會(huì)發(fā)現(xiàn),容器的 ping,有一個(gè)短暫的耗時(shí),然后才會(huì)暢通,這是因?yàn)?iptables-restore 恢復(fù)規(guī)則后,有一個(gè)過程。

最后:

我整理一個(gè)相對(duì)標(biāo)準(zhǔn)的docker iptables規(guī)則備份,如果你也遇到了啟動(dòng)的docker容器,無法訪問外網(wǎng)的問題,可以通過下面的內(nèi)容,恢復(fù)規(guī)則

將下面的規(guī)則,保存到一個(gè)文件,比如 docker-iptables-backup

# Generated by iptables-save v1.4.21 on Thu Apr 30 20:48:42 2015
*nat
:PREROUTING ACCEPT [18:1080]
:INPUT ACCEPT [18:1080]
:OUTPUT ACCEPT [22:1550]
:POSTROUTING ACCEPT [22:1550]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.1/32 -d 172.17.0.1/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 3001 -j DNAT --to-destination 172.17.0.1:80
COMMIT
# Completed on Thu Apr 30 20:48:42 2015
# Generated by iptables-save v1.4.21 on Thu Apr 30 20:48:42 2015
*filter
:INPUT ACCEPT [495:53218]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [480:89217]
:DOCKER - [0:0]
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.1/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
COMMIT
# Completed on Thu Apr 30 20:48:42 2015

然后,執(zhí)行恢復(fù) iptables-restore docker-iptables-backup

注意:

①:如果你的docker在k8s集群內(nèi)部,理論上來說,上面的操作會(huì)有清空iptables的能力,但是你不需要擔(dān)心,因?yàn)閗8s會(huì)自行修復(fù)本身的iptables,也就是說,k8s會(huì)重建自己的iptables。但是假如你的k8s沒能完整重建,就需要手動(dòng)恢復(fù)k8s的iptables。如果是calico網(wǎng)絡(luò),只需要?jiǎng)h除當(dāng)前節(jié)點(diǎn)的calico pod即可,刪除之后,k8s會(huì)重啟這個(gè)pod,自然也就會(huì)重建iptables了。同理,flannel網(wǎng)絡(luò)也是一樣的。

②:上面的規(guī)則,有一個(gè)關(guān)鍵,是 172.17.0.0 和 172.17.0.1,這是docker默認(rèn)安裝后的網(wǎng)段和docker0網(wǎng)卡的IP。如果你是默認(rèn)安裝的docker,上面的規(guī)則不需要改動(dòng),但如果你定制了docker0網(wǎng)卡的IP,記得修改一下上面的規(guī)則,適配你的環(huán)境。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,444評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,794評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,414評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,750評(píng)論 2 370