一文了解 Kubernetes
上一節我們着重講解了 Docker
,其實遺留了一個大問題。 Docker
雖好用,但面對強大的集羣,成千上萬的容器,突然感覺不香了。
這時候就需要我們的主角 Kubernetes
上場了,先來了解一下 K8s
的基本概念,後面再介紹實踐,由淺入深步步爲營。
關於 K8s
的基本概念我們將會圍繞如下七點展開:
1. Docker
的管理痛點
2.什麼是 K8s
?
3.雲架構 & 雲原生
4. K8s
架構原理
5. K8s
核心組件
6. K8s
的服務註冊與發現
7.關鍵問題
一、Docker 的管理痛點
如果想要將 Docker
應用於龐大的業務實現,是存在困難的 編排 、 管理 和 調度 問題。於是,我們迫切需要一套管理系統,對 Docker
及容器進行更高級更靈活的管理。
Kubernetes
應運而生! Kubernetes
,名詞源於希臘語,意爲「舵手」或「飛行員」。 Google
在 2014
年開源了 Kubernetes
項目,建立在 Google
在大規模運行生產工作負載方面擁有十幾年的經驗的基礎上,結合了社區中最好的想法和實踐。
K8s 是 Kubernetes 的縮寫,用 8 替代了 「ubernete」,下文我們將使用簡稱。
二、什麼是 K8s ?
K8s
是一個可移植的、可擴展的開源平臺,用於 管理容器化的工作負載和服務,可促進聲明式配置和自動化 。 K8s
擁有一個龐大且快速增長的生態系統。 K8s
的服務、支持和工具廣泛可用。
通過 K8s
我們可以:
1.快速部署應用
2.快速擴展應用
3.無縫對接新的應用功能
4.節省資源,優化硬件資源的使用
K8s
有如下特點:
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
架構圖中的 Master
和 Node
。
2. Master
節點結構如下:
-
apiserver
即K8s
網關,所有的指令請求都必須要經過apiserver
; -
scheduler
調度器,使用調度算法,把請求資源調度到某一個node
節點; -
controller
控制器,維護K8s
資源對象; -
etcd
存儲資源對象;
3. Node
節點
-
kubelet
在每一個node
節點都存在一份,在node
節點上的資源操作指令由kubelet
來執行; -
kube-proxy
代理服務,處理服務間負載均衡; -
pod
是k8s
管理的基本單元(最小單元),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
管理ReplicaSet
,RS
重新建立新的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 IP
:Pod
的IP
地址 -
Node IP
:物理機IP
地址 -
Cluster IP
:虛擬IP
,是由K8s
抽象出的Service
對象,這個Service
對象就是一個VIP
的資源對象
6. Service VIP
更深入原理探討
-
Service
和Pod
都是一個進程,Service
也不能對外網提供服務; -
Service
和Pod
之間可以直接進行通信,它們的通信屬於局域網通信; - 把請求交給
Service
後,Service
使用iptable
,ipvs
做數據包的分發;
7. Service
對象是如何和 Pod
進行關聯的?
- 不同的業務有不同的
Service
; -
Service
和Pod
通過標籤選擇器進行關聯;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
中的容器很可能因爲各種原因發生故障而死掉。 Deployment
等 Controller
會通過動態創建和銷燬 Pod
來保證應用整體的健壯性。換句話說, Pod
是脆弱的,但應用是健壯的。每個 Pod
都有自己的 IP
地址。當 controller
用新 Pod
替代發生故障的 Pod
時,新 Pod
會分配到新的 IP
地址。
這樣就產生了一個問題:如果一組 Pod
對外提供服務(比如 HTTP
),它們的 IP
很有可能發生變化,那麼客戶端如何找到並訪問這個服務呢?
K8s
給出的解決方案是 Service
。 Kubernetes Service
從邏輯上代表了一組 Pod
,具體是哪些 Pod
則是由 Label
來挑選。
Service
有自己 IP
,而且這個 IP
是不變的。客戶端只需要訪問 Service
的 IP
, K8s
則負責建立和維護 Service
與 Pod
的映射關係。無論後端 Pod
如何變化,對客戶端不會有任何影響,因爲 Service
沒有變。
3.無狀態服務一般使用什麼方式進行部署?
Deployment
爲 Pod
和 ReplicaSet
提供了一個 聲明式定義方法,通常被用來部署無狀態服務。
Deployment
的主要作用:
定義 Deployment
來創建 Pod
和 ReplicaSet
滾動升級和回滾應用擴容和索容暫停和繼續。 Deployment
不僅僅可以滾動更新,而且可以進行回滾,如果發現升級到 V2
版本後,服務不可用,可以迅速回滾到 V1
版本。