當前位置:首頁 » 數據倉庫 » k8s前端如何配置後端IP
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

k8s前端如何配置後端IP

發布時間: 2023-02-22 23:03:12

① kubernetes pod設置靜態IP或者IP池

Pod一般不建議設置靜態IP地址,若想要實現設置靜態IP,可以參考下面的方法。像亞馬遜、阿里雲等廠家是支持靜態IP的,但如果是自己的私有雲,可以參考下面的方法。這里使用的是calico網路方案,其他的網路方案,好像並不支持,更詳細的操作,可以看看calico的官方文檔。

IP Pool資源定義

IPPool資源yaml定義

欄位說明

metadata:

spec:

blockSize說明

請在 V3.3.0 版本後使用blockSize

IPv4 26和IPv6 122的默認塊大小為64個地址的塊。這允許將地址按組分配給在同一主機上運行的工作負載。通過對地址進行分組,主機之間以及與其他BGP對等方之間交換的路由更少。如果主機在一個塊中分配所有地址,則將為其分配一個附加塊。如果沒有更多可用的塊,則主機可以從分配給其他主機的塊中獲取地址。為借用的地址添加了特定的路由,這會影響路由表的大小。

將塊大小從默認值增加(例如,使用24IPv4為每個塊提供256個地址)意味著每個主機更少的塊,並且可能會減少路由。但是,請嘗試確保池中至少有與主機一樣多的塊。

從默認值減小塊大小(例如,使用28IPv4為每個塊提供16個地址)意味著每個主機有更多塊,因此可能有更多路由。如果它允許塊在主機之間更公平地分布,那麼這將是有益的。

關於cidr和blockSize設置

比如你新增一個IPPool,cidr設置為192.169.0.0/29,在沒有設置blockSize情況下,默認是/26的blockSize,這樣是不允許的,192.169.0.0/29可用地址為8個,而默認blockSize為26將會把IP段分為64塊,沒有足夠的IP,所以是無效的,所以blockSize應該等於大於子網掩碼。

新創建的IPPool,可以在原有的IPPool中某一子網,比如

nodeSelector說明

以下所有的語法,都可以使用&&或||進行組合


kubernetes設置指定IP的場景及方法:

主要通過annotations指定。

基於namespace或者每個pod指定IP池

指定靜態IP地址

說明:cni.projectcalico.org/ipAddrsNoIpam:繞過IPAM分配給Pod的IPv4和/或IPv6地址的列表。任何IP沖突和路由都必須手動或由其他系統來處理。Calico僅在其IP地址屬於Calico IP池內時才將路由分配到Pod。如果分配的IP地址不在Calico IP池中,則必須確保通過另一種機制來處理到該IP地址的路由。

申請浮動IP

基於node節點標簽分配IP

IPPool生效優先順序

如果將這些方法中的一種以上用於IP地址分配,則它們將具有以下優先順序,其中1為最高優先順序:

基於namespace指定IP池

查看當前存在的IP池

創建新的IP池

創建新的namespace,並指定IP池

創建應用測試

注意namespace設置test-ippool

為pod指定靜態IP地址或地址范圍

指定地址范圍

創建IP地址池

創建應用測試

注意spec.template.metadata.annotations指定了使用的IPPool

Pod設置靜態IP

創建應用

雖然官方說名cni.projectcalico.org/ipAddrs:後面是IPv4或IPv6列表,實際並不支持,僅可以設置一個IP地址。所以Pod副本數超過1個是不行的。

設置的IP地址必須包含在已存在的IPPool中

根據節點標簽分配IP

刪除或禁用已存在的IPPool

如果不禁用或刪除,創建的Pod也有可能分配到其他IPPool中的地址段

禁用IPPool

刪除IPPool

給節點打上標簽

創建IPPool

創建應用測試

② K8S 容器之間通訊方式

首先k8s裡面容器是存在於pod裡面的,所以容器之間通訊,一般分為三種類型:

1. pod內部容器之間

2. pod 與 pod 容器之間

