Kubernetes網(wǎng)絡(luò)機(jī)制深入淺出-Linux網(wǎng)絡(luò)基礎(chǔ)

筆者在前邊系列文章中反復(fù)強(qiáng)調(diào)過(guò)Kubernetes是云計(jì)算時(shí)代應(yīng)用程序部署的操作系統(tǒng)范删,這個(gè)特殊的操作系統(tǒng)運(yùn)行在一組節(jié)點(diǎn)之上镊绪,這些計(jì)算節(jié)點(diǎn)上通常安裝了Linux或者Windows操作系統(tǒng)垃环,因此如果我們要理解Kubernetes的網(wǎng)絡(luò)實(shí)現(xiàn)細(xì)節(jié)扁掸,理解Linux操作系統(tǒng)的網(wǎng)絡(luò)實(shí)現(xiàn)原理是基礎(chǔ)柏腻,然后在這個(gè)基礎(chǔ)之上杀饵,我們?cè)賮?lái)討論Kubernetes對(duì)操作系統(tǒng)的網(wǎng)絡(luò)實(shí)現(xiàn)做了哪些抽象。

注:由于在Windows上運(yùn)行容器應(yīng)用仍然屬于小眾場(chǎng)景咙鞍,并且Windows容器技術(shù)處于剛剛成熟階段房官,因此筆者在后續(xù)的文章中聚焦于Linux操作系統(tǒng)上的容器技術(shù)方案。

Kubernetes本質(zhì)上只是一套軟件系統(tǒng)续滋,這套設(shè)計(jì)精良的應(yīng)用程序主要功能就是管理一組Linux或者Windows機(jī)器翰守,因此無(wú)論Kubernetes對(duì)外提供了多么豐富的計(jì)算和網(wǎng)絡(luò)等抽象能力,底層還是需要依賴(lài)于Linux或者Windows上的操作系統(tǒng)功能來(lái)實(shí)現(xiàn)疲酌,特別是網(wǎng)絡(luò)部分蜡峰。筆者在實(shí)際的項(xiàng)目中經(jīng)常遇到同學(xué)在講給客戶(hù)設(shè)計(jì)了網(wǎng)絡(luò)方案,或者網(wǎng)絡(luò)拓?fù)浞桨咐士遥强戳藢?shí)際方案后湿颅,很多時(shí)候是一個(gè)部署方案,里邊呈現(xiàn)的是SLB僻肖,網(wǎng)關(guān)肖爵,WAF,防火墻以及EIP臀脏,NAT這樣的云原生技術(shù)組件劝堪。從方案設(shè)計(jì)角度把這些組件按照邏輯關(guān)系組織在一起有沒(méi)有啥問(wèn)題,但是筆者認(rèn)為叫網(wǎng)絡(luò)方案不合適揉稚。

在Kubernetes平臺(tái)上秒啦,網(wǎng)絡(luò)是對(duì)底層工作節(jié)點(diǎn)上的網(wǎng)絡(luò)能力的抽象,集群層級(jí)的網(wǎng)絡(luò)應(yīng)該是跨越了多個(gè)機(jī)器節(jié)點(diǎn)而形成的overlay網(wǎng)絡(luò)搀玖。在這個(gè)網(wǎng)絡(luò)上余境,應(yīng)用程序?qū)嵗≒OD,當(dāng)然一個(gè)POD中可以部署多個(gè)應(yīng)用程序容器實(shí)例)之間可以不經(jīng)過(guò)NAT直接進(jìn)行通信。因此如何解決這層虛擬的overlay網(wǎng)絡(luò)在底層的underlay網(wǎng)絡(luò)上的互訪芳来,IP地址分配等是Kubernetes網(wǎng)絡(luò)方案要解決的核心問(wèn)題含末。

