選單

“Docker VS Kubernetes”是共生還是相愛相殺?

導語 | 當今容器化技術發展盛行。本文將介紹從單機容器化技術Docker到分散式容器化架構方案Kubernetes,主要面向小白讀者,旨在快速帶領讀者瞭解Docker、Kubernetes的架構、原理、元件及相關使用場景。

一、Docker

(一)什麼是Docker

Docker是一個開源的應用容器引擎,是一種資源虛擬化技術,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的Linux機器上。虛擬化技術演歷路徑可分為三個時代:

物理機時代,多個應用程式可能跑在一臺物理機器上:

“Docker VS Kubernetes”是共生還是相愛相殺?

虛擬機器時代,一臺物理機器啟動多個虛擬機器例項,一個虛擬機器跑多個應用程式:

“Docker VS Kubernetes”是共生還是相愛相殺?

容器化時代,一臺物理機上啟動多個容器例項,一個容器跑多個應用程式:

“Docker VS Kubernetes”是共生還是相愛相殺?

在沒有Docker的時代,我們會使用硬體虛擬化(虛擬機器)以提供隔離。這裡,虛擬機器透過在作業系統上建立了一箇中間虛擬軟體層Hypervisor,並利用物理機器的資源虛擬出多個虛擬硬體環境來共享宿主機的資源,其中的應用執行在虛擬機器核心上。但是,虛擬機器對硬體的利用率存在瓶頸,因為虛擬機器很難根據當前業務量動態調整其佔用的硬體資源,加之容器化技術蓬勃發展使其得以流行。

Docker、虛擬機器對比:

“Docker VS Kubernetes”是共生還是相愛相殺?

另外開發人員在實際的工作中,經常會遇到測試環境或生產環境與本地開發環境不一致的問題,輕則修復保持環境一致,重則可能需要返工。但Docker恰好解決了這一問題,它將軟體程式和執行的基礎環境分開。開發人員編碼完成後將程式整合環境透過DockerFile打包到一個容器映象中,從根本上解決了環境不一致的問題。

(二)Docker的構成

Docker由映象、映象倉庫、容器三個部分組成。

映象: 跨平臺、可移植的程式+環境包;