3. pod 訪問service服務

這種情況下容器通訊比較簡單,因為k8s pod內部容器是共享網路空間的,所以容器直接可以使用localhost訪問其他容器。

k8s在啟動容器的時候會先啟動一個pause容器,這個容器就是實現這個功能的。

這種類型又可以分為兩種情況:

1. 兩個pod在一台主機上面

2. 兩個pod分布在不同主機之上

針對第一種情況,就比較簡單了,就是docker默認的docker網橋互連容器。

第二種情況需要更為復雜的網路模型了,k8s官方推薦的是使用flannel組建一個大二層扁平網路,pod的ip分配由flannel統一分配,通訊過程也是走flannel的網橋。

docker --daemon --bip=172.17.18.1/24 

注意其中的「--bip=172.17.18.1/24」這個參數,它限制了所在節點容器獲得的IP范圍。

每個node上面都會創建一個flannel0虛擬網卡,用於跨node之間通訊。所以容器直接可以直接使用pod id進行通訊。

跨節點通訊時,發送端數據會從docker0路由到flannel0虛擬網卡,接收端數據會從flannel0路由到docker0,這是因為flannel會添加一個路由

發送端:

route -n

172.17.0.0    0.0.0.0    255.255.0.0      U  0  0  0   flannel0

172.17.13.0  0.0.0.0    255.255.255.0  U  0  0  0   docker0

接收端:

172.18.0.0    0.0.0.0    255.255.0.0      U  0  0  0  flannel0

172.17.12.0  0.0.0.0    255.255.255.0  U  0  0  0   docker0

例如現在有一個數據包要從IP為172.17.13.2的容器發到IP為172.17.12.2的容器。根據數據發送節點的路由表,它只與172.17.0.0/16匹配這條記錄匹配,因此數據從docker0出來以後就被投遞到了flannel0。同理在目標節點,由於投遞的地址是一個容器,因此目的地址一定會落在docker0對於的172.17.12.0/24這個記錄上,自然的被投遞到了docker0網卡。

flannel的原理是將網路包封裝在udp裡面,所以發送端和接收端需要裝包和解包,對性能有一定的影響。

k8s也支持其他的網路模型,比較有名的還有calico,不過我並沒有使用過。

這里涉及到k8s裡面一個重要的概念service。它是一個服務的抽象,通過label(k8s會根據service和pod直接的關系創建endpoint,可以通過kubectl get ep查看)關聯到後端的pod容器。

Service分配的ip叫cluster ip是一個虛擬ip(相對固定,除非刪除service),這個ip只能在k8s集群內部使用,如果service需要對外提供,只能使用Nodeport方式映射到主機上,使用主機的ip和埠對外提供服務。(另外還可以使用LoadBalance方式,但這種方式是在gce這樣的雲環境裡面使用的 )。

節點上面有個kube-proxy進程,這個進程從master apiserver獲取信息,感知service和endpoint的創建,然後做兩個事:

1. 為每個service 在集群中每個節點上面創建一個隨機埠,任何該埠上面的連接會代理到相應的pod

2. 集群中每個節點安裝iptables規則,用於clusterip + port路由到上一步定義的隨機埠上面,所以集群中每個node上面都有service的轉發規則:

KUBE-PORTALS-CONTAINER 從容器中通過service cluster ip和埠訪問service的請求

KUBE-PORTALS-HOST 從主機中通過service cluster ip和埠訪問service的請求

KUBE-NODEPORT-CONTAINER 從容器中通過service nodeport埠訪問service的請求

KUBE-NODEPORT-HOST 從主機中通過service nodeport埠訪問service的請求。

見下面測試環境的內容:

-A KUBE-NODEPORT-CONTAINER -p tcp -m comment --comment "smart/ccdb:port1521"  -m tcp --dport 50171 -j REDIRECT --to-ports 52244

-A KUBE-NODEPORT-HOST -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 50171 -j DNAT --to-destination 10.45.25.227:52244

