<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:K8s Service 背后是怎么工作的?

          共 11076字,需瀏覽 23分鐘

           ·

          2024-05-17 14:13

          原文鏈接:https://www.cnblogs.com/daemon365/p/18181146

          kube-proxy 是 Kubernetes 集群中負(fù)責(zé)服務(wù)發(fā)現(xiàn)和負(fù)載均衡的組件之一。它是一個(gè)網(wǎng)絡(luò)代理,運(yùn)行在每個(gè)節(jié)點(diǎn)上, 用于 service 資源的負(fù)載均衡。它有兩種模式:iptables 和 ipvs

          iptables

          iptables 是 Linux 系統(tǒng)中的一個(gè)用戶空間實(shí)用程序,用于配置內(nèi)核的網(wǎng)絡(luò)包過(guò)濾和網(wǎng)絡(luò)地址轉(zhuǎn)換(NAT)規(guī)則。它是 Linux 內(nèi)核中的 netfilter 框架的一部分,并負(fù)責(zé)在網(wǎng)絡(luò)包進(jìn)入、轉(zhuǎn)發(fā)或離開(kāi)計(jì)算機(jī)時(shí)進(jìn)行篩選和處理。其主要功能和用途包括:

          1. 防火墻:iptables 提供了強(qiáng)大的防火墻功能,可以根據(jù)不同的規(guī)則來(lái)過(guò)濾和拒絕不需要的網(wǎng)絡(luò)包。管理員可以創(chuàng)建自定義的規(guī)則集,允許或拒絕從特定 IP 地址、端口或協(xié)議的數(shù)據(jù)包。

          2. NAT(網(wǎng)絡(luò)地址轉(zhuǎn)換):iptables 支持 NAT 功能,可以用來(lái)將私有網(wǎng)絡(luò)中的計(jì)算機(jī)與外部網(wǎng)絡(luò)連接。例如,它可以在一個(gè) NAT 路由器上將內(nèi)部網(wǎng)絡(luò)的多個(gè)設(shè)備映射到單個(gè)外部 IP 地址。

          3. 端口轉(zhuǎn)發(fā):iptables 可以將特定的端口流量從一個(gè)網(wǎng)絡(luò)接口轉(zhuǎn)發(fā)到另一個(gè)接口或目標(biāo) IP 地址,通常用于內(nèi)部網(wǎng)絡(luò)的服務(wù)公開(kāi)。

          4. 負(fù)載均衡:它也可以通過(guò) DNAT(目標(biāo)網(wǎng)絡(luò)地址轉(zhuǎn)換)功能將流量轉(zhuǎn)發(fā)給多個(gè)內(nèi)部服務(wù)器,實(shí)現(xiàn)簡(jiǎn)單的負(fù)載均衡。

          iptables 是通過(guò)鏈(chains)和表(tables)來(lái)組織規(guī)則的。每個(gè)鏈由一組規(guī)則組成,當(dāng)網(wǎng)絡(luò)數(shù)據(jù)包經(jīng)過(guò)時(shí),這些規(guī)則會(huì)逐一執(zhí)行。常用的表包括:

          • filter 表:用于包過(guò)濾,是最常用的表。

          • nat 表:用于網(wǎng)絡(luò)地址轉(zhuǎn)換。

          • mangle 表:用于修改數(shù)據(jù)包的 IP 層字段。

          • raw 表:用于繞過(guò)連接跟蹤。

          鏈的流向?yàn)椋?/span>

          所以,根據(jù)上圖,我們能夠想象出某些常用場(chǎng)景中,報(bào)文的流向:

          到本機(jī)某進(jìn)程的報(bào)文:PREROUTING –> INPUT

          由本機(jī)轉(zhuǎn)發(fā)的報(bào)文:PREROUTING –> FORWARD –> POSTROUTING

          由本機(jī)的某進(jìn)程發(fā)出報(bào)文(通常為響應(yīng)報(bào)文):OUTPUT –> POSTROUTING

          盡管在某些情況下配置 iptables 規(guī)則可能復(fù)雜,但它提供了高度的靈活性和強(qiáng)大的功能,使其成為 Linux 網(wǎng)絡(luò)安全的重要組成部分。

          service 負(fù)載均衡

          我啟動(dòng)了一個(gè) 3 個(gè) nginx pod,和一個(gè)對(duì)應(yīng)的 service,service 的類型是 ClusterIP,這樣 service 就會(huì)有一個(gè)虛擬 IP,這個(gè) IP 會(huì)被 kube-proxy 代理到后端的 pod 上。

          
              

          ~ ? k get pod -owide

          NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES

          nginx-deployment-59f546cb79-2k9ng 1/1 Running 2 (31m ago) 50m 10.244.0.28 minikube <none> <none>

          nginx-deployment-59f546cb79-wfw84 1/1 Running 2 (31m ago) 50m 10.244.0.30 minikube <none> <none>

          nginx-deployment-59f546cb79-zr9xm 1/1 Running 2 (31m ago) 50m 10.244.0.27 minikube <none> <none>

          ----------------------------------------------------------------------------------------------------------------------------------------------------

          ~ ? k get svc nginx-service

          NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

          nginx-service ClusterIP 10.101.57.97 <none> 80/TCP 29m

          當(dāng)我們?cè)?master 使用 curl 10.101.57.97 訪問(wèn) service 的時(shí)候,首先會(huì)進(jìn)入 PREROUTING 鏈:

          
              

          root@minikube:/# iptables-save |grep PREROUTING

          :PREROUTING ACCEPT [0:0]

          :PREROUTING ACCEPT [34:2040]

          -A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

          -A PREROUTING -d 192.168.49.1/32 -j DOCKER_OUTPUT

          -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER

          首先會(huì)嘗試匹配 KUBE-SERVICES 鏈,這個(gè)鏈?zhǔn)?kube-proxy 生成的,用于處理 service 的請(qǐng)求。后兩個(gè)是 docker 的鏈,用于處理 docker 的請(qǐng)求。

          
              

          root@minikube:/# iptables-save |grep "\-A KUBE-SERVICES"

          -A KUBE-SERVICES -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -j KUBE-SVC-NPX46M4PTMTKRN6Y

          -A KUBE-SERVICES -d 10.101.57.97/32 -p tcp -m comment --comment "default/nginx-service cluster IP" -j KUBE-SVC-V2OKYYMBY3REGZOG

          -A KUBE-SERVICES -d 10.96.0.10/32 -p udp -m comment --comment "kube-system/kube-dns:dns cluster IP" -j KUBE-SVC-TCOU7JCQXEZGVUNU

          -A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp cluster IP" -j KUBE-SVC-ERIFXISQEP7F7OF4

          -A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:metrics cluster IP" -j KUBE-SVC-JD5MR3NA4I4DYORP

          -A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS

          我們這個(gè) nginx-service 的 cluster IP 是 10.101.57.97, 所以會(huì)走 KUBE-SVC-V2OKYYMBY3REGZOG 鏈:

          
              

          root@minikube:/# iptables-save |grep "\-A KUBE-SVC-V2OKYYMBY3REGZOG"

          -A KUBE-SVC-V2OKYYMBY3REGZOG ! -s 10.244.0.0/16 -d 10.101.57.97/32 -p tcp -m comment --comment "default/nginx-service cluster IP" -j KUBE-MARK-MASQ

          -A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.27:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-POZMZY2HDLRATSJV

          -A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.28:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-Z3HXRORN5VDCFRJU

          -A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.30:80" -j KUBE-SEP-S46ZL6MIFVWDY42O

          -A KUBE-SVC-V2OKYYMBY3REGZOG ! -s 10.244.0.0/16 -d 10.101.57.97/32 -p tcp -m comment --comment "default/nginx-service cluster IP" -j KUBE-MARK-MASQ 這條規(guī)則的如果源ip 不是 10.244.0.0/16 的 ip(也就是不是 pod發(fā)出來(lái)的請(qǐng)求),目的ip 是 service ip,jump 跳轉(zhuǎn)到 這個(gè)鏈 KUBE-MARK-MASQ

          
              

          root@minikube:/# iptables-save |grep "\-A KUBE-MARK-MASQ"

          -A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000

          這條規(guī)則的作用是給數(shù)據(jù)包打上 0x4000 這個(gè)標(biāo)記。這個(gè)標(biāo)記會(huì)被后續(xù)的 NAT 規(guī)則識(shí)別到,從而讓這些數(shù)據(jù)包通過(guò)特定的 NAT 規(guī)則進(jìn)行 IP 地址轉(zhuǎn)換。

          接下來(lái)看主要的三條規(guī)則:

          
              

          -A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.27:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-POZMZY2HDLRATSJV

          -A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.28:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-Z3HXRORN5VDCFRJU

          -A KUBE-SVC-V2OKYYMBY3REGZOG -m comment --comment "default/nginx-service -> 10.244.0.30:80" -j KUBE-SEP-S46ZL6MIFVWDY42O

          第一條是說(shuō)有 33.33% 的幾率會(huì)被轉(zhuǎn)發(fā)到 KUBE-SEP-POZMZY2HDLRATSJV, 第二條是 50% 的幾率會(huì)被轉(zhuǎn)發(fā)到 KUBE-SEP-Z3HXRORN5VDCFRJU, 第三條是一定會(huì)被轉(zhuǎn)發(fā)到 KUBE-SEP-S46ZL6MIFVWDY42O
          轉(zhuǎn)到第一條的概率是 33.33%,轉(zhuǎn)到第二條的概率是 66.67%(沒(méi)有到第一條的概率) * 50% = 33.33%,第三條就是 66.67%(沒(méi)有到第一條的概率) * 50%(沒(méi)有到第二條的概率) = 33.33%。所以這三條規(guī)則的概率是一樣的。都是 33.33%。
          那么 
          KUBE-SEP-POZMZY2HDLRATSJV 又是什么呢?

          
              

          root@minikube:/# iptables-save |grep "\-A KUBE-SEP-POZMZY2HDLRATSJV"

          -A KUBE-SEP-POZMZY2HDLRATSJV -s 10.244.0.27/32 -m comment --comment "default/nginx-service" -j KUBE-MARK-MASQ

          -A KUBE-SEP-POZMZY2HDLRATSJV -p tcp -m comment --comment "default/nginx-service" -m tcp -j DNAT --to-destination 10.244.0.27:80



          root@minikube:/# iptables-save |grep "\-A KUBE-SEP-POZMZY2HDLRATSJV"

          -A KUBE-SEP-Z3HXRORN5VDCFRJU -s 10.244.0.28/32 -m comment --comment "default/nginx-service" -j KUBE-MARK-MASQ

          -A KUBE-SEP-Z3HXRORN5VDCFRJU -p tcp -m comment --comment "default/nginx-service" -m tcp -j DNAT --to-destination 10.244.0.28:80



          root@minikube:/# iptables-save |grep "\-A KUBE-SEP-S46ZL6MIFVWDY42O"

          -A KUBE-SEP-S46ZL6MIFVWDY42O -s 10.244.0.30/32 -m comment --comment "default/nginx-service" -j KUBE-MARK-MASQ

          -A KUBE-SEP-S46ZL6MIFVWDY42O -p tcp -m comment --comment "default/nginx-service" -m tcp -j DNAT --to-destination 10.244.0.30:80

          第一條規(guī)則確保流量從 10.244.0.20 發(fā)出時(shí)被打上 MASQUERADE 標(biāo)記,以便通過(guò) NAT 機(jī)制進(jìn)行 IP 偽裝。
          第二條是將流量轉(zhuǎn)發(fā)到 
          10.244.0.20:80 并使用 DNAT 機(jī)制進(jìn)行目標(biāo)地址轉(zhuǎn)換, 轉(zhuǎn)換的 ip 10.244.0.27:80 就是 pod 的 ip 和端口。
          KUBE-SEP-Z3HXRORN5VDCFRJU 和 KUBE-SEP-S46ZL6MIFVWDY42O 的規(guī)則和這條同理。

          ipvs

          IPVS(IP Virtual Server)是 Linux 內(nèi)核中實(shí)現(xiàn)負(fù)載均衡功能的模塊。是一種高效的負(fù)載均衡技術(shù),可以在第 4 層(傳輸層)進(jìn)行流量轉(zhuǎn)發(fā)和調(diào)度。IPVS 通常被用于構(gòu)建高性能、高可用性的負(fù)載均衡集群。

          查看 ipvs 的規(guī)則:

          
              

          root@minikube:/etc/apt# sudo ipvsadm -Ln|grep -A 4 10.101.57.97

          Prot LocalAddress:Port Scheduler Flags

          -> RemoteAddress:Port Forward Weight ActiveConn InActConn

          TCP 10.101.57.97:80 rr

          -> 10.244.0.27:80 Masq 1 0 0

          -> 10.244.0.28:80 Masq 1 0 0

          -> 10.244.0.30:80 Masq 1 0 0

          UDP 10.96.0.10:53 rr

          這個(gè)的意思是到10.101.57.97:80 的 tcp 瀏覽會(huì)使用 rr(輪詢)的方式轉(zhuǎn)發(fā)到 10.244.0.27:8010.244.0.28:8010.244.0.30:80 這三個(gè) pod 上。Masq:指示 "Masquerading",表示通過(guò) NAT 來(lái)處理網(wǎng)絡(luò)流量。
          所以 ipvs 的模式比 iptables 性能高的多,第一因?yàn)?ipvs 是輪詢選,iptables 是逐條百分比匹配的,這個(gè)還是可以接受的。更要命的是第二條,當(dāng) pod 頻繁變更的時(shí)候 service 對(duì)應(yīng)的 endpoint 的 ENDPOINTS 就會(huì)增加或者是減少。那么 iptables 對(duì)應(yīng) service 的所有規(guī)則的百分比都會(huì)變化,就會(huì)導(dǎo)致一個(gè) service 的規(guī)則全部要重刷,當(dāng) pod 變化太頻繁時(shí),會(huì)吃掉大量的 CPU。

          不是說(shuō)開(kāi)啟了 ipvs 就不會(huì)有 iptables 了,還需要 iptables 的 SNAT 規(guī)則來(lái)處理返回的數(shù)據(jù)包。

          
              

          -A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING

          -A KUBE-POSTROUTING -m comment --comment "Kubernetes endpoints dst ip:port, source ip for solving hairpin purpose" -m set --match-set KUBE-LOOP-BACK dst,dst,src -j MASQUERADE

          -m set --match-set KUBE-LOOP-BACK dst,dst,src 的意思是匹配 KUBE-LOOP-BACK 這個(gè) set,這個(gè) set 里面存放的是 pod 的 ip,這個(gè)規(guī)則的作用是將數(shù)據(jù)包的源地址替換為本機(jī)的地址,以便數(shù)據(jù)包能夠正確返回到客戶端。
          為什么是 pod ip 而不是 service cluster ip 呢?因?yàn)橐呀?jīng)通過(guò) ipvs DNAT 過(guò)了,所以這里是 pod ip。

          
              

          root@minikube:/etc/apt# ipset -L|grep -A 15 KUBE-LOOP-BACK

          Name: KUBE-LOOP-BACK

          Type: hash:ip,port,ip

          Revision: 6

          Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xe4e21451

          Size in memory: 544

          References: 1

          Number of entries: 6

          Members:

          10.244.0.28,tcp:80,10.244.0.28

          10.244.0.30,tcp:80,10.244.0.30

          10.244.0.29,tcp:9153,10.244.0.29

          10.244.0.29,tcp:53,10.244.0.29

          10.244.0.27,tcp:80,10.244.0.27

          10.244.0.29,udp:53,10.244.0.29


          很明顯我們的三個(gè) pod 都在這個(gè) set 里面。

          -A KUBE-POSTROUTING -m comment --comment "Kubernetes endpoints dst ip:port, source ip for solving hairpin purpose" -m set --match-set KUBE-LOOP-BACK dst,dst,src -j MASQUERADE
          這條規(guī)則的作用是將數(shù)據(jù)包的源地址替換為本機(jī)的地址,以便數(shù)據(jù)包能夠正確返回到客戶端。現(xiàn)在我們使用 curl 發(fā)出的包目標(biāo) ip 是 pod ip了,源 ip 是 node ip。等到數(shù)據(jù)包返回的時(shí)候,kernel 會(huì)根據(jù) 鏈路追蹤 中的數(shù)據(jù)記錄,會(huì)把包的源ip 的pod ip 替換為 serice cluster ip, 目標(biāo) ip 從 node ip 替換為我發(fā)起請(qǐng)求的 ip。這樣包就能正確返回到客戶端了。



          瀏覽 36
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品成人毛片 | 中文字幕视频在线播放 | 亚洲有码电影 | 婷婷久久免费视频 | 麻豆传媒在线观看视频 |