k8s的核心對象

1、Deployment的概念前端

K8S自己並不提供網絡的功能,因此須要藉助第三方網絡插件進行部署K8S中的網絡,以打通各個節點中容器的互通。
POD,是K8S中的一個邏輯概念,K8S管理的是POD,一個POD中包含多個容器,容器之間經過localhost互通。而POD須要ip地址。每一個POD都有一個標籤
POD–>RC–>RS–>Deployment (發展歷程)
Deployment,表示用戶對K8S集羣的一次更新操做。Deployment是一個比RS應用模式更廣的API對象。用於保證Pod的副本的數量。
能夠是建立一個新的服務,更新一個新的服務,也能夠是滾動升級一個服務。滾動升級一個服務。實際是建立一個新的RS,而後將新的RS中副本數增長到理想狀態,將舊的RS中的副本數減少到0的複合操做; 這樣的一個複合操做用一個RS是不太好描述的,因此用一個更通用的Deployment來描述。
 
RC、RS和Deployment只是保證了支撐服務的POD數量,可是沒有解決如何訪問這些服務的問題。一個POD只是一個運行服務的實例,隨時能夠能在一個節點上中止,在另外一個節點以一個新的IP啓動一個新的POD,所以不能以肯定的IP和端口號提供服務。
要穩定地提供服務須要服務發現和負載均衡能力。服務發現完成的工做,是針對客戶端訪問的服務,找到對應的後端服務實例。
在K8S的集中當中,客戶端須要訪問的服務就是Service對象。每一個Service會對應一個集羣內部有效的虛擬IP,集羣內部經過虛擬IP訪問一個服務。
 
總結建立的過程:
(1)用戶經過kubectl建立Deployment
(2)Deployment建立ReplicaSet
(3)ReplicaSet建立Pod
 
1、什麼是Ingress?
從前面的學習,咱們能夠了解到Kubernetes暴露服務的方式目前只有三種:LoadBlancer Service、ExternalName、NodePort Service、Ingress;而咱們須要將集羣內服務提供外界訪問就會產生如下幾個問題:
 
一、Pod 漂移問題
Kubernetes 具備強大的副本控制能力,能保證在任意副本(Pod)掛掉時自動從其餘機器啓動一個新的,還能夠動態擴容等,通俗地說,這個 Pod 可能在任什麼時候刻出如今任何節點上,也可能在任什麼時候刻死在任何節點上;那麼天然隨着 Pod 的建立和銷燬,Pod IP 確定會動態變化;那麼如何把這個動態的 Pod IP 暴露出去?這裏藉助於 Kubernetes 的 Service 機制,Service 能夠以標籤的形式選定一組帶有指定標籤的 Pod,並監控和自動負載他們的 Pod IP,那麼咱們向外暴露只暴露 Service IP 就好了;這就是 NodePort 模式:即在每一個節點上開起一個端口,而後轉發到內部 Pod IP 上,
 
二、端口管理問題
採用 NodePort 方式暴露服務面臨問題是,服務一旦多起來,NodePort 在每一個節點上開啓的端口會及其龐大,並且難以維護;這時,咱們能夠可否使用一個Nginx直接對內進行轉發呢?衆所周知的是,Pod與Pod之間是能夠互相通訊的,而Pod是能夠共享宿主機的網絡名稱空間的,也就是說當在共享網絡名稱空間時,Pod上所監聽的就是Node上的端口。那麼這又該如何實現呢?簡單的實現就是使用 DaemonSet 在每一個 Node 上監聽 80,而後寫好規則,由於 Nginx 外面綁定了宿主機 80 端口(就像 NodePort),自己又在集羣內,那麼向後直接轉發到相應 Service IP 就好了,
 