-A KUBE-PORTALS-CONTAINER -d 10.254.120.169/32 -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 1521 -j REDIRECT --to-ports 52244

-A KUBE-PORTALS-HOST -d 10.254.120.169/32 -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 1521 -j DNAT --to-destination 10.45.25.227:52244

52244就是kube-proxy針對service 「"smart/ccdb:port1521"」 在節點上面監聽的埠。

參考:

1.  http://www.open-open.com/news/view/1aa473a

2. 《kubernetes權威指南》

③ k8s網路原理-ipvs

一、背景知識

  本文主要介紹k8s網路中service 的兩種模式(clusterIp、nodeport),數據是如何通過ipvs&iptables流轉的。在學習上述知識的同時,還需要了解一下ipset、conntrack的相關知識。 往期回顧文章

1.1、ipset

  ipset是什麼?ipset其實是iptables的擴展,可以定義一些列地址的集合。拿黑名單來舉例,我想讓黑名單裡面的ip拒絕訪問網站(黑名單有很多個),按照傳統iptables做法,需要在filter表添加很多規則匹配時一條一條匹配效率很低(嚴重影響性能),而有了ipset,則只用添加一條規則即可,使用hash結構效率很高。

而使用ipset命令如下

  當然,ipset還支持 hash:ip,hash:ip,port,ip等多種hash key的組成,具體可以通過 ipset -h 查看。接下來說明一下 -m set 後面 src 和 dst 兩個的含義。src 指來源,dst 指目標,此規則的意思是來自192.178.113.100 ip 訪問本機8410埠的流量給DROP掉。
ipset使用hash結構,比iptables的鏈表遍歷效率要高很多。ipset還有很多更加高級的玩法,本文就不在闡述了。

1.2、ipvs

  lvs是什麼?全稱是Linux Virtual Server,是由章文嵩博士主導的開源負載均衡項目,目前已經集成到linux內核中。lvs提供了豐富的負載均衡能力,接收到用戶請求後根據具體的負載均衡演算法在內核態把請求轉發到後端的某個server上,也就是說lvs不需要監聽具體的埠。接下來我們看一下lvs的一些基本概念。

  ipvs的原理如下。ipvs工作在iptables 的 input鏈上,VIP一般定義在DS節點上的一個虛擬ip,拿nat模式舉例如下。

① : 當請求數據包到DS上最先經過iptables 的PREROUTING鏈,判斷目標ip (VIP) 是本機的ip,於是把請求轉發到INPUT鏈上。
② : 因為lvs工作在INPUT鏈上,數據到達INPUT鏈上後lvs會將用戶請求和定義的後端服務做對比,如果是請求的後端服務,則使用某種負載均衡演算法找到一個後端RIP,修改數據包的目的ip和埠為某個RIP的(DNAT轉換)。
③ : 此時數據到達POSTROUTING鏈(不會做SNAT),數據包的源ip 為CIP,目的ip為RIP,數據包發往RIP上。

lvs提供了三種包轉發模式,如下所示

由於k8s使用的是NAT模式,接下來看下 NAT模式下的數據包流向 。如下圖所示

①:請求數據包到達DS,數據包經過PREROUTING鏈,此時ip 包 src ip為CIP,dst ip 為VIP
②:由於請求的VIP是DS上的虛擬ip,數據包發往INPUT鏈。
③:數據包到INPUT鏈上後,ipvs發現數據包請求是定義的集群服務,於是使用定義好的負載均衡演算法找到一個具體的RS節點,做DNAT,修改數據包dst ip為RIP,數據包到達POSTROUTING鏈,發送給RS。
④:RS收到數據包後對比dst ip 發現是自己,接收數據包做處理,處理完成後ip 數據包 src ip 為RIP,dst ip 為CIP,把數據包發給DS。
⑤:DS 接收到RS的響應包,修改src ip 為自身的VIP,dst ip 為CIP,把數據包發送給client端。

三種模式對比&優缺點