計(jì)算機(jī)網(wǎng)絡(luò)本身就很復(fù)雜,由于涉及到大量的協(xié)議即舌,規(guī)范佣盒,分層等,很容易就陷入到各種協(xié)議理論層面的說(shuō)明顽聂,這樣的信息已經(jīng)汗牛充棟肥惭,也沒(méi)有必要再?gòu)?fù)制粘貼。為了讓我們的討論稍微有點(diǎn)生機(jī)(筆者在很多項(xiàng)目給C級(jí)別做匯報(bào)的時(shí)候紊搪,遵循的一個(gè)基本原則就是給客戶(hù)除了展現(xiàn)靜態(tài)層面的系統(tǒng)架構(gòu)之外蜜葱,會(huì)通過(guò)一個(gè)真實(shí)的請(qǐng)求如何在系統(tǒng)中被處理來(lái)展示動(dòng)態(tài)的一面),我們后續(xù)的討論會(huì)使用如下用Golang編寫(xiě)的極簡(jiǎn)Web服務(wù)耀石,以期通過(guò)這個(gè)服務(wù)如何處理curl發(fā)出的請(qǐng)求牵囤,來(lái)庖丁解牛式的分析請(qǐng)求從應(yīng)用層,到傳輸層娶牌,到網(wǎng)絡(luò)層奔浅,數(shù)據(jù)鏈路層的處理細(xì)節(jié)。

package main

import (

? ? ? ? "fmt"

? ? ? ? "net/http"

)

func hello(w http.ResponseWriter, _ *http.Request) {

? ? fmt.Fprintf(w, "qiwangyue")

}

func main() {

? ? http.HandleFunc("/", hello)

? ? http.ListenAndServe("0.0.0.0:8080", nil)

}

注:在Linux操作系統(tǒng)上诗良,端口號(hào)1-1023屬于特權(quán)端口,需要root權(quán)限才能bind鲁驶。咱們編寫(xiě)的應(yīng)用程序應(yīng)該避免使用低于1024的端口號(hào)鉴裹,而應(yīng)該選擇1024-65535之間的值。咱們這個(gè)極簡(jiǎn)Web服務(wù)使用的就是大家熟知的8080钥弯,如果這個(gè)服務(wù)被部署在Kubernetes集群中径荔,可以選擇Service或者外部負(fù)載均衡重定向的能力,來(lái)把從80端口上收到的客戶(hù)端請(qǐng)求脆霎,重定向到這個(gè)POD上的8080端口服務(wù)总处。

接下來(lái),假設(shè)這個(gè)Golang的Web服務(wù)運(yùn)行在Linux服務(wù)器上睛蛛,外部用戶(hù)可以直接通過(guò)路徑/來(lái)訪問(wèn)這個(gè)服務(wù)鹦马,那么當(dāng)服務(wù)啟動(dòng)的時(shí)候,在操作系統(tǒng)上具體發(fā)生了什么忆肾?或者說(shuō)服務(wù)啟動(dòng)的時(shí)候荸频,從網(wǎng)絡(luò)設(shè)備和組件的角度,具體發(fā)生了哪些動(dòng)作客冈?計(jì)算機(jī)專(zhuān)業(yè)的同學(xué)應(yīng)該大概知道當(dāng)我們啟動(dòng)這個(gè)編譯好的二進(jìn)制文件時(shí)旭从,應(yīng)用程序會(huì)監(jiān)聽(tīng)某個(gè)網(wǎng)絡(luò)地址(Linux服務(wù)器的IP地址)和端口號(hào)(8080)。具體來(lái)說(shuō)應(yīng)用程序會(huì)基于IP地址和端口號(hào)創(chuàng)建socket結(jié)構(gòu),并且和機(jī)器上的IP地址和端口號(hào)綁定(bind)和悦,這樣就完成了服務(wù)的啟動(dòng)工作退疫。

很多同學(xué)可能不理解為啥分為創(chuàng)建socket和bind這兩個(gè)步驟,咱們后續(xù)的內(nèi)容會(huì)詳細(xì)說(shuō)明鸽素,這里你可以簡(jiǎn)單的理解為創(chuàng)建這個(gè)叫socket的邏輯對(duì)象褒繁,以及將這個(gè)邏輯對(duì)象和物理設(shè)備進(jìn)行關(guān)聯(lián)這么兩步操作。當(dāng)應(yīng)用程序運(yùn)行起來(lái)之后付鹿,我們的應(yīng)用就可以收到來(lái)自于客戶(hù)端的請(qǐng)求澜汤,具體來(lái)說(shuō)就是目標(biāo)地址是機(jī)器的IP地址和端口號(hào)為8080的請(qǐng)求。