三、域名分配及動態更新問題
從上面的方法,採用 Nginx-Pod 彷佛已經解決了問題,可是其實這裏面有一個很大缺陷:當每次有新服務加入又該如何修改 Nginx 配置呢??咱們知道使用Nginx能夠經過虛擬主機域名進行區分不一樣的服務,而每一個服務經過upstream進行定義不一樣的負載均衡池,再加上location進行負載均衡的反向代理,在平常使用中只須要修改nginx.conf便可實現,那在K8S中又該如何實現這種方式的調度呢???
 
假設後端的服務初始服務只有ecshop,後面增長了bbs和member服務,那麼又該如何將這2個服務加入到Nginx-Pod進行調度呢?總不能每次手動改或者Rolling Update 前端 Nginx Pod 吧!!此時 Ingress 出現了,若是不算上面的Nginx,Ingress 包含兩大組件:Ingress Controller 和 Ingress。
 
Ingress 簡單的理解就是你原來須要改 Nginx 配置,而後配置各類域名對應哪一個 Service,如今把這個動做抽象出來,變成一個 Ingress 對象,你能夠用 yaml 建立,每次不要去改 Nginx 了,直接改 yaml 而後建立/更新就好了;那麼問題來了:」Nginx 該怎麼處理?」
 
Ingress Controller 這東西就是解決 「Nginx 的處理方式」 的;Ingress Controoler 經過與 Kubernetes API 交互,動態的去感知集羣中 Ingress 規則變化,而後讀取他,按照他本身模板生成一段 Nginx 配置,再寫到 Nginx Pod 裏,最後 reload 一下,
 
實際上Ingress也是Kubernetes API的標準資源類型之一,它其實就是一組基於DNS名稱(host)或URL路徑把請求轉發到指定的Service資源的規則。用於將集羣外部的請求流量轉發到集羣內部完成的服務發佈。咱們須要明白的是,Ingress資源自身不能進行「流量穿透」,僅僅是一組規則的集合,這些集合規則還須要其餘功能的輔助,好比監聽某套接字,而後根據這些規則的匹配進行路由轉發,這些可以爲Ingress資源監聽套接字並將流量轉發的組件就是Ingress Controller。
 
PS:Ingress 控制器不一樣於Deployment 控制器的是,Ingress控制器不直接運行爲kube-controller-manager的一部分,它僅僅是Kubernetes集羣的一個附件,相似於CoreDNS,須要在集羣上單獨部署。
 
1、Service的概念
  運行在Pod中的應用是向客戶端提供服務的守護進程,好比,nginx、tomcat、etcd等等,它們都是受控於控制器的資源對象,存在生命週期,咱們知道Pod資源對象在自願或非自願終端後,只能被重構的Pod對象所替代,屬於不可再生類組件。而在動態和彈性的管理模式下,Service爲該類Pod對象提供了一個固定、統一的訪問接口和負載均衡能力。是否是以爲一堆話都沒聽明白呢????
 
  其實,就是說Pod存在生命週期,有銷燬,有重建,沒法提供一個固定的訪問接口給客戶端。而且爲了同類的Pod都可以實現工做負載的價值,由此Service資源出現了,能夠爲一類Pod資源對象提供一個固定的訪問接口和負載均衡,相似於阿里雲的負載均衡或者是LVS的功能。
 
  可是要知道的是,Service和Pod對象的IP地址,一個是虛擬地址,一個是Pod IP地址,都僅僅在集羣內部能夠進行訪問,沒法接入集羣外部流量。而爲了解決該類問題的辦法能夠是在單一的節點上作端口暴露(hostPort)以及讓Pod資源共享工做節點的網絡名稱空間(hostNetwork)之外,還可使用NodePort或者是LoadBalancer類型的Service資源,或者是有7層負載均衡能力的Ingress資源。
 
  Service是Kubernetes的核心資源類型之一,Service資源基於標籤選擇器將一組Pod定義成一個邏輯組合,並經過本身的IP地址和端口調度代理請求到組內的Pod對象,以下圖所示,它向客戶端隱藏了真是的,處理用戶請求的Pod資源,使得從客戶端上看,就像是由Service直接處理並響應同樣,是否是很像負載均衡器呢!
 
  Service對象的IP地址也稱爲Cluster IP,它位於爲Kubernetes集羣配置指定專用的IP地址範圍以內,是一種虛擬的IP地址,它在Service對象建立以後保持不變,而且可以被同一集羣中的Pod資源所訪問。Service端口用於接受客戶端請求,並將請求轉發至後端的Pod應用的相應端口,這樣的代理機制,也稱爲端口代理,它是基於TCP/IP 協議棧的傳輸層。
 
