云原生系列二【Kubernetes】Kubernetes是如何运行的?
一、概述
隨著系統可部署組件的數量增長,把它們都管理起來會變得越來越困難。需要一個更好的方式來部署和管理這些組件, 并支持基礎設施的全球性伸縮,谷歌可能是第一個意識到這一點的公司。谷歌等全球少數幾個公司運行著成千上萬的服務器,而且在如此海量規模下,不得不處理部署管理的問題。這推動著他們找出解決方案使成千上萬組件的管理變得有效且成本低廉。
初衷
- 這些年來,谷歌開發出了一個叫Borg的內部系統(后來還有一個新 系統叫Omega),應用開發者和系統管理員管理那些數以千計的應用程序和服務都受益于它的幫助。除了簡化開發和管理,它也幫助他們獲得了更高的基礎設施利用率,在你的組織如此龐大時,這很重要。當你運行成千上萬臺機器時,哪怕一丁點的利用率提升也意味著節約了數百萬美元,所以,開發這個系統的動機是顯而易見的
在保守Borg和Omega秘密數十年之后,2014年,谷歌開放了Kubernetes,一個基于Borg、Omega及其他谷歌內部系統實踐的開源系統。 - Kubernetes是一個軟件系統,它允許你在其上很容易地部署和管理容器化的應用。它依賴于Linux容器的特性來運行異構應用,而無須知道這些應用的內部詳情,也不需要手動將這些應用部署到每臺機器。因為這些應用運行在容器里,它們不會影響運行在同一臺服務器上的其他應用,當你是為完全不同的組織機構運行應用時,這就很關鍵了。這對于云供應商來說是至關重要的,因為它們在追求高硬件可用率的同時也必須保障所承載應用的完全隔離。Kubernetes使你在數以千計的電腦節點上運行軟件時就像所有這些節點是單個大節點一樣。它將底層基礎設施抽象,這樣做同時簡化了應用的開發、部署,以及對開發和運維團隊的管理
通過Kubernetes部署應用程序時,你的集群包含多少節點都是一樣的。集群規模不會造成什么差異性,額外的集群節點只是代表一些額外的可用來部署應用的資源
Kubernetes的核心功能:
下圖展示了一幅最簡單的Kubernetes系統圖。整個系統由一個主節點和若干個工作節點組成。開發者把一個應用列表提交到主節點, Kubernetes會將它們部署到集群的工作節點。組件被部署在哪個節點對 于開發者和系統管理員來說都不用關心
開發者能指定一些應用必須一起運行,Kubernetes將會在一個工作節點上部署它們。其他的將被分散部署到集群中,但是不管部署在哪 兒,它們都能以相同的方式互相通信。
- 幫助開發者聚焦核心應用功能:Kubernetes可以被當作集群的一個操作系統來看待。它降低了開發者不得不在他們的應用里實現一些和基礎設施相關服務的心智負擔。他們現在依賴于Kubernetes來提供這些服務,包括服務發現、擴容、負載均衡、自恢復,甚至領導者的選舉。應用程序開發者因此能集中精力實現應用本身的功能而不用浪費時間思索怎樣集成應用與基礎設施。?????
-幫助運維團隊獲取更高的資源利用率:Kubernetes將你的容器化應用運行在集群的某個地方,并提供信息給應用組件來發現彼此并保證它們的運行。因為你的應用程序不關心它 運行在哪個節點上,Kubernetes能在任何時間遷移應用并通過混合和匹 配應用來獲得比手動調度高很多的資源利用率
二、核心組件
在硬件級別,一個Kubernetes集群由很多節點Node組成,Node是Kubernetes中的工作機器,可以是實體機可以是虛擬機,這些節點被分成以下兩種類型:
1、主節點(master Node),它承載著Kubernetes控制和管理整個集群系統的控制面板;
- etcd 保存了整個集群的狀態,是一個分布式的,一致的 key-value 存儲,主要用途是共享配置和服務發現,保存集群狀態數據,比如 Pod、Service 等對象信息;
- apiserver 是集群的統一入口,各組件協調者,以 HTTP Rest 提供接口服務,所有對象資源的增、刪、改、查和監聽操作都交給 apiserver 處理后再提交給 Etcd 存儲;
- controller manager 負責維護集群的狀態,比如故障檢測、自動擴展、滾動更新等,是 K8S 里所有資源對象的自動化控制中心,處理集群中常規后臺任務,一個資源對應一個控制器,而 controller-manager 就是負責管理這些控制器的;
- scheduler 負責資源的調度,按照預定的調度策略將 Pod 調度到相應的機器上,根據調度算法為新創建的 Pod 選擇一個 Node 節點,可以任意部署,可以部署在同一個節點上,也可以部署在不同的節點上;
2、工作節點(worker Node),它們運行用戶實際部署的應用;
除了 Master,K8S 集群中的其它機器被稱為 Node 節點,Node 節點是 K8S 集群中的工作負載節點,每個 Node 都會被 Master 分配一些工作負載,當某個 Node 宕機時,其上的工作負載會被 Master 自動轉移到其它節點上去。
- kubelet 負責與api server通信,并維護容器的生命周期,負責 Pod 對應的容器的創建、啟停等任務,實現集群管理的基本功能,同時也負責 Volume(CVI)和網絡(CNI)的管理。類似Master大王派我來巡山;
- Container runtime 負責鏡像管理以及 Pod 和容器的真正運行(CRI);
- kube-proxy 負責為 Service 提供 cluster 內部的服務發現和負載均衡,在 Node 節點上實現 Pod 網絡代理,實現 Kubernetes Service 的通信,維護網絡規則和四層負載均衡工作。
- docker engine:Docker 引擎,負責本機的容器創建和管理工作。Node 節點可以在運行期間動態增加到 K8S 集群中,前提是這個節點上已經正確安裝、配置和啟動了上述關鍵組件。在默認情況下 kubelet 會向 Master 注冊自己,一旦 Node 被納入集群管理范圍,kubelet 就會定時向 Master 節點匯報自身的情況,例如操作系統、Docker 版本、機器的 CPU 和內存情況,以及之前有哪些 Pod 在運行等,這樣 Master 可以獲知每個 Node 的資源使用情況,并實現高效均衡的資源調度策略。而某個 Node 超過指定時間不上報信息時,會被 Master 判定為“失聯”,Node 的狀態被標記為不可用(Not Ready),隨后 Master 會觸發“工作負載大轉移”的自動流程。
Kubernetes基本概念
Container Runtime
Container(容器)是一種便攜式、輕量級的操作系統級虛擬化技術。它使用 namespace 隔離不同的軟件運行環境,并通過鏡像自包含軟件的運行環境,從而使得容器可以很方便的在任何地方運行。
由于容器體積小且啟動快,因此可以在每個容器鏡像中打包一個應用程序。這種一對一的應用鏡像關系擁有很多好處。使用容器,不需要與外部的基礎架構環境綁定, 因為每一個應用程序都不需要外部依賴,更不需要與外部的基礎架構環境依賴。完美解決了從開發到生產環境的一致性問題。容器同樣比虛擬機更加透明,這有助于監測和管理。尤其是容器進程的生命周期由基礎設施管理,而不是被進程管理器隱藏在容器內部。最后,每個應用程序用容器封裝,管理容器部署就等同于管理應用程序部署。
Kubernetes 支持多個容器運行環境:Docker、containerd、cri-o、rktlet 以及任何實現 Kubernetes CRI (容器運行環境接口) 的軟件
Pod
Kubernetes 使用 Pod 來管理容器,每個 Pod 可以包含一個或多個緊密關聯的容器。
- Pod 是一組緊密關聯的容器集合,它們共享 IPC 和 Network namespace,是 Kubernetes 調度的基本單位。Pod 內的多個容器共享網絡和文件系統,可以通過進程間通信和文件共享這種簡單高效的方式組合完成服務。
- 在創建新部署時,Kubernetes會建立一個Pod來寄存你的應用實例,Pod是一個抽象的概念,但是每個pod在k8s網絡內有屬于它自己的ip,這個ip是由k8s創建的網絡統一分配的。Pod是Kuberlnetes平臺中的原子單位。在部署創建時,部署并不直接創建容器,而是創建包含了容器的Pod。Pod被分配綁定在指定的Node上,除非被停止或者刪除它會一直在該Node上工作。萬一出現Node宕機的情況,集群中另外一個可用的Node會馬上啟動運行一個完全一樣的Pod。其生命周期是短暫的(服務器重啟后,就找不到了)
- 每個 Pod 都由一個特殊的根容器 Pause 容器,以及一個或多個緊密相關的用戶業務容器組成。Pause 容器作為 Pod 的根容器,以它的狀態代表整個容器組的狀態。K8S 為每個 Pod 都分配了唯一的 IP 地址,稱之為 Pod IP。Pod 里的多個業務容器共享 Pause 容器的IP,共享 Pause 容器掛載的 Volume。 在設計時我們可以充分利用這一特性將一組密切相關的服務進程放入同一個Pod中,同一個Pod里的容器之間僅需通過localhost就能互相通信。
Label
標簽,附加到某個資源上,用于關聯對象、查詢和篩選。一個 Label 是一個 key=value 的鍵值對,key 與 value 由用戶自己指定。Label 可以附加到各種資源上,一個資源對象可以定義任意數量的 Label,同一個 Label 也可以被添加到任意數量的資源上。
我們可以通過給指定的資源對象捆綁一個或多個不同的 Label 來實現多維度的資源分組管理功能,以便于靈活、方便地進行資源分配、調度、配置、部署等工作。
K8S 通過 Label Selector(標簽選擇器)來查詢和篩選擁有某些 Label 的資源對象。Label Selector 有基于等式( name=label1 )和基于集合( name in (label1, label2) )的兩種方式。
ReplicaSet(RC)
ReplicaSet 用來確保預期的 Pod 副本數量,如果有過多的 Pod 副本在運行,系統就會停掉一些 Pod,否則系統就會再自動創建一些 Pod。
我們很少單獨使用 ReplicaSet,它主要被 Deployment 這個更高層的資源對象使用,從而形成一整套 Pod 創建、刪除、更新的編排機制。
Deployment
Deployment通常用來部署無狀態應用,如Web服務, 該服務運行的實例不會在本地存儲需要持久化的數據,并且多個實例對于同一個請求響應的結果是完全一致的。在內部使用ReplicaSet來實現Pod副本的創建。Deployment確保指定數量的Pod“副本”在運行,并且支持回滾和滾動升級。創建Deployment時,需要指定 Pod模板和Label標簽。
Horizontal Pod Autoscaler(HPA)
HPA 為 Pod 橫向自動擴容,也是 K8S 的一種資源對象。HPA 通過追蹤分析 RC 的所有目標 Pod 的負載變化情況,來確定是否需要針對性調整目標 Pod 的副本數量。
Service
Service 是應用服務的抽象,通過 labels 為應用提供負載均衡和服務發現。匹配 labels 的 Pod IP 和端口列表組成 endpoints,由 kube-proxy 負責將服務 IP 負載均衡到這些 endpoints 上。
Service 定義了一個服務的訪問入口,通過 Label Selector 與 Pod 副本集群之間“無縫對接”,定義了一組 Pod 的訪問策略,防止 Pod 失聯。
創建 Service 時,K8S會自動為它分配一個全局唯一的虛擬 IP 地址,即 Cluster IP。服務發現就是通過 Service 的 Name 和 Service 的 ClusterIP 地址做一個 DNS 域名映射來解決的。
Service能夠提供負載均衡的能力,但是在使用上有以下限制:
-
默認只提供 4 層負載均衡能力(IP+端口),而沒有 7 層功能(主機名和域名),但有時我們可能需要更多的匹配規則來轉發請求,這點上 4 層負載均衡是不支持的
-
后續可以通過Ingress方案,添加7層的能力
Service 在 K8s 中有以下四種類型(這部分看不懂可以先跳過,說的service如何對外暴露服務,后面使用ingress簡單很多) -
Clusterlp:默認類型,自動分配一個僅Cluster內部可以訪問的虛擬IP
-
NodePort:在ClusterlP基礎上為Service在每臺機器上綁定一個端口,這樣就可以通過:NodePort 來訪問該服務。訪問node01的30001相當于訪問定義的SVC后端的80的三個不pod同服務(RR)
client——》nginx(負載接收器,反向代理)——》node1,node2
-
LoadBalancer:在NodePort的基礎上,借助 cloud provider 創建一個外部負載均衡器,并將請求轉發到
:NodePort
-
ExternalName:把集群外部的服務引入到集群內部來,在集群內部直接使用。沒有任何類型代理被創建,這只有kubernetes1.7或更高版本的kube-dns才支持
其它
StatefulSet
StatefulSet通常用來部署有狀態應用,如Mysql服務,服務運行的實例需要在本地存儲持久化數據,多個實例之間有依賴拓撲關系,比如:主從關系、主備關系。如果停止掉依賴中的一個Pod,就會導致數據丟失或者集群崩潰。他的核心功能就是通過某種方式記錄這些狀態,然后在 Pod 被重新創建時,能夠為新 Pod 恢復這些狀態。它包含Deployment控制器ReplicaSet的所有功能,增加可以處理Pod的啟動順序,為保留每個Pod的狀態設置唯一標識,同時具有以下功能:
穩定的、唯一的網絡標識符
穩定的、持久化的存儲
有序的、優雅的部署和縮放
DaemonSet
DaemonSet:服務守護進程,它的主要作用是在Kubernetes集群的所有節點中運行我們部署的守護進程,相當于在集群節點上分別部署Pod副本,如果有新節點加入集群,Daemonset會自動的在該節點上運行我們需要部署的Pod副本,相反如果有節點退出集群,Daemonset也會移除掉部署在舊節點的Pod副本。
DaemonSet的主要特征:
這個 Pod 運行在 Kubernetes 集群里的每一個節點(Node)上;
每個節點上只會運行一個這樣的 Pod 實例;
如果新的節點加入 Kubernetes 集群后,該 Pod 會自動地在新節點上被創建出來;
而當舊節點被刪除后,它上面的 Pod 也相應地會被回收掉。
DaemonSet常用場景:
網絡插件的 Agent 組件,如(Flannel,Calico)需要運行在每一個節點上,用來處理這個節點上的容器網絡;
存儲插件的 Agent 組件,如(Ceph,Glusterfs)需要運行在每一個節點上,用來在這個節點上掛載F遠程存儲目錄;
監控系統的數據收集組件,如(Prometheus Node Exporter,Cadvisor)需要運行在每一個節點上,負責這個節點上的監控信息搜集。
日志系統的數據收集組件,如(Fluent,Logstash)需要運行在每一個節點上,負責這個節點上的日志信息搜集。
Job/CronJob
Job負責處理任務,即僅執行一次的任務,它保證批處理任務的一個或多個Pod成功結束,解決一些需要進行批量數據處理和分析的需求,,比如Jenkins Slave,發布完代碼后任務結束,Pod自動銷毀;
CronJob則就是在Job上加上了時間調度,用來執行一些周期性的任務。
ConfigMap
ConfigMap:就是為了讓鏡像和配置文件解耦,以便實現鏡像的可移植性和可復用性,因為一個configMap其實就是一系列配置信息的集合,將來可直接注入到Pod中的容器使用,而注入方式有兩種,一種將configMap做為存儲卷,一種是將configMap通過env中configMapKeyRef注入到容器中;
RBAC
RBAC:基于角色的訪問控制,可以用來給用戶授予對集群操作不同的權限。
Secret
Secret:用來保存敏感信息,例如密碼、OAuth 令牌和 ssh key等等,將這些信息放在Secret中比放在Pod的定義中或者docker鏡像中來說更加安全和靈活。
網絡
在實際的業務場景中,業務組件之間的關系十分復雜,特別是隨著微服務理念逐步深入人心,應用部署的粒度更加細小和靈活。為了支持業務應用組件的通信,Kubernetes網絡的設計主要致力于解決以下問題。
(1)容器到容器之間的直接通信。
(2)抽象的Pod到Pod之間的通信。
(3)Pod到Service之間的通信。
(4)集群外部與內部組件之間的通信。
Kubernetes的網絡模型假定了所有Pod都在一個可以直接連通的扁平的網絡空間中(都可以通過IP直接到達,其實底層有很多轉換機制),這在GCE(Google Compute Engine) 里面是現成的網絡模型,K8S假定這個網絡已存在。而在私有云搭建K8S集群,就不能假定這個網絡已經存在了。我們需要自己實現這個網絡假設,將不同節點上的Docker容器之間互相訪問先打通,然后再運行K8S。
1.容器到容器的通信
在上節講過了: docker 在bridge模式下,Docker Daemon第1次啟動時會創建一個虛擬的網橋,默認的名稱是docker0,然后按照RPC1918的模型在私有網絡空間中給這個網橋分配一個子網。針對由Docker創建的每一個容器,都會創建一個虛擬的以太網設備(Veth設備對),其中一端關聯到網橋上,另一端使用Linux的網絡命名空間技術,映射到容器內的eth0設備,然后從網橋的地址段內給eth0接口分配一個IP地址。
如上圖中的陰影部分所示,在Node上運行著一個Pod實例。在我們的例子中,容器就是圖中的容器1和容器2。容器1和容器2共享一個網絡的命名空間,共享一個命名空間的結果就是它們好像在一臺機器上運行,它們打開的端口不會有沖突,可以直接使用Linux的本地IPC進行通信(例如消息隊列或者管道)。其實,這和傳統的一組普通程序運行的環境是完全一樣的,傳統程序不需要針對網絡做特別的修改就可以移植了,它們之間的互相訪問只需要使用localhost就可以。例如,如果容器2運行的是MySQL,那么容器1使用localhost:3306就能直接訪問這個運行在容器2上的MySQL了。
- 同一個主機的容器,都可以通過doker0網橋和物理機網卡交互。我們這里講的還是同一個物理機或者虛擬機中的容器互相通信,不同的主機中的容器現在還交互不了,需要搭載pod網絡的順風車。
Pod之間的通信
我們看了同一個Pod內的容器之間的通信情況,再看看Pod之間的通信情況。
每一個Pod都有一個真實的全局IP地址,同一個Node內的不同Pod之間可以直接采用對方Pod的IP地址通信,而且不需要采用其他發現機制,例如DNS、Consul或者etcd。
Pod容器既有可能在同一個Node上運行,也有可能在不同的Node上運行,所以通信也分為兩類:同一個Node內Pod之間的通信和不同Node上的Pod之間的通信。
同一個Node內Pod之間的通信
我們看一下同一個Node內兩個Pod之間的關系,如下圖所示:
可以看出,Pod1和Pod2都是通過Veth連接到同一個docker0網橋上的,它們的IP地址IP1、IP2都是從docker0的網段上動態獲取的,它們和網橋本身的IP3是同一個網段的。
另外,在Pod1、Pod2的Linux協議棧上,默認路由都是docker0的地址,也就是說所有非本地地址的網絡數據,都會被默認發送到docker0網橋上,由docker0網橋直接中轉。
綜上所述,由于它們都關聯在同一個docker0網橋上,地址段相同,所以它們之間是能直接通信的。
不同Node上Pod之間的通信
Pod的地址是與docker0在同一個網段的,我們知道docker0網段與宿主機網卡是兩個完全不同的IP網段,并且不同Node之間的通信只能通過宿主機的物理網卡進行,因此要想實現不同Node上Pod容器之間的通信,就必須想辦法通過主機的這個IP地址進行尋址和通信。
另一方面,這些動態分配且藏在docker0之后的所謂“私有”IP地址也是可以找到的。Kubernetes會記錄所有正在運行的Pod的IP分配信息,并將這些信息保存在etcd中(作為Service的Endpoint)。這些私有IP信息對于Pod到Pod的通信也是十分重要的,因為我們的網絡模型要求Pod到Pod使用私有IP進行通信。所以首先要知道這些IP是什么。
之前提到,Kubernetes的網絡對Pod的地址是平面的和直達的,所以這些Pod的IP規劃也很重要,不能有沖突。只要沒有沖突,我們就可以想辦法在整個Kubernetes的集群中找到它。
綜上所述,要想支持不同Node上Pod之間的通信,就要滿足兩個條件:
- (1)在整個Kubernetes集群中對Pod的IP分配進行規劃,不能有沖突;
(2)找到一種辦法,將Pod的IP和所在Node的IP關聯起來,通過這個關聯讓Pod可以互相訪問。 - 根據條件1的要求,我們需要在部署Kubernetes時對docker0的IP地址進行規劃,保證每個Node上的docker0地址都沒有沖突。我們可以在規劃后手工配置到每個Node上,或者做一個分配規則,由安裝的程序自己去分配占用。例如,Kubernetes的網絡增強開源軟件Flannel就能夠管理資源池的分配。
根據條件2的要求,Pod中的數據在發出時,需要有一個機制能夠知道對方Pod的IP地址掛在哪個具體的Node上。也就是說先要找到Node對應宿主機的IP地址,將數據發送到這個宿主機的網卡,然后在宿主機上將相應的數據轉發到具體的docker0上。一旦數據到達宿主機Node,則那個Node內部的docker0便知道如何將數據發送到Pod。如下圖所示:
網絡解決方案K8S+Flannel
ETCD之Flannel提供說明:
>存儲管理Flannel可分配的IP地址段資源
>監控ETCD中每個Pod的實際地址,并在內存中建立維護Pod節點路由表
(RealServer可以理解為物理機或者虛擬機,黃色部分代表我們部署的一個真實應用,這個應用部署一個一個pod中。app1=pod1,app2=pod2,app3=pod3,backend=pod4)
- 同一個 Pod 內部通訊:同一個 Pod 共享同一個網絡命名空間,共享同一個 Linux 協議棧,apache和mysql可以直接localhost訪問。
- Pod1 與 Pod2 在同一臺機器,由 Docker0 網橋直接轉發請求至 Pod2,不需要經過 Flannel
- Pod1 與 Pod3不在同一臺主機,Pod的地址是與docker0在同一個網段的,但docker0網段與宿主機網卡是兩個完全不同的IP網段,并且不同Node之間的通信只能通過宿主機的物理網卡進行。將Pod的IP和所在Node的IP關聯起來,通過這個關聯讓Pod可以互相訪問。docker0轉發到flannel,flannel從etcd查到要訪問pod主機的物理ip地址,封裝成udp報文轉發出去。
??
圖片來自網絡
Pod到Service
直接訪問Pod資源,存在的缺陷
- 1.Pod會隨時被Deployment這樣的控制器刪除重建,訪問Pod的結果就會變得不可預知
- 2.Pod的地址是在Pod啟動后才被分配,在啟動之前并不知道Pod的IP地址
- 3.應用往往都是由多個運行相同鏡像的一組Pod組成,一個個Pod的訪問變得不現實
k8s中Service對象是用來解決上述Pod訪問的問題
Service有一個固定IP地址,Service將訪問該地址的流量轉發給Pod,pod會將自身的ip上報到api server,然后建立service和pod到Iptables,具體轉發給那些Pod通過Label來選擇,而且Service可以給這些Pod做負載均衡。各節點的Iptables規則,新版本支持LVS 轉發上限、效率更高。
我們來看看這個pod建立的過程:
etcd鍵值庫只對API server開放,API server就是k8s集群中的控制中心,一般對API server所在的Master做集群,避免因單點故障影響k8s集群中業務的訪問。
創建pod
- 通過kubectl命令輸入create pod命令
- 創建命令到達API server后,API server把創建pod的信息寫入到etcd鍵值庫中
- API server把創建新pod的需求傳給scheduler,scheduler通過算法計算分配到合適的Node節點,分配綁定到后端Node上的信息傳回至API - server,API server在把此信息寫入到etcd鍵值庫中
- API server傳遞新建pod信息至Scheduler指定node節點的kubelet程序,kubelet接管后,創建出本地指定的container后,完成信息返回至API server
- API server把新建好的pod信息寫入到etcd鍵值庫中
至此,一個簡單的kubectl create POD_NAME ***就新建完成。這里就建立來pod ip到物理主機到ip映射規則
創建pod節點的service
- 通過kubectl提交一個pod的service創建請求
- Controller Manager會通過對應的Label標簽查詢到相關的pod實例,生-- 成Serveice的Endpoints信息,并通過API server寫入到etcd鍵值庫中
- Worker Node節點上的kube proxy通過API server查詢并監聽service對象與其對應的Endpoints信息(服務發現),創建一個類似負載均衡器實現- - Service訪問到后端Pod的流量轉發功能(負載均衡)。
這就建立來service 別名到pod ip地址之間的映射規則
集群外部與內部組件之間的通信
前面講到的都是k8s的內部網絡,公網是看不見到,要想與外部訪問,k8s必須講服務暴露出去。Kubernetes 暴露服務的有三種方式,分別為 LoadBlancer Service、NodePort Service、Ingress。官網對 Ingress 的定義為管理對外服務到集群內服務之間規則的集合,通俗點講就是它定義規則來允許進入集群的請求被轉發到集群中對應服務上,從來實現服務暴露。 Ingress 能把集群內 Service 配置成外網能夠訪問的 URL,流量負載均衡,終止SSL,提供基于域名訪問的虛擬主機等等。
LoadBlancer Service
LoadBlancer Service 是 Kubernetes 結合云平臺的組件,如國外 GCE、AWS、國內阿里云等等,使用它向使用的底層云平臺申請創建負載均衡器來實現,有局限性,對于使用云平臺的集群比較方便。
NodePort Service
NodePort Service 是通過在節點上暴露端口,然后通過將端口映射到具體某個服務上來實現服務暴露,比較直觀方便,但是對于集群來說,隨著 Service 的不斷增加,需要的端口越來越多,很容易出現端口沖突,而且不容易管理。當然對于小規模的集群服務,還是比較不錯的。
Ingress網關
Ingress 使用開源的反向代理負載均衡器來實現對外暴露服務,其實就相當于 nginx、haproxy 等負載均衡代理服務器,目前選擇有很多: traefik、nginx-controller、Kubernetes Ingress Controller for Kong、HAProxy Ingress controller等。Nginx Ingress 一般有三個組件組成:
1)ingress是kubernetes的一個資源對象,用于編寫定義規則。指的是k8s中的一個api對象,一般用yaml配置。作用是定義請求如何轉發到service的規則,可以理解為配置模板。
2)反向代理負載均衡器,通常以Service的Port方式運行,接收并按照ingress定義的規則進行轉發,通常為nginx,haproxy,traefik等,本文使用nginx。
3)ingress-controller,監聽apiserver,獲取服務新增,刪除等變化,并結合ingress規則動態更新到反向代理負載均衡器上,并重載配置使其生效。簡單來說,ingress-controller才是負責具體轉發的組件,通過各種方式將它暴露在集群入口,外部對集群的請求流量會先到ingress-controller,而ingress對象是用來告訴ingress-controller該如何轉發請求,比如哪些域名哪些path要轉發到哪些服務等等
以上三者有機的協調配合起來,就可以完成 Kubernetes 集群服務的暴露。
- externalLB : 外部的4層負載均衡器
- ingress-nginx : nodePort 類型的 service 為 ingress-nginx 的 pod 接入外部流量
- ingress-nginx : ingress-nginx pod, 負責創建負載均衡(一個安裝了nginx 的 pod)
- : Ingress 根據后端 Service 實時識別分類及 IP 把結果生成配置文件注入到 ingress-nginx pod 中
- site1 : Service 對后端的pod 進行分類(只起分類作用)
總結:到現在我們已經了解完了:
- 同主機容器到容器間的通信,docker0網橋
- 同主機pod之間的通信,通過pause的docker0網橋
- pod和自身物理主機的訪問,docker0和物理網卡
- 不同主機容器間訪問,通過pod 網絡訪問
- 不同主機的pod訪問,通過etcd的pod和物理網卡ip地址映射表訪問
- pod和service,通過service-label-podip
- 外部和service訪問,通過svc機制,暴露服務,通過代理訪問。
以及k8s中各個關鍵組件之間如何協同工作的。
集群搭建 —— 平臺規劃
1、生產環境 K8S 平臺規劃
K8S 環境有兩種架構方式,單 Master 集群和多 Master 集群,將先搭建起單 Master 集群,再擴展為多 Master 集群。開發、測試環境可以部署單 Master 集群,生產環境為了保證高可用需部署多 Master 集群。
① 單 Master 集群架構
單 Master 集群架構相比于多 Master 集群架構無法保證集群的高可用,因為 master 節點一旦宕機就無法進行集群的管理工作了。單 master 集群主要包含一臺 Master 節點,及多個 Node 工作節點、多個 Etcd 數據庫節點。
Etcd 是 K8S 集群的數據庫,可以安裝在任何地方,也可以與 Master 節點在同一臺機器上,只要 K8S 能連通 Etcd。
② 多 Master 集群架構
多 Master 集群能保證集群的高可用,相比單 Master 架構,需要一個額外的負載均衡器來負載多個 Master 節點,Node 節點從連接 Master 改成連接 LB 負載均衡器。
參考文獻:
1、https://www.e-learn.cn/topic/3880559
2、https://www.pianshen.com/article/54812149204/
3、https://www.cnblogs.com/chiangchou/p/k8s-1.html
4、https://www.cnblogs.com/klvchen/p/9903480.html
5、https://blog.csdn.net/qq_39578545/article/details/108893076?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-108893076-blog-109775528.pc_relevant_antiscanv3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-108893076-blog-109775528.pc_relevant_antiscanv3&utm_relevant_index=2
總結
以上是生活随笔為你收集整理的云原生系列二【Kubernetes】Kubernetes是如何运行的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle中trim函数的用法
- 下一篇: Python学海无涯路【第01回】初始P