上一節我們着重講解了 Docker ,其實遺留了一個大問題。 Docker 雖好用,但面對強大的集羣,成千上萬的容器,突然感覺不香了。

這時候就需要我們的主角 Kubernetes 上場了,先來了解一下 K8s 的基本概念,後面再介紹實踐,由淺入深步步爲營。

關於 K8s 的基本概念我們將會圍繞如下七點展開:

1. Docker 的管理痛點

2.什麼是 K8s

3.雲架構 & 雲原生

4. K8s 架構原理

5. K8s 核心組件

6. K8s 的服務註冊與發現

7.關鍵問題

一、Docker 的管理痛點

如果想要將 Docker 應用於龐大的業務實現,是存在困難的 編排管理調度 問題。於是,我們迫切需要一套管理系統,對 Docker 及容器進行更高級更靈活的管理。

Kubernetes 應運而生! Kubernetes ,名詞源於希臘語,意爲「舵手」或「飛行員」。 Google2014 年開源了 Kubernetes 項目,建立在 Google 在大規模運行生產工作負載方面擁有十幾年的經驗的基礎上,結合了社區中最好的想法和實踐。

K8s 是 Kubernetes 的縮寫,用 8 替代了 「ubernete」,下文我們將使用簡稱。

二、什麼是 K8s ?

K8s 是一個可移植的、可擴展的開源平臺,用於 管理容器化的工作負載和服務,可促進聲明式配置和自動化K8s 擁有一個龐大且快速增長的生態系統。 K8s 的服務、支持和工具廣泛可用。

通過 K8s 我們可以:

1.快速部署應用

2.快速擴展應用

3.無縫對接新的應用功能

4.節省資源,優化硬件資源的使用

K8s 有如下特點:

1.可移植: 支持公有云,私有云,混合雲,多重雲 multi-cloud

2.可擴展: 模塊化,插件化,可掛載,可組合

3.自動化: 自動部署,自動重啓,自動複製,自動伸縮/擴展

三、雲架構 & 雲原生

1.雲和 K8s 是什麼關係

雲就是使用容器構建的一套服務集羣網絡,雲由很多的大量容器構成。 K8s 就是用來管理雲中的容器。

2.常見幾類雲架構

  • On-Premises (本地部署)
  • iaas (基礎設施即服務)
    DNS
    DNS
    
  • paas (平臺即服務)
    • mysql/es/mq/...
  • saas (軟件即服務)
    • 釘釘
    • 財務管理
  • serverless
    • 無服務,不需要服務器。站在用戶的角度考慮問題,用戶只需要使用雲服務器即可,在雲服務器所在的基礎環境,軟件環境都不需要用戶關心。

如果覺得不好理解,推薦閱讀這篇文章: 如何通俗解釋 IaaS、PaaS、SaaS 的區別

可以預見:未來服務開發都是 Serverless,企業都構建了自己的私有云環境,或者是使用公有云環境。

3.雲原生

爲了讓應用程序(項目,服務軟件)都運行在雲上的解決方案,這樣的方案叫做 雲原生

雲原生有如下特點:

Web
CI/CD
DevOps

四、K8s 架構原理

1. K8s 架構

概括來說 K8s 架構就是一個 Master 對應一羣 Node 節點。

下面我們來逐一介紹 K8s 架構圖中的 MasterNode

2. Master 節點結構如下:

  • apiserverK8s 網關,所有的指令請求都必須要經過 apiserver
  • scheduler 調度器,使用調度算法,把請求資源調度到某一個 node 節點;
  • controller 控制器,維護 K8s 資源對象;
  • etcd 存儲資源對象;

3. Node 節點

  • kubelet 在每一個 node 節點都存在一份,在 node 節點上的資源操作指令由 kubelet 來執行;
  • kube-proxy 代理服務,處理服務間負載均衡;
  • podk8s 管理的基本單元(最小單元), pod 內部是容器, k8s 不直接管理容器,而是管理 pod
  • docker 運行容器的基礎環境,容器引擎;
  • fluentd 日誌收集服務;

在介紹完 K8s 架構後,我們又引入了很多技術名詞。不要着急,先有 整體概念,再各個擊破 。請耐心閱讀下文,相信你一定會有不一樣的收穫。

五、K8s 核心組件

1. K8s 組件