接下來在簡單聊一下ipvs的負載均衡策略,簡單介紹下面四種。

  上面介紹完了ipvs內核態的基本原理,接下來介紹一下如何使用 ipvsadm 用戶態命令來操作ipvs。說明:此次試驗是在四個虛擬機上,ipvs的模式使用的nat模式,RS的網關沒有指向DS的ip(沒辦法做到)在DS節點上手動創建SNAT命令,下文有詳細介紹。創建一個vip,在ip為192.168.113.101上

為vip添加RS

添加完成RS後,查看ipvs規則,如下圖所示

client端的ip地址為192.168.113.102,client端要想直接訪問vip的話,需要在client端添加靜態路由,添加命令如下

添加完命令後,在client端curl 10.10.0.1:8410 發現不通,此時去某個RS上抓包如下

  上圖抓包顯示,client 直接訪問的vip,而數據包的目的ip 變為了rs的ip,因此可以看出ipvs做了DNAT轉換。因為做了DNAT,RS發送響應數據直接發給client,client收到RS的數據包。client給vip發的包卻收到了RS的響應包(client 想我從來沒有給RS發過數據),因此client端會把此數據包丟棄。

  因為ipvs沒有做SNAT,接下來在DS上添加iptables規則自己實現SNAT的功能,添加完SNAT後, RS就看不到真實的CIP了

  此時還是不通,查找資料後發現ipvs 的 conntrack 沒有開,手動打開,後續文章介紹conntrack是什麼,設置完成後可以愉快的訪問了。

  總結:通過ipvs提供的DNAT功能和負載均衡功能,很容易實現外部用戶訪問內網的需求。但是還要考慮高可用層面,比如主DS宕機VIP要漂移到備DS上,後端RS重啟或宕機,ipvs負載均衡列表中要及時把有問題的RS剔除,這樣才能真正的實現高可用。

1.3、conntrack

  大家在家上網時用到的都是192.168.x.x的ip地址,這是私網ip地址。那麼大家是如何能夠成功的訪問外網的呢?答案是路由器幫我們做了SNAT的功能,使我們發出的數據包的src ip變為路由器的公網ip,這樣數據包就能在互聯網上愉快的轉發了。從而實現了對內網的保護。

  那麼問題來了,既然做了SNAT轉換,那響應數據包回來以後路由器怎麼知道轉到哪台PC上呢?路由器可能鏈接了很多PC,不可能都給每一個PC轉發吧。。。答案就是conntrack實現的。

  接下來我拿上面ipvs的例子舉例,我們手動實現了在DS上SNAT轉換,在client上curl vip:8410,這時候查看DS上和client上的conntrack表如下

先從client上的連接跟蹤分析起:主要看 src、dst、sport、dport這幾個欄位。
client發送數據包

client端發出數據包的src ip 為192.168.113.102,dst ip 為10.10.0.1 (VIP), sport 為35562這個埠,dport為8410(VIP 定義埠)。

client端接收響應數據包

期望src ip 為vip(10.10.0.1),dst ip 為CIP(192.168.113.102),sport為8410,dport為35562

DS接收數據包

DS接收到src ip 為CIP(192.168.113.102),dst ip 為vip(10.10.0.1),sport為35562,dport為8410的數據包

DS接收響應數據包

  由於在DS側做了DNAT轉換,根據負載均衡策略找到了一個RS(RIP 192.168.113.99),同時也做了SNAT轉換(判斷是否是VIP和埠),轉換為DS的DIP。所以當DS收到src ip 為192.168.113.99(RIP),dst ip 為192.168.113.101(DIP),sport為8080,dport為35562,會根據連接跟蹤表找到這個包是192.168.113.102這個client發過來的,因此把數據包在轉發給192.168.113.102:35562 上。

conntrack各個欄位的含義

總結:

  本文只是簡單的說明了一下conntrack,並沒有具體說明數據流經netfilter時何時創建記錄,數據存儲的數據結構啥樣,底層比較復雜,感興趣的大佬可以自行研究~