2、Service的實現模型
  在 Kubernetes 集羣中,每一個 Node 運行一個 kube-proxy 進程。kube-proxy 負責爲 Service 實現了一種 VIP(虛擬 IP)的形式,而不是 ExternalName 的形式。 在 Kubernetes v1.0 版本,代理徹底在 userspace。在 Kubernetes v1.1 版本,新增了 iptables 代理,但並非默認的運行模式。 從 Kubernetes v1.2 起,默認就是 iptables 代理。在Kubernetes v1.8.0-beta.0中,添加了ipvs代理。在 Kubernetes v1.0 版本,Service 是 「4層」(TCP/UDP over IP)概念。 在 Kubernetes v1.1 版本,新增了 Ingress API(beta 版),用來表示 「7層」(HTTP)服務。
 
kube-proxy 這個組件始終監視着apiserver中有關service的變更信息,獲取任何一個與service資源相關的變更狀態,經過watch監視,一旦有service資源相關的變更和建立,kube-proxy都要轉換爲當前節點上的可以實現資源調度規則(例如:iptables、ipvs)
 
 
2.一、userspace代理模式
  這種模式,當客戶端Pod請求內核空間的service iptables後,把請求轉到給用戶空間監聽的kube-proxy 的端口,由kube-proxy來處理後,再由kube-proxy將請求轉給內核空間的 service ip,再由service iptalbes根據請求轉給各節點中的的service pod。
 
  因而可知這個模式有很大的問題,由客戶端請求先進入內核空間的,又進去用戶空間訪問kube-proxy,由kube-proxy封裝完成後再進去內核空間的iptables,再根據iptables的規則分發給各節點的用戶空間的pod。這樣流量從用戶空間進出內核帶來的性能損耗是不可接受的。在Kubernetes 1.1版本以前,userspace是默認的代理模型。
 
 
2.二、 iptables代理模式
  客戶端IP請求時,直接請求本地內核service ip,根據iptables的規則直接將請求轉發到到各pod上,由於使用iptable NAT來完成轉發,也存在不可忽視的性能損耗。另外,若是集羣中存在上萬的Service/Endpoint,那麼Node上的iptables rules將會很是龐大,性能還會再打折扣。iptables代理模式由Kubernetes 1.1版本引入,自1.2版本開始成爲默認類型。
 
 
2.三、ipvs代理模式
  Kubernetes自1.9-alpha版本引入了ipvs代理模式,自1.11版本開始成爲默認設置。客戶端IP請求時到達內核空間時,根據ipvs的規則直接分發到各pod上。kube-proxy會監視Kubernetes Service對象和Endpoints,調用netlink接口以相應地建立ipvs規則並按期與Kubernetes Service對象和Endpoints對象同步ipvs規則,以確保ipvs狀態與指望一致。訪問服務時,流量將被重定向到其中一個後端Pod。
 
與iptables相似,ipvs基於netfilter 的 hook 功能,但使用哈希表做爲底層數據結構並在內核空間中工做。這意味着ipvs能夠更快地重定向流量,而且在同步代理規則時具備更好的性能。此外,ipvs爲負載均衡算法提供了更多選項,例如:
 
rr:輪詢調度
lc:最小鏈接數
dh:目標哈希
sh:源哈希
sed:最短時間望延遲
nq:不排隊調度
注意: ipvs模式假定在運行kube-proxy以前在節點上都已經安裝了IPVS內核模塊。當kube-proxy以ipvs代理模式啓動時,kube-proxy將驗證節點上是否安裝了IPVS模塊,若是未安裝,則kube-proxy將回退到iptables代理模式。
 