K8s 是用來管理容器,但是不直接操作容器,最小操作單元是 Pod (間接管理容器)

  • 一個 Master 有一羣 Node 節點與之對應
  • Master 節點不存儲容器,只負責調度、網管、控制器、資源對象存儲
  • 容器的存儲在 Node 節點,容器是存儲在 Pod 內部的)
  • Pod 內部可以有一個容器,或者多個容器
  • Kubelet 負責本地 Pod 的維護
  • Kube-proxy 負責負載均衡,在多個 Pod 之間來做負載均衡

2. Pod 是什麼?

  • pod 也是一個容器,這個容器中裝的是 Docker 創建的容器, Pod 用來封裝容器的一個容器, Pod 是一個虛擬化分組;
  • Pod 相當於獨立主機,可以封裝一個或者多個容器;

Pod 有自己的 IP 地址、主機名,相當於一臺獨立沙箱環境。

3. Pod 到底用來幹什麼?

通常情況下,在服務部署時候,使用 Pod 來管理一組相關的服務。一個 Pod 中要麼部署一個服務,要麼部署一組有關係的服務。

一組相關的服務是指:在鏈式調用的調用連路上的服務。

4. Web 服務集羣如何實現?

實現服務集羣:只需要複製多方 Pod 的副本即可,這也是 K8s 管理的先進之處, K8s 如果繼續擴容,只需要控制 Pod 的數量即可,縮容道理類似。

5. Pod 底層網絡,數據存儲是如何進行的?

  • Pod 內部容器創建之前,必須先創建 Pause 容器;
  • 服務容器之間訪問 localhost ,相當於訪問本地服務一樣,性能非常高;

6. ReplicaSet 副本控制器

控制 Pod 副本「服務集羣」的數量,永遠與預期設定的數量保持一致即可。當有 Pod 服務宕機時候,副本控制器將會立馬重新創建一個新的 Pod ,永遠保證副本爲設置數量。

副本控制器:標籤選擇器-選擇維護一組相關的服務(它自己的服務)

selector:
    app = web
    Release = stable
  • ReplicationController 副本控制器:單選
  • ReplicaSet 副本控制器:單選,複合選擇

在新版的 K8s 中,建議使用 ReplicaSet 作爲副本控制器, ReplicationController 不再使用了。

7. Deployment 部署對象

  • 服務部署結構模型
  • 滾動更新

ReplicaSet 副本控制器控制 Pod 副本的數量。但是,項目的需求在不斷迭代、不斷的更新,項目版本將會不停的的發版。版本的變化,如何做到服務更新?

部署模型:

  • ReplicaSet 不支持滾動更新, Deployment 對象支持滾動更新,通常和 ReplicaSet 一起使用;
  • Deployment 管理 ReplicaSetRS 重新建立新的 RS ,創建新的 Pod

8. MySQL 使用容器化部署,存在什麼樣的問題?

  • 容器是生命週期的,一旦宕機,數據丟失
  • Pod 部署, Pod 有生命週期,數據丟失

對於 K8s 來說,不能使用 Deployment 部署 有狀態 服務。

通常情況下, Deployment 被用來部署無狀態服務,那麼對於有狀態服務的部署,使用 StatefulSet 進行有狀態服務的部署。

什麼是有狀態服務?

  • 有實時的數據需要存儲
  • 有狀態服務集羣中,把某一個服務抽離出去,一段時間後再加入機器網絡,如果集羣網絡無法使用

什麼是無狀態服務?

  • 沒有實時的數據需要存儲
  • 無狀態服務集羣中,把某一個服務抽離出去,一段時間後再加入機器網絡,對集羣服務沒有任何影響

9. StatefulSet
爲了解決有狀態服務使用容器化部署的一個問題。

  • 部署模型
  • 有狀態服務

StatefulSet 保證 Pod 重新建立後, Hostname 不會發生變化, Pod 就可以通過 Hostname 來關聯數據。

六、K8s 的服務註冊與發現

1. Pod 的結構是怎樣的?

  • Pod 相當於一個容器, Pod 有獨立 IP 地址,也有自己的 Hostname ,利用 Namespace 進行資源隔離,獨立沙箱環境。
  • Pod 內部封裝的是容器,可以封裝一個,或者多個容器(通常是一組相關的容器)

2. Pod 網絡

  • Pod 有自己獨立的 IP 地址
  • Pod 內部容器之間訪問採用 Localhost 訪問

Pod 內部容器訪問是 Localhost,Pod 之間的通信屬於遠程訪問。

3. Pod 是如何對外提供服務訪問的?