二、k8s網路通信

  介紹完了ipset、ipvs、conntrack,接下來進入正題,看一下ipvs模式下k8s的網路通信。kube-proxy 的主要作用是watch apiserver,當監聽到pod 或service變化時,修改本地的iptables規則或ipvs規則。

2.1、clusterIp模式

clusterIp模式為一個集群內部可訪問的ip,集群外部沒辦法訪問這個ip,試驗環境如下:

創建完deployment和service後,查看一下service的ip如下。

接下來看下宿主機網卡、ipvs規則、ipset規則有什麼變化

查看iptables 的nat表和filter表,看一下k8s創建了哪些規則以及經過哪些鏈

接下來分析一下curl 10.108.113.237 數據是如何走的,只討論在nat表和filter表的流向,因為在mangle和raw都沒有規則。

1、nat表PREROUTING鏈
①:數據首先進入PREROUTING鏈,所有請求都會進入KUBE-SERVICES鏈。
②:進入KUBE-SERVICES後,查看對應在此鏈上的規則,發現請求的目的ip和port在KUBE-CLUSTER-IP 對應的ipset裡面(上面已有展示),匹配上了則跳往KUBE-MARK-MASQ鏈。

③:數據流向KUBE-MARK-MASQ鏈,主要做了mark 打標記的功能,iptables命令如下

④:之後走向KUBE-NODE-PORT鏈,因為沒有定義nodepode 類型的service,此處先略過。 2、filter表的INPUT鏈
⑤:首先進入INPUT鏈,所有數據轉向KUBE-FIREWALL鏈。
⑥:進入KUBE-FIREWALL鏈,如果發現數據包打了0x8000/0x8000,DROP掉。因為ipvs工作在INPUT鏈上,做完DNAT之後直接轉發到POSTROUTING鏈上。
3、nat表POSTROUTING鏈
⑦:進入POSTROUTING鏈,所有數據轉向KUBE-POSTROUTING鏈
⑧:進入KUBE-POSTROUTING鏈,對有0x4000/0x4000標記的數據包做SNAT轉換,因為ipvs只有DNAT功能。

4、數據轉發給flannel網卡,進行轉發
⑨:flannel 根據具體的backend模式,對數據做封包等操作,然後發出去。flannel的網路模式比較復雜,之後會專門文章進行說明。

2.2、nodeport模式

  要想把集群內部的服務可以讓集群外部訪問,可以使用nodeport模式在物理機上開一個埠,這樣外部就能訪問集群內部的服務了。說明:還是使用上面創建的deployment。

查看創建service的信息,發現也創建了集群內部的一個ip。

iptables規則如下

接下來看下ipset規則有什麼變化,發現KUBE-NODE-PORT-TCP下的一個成員是剛才我們指定的那個nodePort的值。

接下來看一下iptables規則,nat表和filter表
1、nat表PREROUTING鏈
①:數據首先進入PREROUTING鏈,所有請求都會進入KUBE-SERVICES鏈。
②:ip和port匹配不上KUBE-CLUSTER-IP 的ipset,判斷是訪問的本地地址,進入KUBE-NODE-PORT鏈。

③:進入KUBE-NODE-PORT鏈後,判斷訪問埠在 KUBE-NODE-PORT-TCP ipset規則中,因此進入KUBE-MARK-MASQ鏈。

④:進入KUBE-MARK-MASQ鏈,對數據做mark標記

後續流程跟clusterIp一樣,此處就不在闡述。
2.3、dns相關

  k8s中的dns默認使用的是coredns,通過以下命令查看。k8s中定義的service是有域名的,訪問域名要通過dns解析,此時coredns就發揮它的作用了。

  上面的試驗時我們創建了一個my-service 的nodePort的service,此時查看一下此域名對應的ip,如下圖所示,域名解析出來的ip與service對應的ip相同,大功告成。

參考:


以上相關內容介紹了k8s service ipvs的相關實現,如有錯誤歡迎指出~

④ k8s 網路基礎