若是某個服務後端pod發生變化,標籤選擇器適應的pod有多一個,適應的信息會當即反映到apiserver上,而kube-proxy必定能夠watch到etc中的信息變化,而將它當即轉爲ipvs或者iptables中的規則,這一切都是動態和實時的,刪除一個pod也是一樣的原理。
 
4、Headless Service
有時不須要或不想要負載均衡,以及單獨的 Service IP。 遇到這種狀況,能夠經過指定 Cluster IP(spec.clusterIP)的值爲 "None" 來建立 Headless Service。
 
這個選項容許開發人員自由尋找他們本身的方式,從而下降與 Kubernetes 系統的耦合性。 應用仍然可使用一種自注冊的模式和適配器,對其它須要發現機制的系統可以很容易地基於這個 API 來構建。
 
對這類 Service 並不會分配 Cluster IP,kube-proxy 不會處理它們,並且平臺也不會爲它們進行負載均衡和路由。 DNS 如何實現自動配置,依賴於 Service 是否認義了 selector。
 
一、Pod資源對象
Pod資源對象是一種集合了一個或多個應用容器、存儲資源、專用ip、以及支撐運行的其餘選項的邏輯組件。
 
Kubernetes的網絡模型要求每一個Pod的IP地址同一IP網段,各個Pod之間可使用IP地址進行通訊,不管這些Pod運行在集羣內的哪一個節點上,這些Pod對象都相似於運行在同一個局域網內的虛擬機通常。
 
咱們能夠將每個Pod對象類比爲一個物理主機或者是虛擬機,那麼運行在同一個Pod對象中的多個進程,也就相似於跑在物理主機上的獨立進程,而不一樣的是Pod對象中的各個進程都運行在彼此隔離的容器當中,而各個容器之間共享兩種關鍵性資源:網絡和存儲卷。
 
網絡:每個Pod對象都會分配到一個Pod IP地址,同一個Pod內部的全部容器共享Pod對象的Network和UTS名稱空間,其中包括主機名、IP地址和端口等。所以,這些容器能夠經過本地的迴環接口lo進行通訊,而在Pod以外的其餘組件的通訊,則須要使用Service資源對象的Cluster IP+端口完成。
 
存儲卷:用戶能夠給Pod對象配置一組存儲卷資源,這些資源能夠共享給同一個Pod中的全部容器使用,從而完成容器間的數據共享。存儲卷還能夠確保在容器終止後被重啓,或者是被刪除後也能確保數據的持久化存儲。
 
一個Pod表明着某個應用程序的特定實例,若是咱們須要去擴展這個應用程序,那麼就意味着須要爲該應用程序同時建立多個Pod實例,每一個實例都表明着應用程序的一個運行副本。而這些副本化的Pod對象的建立和管理,都是由一組稱爲Controller的對象實現,好比Deployment控制器對象。
 
當建立Pod時,咱們還可使用Pod Preset對象爲Pod注入特定的信息,好比Configmap、Secret、存儲卷、卷掛載、環境變量等。有了Pod Preset對象,Pod模板的建立就不須要爲每一個模板顯示提供全部信息。
 
基於預約的指望狀態和各個節點的資源可用性,Master會把Pod對象調度至選定的工做節點上運行,工做節點從指向的鏡像倉庫進行下載鏡像,並在本地的容器運行時環境中啓動容器。Master會將整個集羣的狀態保存在etcd中,並經過API Server共享給集羣的各個組件和客戶端。
 
二、Controller
在K8S的集羣設計中,Pod是一個有生命週期的對象。那麼用戶經過手工建立或者經過Controller直接建立的Pod對象會被調度器(Scheduler)調度到集羣中的某個工做節點上運行,等到容器應用進程運行結束以後正常終止,隨後就會被刪除。而須要注意的是,當節點的資源耗盡或者故障,也會致使Pod對象的回收。
 