映象倉庫: 映象的儲存位置,有云端倉庫和本地倉庫之分,官方映象倉庫地址(https://hub。docker。com/);

容器: 進行了資源隔離的映象執行時環境。

(三)Docker的實現原理

到此讀者們肯定很好奇Docker是如何進行資源虛擬化的,並且如何實現資源隔離的,其核心技術原理主要有(內容部分參考自Docker核心技術與實現原理):

(https://draveness。me/docker/)

“Docker VS Kubernetes”是共生還是相愛相殺?

Namespace

>在日常使用Linux或者macOS時,我們並沒有執行多個完全分離的伺服器的需要,但是如果我們在伺服器上啟動了多個服務,這些服務其實會相互影響的,每一個服務都能看到其他服務的程序,也可以訪問宿主機器上的任意檔案,這是很多時候我們都不願意看到的,我們更希望執行在同一臺機器上的不同服務能做到完全隔離,就像執行在多臺不同的機器上一樣。

名稱空間(Namespaces)是Linux為我們提供的用於分離程序樹、網路介面、掛載點以及程序間通訊等資源的方法。Linux的名稱空間機制提供了以下七種不同的名稱空間,透過這七個選項我們能在建立新的程序時設定新程序應該在哪些資源上與宿主機器進行隔離。

1。 CLONE_NEWCGROUP;

2。 CLONE_NEWIPC;

3。 CLONE_NEWNET;

4。 CLONE_NEWNS;

5。 CLONE_NEWPID;

6。 CLONE_NEWUSER;

7。 CLONE_NEWUTS。

“Docker VS Kubernetes”是共生還是相愛相殺?

在Linux系統中,有兩個特殊的程序,一個是pid為1的/sbin/init程序,另一個是pid為2的kthreadd程序,這兩個程序都是被Linux中的上帝程序 idle創建出來的,其中前者負責執行核心的一部分初始化工作和系統配置,也會建立一些類似getty的註冊程序,而後者負責管理和排程其他的核心程序。

當在宿主機執行Docker,透過`docker run`或`docker start`建立新容器程序時,會傳入CLONE_NEWPID實現程序上的隔離。

“Docker VS Kubernetes”是共生還是相愛相殺?

接著,在方法`createSpec`的`setNamespaces`中,完成除程序名稱空間之外與使用者、網路、IPC以及UTS相關的名稱空間的設定。

網路

當Docker容器完成名稱空間的設定,其網路也變成了獨立的名稱空間,與宿主機的網路互聯便產生了限制,這就導致外部很難訪問到容器內的應用程式服務。Docker提供了4種網路模式,透過`——net`指定。

host

container

none

bridge

由於後續介紹Kubernetes利用了Docker的bridge網路模式,所以僅介紹該模式。Linux中為了方便各網路名稱空間的網路互相訪問,設定了Veth Pair和網橋來實現,Docker也是基於此方式實現了網路通訊。

下圖`eth0`與`veth9953b75`是一個Veth Pair,`eth0`與`veth3e84d4f`為另一個Veth Pair。Veth Pair在容器內一側會被設定為`eth0`模擬網絡卡,另一側連線Docker0網橋,這樣就實現了不同容器間網路的互通。加之Docker0為每個容器配置的iptables規則,又實現了與宿主機外部網路的互通。

“Docker VS Kubernetes”是共生還是相愛相殺?

掛載點

在新的程序中建立隔離的掛載點名稱空間需要在clone函式中傳入 CLONE_NEWNS,這樣子程序就能得到父程序掛載點的複製,如果不傳入這個引數子程序對檔案系統的讀寫都會同步回父程序以及整個主機的檔案系統。當一個容器需要啟動時,它一定需要提供一個根檔案系統rootfs,容器需要使用這個檔案系統來建立一個新的程序,所有二進位制的執行都必須在這個根檔案系統中,並建立一些符號連結來保證IO不會出現問題。

“Docker VS Kubernetes”是共生還是相愛相殺?

另外,透過Linux的`chroot`命令能夠改變當前的系統根目錄結構,透過改變當前系統的根目錄,我們能夠限制使用者的權利,在新的根目錄下並不能夠訪問舊系統根目錄的結構個檔案,也就建立了一個與原系統完全隔離的目錄結構。

Control Groups(CGroups)

Control Groups(CGroups)提供了宿主機上物理資源的隔離,例如 CPU、記憶體、磁碟 I/O和網路頻寬。主要由這幾個元件構成:

控制組(CGroups)一個CGroup包含一組程序,並可以在這個CGroup上增加Linux Subsystem的各種引數配置,將一組程序和一組Subsystem關聯起來。

Subsystem子系統是一組資源控制模組,比如CPU子系統可以控制CPU時間分配,記憶體子系統可以限制CGroup記憶體使用量。可以透過`lssubsys -a`命令檢視當前核心支援哪些Subsystem。

Hierarchy層級樹主要功能是把CGroup串成一個樹型結構,使CGruop可以做到繼承,每個Hierarchy透過繫結對應的Subsystem進行資源排程。

Task在CGroups中,task就是系統的一個程序。一個任務可以加入某個 CGroup,也可以從某個CGroup遷移到另外一個CGroup。

在Linux的Docker安裝目錄下有一個docker目錄,當啟動一個容器時,就會建立一個與容器識別符號相同的CGroup,舉例來說當前的主機就會有以下層級關係:

“Docker VS Kubernetes”是共生還是相愛相殺?

每一個CGroup下面都有一個tasks檔案,其中儲存著屬於當前控制組的所有程序的pid,作為負責cpu的子系統,cpu。cfs_quota_us檔案中的內容能夠對CPU的使用作出限制,如果當前檔案的內容為50000,那麼當前控制組中的全部程序的CPU佔用率不能超過50%。

當我們使用Docker關閉掉正在執行的容器時,Docker的子控制組對應的資料夾也會被Docker程序移除。

UnionFS

Docker中的每一個映象都是由一系列只讀的層組成的,Dockerfile中的每一個命令都會在已有的只讀層上建立一個新的層:

Docker中的每一個映象都是由一系列只讀的層組成的,Dockerfile中的每一個命令都會在已有的只讀層上建立一個新的層:

容器中的每一層都只對當前容器進行了非常小的修改,上述的Dockerfile 檔案會構建一個擁有四層layer的映象:

“Docker VS Kubernetes”是共生還是相愛相殺?

當映象被`docker run`命令建立時就會在映象的最上層新增一個可寫的層,也就是容器層,所有對於執行時容器的修改其實都是對這個容器讀寫層的修改。容器和映象的區別就在於,所有的映象都是隻讀的,而每一個容器其實等於映象加上一個可讀寫的層,也就是同一個映象可以對應多個容器。

“Docker VS Kubernetes”是共生還是相愛相殺?

二、Kubernetes

(一)

為什麼要Kubernetes

儘管Docker為容器化的應用程式提供了開放標準,但隨著容器越來越多出現了一系列新問題:

單機不足以支援更多的容器

分散式環境下容器如何通訊?

如何協調和排程這些容器?

如何在升級應用程式時不會中斷服務?

如何監視應用程式的執行狀況?

如何批次重新啟動容器裡的程式?

。。。

Kubernetes應運而生。

(二)什麼是Kubernetes

Kubernetes是一個全新的基於容器技術的分散式架構方案,這個方案雖然還很新,但卻是Google十幾年來大規模應用容器技術的經驗積累和昇華的重要成果,確切的說是Google一個久負盛名的內部使用的大規模叢集管理系統——Borg的開源版本,其目的是實現資源管理的自動化以及跨資料中心的資源利用率最大化。

Kubernetes具有完備的叢集管理能力,包括多層次的安全防護和准入機制、多租戶應用支撐能力、透明的服務註冊和服務發現機制、內建的智慧負載均衡器、強大的故障發現和自我修復能力、服務滾動升級和線上擴容能力、可擴充套件的資源自動排程機制,以及多力度的資源配額管理能力。同時,Kubernetes提供了完善的管理工具,這些工具涵蓋了包括開發、部署測試、運維監控在內的各個環節,不僅是一個全新的基於容器技術的分散式架構解決方案,還是一個一站式的完備分散式系統開發和支撐平臺。

(三)Kubernetes術語

Pod

Pod是Kubernetes最重要的基本概念,可由多個容器(一般而言一個容器一個程序,不建議一個容器多個程序)組成,它是系統中資源分配和排程的最小單位。下圖是Pod的組成示意圖,其中有一個特殊的Pause容器:

“Docker VS Kubernetes”是共生還是相愛相殺?

Pause容器的狀態標識了一個Pod的狀態,也就是代表了Pod的生命週期。另外Pod中其餘容器共享Pause容器的名稱空間,使得Pod內的容器能夠共享Pause容器的IP,以及實現檔案共享。以下是一個Pod的定義:

Label

Label是Kubernetes系統中的一個核心概念,一個Label表示一個 key=value的鍵值對,key、value的值由使用者指定。Label可以被附加到各種資源物件上,例如Node、Pod、Service、RC等,一個資源物件可以定義任意數量的Label,同一個Label也可以被新增到任意數量的資源物件上。Label通常在資源物件定義時確定,也可以在物件建立後動態新增或者刪除。給一個資源物件定義了Label後,我們隨後可以透過Label Selector查詢和篩選擁有這個Label的資源物件,來實現多維度的資源分組管理功能,以便靈活、方便地進行資源分配、排程、配置、部署等管理工作。Label Selector當前有兩種表示式,基於等式的和基於集合的:

`name=redis-slave`: 匹配所有具有標籤`name=redis-slave`的資源物件。

`env!=production`: 匹配所有不具有標籤`env=production`的資源物件。

`name in(redis-master, redis-slave)`:`name=redis-master`或者`name=redis-slave`的資源物件。

`name not in(php-frontend)`:匹配所有不具有標籤`name=php-frontend`的資源物件。

以myWeb Pod為例:

當一個Service的selector中指明瞭這個Pod時,該Pod就會與該Service繫結:

Replication Controller

Replication Controller,簡稱RC,簡單來說,它其實定義了一個期望的場景,即宣告某種Pod的副本數量在任意時刻都符合某個預期值。

RC的定義包括如下幾個部分:

Pod期待的副本數量;

用於篩選目標Pod的Label Selector;

當Pod的副本數小於預期數量時,用於建立新Pod的模版(template)。

當提交這個RC在叢集中後,Controller Manager會定期巡檢,確保目標Pod例項的數量等於RC的預期值,過多的數量會被停掉,少了則會建立補充。透過`kubectl scale`可以動態指定RC的預期副本數量。

Deployment

Deployment和RC相似度超過90%,無論是作用、目的、Yaml定義還是具體命令列操作,所以可以將其看作是RC的升級。而Deployment 相對於RC的一個最大區別是我們可以隨時知道當前Pod“部署”的進度。實際上由於一個Pod的建立、排程、繫結節點及在目 標Node上啟動對應的容器這一完整過程需要一定的時間,所以我們期待系統啟動N個Pod副本的目標狀態,實際上是一個連續變化的“部署過程”導致的最終狀態。

Horizontal Pod Autoscaler

除了手動執行`kubectl scale`完成Pod的擴縮容之外,還可以透過Horizontal Pod Autoscaling(HPA)橫向自動擴容來進行自動擴縮容。其原理是追蹤分析目標Pod的負載變化情況,來確定是否需要針對性地調整目標Pod數量。當前,HPA有一下兩種方式作為Pod負載的度量指標:

CPUUtilizationPercentage,目標Pod所有副本自身的CPU利用率的平均值。

應用程式自定義的度量指標,比如服務在每秒內的相應請求數(TPS或QPS)

根據上邊定義,當Pod副本的CPUUtilizationPercentage超過90%時就會出發自動擴容行為,數量約束為1~3個。

StatefulSet

在Kubernetes系統中,Pod的管理物件RC、Deployment、DaemonSet和Job都面向無狀態的服務。但現實中有很多服務是有狀態的,特別是 一些複雜的中介軟體叢集,例如MySQL叢集、MongoDB叢集、Akka集 群、ZooKeeper叢集等,這些應用叢集有4個共同點。

每個節點都有固定的身份ID,透過這個ID,叢集中的成員可以相互發現並通訊。

叢集的規模是比較固定的,叢集規模不能隨意變動。

叢集中的每個節點都是有狀態的,通常會持久化資料到永久儲存中。

如果磁碟損壞,則集群裡的某個節點無法正常執行,叢集功能受損。

因此,StatefulSet具有以下特點:

StatefulSet裡的每個Pod都有穩定、唯一的網路標識,可以用來發現叢集內的其他成員。假設StatefulSet的名稱為kafka,那麼第1個Pod叫kafka-0,第2個叫kafka-1,以此類推。

StatefulSet控制的Pod副本的啟停順序是受控的,操作第n個Pod 時,前n-1個Pod已經是執行且準備好的狀態。

StatefulSet裡的Pod採用穩定的持久化儲存卷,透過PV或PVC來實現,刪除Pod時預設不會刪除與StatefulSet相關的儲存卷(為了保證數 據的安全)。

StatefulSet除了要與PV卷捆綁使用以儲存Pod的狀態資料,還要與 Headless Service配合使用。

Service

Service在Kubernetes中定義了一個服務的訪問入口地址,前端的應用(Pod)透過這個入口地址訪問其背後的一組由Pod副本組成的叢集例項Service與其後端Pod副本叢集之間則是透過Label Selector,來實現無縫對接的。

“Docker VS Kubernetes”是共生還是相愛相殺?

Service的負載均衡

在Kubernetes叢集中,每個Node上會執行著kube-proxy元件,這其實就是一個負載均衡器,負責把對Service的請求轉發到後端的某個Pod例項上,並在內部實現服務的負載均衡和繪畫保持機制。其主要的實現就是每個Service在叢集中都被分配了一個全域性唯一的Cluster IP,因此我們對 Service的網路通訊根據內部的負載均衡演算法和會話機制,便能與Pod副本叢集通訊。

Service的服務發現

因為ClusterIP在Service的整個宣告週期內是固定的,所以在Kubernetes中,只需將Service的Name和其Cluster IP做一個DNS域名對映即可解決。

Volume

Volume是Pod中能夠被多個容器訪問的共享目錄,Kubernetes中的 Volume概念、用途、目的與Docker中的Volumn比較類似,但不等價。首先,其可被定義在Pod上,然後被一個Pod裡的多個容器掛載到具體的檔案目錄下;其次,Kubernetes中的Volume與Pod的生命週期相同,但與容器的生命週期不相關,當容器終止或者重啟時,Volume中的資料也不會丟失。

Kubernetes提供了非常豐富的Volume型別:

emptyDir,它的初始內容為空,並且無須指定宿主機上對應的目錄檔案,因為這是Kubernetes自動分配的一個目錄,當Pod從Node上移除 emptyDir中的資料也會被永久刪除,適用於臨時資料。

hostPath,hostPath為在Pod上掛載宿主機上的檔案或目錄,適用於持久化儲存的資料,比如容器應用程式生成的日誌檔案。

NFS,可使用NFS網路檔案系統提供的共享目錄儲存資料。

其他雲持久化盤等。

Persistent Volume

在使用虛擬機器的情況下,我們通常會先定義一個網路儲存,然後從中劃出一個“網盤”並掛接到虛擬機器上。Persistent Volume(PV) 和與之相關聯的 Persistent Volume Claim(PVC) 也起到了類似的作用。PV可以被理解成Kubernetes叢集中的某個網路儲存對應的一塊儲存,它與Volume類似,但有以下區別:

PV只能是網路儲存,不屬於任何Node,但可以在每個Node上訪問。

PV並不是被定義在Pod上的,而是獨立於Pod之外定義的。

如果Pod想申請某種型別的PV,首先需要定義一個PersistentVolumeClaim物件:

然後在Pod的Volume中引用PVC即可。

PV有以下幾種狀態:

Available:空閒。

Bound:已繫結到PVC。

Relead:對應PVC被刪除,但PV還沒被回收。

Faild:PV自動回收失敗。

Namespace

Namespace在很多情況下用於實現多租戶的資源隔離。分組的不同專案、小組或使用者組,便於不同的分組在共享使用整個叢集的資源的同時還能被分別管理。Kubernetes叢集在啟動後會建立一個名為default的Namespace,透過kubectl可以檢視:

ConfigMap

我們知道,Docker透過將程式、依賴庫、資料及 配置檔案“打包固化”到一個不變的映象檔案中的做法,解決了應用的部署的難題,但這同時帶來了棘手的問題,即配置檔案中的引數在執行期如何修改的問題。我們不可能在啟動Docker容器後再修改容器裡的配置檔案,然後用新的配置檔案重啟容器裡的使用者主程序。為了解決這個問題,Docker提供了兩種方式:

在執行時透過容器的環境變數來傳遞引數;

透過Docker Volume將容器外的配置檔案對映到容器內。

在大多數情況下,後一種方式更合適我們的系統,因為大多數應用通常從一個或多個配置檔案中讀取引數。但這種方式也有明顯的缺陷:我們必須在目標主機上先建立好對應 配置檔案,然後才能對映到容器裡。上述缺陷在分散式情況下變得更為嚴重,因為無論採用哪種方式,寫入(修改)多臺伺服器上的某個指定檔案,並確保這些檔案保持一致,都是一個很難完成的目標。針對上述問題,Kubernetes給出了一個很巧妙的設計實現。

首先,把所有的配置項都當作key-value字串,這些配置項可以作為Map表中的一個項,整個Map的資料可以被持久化儲存在Kubernetes的 Etcd資料庫中,然後提供API以方便Kubernetes相關元件或客戶應用 CRUD操作這些資料,上述專門用來儲存配置引數的Map就是Kubernetes ConfigMap資源物件。Kubernetes提供了一種內建機制,將儲存在etcd中的ConfigMap透過Volume對映的方式變成目標Pod內的配置檔案,不管目標Pod被排程到哪臺伺服器上,都會完成自動對映。進一步地,如果ConfigMap中的key-value資料被修改,則對映到Pod中的“配置檔案”也會隨之自動更新。

“Docker VS Kubernetes”是共生還是相愛相殺?

(四)Kubernetes的架構

“Docker VS Kubernetes”是共生還是相愛相殺?

Kubernetes由Master節點、Node節點以及外部的ETCD叢集組成,叢集的狀態、資源物件、網路等資訊儲存在ETCD中,Mater節點管控整個叢集,包括通訊、排程等,Node節點為工作真正執行的節點,並向主節點報告。Master節點由以下元件構成:

Master元件

API Server——提供HTTP Rest介面,是所有資源增刪改查和叢集控制的唯一入口。(在叢集中表現為名稱是kubernetes的service)。可以透過Dashboard的UI或kubectl工具來與其互動:

叢集管理的API入口;

資源配額控制入口;

提供完備的叢集安全機制。

Controller Manager——資源物件的控制自動化中心。即監控Node,當故障時轉移資源物件,自動修復叢集到期望狀態。

Scheduler——負責Pod的排程,排程到最優的Node。

Node元件

kubelet——負責Pod內容器的建立、啟停,並與Master密切協作實現叢集管理(註冊自己,彙報Node狀態)。

kube-proxy——實現k8s Service的通訊與負載均衡。

Docker Engine——Docker引擎,負責本機容器的建立和管理。

(五)Kubernetes架構模組實現原理

API Server

Kubernetes API Server透過一個名為kube-apiserver的程序提供服務,該程序執行在Master上。在預設情況下,kube-apiserver程序在本機的8080埠(對應引數——insecure-port)提供REST服務。我們可以同時啟動HTTPS安全埠(——secure-port=6443)來啟動安全機制,加強 REST API訪問的安全性。

由於API Server是Kubernetes叢集資料的唯一訪問入口,因此安全性與高效能就成為API Server設計和實現的兩大核心目標。透過採用HTTPS安全傳輸通道與CA簽名數字證書強制雙向認證的方式,API Server的安全性得以保障。此外,為了更細粒度地控制使用者或應用對Kubernetes資源物件的訪問許可權,Kubernetes啟用了RBAC訪問控制策略。Kubernetes的設計者綜合運用以下方式來最大程度地保證API Server的效能。

API Server擁有大量高效能的底層程式碼。在API Server原始碼中使用協程(Coroutine)+佇列(Queue)這種輕量級的高效能併發程式碼,使得單程序的API Server具備了超強的多核處理能力,從而以很快的速 度併發處理大量的請求。

普通List介面結合非同步Watch介面,不但完美解決了Kubernetes中各種資源物件的高效能同步問題,也極大提升了Kubernetes叢集實時響應各種事件的靈敏度。

採用了高效能的etcd資料庫而非傳統的關係資料庫,不僅解決了資料的可靠性問題,也極大提升了API Server資料訪問層的效能。在常見的公有云環境中,一個3節點的etcd叢集在輕負載環境中處理一個請求的時間可以低於1ms,在重負載環境中可以每秒處理超過30000個請求。

安全認證

RBAC:

Role-Based Access Control(RBAC),基於角色的訪問控制。

4種資源物件:

Role

RoleBinding

ClusterRole

ClusterRoleBinding

Role與ClusterRole

一個角色就是一組許可權的集合,都是以許可形式,不存在拒絕的規則。Role作用於一個名稱空間中,ClusterRole作用於整個叢集。

RoleBinding和ClusterRoleBinding是把Role和ClusterRole的許可權繫結到ServiceAccount上。

Service Account

Service Account也是一種賬號,但它並不是Kubernetes叢集的使用者 (系統管理員、運維人員、租戶使用者等)用的,而是給執行在Pod裡的程序用的,它為Pod裡的程序提供了必要的身份證明。在每個Namespace下都有一個名為default的預設Service Account物件,在這個Service Account裡面有一個名為Tokens的可以當作Volume被掛載到Pod裡的 Secret,當Pod啟動時,這個Secret會自動被掛載到Pod的指定目錄下,用來協助完成Pod中的程序訪問API Server時的身份鑑權。

Controller Manager

下邊介紹幾種Controller Manager的實現元件:

ResourceQuota Controller

kubernetes 的配額管理使用過 Admission Control來控制的,提供了兩種約束,LimitRanger和 ResourceQuota。LimitRanger 作用於 Pod 和 Container 之上(limit ,request),ResourceQuota 則作用於 Namespace。資源配額,分三個層次:

容器級別,對容器的CPU、memory做限制

Pod級別,對一個Pod內所有容器的可用資源做限制

Namespace級別,為namespace做限制,包括:

Namespace Controller

管理Namesoace建立刪除。

Endpoints Controller

Endpoints表示一個service對應的所有Pod副本的訪問地址,而Endpoints Controller就是負責生成和維護所有Endpoints物件的控制器。

> 負責監聽Service和對應Pod副本的變化,若Service被建立、更新、刪除,則相應建立、更新、刪除與Service同名的Endpoints物件。

> EndPoints物件被Node上的kube-proxy使用。

Scheduler

Kubernetes Scheduler的作用是將待排程的Pod(API新創 建的Pod、Controller Manager為補足副本而建立的Pod等)按照特定的調 度演算法和排程策略繫結(Binding)到叢集中某個合適的Node上,並將繫結資訊寫入etcd中。Kubernetes Scheduler當前提供的預設排程流程分為以下兩步:

預選排程過程,即遍歷所有目標Node,篩選出符合要求的候選節點。為此,Kubernetes內建了多種預選策略(xxx Predicates)供使用者選擇。

確定最優節點,在第1步的基礎上,採用優選策略(xxx Priority)計算出每個候選節點的積分,積分最高者勝出。

網路

Kubernetes的網路利用了Docker的網路原理,並在此基礎上實現了跨Node容器間的網路通訊。

同一個Node下Pod間通訊模型:

“Docker VS Kubernetes”是共生還是相愛相殺?

不同Node下Pod間的通訊模型(CNI模型實現):

“Docker VS Kubernetes”是共生還是相愛相殺?

CNI提供了一種應用容器的外掛化網路解決方案,定義對容器網路 進行操作和配置的規範,透過外掛的形式對CNI介面進行實現,以Flannel舉例,完成了Node間容器的通訊模型。

“Docker VS Kubernetes”是共生還是相愛相殺?

可以看到,Flannel首先建立了一個名為flannel0的網橋,而且這個網橋的一端連線docker0網橋,另一端連線一個叫作flanneld的服務程序。flanneld程序並不簡單,它上連etcd,利用etcd來管理可分配的IP地址段資源,同時監控etcd中每個Pod的實際地址,並在記憶體中建立了一個Pod節點路由表;它下連docker0和物理網路,使用記憶體中的Pod節點路由表,將docker0發給它的資料包包裝起來,利用物理網路的連線將資料包投遞到目標flanneld上,從而完成Pod到Pod之間的直接地址通訊。

服務發現

從Kubernetes1。11版本開始,Kubernetes叢集的DNS服務由CoreDNS提供。CoreDNS是CNCF基金會的一個專案,是用Go語言實現的高效能、外掛式、易擴充套件的DNS服務端。

“Docker VS Kubernetes”是共生還是相愛相殺?

三、結語

文章包含的內容說多不多,說少不少,但對於Docker、Kubernetes知識原理的小白來說是足夠的,筆者按照自己的學習經驗,以介紹為出發點,讓大家更能瞭解相關技術原理,所以實操的部分較少。Kubernetes技術元件還是十分豐富的,文章有選擇性地進行了介紹,感興趣的讀者可以再自行從官方或者書籍中學習瞭解。

作者簡介

胡洪昊

騰訊後臺開發工程師

胡洪昊,騰訊後臺開發工程師。畢業於東北大學,對雲原生相關技術有濃厚興趣,有一定二次開發實踐經驗,目前負責看點資訊流投放鏈路相關工作。