kubernetes與web叢集

店家小二發表於2018-12-13

k8s架構

Kubernetes最初源於谷歌內部的Borg,提供了面向應用的容器叢集部署和管理系統。Kubernetes借鑑了Borg的設計理念,比如Pod、Service、Labels和單Pod單IP等。

乍一看Kubernetes的架構圖會覺得有點暈

網上好多關於k8s的介紹都是從大講到小,從master節點講到pod。可是對於我這種對叢集的理解不是很深的人,我看了好幾遍都是一知半解。於是我決定從小往大擴充套件講起。

pod

上次我們使用docker搭建了一個web叢集(原文連結https://my.oschina.net/daba0007/blog/1605365)

我們就從這個叢集開始講起。docker十分成功的把開發環境打包到一個個容器中,對外看來它只是一個個服務,遷移也十分簡單,寫成映象就可以帶走了。我們部署的web叢集,其實就是四個服務:

  • nginx服務

  • web服務

  • redis快取服務

  • mysql儲存服務

在k8s中,最基礎、最小的原件就是pod。一個pod代表著叢集中執行的一個程式。在一個pod中可以執行一個或多個容器,即它就是一個單位。對於我們的web叢集來說,我們可以把它變成三個pod

  • redis

  • mysql

  • nginx和web(這兩個放一起,因為它們共享著資料卷)


對於pod來說,它們可以共享兩種資源:網路和儲存

  • 網路:每個Pod都會被分配一個唯一的IP地址。Pod中的所有容器共享網路空間,包括IP地址和埠。Pod內部的容器可以使用localhost互相通訊。Pod中的容器與外界通訊時,必須分配共享網路資源(例如使用宿主機的埠對映)。【比如pod:redis共享了ip:dabaredis和port:6379,pod:mysql共享了ip:dabamysql和port:3306】

  • 儲存:Pod可以指定多個共享的Volume。Pod中的所有容器都可以訪問共享的volume。Volume也可以用來持久化Pod中的儲存資源,以防容器重啟後檔案丟失。【比如pod:N&W共享了volume:dabadjango】

不過我們很少直接在kubernetes中建立單個Pod。因為Pod的生命週期是短暫的,用後即焚的實體。當Pod被建立後(不論是由你直接建立還是被其他Controller),都會被Kuberentes排程到叢集的節點上。直到Pod的程式終止、被刪掉、因為缺少資源而被驅逐、或者Node故障之前這個Pod都會一直保持在那個Node上。Pod不會自愈。如果Pod執行的Node故障,或者是排程器本身故障,這個Pod就會被刪除。同樣的,如果Pod所在Node缺少資源或者Pod處於維護狀態,Pod也會被驅逐。

Kubernetes使用更高階的稱為Controller的抽象層,來管理Pod例項。

ReplicationController(rc)

rc是Kubernetes系統中最有用的功能,實現複製多個Pod副本,往往一個應用需要多個Pod來支撐,並且可以保證其複製的副本數,即使副本所排程分配的宿主機出現異常,通過Replication Controller可以保證在其它主宿機啟用同等數量的Pod。當某一個pod出現故障down掉的時候,rc會為我們馬上再生成一個pod來保持pod的數量。

然而,每個pod都會獲取它自己的ip地址,即使這些ip地址不總是穩定可依賴的。這會導致一個問題:在 Kubernetes 叢集中,如果一組 Pod為其它 Pod 提供備份,那麼那些備份該如何發現,並連線到這組 Pod 中的哪些備份呢?

Service(svc)

Service 定義了這樣一種抽象:一個Pod的邏輯分組,一種可以訪問它們的策略——通常稱為微服務。

當外界有請求服務的時候(比如web請求資料時),它將會向redis和mysql同時請求資料,這時候web就會請求dabaredis或dabamysql服務,通過service將會把指派redis或pod的一個pod的ip給web。(支援TCP和UDP協議,預設TCP)

但是有很多Service需要暴露多個埠(比如Service:N&W需要暴露12000,8888等),Kubernetes 支援在Service物件中定義多個埠。當使用多個埠時,必須給出所有的埠的名稱(name),這樣 Endpoint 就不會產生歧義

k8s的serviceTypes允許指定一個需要的型別:

  • ClusterIP:通過叢集的內部IP暴露服務,選擇該值,服務只能夠在叢集內部可以訪問,這也是預設的ServiceType。

  • NodePort:通過每個Node上的IP和靜態埠(NodePort)暴露服務。NodePort服務會路由到ClusterIP服務,這個ClusterIP服務會自動建立。通過請求 <NodeIP>:<NodePort>,可以從叢集的外部訪問一個 NodePort 服務。

  • LoadBalancer:使用雲提供商的負載均衡器,可以向外部暴露服務。外部的負載均衡器可以路由到 NodePort 服務和 ClusterIP 服務。

  • ExternalName:通過返回CNAME和它的值,可以將服務對映到externalName欄位的內容(例如,foo.bar.example.com)。沒有任何型別代理被建立,這隻有 Kubernetes 1.7 或更高版本的 kube-dns 才支援。

當然,Pod 想要能夠被Service訪問到,通常是通過Label Selector實現的。

kube-proxy

在 Kubernetes 叢集中,每個 Node 執行一個 kube-proxy 程式。kube-proxy 負責為 Service 實現了一種 VIP(虛擬 IP)的形式。

Proxy不但解決了同一主宿機相同服務埠衝突的問題,還提供了Service轉發服務埠對外提供服務的能力,Proxy後端使用了隨機、輪循負載均衡演算法。

節點介紹

接下來是一些節點功能的介紹:

  1. etcd

    它是用於共享配置和服務發現的分散式、一致性的KV儲存系統

  2. apiserver

    apiserver提供了資源操作的唯一入口,並提供認證、授權、訪問控制、api註冊和發現等機制。

  3. controller manager

    controller manager負責維護叢集的狀態,比如故障檢測、自動擴充套件、滾動更新等;

  4. scheduler

    scheduler負責資源的排程,按照預定的排程策略將Pod排程到相應的機器上;

  5. kubelet

    kubelet負責維護容器的生命週期,同時也負責Volume(CVI)和網路(CNI)的管理;

  6. Container runtime

    Container runtime負責映象管理以及Pod和容器的真正執行(CRI)

叢集

我們再回到之前我們的叢集

這時候我們就可以使用k8s的服務概念來實現這個叢集了

而對於每一個服務(svc),都會有應用控制器(rc)來保證其具有足夠的數量來跑pod

這樣就實現了LB和HA。一個比較可靠的服務叢集就這樣搭建起來。如果服務需要擴充套件,我們只需要增加節點(新加進一臺主機)即可。

本文轉移開源中國-kubernetes與web叢集


相關文章