author:sufei
說明:本文主要記錄在學習k8s網路方面的相關知識

 Linux在內核網路棧中引入網路命名空間,將 獨立的網路協議棧隔離 到不同的命令空間中,彼此間無法通信;

1、Linux操作系統,解析和封裝網路包是通過一個網路協議棧完成,下層為上層服務,這個 協議棧中即包括如軟體也包括硬體網路設 備。網路命名空間就是以軟體方式隔離出單獨的網路棧信息;

2、不同network namespace的軟硬體資源相互不可見,好像處在物理隔離的不同物理機上一樣,彼此隔離;

3、不同的網路命名空間會有自己獨立的網卡、路由表、ARP 表、iptables 等和網路相關的資源

4、實驗:可以藉助 ip netns 命令來完成對 Network Namespace 的各種操作,如:

問題 :什麼是轉移設備?

 可以在不同的 Network Namespace 之間轉移設備(如veth)。由於一個設備只能屬於一個 Network Namespace ,所以轉移後在這個 Network Namespace 內就看不到這個設備了。 veth設備屬於可轉移設備 ,而很多其它設備(如lo、bridge等)是不可以轉移的。

 veth pair 全稱是 Virtual Ethernet Pair,是一個成對的埠,所有從這對埠一 端進入的數據包都將從另一端出來,反之也是一樣。而veth pair就是為了在不同的 Network Namespace 直接進行通信,利用它可以直接將兩個 Network Namespace 連接起來。

實驗

 veth pair打破了 Network Namespace 的限制,實現了不同 Network Namespace 之間的通信。但veth pair有一個明顯的缺陷,就是只能實現兩個網路介面之間的通信。如果我們想實現多個網路介面之間的通信,就可以使用下面介紹的網橋(Bridge)技術( 類似於物理交換機 )。
 簡單來說,網橋就是把一台機器上的若干個網路介面「連接」起來。其結果是,其中一個網口收到的報文會被復制給其他網口並發送出去。以使得網口之間的報文能夠互相轉發。

 網橋是一個二層網路設備,通過網橋可以將linux支持的不同的埠連接起來,並實現類似交換機那樣的多對多的通信。

實驗:

 Netfilter負責在內核中執行各種掛接的規則(過濾、修改、丟棄等),運行在內核 模式中;Iptables模式是在用戶模式下運行的進程,負責協助維護內核中Netfilter的各種規則表;通過二者的配合來實現整個Linux網路協議棧中靈活的數據包處理機制。

 iptables/netfilter(簡稱iptables)組成了Linux平台下的包過濾防火牆,可以完成封包過濾、封包重定向和網路地址轉換(NAT)等功能。這部分主要了解兩部分知識:

 應用層不管是要發送還是接收網路消息,都需要通過linux內核提供的一系列關卡。每個」關卡「擔負著不同的工作。這里的」關卡「被稱為」鏈「。如下圖:

 Docker啟動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱為Container-IP,同時Docker網橋是每個容器的默認網關(如上面的172.17.0.1)。因為在同一宿主機內的容器都接入同一個網橋,這樣容器之間就能夠通過容器的Container-IP直接通信。

 Docker網橋是宿主機虛擬出來的,並不是真實存在的網路設備,外部網路是無法定址到的,這也意味著外部網路無法通過直接Container-IP訪問到容器。如果容器希望外部訪問能夠訪問到,可以通過映射容器埠到宿主主機(埠映射),即docker run創建容器時候通過 -p 或 -P 參數來啟用,訪問容器的時候就通過[宿主機IP]:[容器埠]訪問容器。

 下面具體來說說docker容器的幾種網路模式,以便後續學習k8s網路。

 在host模式下( –net=host),容器不會去建立新的網路命名空間,而直接使用宿主機的網路設備以及網路協議棧。這樣自然不會虛擬出自己的網卡,配置自己的IP等。其特點如下:

 這個模式就是在創建容器時,指定網路(–net=container:NAME_or_ID)與之前容器在同一個網路命名空間中,而不是和宿主機共享(這也就是k8s中pod內各容器的一種網路模式)。下面說明幾點:

 none模式(–net=none)Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網路配置。也就是說,這個Docker容器沒有網卡、IP、路由等信息。需要我們自己為Docker容器添加網卡、配置IP等。

 bridge模式是docker容器的默認模式,當Docker進程啟動時,會在主機上創建一個名為docker0的虛擬網橋,此主機上啟動的Docker容器在bridge模式下會連接到這個虛擬網橋上,並由網橋自動分配ip。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網路中。

 下面說明這個模式下的工作方式:

 首先我們來看看k8s想要一個什麼樣的網路,也就是k8s網路設計的要求,具體如下:

 下面簡單從幾中不同的通信要求來看看k8s網路實現。

 在 Kubernetes 的世界裡,IP 是以 Pod 為單位進行分配的。一個 Pod 內部的所有容器共享一個網路堆棧。實際上就是docker container網路模式。可以直接通過本地localhost進行網路訪問。這個模式在mysql容器化中就是agent容器與mysql容器的網路通信方式。

 Pod1和Pod2都是通信veth pair連接到同一個docker0網橋上,它們的IP地址都是從docker0網段上動態獲取的,它們和網橋本身的IP是同一個網段的。可以通過docker0作為交換機進行通信,也就是採用的docker bridge網路模式進行通信。

 由於在同一個網橋docker0上即可以保證分配的pod IP不會沖突,且可以相互通信,而如果需要跨Node物理節點,則無法通過docker網路直接滿足要求了,那這些要求具體有哪些呢?