注:咱們的極簡(jiǎn)Web服務(wù)監(jiān)聽(tīng)的IP地址是0.0.0.0這樣的IPv4地址舵匾,在IPv6應(yīng)該寫(xiě)成【::】通配符地址俊抵,這是個(gè)特殊的地址,用來(lái)標(biāo)識(shí)這個(gè)服務(wù)監(jiān)聽(tīng)這臺(tái)機(jī)器上的所有可用的IP地址坐梯。這是一種非常有效的監(jiān)聽(tīng)和bind機(jī)制徽诲,因?yàn)楹芏鄷r(shí)候我們可能在編寫(xiě)應(yīng)用程序的時(shí)候,不知道應(yīng)用程序?qū)⒁\(yùn)行在哪些IP地址上吵血,大部分的網(wǎng)絡(luò)服務(wù)都是以這種方式啟動(dòng)并綁定到宿主機(jī)(容器實(shí)例)的網(wǎng)絡(luò)接口上谎替。

基于上邊的信息,我們知道socket對(duì)象是運(yùn)行中的應(yīng)用程序的入口蹋辅,那么如何能觀察到這個(gè)在服務(wù)啟動(dòng)時(shí)創(chuàng)建的socket對(duì)象呢钱贯?還記得我們?cè)谇斑叾嗥恼轮蟹磸?fù)提到的Linux至理名言:一切皆文件。實(shí)際上咱們可以通過(guò)ls -lah /proc/<server proc/fd來(lái)羅列相關(guān)進(jìn)程(服務(wù))的網(wǎng)絡(luò)套接字socket侦另。在筆者的機(jī)器上輸出如下:

# ps -aux

USER? ? ? PID %CPU %MEM? ? VSZ? RSS TTY? ? ? STAT START? TIME COMMAND

root? ? ? ? 22? 0.3? 0.9 928116 19960 pts/1? ? Sl+? 10:11? 0:00 go run web-server.go

root? ? ? ? 90? 0.0? 0.2 477816? 5760 pts/1? ? Sl+? 10:11? 0:00 /tmp/go-build957677948/b001/exe/web-server

# ls -lah /proc/90/fd

total 0

dr-x------ 2 root root? 0 Dec 17 10:13 .

dr-xr-xr-x 9 root root? 0 Dec 17 10:11 ..

lrwx------ 1 root root 64 Dec 17 10:13 0 -> /dev/pts/1

lrwx------ 1 root root 64 Dec 17 10:13 1 -> /dev/pts/1

lrwx------ 1 root root 64 Dec 17 10:13 2 -> /dev/pts/1

lrwx------ 1 root root 64 Dec 17 10:13 3 -> 'socket:[26705]'

lrwx------ 1 root root 64 Dec 17 10:13 5 -> 'anon_inode:[eventpoll]'

當(dāng)內(nèi)核從socket上接收到數(shù)據(jù)包packt之后秩命,會(huì)將packet和特定的connection進(jìn)行管理,并且操作系統(tǒng)通過(guò)狀態(tài)機(jī)來(lái)管理connection的狀態(tài)褒傅,大白話說(shuō)就是連接狀態(tài)弃锐。同樣咱們有非常豐富的工具供選擇來(lái)觀察連接以及狀態(tài),后續(xù)文章會(huì)詳細(xì)介紹殿托。在Linux操作系統(tǒng)上霹菊,連接也是通過(guò)文件來(lái)表示,當(dāng)應(yīng)用accept一個(gè)連接請(qǐng)求后支竹,實(shí)質(zhì)上在操作系統(tǒng)的對(duì)應(yīng)目錄創(chuàng)建一個(gè)文件旋廷,后續(xù)的數(shù)據(jù)寫(xiě)入和讀出都是通過(guò)這個(gè)文件來(lái)進(jìn)行。