Pod 是虛擬的資源對象(進程),沒有對應實體(物理機,物理網卡)與之對應,無法直接對外提供服務訪問。

那麼該 如何解決這個問題 呢?

Pod 如果想要對外提供服務,必須綁定物理機端口。也就是說在物理機上開啓端口,讓這個端口和 Pod 的端口進行映射,這樣就可以通過物理機進行數據包的轉發。

概括來說:先通過物理機 IP + Port 進行訪問,再進行數據包轉發。

4.一組相關的 Pod 副本,如何實現訪問負載均衡?

我們先明確一個概念, Pod 是一個進程,是有 生命週期 的。宕機、版本更新,都會創建新的 Pod 。這時候 IP 地址會發生變化, Hostname 會發生變化,使用 Nginx 做負載均衡就不太合適了。

所以我們需要依賴 Service 的能力。

5. Service 如何實現負載均衡?

簡單來說, Service 資源對象包括如下三部分:

  • Pod IPPodIP 地址
  • Node IP :物理機 IP 地址
  • Cluster IP :虛擬 IP ,是由 K8s 抽象出的 Service 對象,這個 Service 對象就是一個 VIP 的資源對象

6. Service VIP 更深入原理探討

  • ServicePod 都是一個進程, Service 也不能對外網提供服務;
  • ServicePod 之間可以直接進行通信,它們的通信屬於局域網通信;
  • 把請求交給 Service 後, Service 使用 iptableipvs 做數據包的分發;

7. Service 對象是如何和 Pod 進行關聯的?

  • 不同的業務有不同的 Service
  • ServicePod 通過標籤選擇器進行關聯;
    selector:
        app=x 選擇一組訂單的服務 pod ,創建一個 service;
        通過 endpoints 存放一組 pod ip;
    

Service 通過標籤選擇器選擇一組相關的副本,然後創建一個 Service

8. Pod 宕機、發佈新的版本的時候, Service 如何發現 Pod 已經發生了變化?

每個 Pod 中都有 Kube-Proxy ,監聽所有 Pod 。如果發現 Pod 有變化,就動態更新( etcd 中存儲)對應的 IP 映射關係。

七、關鍵問題

1.企業使用 K8s 主要用來做什麼?

  • 自動化運維平臺

    創業型公司,中小型企業,使用 K8s 構建一套自動化運維平臺,自動維護服務數量,保持服務永遠和預期的數據保持一致性,讓服務可以永遠提供服務。這樣最直接的好處就是降本增效。

  • 充分利用服務器資源

    互聯網企業,有很多服務器資源「物理機」,爲了充分利用服務器資源,使用 K8s 構建私有云環境,項目運行在雲。 這在大型互聯網公司尤爲重要

  • 服務的無縫遷移

    項目開發中,產品需求不停的迭代,更新產品。這就意味着項目不停的發佈新的版本,而 K8s 可以實現項目從開發到生產無縫遷移。

2. K8s 服務的負載均衡是如何實現的?

Pod 中的容器很可能因爲各種原因發生故障而死掉。 DeploymentController 會通過動態創建和銷燬 Pod 來保證應用整體的健壯性。換句話說, Pod 是脆弱的,但應用是健壯的。每個 Pod 都有自己的 IP 地址。當 controller 用新 Pod 替代發生故障的 Pod 時,新 Pod 會分配到新的 IP 地址。

這樣就產生了一個問題:如果一組 Pod 對外提供服務(比如 HTTP ),它們的 IP 很有可能發生變化,那麼客戶端如何找到並訪問這個服務呢?

K8s 給出的解決方案是 ServiceKubernetes Service 從邏輯上代表了一組 Pod ,具體是哪些 Pod 則是由 Label 來挑選。

Service 有自己 IP ,而且這個 IP 是不變的。客戶端只需要訪問 ServiceIPK8s 則負責建立和維護 ServicePod 的映射關係。無論後端 Pod 如何變化,對客戶端不會有任何影響,因爲 Service 沒有變。

3.無狀態服務一般使用什麼方式進行部署?

DeploymentPodReplicaSet 提供了一個 聲明式定義方法,通常被用來部署無狀態服務。

Deployment 的主要作用:

定義 Deployment 來創建 PodReplicaSet 滾動升級和回滾應用擴容和索容暫停和繼續。 Deployment 不僅僅可以滾動更新,而且可以進行回滾,如果發現升級到 V2 版本後,服務不可用,可以迅速回滾到 V1 版本。

相關文章