解決方案

方法一:k8s中通過在etcd中記錄正在運行中pod的IP分配信息,這樣我們就可以滿足Pod IP與Node IP之間映射關系的記錄;

方法二:可以在etcd中規劃配置好所有主機docker0網橋的子網范圍,從而滿足Pod IP不沖突的要求;如:

方法三:要實現Pod跨Node通信,以k8s默認網路Flannel為例,就是採用overlay(覆蓋網路)實現。具體下面說明:

問題:什麼是覆蓋網路?

覆蓋網路就是應用層網路,是指建立在另一個網路上的網路。怎麼理解呢?簡單理解就是將TCP數據包裝在另一種網路包裡面進行路由轉發和通信,另一種網路包目前可以是UDP、VxLAN、AWS VPC和GCE路由等數據轉發方式。默認以UDP為例來說明flannel工作方式。

下面看看具體實現

問題 :為保證各node內docker容器分配的ip地址不沖突,每個節點上的Docker會使用不同的IP地址段?如何實現的呢?

問題 :為什麼在發送節點上的數據會從docker0路由到flannel0虛擬網卡,在目的節點會從flannel0路由到docker0虛擬網卡?

⑤ 超全K8s集群構建指南,建議收藏

1. 什麼是kubernetes
Kubernetes(k8s)是Google開源的容器集群管理系統(谷歌內部:Borg)。在Docker技術的基礎上,為容器化的應用提供部署運行、資源調度、服務發現和動態伸縮等一系列完整功能,提高了大規模容器集群管理的便捷性。


2. kubernetes核心組件說明
Kubernetes 集群中主要存在兩種類型的節點,分別是 master 節點 ,以及 minion 節點

Minion 節點是實際運行 Docker 容器的節點,負責和節點上運行的 Docker 進行交互,並且提供了代理功能。

Master 節點負責對外提供一系列管理集群的 API 介面,並且通過和 Minion 節點交互來實現對集群的操作管理。

apiserver :用戶和 kubernetes 集群交互的入口,封裝了核心對象的增刪改查操作,提供了 RESTFul 風格的 API 介面,通過 etcd 來實現持久化並維護對象的一致性。


scheler :負責集群資源的調度和管理,例如當有 pod 異常退出需要重新分配機器時,scheler 通過一定的調度演算法從而找到最合適的節點。


controller-manager :主要是用於保證 replicationController 定義的復制數量和實際運行的 pod 數量一致,另外還保證了從 service 到 pod 的映射關系總是最新的。