有了這些基礎(chǔ)之后唾戚,咱們回到極簡(jiǎn)Golang服務(wù)上柳洋,我們可以通過(guò)strace來(lái)觀察服務(wù)的運(yùn)行情況,通過(guò)命令strace ./main來(lái)監(jiān)控咱們的應(yīng)用程序叹坦,由于strace會(huì)捕捉到所有在這臺(tái)機(jī)器上進(jìn)行的系統(tǒng)調(diào)用熊镣,因此輸出的內(nèi)容會(huì)非常豐富。為了能夠捕捉到關(guān)鍵信息,咱們對(duì)輸出結(jié)果進(jìn)行了簡(jiǎn)化绪囱,只保留了和極簡(jiǎn)Golang服務(wù)相關(guān)的內(nèi)容测蹲,如下圖所示:

《圖1.1 strace捕捉的和極簡(jiǎn)Web服務(wù)相關(guān)的系統(tǒng)調(diào)用》

從上圖我們可以看到web服務(wù)在啟動(dòng)的時(shí)候,發(fā)生了如下四個(gè)關(guān)鍵的系統(tǒng)調(diào)用:

- 打開(kāi)一個(gè)文件描述符

- 為IPv6協(xié)議的連接創(chuàng)建socket

- 在socket上禁用IPV6_V6oNLY鬼吵,應(yīng)用可以同時(shí)提供IPV4和V6服務(wù)

- 將socket綁定(bind)到機(jī)器上的所有IP地址的8080端口號(hào)

- 等待連接請(qǐng)求

特別是最后一步扣甲,當(dāng)服務(wù)啟動(dòng)后,我們從輸出的信息中可以看到齿椅,strace卡在epoll_wait上等待訪問(wèn)請(qǐng)求琉挖。

到這里為止,服務(wù)已經(jīng)啟動(dòng)涣脚,并且監(jiān)聽(tīng)在8080端口上等待請(qǐng)求的到來(lái)示辈,請(qǐng)求一般是內(nèi)核通知socket有符合你處理的packt,這個(gè)時(shí)候服務(wù)受到通知遣蚀,從內(nèi)核的緩沖區(qū)讀取到數(shù)據(jù)矾麻,繼續(xù)處理。這個(gè)時(shí)候需要curl給這個(gè)極簡(jiǎn)服務(wù)發(fā)送一個(gè)實(shí)際請(qǐng)求了芭梯。在相同機(jī)器的另外一個(gè)窗口上執(zhí)行curl localhost:8080/命令险耀,如下所示:

# curl http://localhost:8080/

qiwangyue

注:筆者強(qiáng)烈建議大家在開(kāi)發(fā)服務(wù)的使用postman或者postwomen這樣的測(cè)試工具,最好不要使用瀏覽器玖喘,除非你編寫(xiě)的是前端頁(yè)面甩牺。原因是瀏覽器會(huì)發(fā)送很多額外的請(qǐng)求給服務(wù)器,比如獲取favicon文件等累奈,這會(huì)讓我們調(diào)試變得異常的困哪柴灯,增加額外的工作量來(lái)分析結(jié)果。特別是瀏覽器有緩存功能费尽,有時(shí)候我們的請(qǐng)求直接從緩存返回,根本就沒(méi)有到服務(wù)器端羊始,有時(shí)候把開(kāi)發(fā)人員折磨的痛不欲生啊旱幼。因此選擇curl或者telnet這樣的輕量級(jí)工具,簡(jiǎn)潔明了突委,還節(jié)省時(shí)間柏卤,是開(kāi)發(fā)調(diào)試之良具。

當(dāng)服務(wù)端接受并處理請(qǐng)求后匀油,strace的輸出如下:

[{EPOLLIN, {u32=1714573248, u64=1714573248}}], 128, -1) = 1

accept4(3, {sa_family=AF_INET6, sin6_port=htons(54202), inet_pton(AF_INET6,

"::ffff:10.0.0.63", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0},

[112->28], SOCK_CLOEXEC|SOCK_NONBLOCK) = 5

epoll_ctl(4, EPOLL_CTL_ADD, 5, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET,

{u32=1714573120, u64=1714573120}}) = 0

