① k8s五分鍾快速入門
k8s是谷歌開源的容器集群管理系統,是谷歌多年大規模容器管理技術Borg的開源版本,主要功能包括:
從功能上講Kubernetes是一種綜合的基於容器構建分布式系統的基礎架構環境,它不僅能夠實現基本的拉取用戶鏡像、運行容器,還可以提供路由網關、水平擴展、監控、備份、災難恢復等一系列運維能力,而更重要的是Kubernetes可以按照用戶的意願和整個系統的規則,高度自動化的處理好容器之間的各種關系實現「編排」能力。
簡單概括,提供創建應用>應用部署>提供服務>動態伸縮>應用更新一系列服務。
k8s主要由以下幾個核心組件:
一個kubernetes集群由分布式存儲etcd、控制節點controller以及服務節點Node組成。
如上圖所示,Kubernetes在架構上主要由Master和Node兩種類型的節點組成,這兩種節點分別對應著控制節點和計算節點。其中Master即控制節點,是整個Kubernetes集群的大腦,負責整個集群的管理,比如容器的調度、維護資源的狀態、自動擴展以及滾動更新等,並能根據集群系統資源的整體使用情況將作業任務自動分發到可用Node計算節點。
看Master節點主要由三個緊密協作的獨立組件組合而成。
需要說明的是,上述組件在工作狀態下還會產生許多需要進行持久化的數據,這些數據會通過kube-apiserver處理後統一保存到Etcd存儲服務中。 所以從這個角度看kube-apiserver不僅是外部訪問Kubernetes集群的入口,也是維護整個Kubernetes集群狀態的信息中樞。
而在Kubernetes計算節點中,除了上述3個系統組件外,其他基本與Master節點相同,而其中最核心的部分就是kubelet組件。它的核心功能具如下:
在Kubernetes中kubelet會通過CRI介面同容器運行時進行交互,而容器運行時則通過叫做OCI容器運行時規范與底層Linux操作系統進行交互(涉及對Namespace、Cgroups等資源的操作,具體可以了解下Docker的技術原理)。需要強調的是,這里所說的容器運行時並不僅僅指Docker,而是所有實現了CRI介面規范的容器項目都可以作為Kubernetes的容器運行時存在。這是因為Kubernetes從設計之初就沒有把Docker作為整個架構的核心,而只是將其作為最底層的一個容器運行時來實現。
況且從Kubernetes架構設計上看,Kubernetes並沒有打算重復造輪子而對已有的容器技術進行替代,它更關注的是對運行在大規模集群中的各種任務根據其關系進行作業編排及管理,所以任何實現了CRI、CNI、CSI等協議標準的容器技術都可以無縫地與Kubernetes集成。從這個角度看,Docker與Kubernetes的關系並不是替代的關系,而是平台與組件的關系,Kubernetes可以利用現有的Docker容器運行時技術,但卻並不完全依賴Docker。而這也正是Kubernetes為什麼被稱作容器編排技術而不僅僅只是容器技術的原因。
[1] Kubernetes和Docker的關系是什麼?
[2] 《k8s入門指南》這是一個博主寫的書
② 簡述Kubernetes外部如何訪問集群內的服務
對於Kubernetes,集群外的客戶端默認情況,無法通過Pod的IP地址或者Service的虛擬IP地址:虛擬埠號進行訪問。通常可以通過以下方式進行訪問Kubernetes集群內的服務:
映射Pod到物理機:將Pod埠號映射到宿主機,即在Pod中採用hostPort方式,以使客戶端應用能夠通過物理機訪問容器應用。
映射Service到物理機:將Service埠號映射到宿主機,即在Service中採用nodePort方式,以使客戶端應用能夠通過物理機訪問容器應用。
映射Sercie到LoadBalancer:通過設置LoadBalancer映射到雲服務商提供的LoadBalancer地址。這種用法僅用於在公有雲服務提供商的雲平台上設置Service的場景。我推薦你去看看時速雲,他們是一家全棧雲原生技術服務提供商,提供雲原生應用及數據平台產品,其中涵蓋容器雲PaaS、DevOps、微服務治理、服務網格、API網關等。大家可以去體驗一下。 如果我的回答能夠對您有幫助的話,求給大大的贊。
③ k8s 基本使用(上)
本文將介紹 k8s 中的一些最基本的命令,並輔以解釋一些基本概念來方便理解,也就是說,本文是一篇偏向實用性而非學術性的文章,如果你想提前了解一下 k8s 相關的知識的話,可以通過以下鏈接進行學習:
k8s 是經典的一對多模型,有一個主要的管理節點 master 和許多的工作節點 slaver 。當然,k8s 也可以配置多個管理節點,擁有兩個以上的管理節點被稱為 高可用 。k8s 包括了許多的組件,每個組件都是單運行在一個 docker 容器中,然後通過自己規劃的虛擬網路相互訪問。你可以通過 kubectl get pod -n kube-system 查看所有節點上的組件容器。
在管理節點中會比工作節點運行更多的 k8s 組件,我們就是靠著這些多出來的組件來對工作節點發號施令。他們都叫什麼這里就不詳細提了。反正對於」基本使用「來說,這些名字並不重要。
要想理解一個東西就要先明白它的內在理念。通俗點就是,k8s 做了什麼?為了提供更加可靠的服務,就要增加伺服器的數量,減少每個伺服器的體量來平攤負載,而越來越多的虛擬機就會帶來越來越高的運維成本。如何讓少量的運維人員就可以管理數量眾多的伺服器及其上的服務呢?這就是 k8s 做的工作。
k8s 把數量眾多的伺服器重新抽象為一個統一的資源池 ,對於運維人員來說,他們面前沒有伺服器1、伺服器2的概念,而是一個統一的資源池,增加新的伺服器對運維人員來說,只是增加自資源池的可用量。不僅如此,k8s 把所有能用的東西都抽象成了資源的概念,從而提供了一套更統一,更簡潔的管理方式。
接下來,我會把每個基本命令當做一節來進行介紹,並輔以介紹一些基本概念。本文介紹的命令涵蓋了增刪改查四方面,可參加下面表格,因為篇幅較長,我們將 create 及之後的不那麼常用的命令放在下一篇文章 k8s 基本使用(下) 里講:
接下來進入正題,首先來了解一下 k8s 中最最最常用的命令 kubectl get ,要記住,k8s 把所有的東西都抽象成了資源,而 kubectl get 就是用來查看這些資源的。最常見的資源就是 pod 。
不僅我們自己的服務是要包裝成 pod 的,就連 k8s 自己也是運行在一堆 pod 上。接下來就讓我們查看一下 k8s 的 pod :
-n 參數指定了要查看哪個命名空間下的 pod 。 k8s 所有的 pod 都被放置在 kube-system 命名空間下。
執行了 kubectl get pod -n kube-system 命令後,你就可以看到如下內容:
其中每一行就是一個資源,這里我們看到的資源是 pod 。你看到的 pod 數量可能和我的不一致,因為這個列表裡包含了 k8s 在所有節點上運行的 pod ,你加入的節點越多,那麼顯示的 pod 也就越多。我們來一列一列的看:
kubectl get 可以列出 k8s 中所有資源
這里只介紹了如何用 kubectl 獲取 pod 的列表。但是不要把 get 和 pod 綁定在一起,pod 只是 k8s 中的一種服務,你不僅可以 get pod ,還可以 get svc ( 查看服務 )、 get rs ( 查看副本控制器 )、 get deploy ( 查看部署 )等等等等,雖然說 kubectl get pod 是最常用的一個,但是如果想查看某個資源而又不知道命令是什麼, kbuectl get <資源名> 就對了。
如果你想看更多的信息,就可以指定 -o wide 參數,如下:
加上這個參數之後就可以看到資源的所在 ip 和所在節點 node 了。
記得加上 -n
-n 可以說是 kubectl get 命令使用最頻繁的參數了,在正式使用中,我們永遠不會把資源發布在默認命名空間。所以,永遠不要忘記在 get 命令後面加上 -n 。
kubectl get 命令可以列出 k8s 中的資源,而 kubectl get pod 是非常常用的查看 pod 的命令。而 -n 參數則可以指定 pod 所在的命名空間。
kubectl describe 命令可以用來查看某一資源的具體信息,他同樣可以查看所有資源的詳情, 不過最常用的還是查看 pod 的詳情 。他也同樣可以使用 -n 參數指定資源所在的命名空間。
舉個例子,我們可以用下面命令來查看剛才 pod 列表中的某個 pod,注意不要忘記把 pod 名稱修改成自己的:
然後你就可以看到很多的信息,咱們分開說,首先是基本屬性,你可以在詳細信息的開頭找到它:
基本屬性
其中幾個比較常用的,例如 Node 、 labels 和 Controlled By 。通過 Node 你可以快速定位到 pod 所處的機器,從而檢查該機器是否出現問題或宕機等。通過 labels 你可以檢索到該 pod 的大致用途及定位。而通過 Controlled By ,你可以知道該 pod 是由那種 k8s 資源創建的,然後就可以使用 kubectl get <資源名> 來繼續查找問題。例如上文 DaemonSet/kube-flannel-ds-amd64 ,就可以通過 kubectl get DaemonSet -n kube-system 來獲取上一節資源的信息。
內部鏡像信息
在中間部分你可以找到像下面一樣的 Containers 段落。該段落詳細的描述了 pod 中每個 docker 容器的信息,常用的比如 Image 欄位,當 pod 出現 ImagePullBackOff 錯誤的時候就可以查看該欄位確認拉取的什麼鏡像。其他的欄位名都很通俗,直接翻譯即可。
事件
在 describe 查看詳情的時候,最常用的信息獲取處就是這個 Event 段落了,你可以在介紹內容的末尾找到它,如下:
是的,如果你看到上面這樣,沒有任何 Events 的話,就說明該 pod 一切正常。當 pod 的狀態不是 Running 時,這里一定會有或多或少的問題,長得像下面一樣,然後你就可以通過其中的信息分析 pod 出現問題的詳細原因了:
kubectl describe <資源名> <實例名> 可以查看一個資源的詳細信息,最常用的還是比如 kubectl describe pod <pod名> -n <命名空間> 來獲取一個 pod 的基本信息。如果出現問題的話,可以在獲取到的信息的末尾看到 Event 段落,其中記錄著導致 pod 故障的原因。
如果你想查看一個 pod 的具體日誌,就可以通過 kubectl logs <pod名> 來查看。注意,這個只能查看 pod 的日誌。通過添加 -f 參數可以持續查看日誌。例如,查看 kube-system 命名空間中某個 flannel pod 的日誌,注意修改 pod 名稱:
然後就可以看到如下輸出:
如果你發現某個 pod 的服務有問題,但是狀態還是顯示 Running ,就可以使用 kubectl logs 來查看其詳細日誌。
在本篇文章里,我們了解了 k8s 的宗旨和一些基本概念,並知道了最為常用的 get 、 descibe 及 logs 命令,知道了這三條命令之後就幾乎可以從 k8s 中獲取所有常用信息了。接下來的 k8s 基本使用(下) 里,我們會更深一步,來了解 k8s 中如何創建、修改及刪除資源。
④ k8s 之 service ip
本文通過下面的例子,分析訪問service ip的流程及iptables規則如何生效。
通過此yaml文件創建三個pod,一個client,兩個nginx(監聽在80埠),和一個service(將9999映射到nginx的80埠),實現到nginx後端的負載均衡。
查看創建的三個pod,兩個nginx pod部署在worker1上,client部署在worker2上。
查看創建的service,可看到對應的兩個endpoint。
service創建成功後,會在每個worker node上添加如下iptable規則
有如下三種訪問service ip的場景,下面分別驗證並分析iptables規則
a. 在client pod內部訪問
b. 在worker node上訪問
c. 在監聽80埠的nginx pod中訪問
a. 在client pod內部訪問
然後進入nat表的處理,在PREROUTING 鏈上依次查找如下的規則
雖然POSTROUTING鏈上也有規則,但是都不匹配。
所以查找nat表的結果就是做了dnat。
b. 在worker node上訪問
然後進入nat表的處理,依次查找如下的規則
在OUTPUT鏈上,匹配到dnat規則,將數據包的目的ip/port換成了10.1.139.84:80或者10.1.139.93:80,並且給數據包做了標記0x4000/0x4000。
根據MASQUERADE做snat時,源地址選擇可以通過下面命令獲取,在此例中,源ip為10.1.236.128
c. 在nginx pod訪問
這里還要再分兩種場景,負載均衡後的ip是發起訪問的pod和不是發起訪問的pod。比如 在nginx1 pod內部訪問nginx的service服務,負載均衡後的ip為nginx1 pod的ip,或者為nginx2 pod的ip。
不同pod
在nginx1 pod內部訪問nginx的service服務,負載均衡後的ip為nginx2 pod的ip。
將目的ip修改為10.1.139.93後,查找路由表時,發現只需要發給本worker上的calic6244c9748e即可。
此場景下的鏈接跟蹤表項
同一個pod
在nginx1 pod內部訪問nginx的service服務,負載均衡後的ip為nginx1 pod的ip。和上面的場景的區別是,不只做dnat,還要做snat。
將目的ip修改為10.1.139.84後,查找路由表時,發現只需要發給本worker上的calic6244c9748e。
但是在POSTROUTING處,還需要執行如下兩條規則,因為數據包已經被打上標記0x4000/0x4000,所以在這里還要執行MASQUERADE,即snat
snat後的源ip可以通過如下命令獲取
最後數據包經過dnat和snat後發給給本worker node上的calif67c1668c34。
此場景下的鏈接跟蹤表項
⑤ 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
k8s全稱kubernetes,這個名字大家應該都不陌生,k8s是為容器服務而生的一個可移植容器的編排管理工具,越來越多的公司正在擁抱k8s,並且當前k8s已經主導了雲業務流程,推動了微服務架構等熱門技術的普及和落地,正在如火如荼的發展。想要了解更多,我推薦你去看看時速雲,他們是一家全棧雲原生技術服務提供商,提供雲原生應用及數據平台產品,其中涵蓋容器雲PaaS、DevOps、微服務治理、服務網格、API網關等。大家可以去體驗一下。
希望能給您提供幫助,可以給個大大的贊不。
⑦ 09-kubernetes中的域名解析流程
從Kubernetes 1.11版本開始,Kubernetes集群的DNS服務由CoreDNS提供。CoreDNS是CNCF基金會的一個項目,是用Go語言實現的高性能、插件式、易擴展的DNS服務端。CoreDNS解決了KubeDNS的一些問題,例如dnsmasq的安全漏洞、externalName不能使用stubDomains設置,等等。
CoreDNS支持自定義DNS記錄及配置upstream DNS Server,可以統一管理Kubernetes基於服務的內部DNS和數據中心的物理DNS。
CoreDNS沒有使用多個容器的架構,只用一個容器便實現了KubeDNS內3個容器的全部功能。
從kubernetes官方提供的 coredns.yml 文件中,不難看出coredns服務配置至少需要一個ConfigMap、一個Deployment和一個Service共3個資源對象。ConfigMap coredns 主要配置文件Corefile的內容:
其中主要有二個地方來解析配置
1、這段配置的意思是cluster.local後綴的域名都是kubernetes內部域名,coredns會監控service的變化來修改域名的記錄
2、如果coredns沒有找到dns記錄,則去找 /etc/resolv.conf 中的 nameserver 解析
接下來使用一個帶有nslookup工具的Pod來驗證DNS服務能否正常工作:
通過nslookup進行測試。
查找defaul命名空間存在的ng-deploy-80服務
如果某個Service屬於不同的命名空間,那麼在進行Service查找時,需要補充Namespace的名稱,組合成完整的域名。下面以查找kubernetes-dashboard服務為例,
眾所周知, DNS 伺服器用於將域名轉換為 IP (具體為啥要轉換建議復習下 7 層網路模型). Linux 伺服器中 DNS 解析配置位於 /etc/resolv.conf , 在 Pod 中也不例外,
DNS 策略可以逐個 Pod 來設定。當前kubernetes支持這4中DNS 策略
如果我們不填dnsPolicy, 默認策略就是 ClusterFirst 。
kubelet 在起 pause 容器的時候,會將其 DNS 解析配置初始化成集群內的配置。配置: 它的 nameserver 就是指向 coredns 的
k8s裡面有4種DNS策略, 而coredns使用的DNS策略就是Default, 這個策略的意思就是繼承宿主機上的/etc/resolve.conf, 所以coredns Pod 裡面的/etc/resolve.conf 的內容就是宿主機上的內容。
在集群中 pod 之間互相用 svc name 訪問的時候,會根據 resolv.conf 文件的 DNS 配置來解析域名,下面來分析具體的過程。
pod 的 resolv.conf 文件主要有三個部分,分別為 nameserver、search 和 option。而這三個部分可以由 K8s 指定,也可以通過 pod.spec.dnsConfig 欄位自定義。
nameserver
resolv.conf 文件的第一行 nameserver 指定的是 DNS 服務的 IP,這里就是 coreDNS 的
clusterIP:
也就是說所有域名的解析,都要經過coreDNS的虛擬IP 10.100.0.2 進行解析, 不論是內部域還是外部域名。
search 域
resolv.conf 文件的第二行指定的是 DNS search 域。解析域名的時候,將要訪問的域名依次帶入 search 域,進行 DNS 查詢。
比如我要在剛才那個 pod 中訪問一個域名為 ng-deploy-80的服務,其進行的 DNS 域名查詢的順序是:
options
resolv.conf 文件的第三行指定的是其他項,最常見的是 dnots。dnots 指的是如果查詢的域名包含的點 「.」 小於 5,則先走 search 域,再用絕對域名;如果查詢的域名包含點數大於或等於 5,則先用絕對域名,再走 search 域。K8s 中默認的配置是 5。
也就是說,如果我訪問的是 a.b.c.e.f.g ,那麼域名查找的順序如下:
通過 svc 訪問
在 K8s 中,Pod 之間通過 svc 訪問的時候,會經過 DNS 域名解析,再拿到 ip 通信。而 K8s 的域名全稱為 "<service-name>.<namespace>.svc.cluster.local",而我們通常只需將 svc name 當成域名就能訪問到 pod,這一點通過上面的域名解析過程並不難理解。
參考
(1)K8S落地實踐 之 服務發現(CoreDNS)
https://blog.51cto.com/u_12965094/2641238
(2)自定義 DNS 服務
https://kubernetes.io/zh/docs/tasks/administer-cluster/dns-custom-nameservers/
(3)Kubernetes 服務發現之 coreDNS
https://juejin.cn/post/6844903965520297991
(4)Kubernetes 集群 DNS 服務發現原理
https://developer.aliyun.com/article/779121
(5)Kubernetes之服務發現和域名解析過程分析
https://www.jianshu.com/p/80ad7ff37744
⑧ 如何訪問k8s集群內部署的mysql服務
雖然 kubernetes 社區一直在努力使得有狀態應用成為一等公民,也推出了 statefulset 控制器支持 pod 的順序部署,穩定的域名訪問和存儲訪問。但鑒於 MySQL 部署運維的多樣性和復雜性,在 kubernetes 上部署 MySQL 仍然要面臨眾多挑戰。
1、業務流量入口的配置方式
傳統虛擬機環境下,我們通過虛IP的方式,讓業務應用都配置事先定義的一個虛IP為鏈接資料庫的地址,然後由高可用服務保證虛IP始終能被路由到master資料庫。在kubernetes中,出現了一層網路插件屏蔽了底層網路拓撲,高可用服務管理虛IP的方式需要隨之適應調整,比如通過service結合標簽完成虛IP的漂移,但service本身是kubernetes提供的一項功能,其可靠性和性能都取決於kubernetes服務的穩定。以性能來說,service是kubeproxy組件通過配置iptables實現的,當iptables規則較多時不可避免的會產生時延,需要我們針對性的解決。
2、容器隔離帶來的監控視野問題
在 kubernetes 中,如果將 MySQL 製作為 container 運行在一個 pod 中,container 會將 MySQL 進程和運行環境隔離在一個單獨的 namespace 中。監控組件在獲取 MySQL 的一些 metirc 時,可能不得不進入與 MySQL 同一個 namespace 中,在部署和設計監控組件時需要考慮到這些限制。
3、存儲在 kubernetes 中,支持配置各種不同的存儲。
如果使用本地存儲 local persistent volume,則需要綁定 MySQL 在一個固定的節點,這就完全浪費了 kubernetes 靈活調度的天然優勢;而如果使用遠程共享存儲,確實是將 MySQL 進程與其存儲完全解耦,使得 MySQL 進程可以在任意節點調度,然而考慮到高 I/O 吞吐量的情況,就不是那麼美好了。設計時需要考量遠程存儲是否能夠滿足 MySQL 的帶寬要求。
4、高可用/備份恢復
kubernetes 提供的 statefulset 控制器只能提供最基本的部署,刪除功能,無法實現完善的 MySQL 集群高可用/備份恢復操作。對於有狀態應用的部署,仍需要定製開發,所以多數公司提供了定製的 operator 來完成應用容器的管理。比如 etcd operator,MySQL operator,後文將為大家詳述我測試使用 MySQL operator 的一些記錄。
⑨ K8s中pod的數據通訊
k8s的網路通訊方式
k8s的網路模型假定是所有Pod都在一個可以直接聯通的扁平的網路空間,我們需要自己實現這個網路假設,將不同節點上的Docker容器之間的互相訪問先打通,然後運行K8s。
同一個Pod內的多個容器: 同一個pod共享一個網路命名空間,共享同一個linux協議棧
同一個節點各pod之間的通訊: 通過docker0網橋直接發送數據,不通過flannel
pod與service之間的通訊: 各節點的iptables規則。
pod到外網: pod向外網發送請求,查找路由表轉發數據包到宿主機的網卡,宿主機網卡完成路由選擇後,iptables執行Masquerade,把源IP更改為著網卡的IP,然後向外網發送請求。
flannel的功能是讓集群中的不同節點主機創建的Docker容器具有集群唯一的虛擬IP地址,能夠在這些Ip地址之間建立
一個覆蓋網路(OverlayNetwork),通過這個覆蓋網路,將數據包原封不動傳遞到目標容器內部。
不同節點的pod之間的訪問:
首先,在node伺服器上會安裝flanneld的守護進程,這個進程會監聽一個埠,這個埠是用於接收和轉發數據包的埠,flanneld進程啟動以後,會開啟一個網橋叫flannel0,flannel0會抓取docker0轉發的數據包,docker0會分配自己的IP到對應的pod上,如果是同一台主機中的不同pod的話,他們之間的通訊走的是docker0網橋。如果是不同節點之間的pod進行通訊,數據包源地址寫自己的ip,目標地址寫目標地址的ip,然後將數據發送到docker0網橋也就是網關,此時flannel0有自己鉤子函數,將數據從docker0抓取,flannel0是flanneld開啟埠,數據到了flanneld之後會將數據報文進行一個封裝,然後將數據轉發到目標節點,然後到了目標節點之後會將數據進行一次解封,到達目標節點的flanneld,然後數據會進行二次解封,flanneld會通過自己的埠將數據發送到docker0網橋,然後在對數據進行轉發,從而發送到相應的目標pod。
這里的etcd與flannel的關系:
存儲管理flannel可分配的IP地址段資源
監控etcd中每個pod的實際地址,並在內存中建立維護pod節點路由表。
flannel啟動以後會向etcd中插入需要分配的網段以及這些網段分別分配在哪個節點上。