kubelet :運行在 minion 節點,負責和節點上的 Docker 交互,例如啟停容器,監控運行狀態等。


proxy :運行在 minion 節點,負責為 pod 提供代理功能,會定期從 etcd 獲取 service 信息,並根據 service 信息通過修改 iptables 來實現流量轉發(最初的版本是直接通過程序提供轉發功能,效率較低。),將流量轉發到要訪問的 pod 所在的節點上去。


etcd :key-value鍵值存儲資料庫,用來存儲kubernetes的信息的。


flannel :Flannel 是 CoreOS 團隊針對 Kubernetes 設計的一個覆蓋網路(Overlay Network)工具,需要另外下載部署。


我們知道當我們啟動 Docker 後會有一個用於和容器進行交互的 IP 地址,如果不去管理的話可能這個 IP 地址在各個機器上是一樣的,並且僅限於在本機上進行通信,無法訪問到其他機器上的 Docker 容器。


Flannel 的目的就是為集群中的所有節點重新規劃 IP 地址的使用規則,從而使得不同節點上的容器能夠獲得同屬一個內網且不重復的 IP 地址,並讓屬於不同節點上的容器能夠直接通過內網 IP 通信。


3. Kubernetes的核心概念

Pod
運行於Node節點上,若干相關容器的組合。Pod內包含的容器運行在同一宿主機上,使用相同的網路命名空間、IP地址和埠,能夠通過localhost進行通。


Pod是Kurbernetes進行創建、調度和管理的最小單位,它提供了比容器更高層次的抽象,使得部署和管理更加靈活。一個Pod可以包含一個容器或者多個相關容器。


Replication Controller
Replication Controller用來管理Pod的副本,保證集群中存在指定數量的Pod副本。

集群中副本的數量大於指定數量,則會停止指定數量之外的多餘容器數量,反之,則會啟動少於指定數量個數的容器,保證數量不變。

Replication Controller是實現彈性伸縮、動態擴容和滾動升級的核心。


Service
Service定義了Pod的邏輯集合和訪問該集合的策略,是真實服務的抽象。

Service提供了一個統一的服務訪問入口以及服務代理和發現機制,用戶不需要了解後台Pod是如何運行。


Label
Kubernetes中的任意API對象都是通過Label進行標識,Label的實質是一系列的K/V鍵值對。Label是Replication Controller和Service運行的基礎,二者通過Label來進行關聯Node上運行的Pod。

Node
Node是Kubernetes集群架構中運行Pod的服務節點(或agent)。

Node是Kubernetes集群操作的單元,用來承載被分配Pod的運行,是Pod運行的宿主機。


4. 前置條件設置
三台Centos7系統的虛擬機(1個master+2個node),三台機器上的防火牆,SELINUX全部關掉。我的實驗壞境可以上網,默認的YUM源就可以用。


5. 部署規劃
192.168.10.1 # master節點(etcd,kubernetes-master)
192.168.10.2 # node1節點(etcd,kubernetes-node,docker,flannel)
192.168.10.3 # node2節點(etcd,kubernetes-node,docker,flannel)


6. 開始安裝

step1:在master上安裝
yum install kubernetes-master etcd flannel -y


step2:在node上安裝
yum install kubernetes-node etcd flannel -y


step3:etcd集群配置
在master節點上編輯etcd配置文件


在node1節點上編輯etcd配置文件


在node2節點上編輯etcd配置文件


到此etcd集群就部署完了,然後每個節點上啟動
systemctl start etcd


step4:驗證


step6:啟動Master上的三個服務


step7:kubernetes node安裝


node2 節點重復上述操作
step8:分別啟動kubernetes node服務


7. 網路配置
因為kubernetes集群中網路部分是插件形式安裝的,我們這里選用flannel
上述安裝步驟已經install 了


為flannel創建分配的網路


8. 執行kubectl 命令檢查
在master上執行下面,檢查kubernetes的狀態


9. 常用排錯命令如下