getsockname(5, {sa_family=AF_INET6, sin6_port=htons(8080),

inet_pton(AF_INET6, "::ffff:10.0.0.30", &sin6_addr), sin6_flowinfo=htonl(0),

sin6_scope_id=0}, [112->28]) = 0

setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0

setsockopt(5, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0

setsockopt(5, SOL_TCP, TCP_KEEPINTVL, [180], 4) = 0

setsockopt(5, SOL_TCP, TCP_KEEPIDLE, [180], 4) = 0

accept4(3, 0x2032d70, [112], SOCK_CLOEXEC|SOCK_NONBLOCK) = -1 EAGAIN

(Resource temporarily unavailable)

從strace輸出的數(shù)據(jù)中可以看到缘缚,服務(wù)器會(huì)將響應(yīng)數(shù)據(jù)“qiwangyue”寫(xiě)到response數(shù)據(jù)中,通過(guò)http協(xié)議來(lái)進(jìn)行封裝敌蚜,并最后寫(xiě)到文件描述符fd中桥滨。從Linux操作系統(tǒng)內(nèi)核將這些數(shù)據(jù)轉(zhuǎn)換成packet,然后協(xié)議棧發(fā)現(xiàn)這個(gè)數(shù)據(jù)的目的地址是本機(jī),內(nèi)核通知curl有數(shù)據(jù)可以讀取齐媒,因此curl被喚醒蒲每,從內(nèi)核讀取數(shù)據(jù),將結(jié)果“qiwangyue”在控制臺(tái)打印出來(lái)喻括。

對(duì)上邊數(shù)據(jù)的服務(wù)器處理客戶(hù)端請(qǐng)求的處理過(guò)程按順序進(jìn)行梳理邀杏,描述如下:

- Epoll返回,喚醒咱們的極簡(jiǎn)Web服務(wù)應(yīng)用程序

- 服務(wù)從請(qǐng)求信息中獲取到客戶(hù)端的IP地址是::ffff:10.0.0.63

- 服務(wù)器端會(huì)檢查socket的狀態(tài)以及設(shè)置相關(guān)的參數(shù)

上邊就是一個(gè)極簡(jiǎn)的Golang服務(wù)從客戶(hù)端當(dāng)服務(wù)器端的處理過(guò)程唬血,特別是在操作系統(tǒng)內(nèi)核層級(jí)發(fā)生的各種類(lèi)型的系統(tǒng)調(diào)用望蜡。咱們下篇文章繼續(xù)介紹網(wǎng)絡(luò)接口以及Linux操作系統(tǒng)如何處理數(shù)據(jù)包packet,敬請(qǐng)期待拷恨!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末脖律,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挑随,更是在濱河造成了極大的恐慌状您,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兜挨,死亡現(xiàn)場(chǎng)離奇詭異膏孟,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)拌汇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)柒桑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人噪舀,你說(shuō)我怎么就攤上這事魁淳。” “怎么了与倡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵界逛,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我纺座,道長(zhǎng)息拜,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任净响,我火速辦了婚禮少欺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘馋贤。我一直安慰自己赞别,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布配乓。 她就那樣靜靜地躺著仿滔,像睡著了一般惠毁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上堤撵,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天仁讨,我揣著相機(jī)與錄音,去河邊找鬼实昨。 笑死洞豁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的荒给。 我是一名探鬼主播丈挟,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼志电!你這毒婦竟也來(lái)了曙咽?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤挑辆,失蹤者是張志新(化名)和其女友劉穎例朱,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鱼蝉,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡洒嗤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了魁亦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渔隶。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖洁奈,靈堂內(nèi)的尸體忽然破棺而出间唉,到底是詐尸還是另有隱情,我是刑警寧澤利术,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布呈野,位于F島的核電站,受9級(jí)特大地震影響印叁,放射性物質(zhì)發(fā)生泄漏际跪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一喉钢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧良姆,春花似錦肠虽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)闲延。三九已至,卻和暖如春韩玩,著一層夾襖步出監(jiān)牢的瞬間垒玲,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工找颓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留合愈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓击狮,卻偏偏與公主長(zhǎng)得像佛析,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子彪蓬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容