而K8S在這一設計上,使用了控制器實現對一次性的Pod對象進行管理操做。好比,要確保部署的應用程序的Pod副本數達到用戶預期的數目,以及基於Pod模板來重建Pod對象等,從而實現Pod對象的擴容、縮容、滾動更新和自愈能力。例如,在某個節點故障,相關的控制器會將運行在該節點上的Pod對象從新調度到其餘節點上進行重建。
 
控制器自己也是一種資源類型,其中包括Replication、Controller、Deployment、StatefulSet、DaemonSet、Jobs等等,它們都統稱爲Pod控制器。以下圖的Deployment就是這類控制器的表明實現,是目前用於管理無狀態應用的Pod控制器。
 
 
Pod控制器的定義一般由指望的副本數量、Pod模板、標籤選擇器組成。Pod控制器會根據標籤選擇器來對Pod對象的標籤進行匹配篩選,全部知足選擇條件的Pod對象都會被當前控制器進行管理並計入副本總數,確保數目可以達到預期的狀態副本數。
 
須要注意的是,在實際的應用場景中,在接收到的請求流量負載低於或接近當前已有Pod副本的承載能力時,須要咱們手動修改Pod控制器中的指望副本數量以實現應用規模的擴容和縮容。而在集羣中部署了HeapSet或者Prometheus的這一類資源監控組件時,用戶還能夠經過HPA(HorizontalPodAutoscaler)來計算出合適的Pod副本數量,並自動地修改Pod控制器中指望的副本數,從而實現應用規模的動態伸縮,提升集羣資源的利用率。
 
K8S集羣中的每一個節點上都運行着cAdvisor,用於收集容器和節點的CPU、內存以及磁盤資源的利用率直播數據,這些統計數據由Heapster聚合以後能夠經過API server訪問。而HorizontalPodAutoscaler基於這些統計數據監控容器的健康狀態並做出擴展決策。
 
三、Service
咱們知道Pod對象有Pod IP地址,可是該地址沒法確保Pod對象重啓或者重建以後保持不變,這會帶來集羣中Pod應用間依賴關係維護的麻煩。好比前段Pod應用沒法基於固定的IP地址跟中後端的Pod應用。
 
而Service資源就是在被訪問的Pod對象中添加一個有着固定IP地址的中間層,客戶端向該地址發起訪問請求後,由相關的Service資源進行調度並代理到後端的Pod對象。
 
Service並非一個具體的組件,而是一個經過規則定義出由多個Pod對象組成而成的邏輯集合,並附帶着訪問這組Pod對象的策略。Service對象挑選和關聯Pod對象的方式和Pod控制器是同樣的,都是經過標籤選擇器進行定義。以下圖:
 
 
Service IP是一種虛擬IP,也稱爲Cluster IP,專用於集羣內通訊,一般使用專有的地址段,如:10.96.0.0/12網絡,各Service對象的IP地址在該範圍內由系統動態分配。
 
集羣內的Pod對象可直接請求這類Cluster IP,好比上圖中來自Pod client的訪問請求,能夠經過Service的Cluster IP做爲目標地址進行訪問,可是在集羣網絡中是屬於私有的網絡地址,僅僅能夠在集羣內部訪問。
 
而須要將集羣外部的訪問引入集羣內部的經常使用方法是經過節點網絡進行,其實現方法以下:
 
經過工做節點的IP地址+端口(Node Port)接入請求。
將該請求代理到相應的Service對象的Cluster IP的服務端口上,通俗地說:就是工做節點上的端口映射了Service的端口。
由Service對象將該請求轉發到後端的Pod對象的Pod IP和 應用程序的監聽端口。
所以,相似於上圖來自Exxternal Client的集羣外部客戶端,是沒法直接請求該Service的Cluster IP,而是須要實現通過某一工做節點(如 Node Y)的IP地址,着了請求須要2次轉發才能到目標Pod對象。這一類訪問的缺點就是在通訊效率上有必定的延時。
相關文章
相關標籤/搜索