1. 程式人生 > >【K8s學習筆記】K8s是如何部署應用的?

【K8s學習筆記】K8s是如何部署應用的?

## 本文內容 ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620120651443-1149123992.png) 本文致力於介紹K8s一些基礎概念與串聯部署應用的主體流程,使用Minikube實操 ## 基礎架構概念回顧 溫故而知新,上一節[【K8S學習筆記】初識K8S 及架構元件](https://www.cnblogs.com/hellxz/p/first-impression-of-k8s.html) 我們學習了K8s的發展歷史、基礎架構概念及用途,本節講的內容建立在其上,有必要把之前的架構小節提出來回顧下: > K8s架構分為控制平臺(位於的Master節點)與執行節點Node > > 控制平臺包含: > > - kube-apiserver(訪問入口,接收命令) > > - etcd(KV資料庫,儲存叢集狀態與資料) > > - kube-scheduler(監控節點狀態,排程容器部署) > > - kube-controller-manager(監控叢集狀態,控制節點、副本、端點、賬戶與令牌) > > - cloud-controller-manager(控制與雲互動的節點、路由、服務、資料卷) > > 執行節點包含: > > - kubelet(監控與實際操作容器) > > - kube-proxy(每個節點上執行的網路代理,維護網路轉發規則,實現了Service) > > - 容器執行時環境CRI(支援多種實現K8s CRI的容器技術) 接下來需要引入 Pod 與 Service 的概念,這也是在上一篇文章中未給出的 ## Pod、Service與Label概念 ### Pod概念與結構 Pod 是 K8s最重要的基本概念,官網給出概念:Pod是Kubernates可排程的最小的、可部署的單元。怎麼理解呢?最簡單的理解是,Pod是一組容器。 再詳細些,Pod是一組容器組成的概念,這些容器都有共同的特點: - 都有一個特殊的被稱為“根容器”的Pause容器。Pause容器映象屬於K8s平臺的一部分 - 包含一個或多個緊密相關的使用者業務容器。假設個場景:業務容器需要獨立的redis提供服務,這裡就可以將它們兩個部署在同一Pod中。 下邊是Pod的組成示意圖: ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620111300659-1056373233.jpg) 為什麼Kubernetes會設計出一個全新的概念與Pod會有這樣特殊的結構呢? - 原因之一:K8s需要將一組容器視為一個單元處理。當其中某些容器死亡了,此時無法判定這組容器的狀態。而當成一個單元,只要其中有一個容器掛了,這個單元就判定掛了。 - 原因之二:通過Pause共享容器IP,共享Pause掛接的Volume,簡化密切關聯的業務容器之間的通訊問題和檔案共享問題 K8s為每個Pod都分配了唯一的IP地址,稱為Pod IP,一個Pod裡的多個容器共享Pod IP地址。需要牢記的一點是:在 kubernetes 裡,一個 Pod 裡的容器與另外主機上的 Pod 容器能夠直接通訊。 ### Pod的建立流程 當一個普通的Pod被建立,就會被放入etcd中儲存,隨後被 K8s Master節點排程到某個具體的Node上並進行繫結(Binding),隨後該Pod被對應的Node上的kubelet程序例項化成一組相關的Docker容器並啟動。 當Pod中有容器停止時,K8s 會自動檢測到這個問題並重啟這個 Pod(Pod裡所有容器);如果Pod所在的Node宕機,就會將這個Node上的所有Pod重新排程到其他節點上。 ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620114650288-388778616.jpg) > 細心的讀者是否發現: > > 當Pod越來越多,Pod IP 也越來越多,那是如何從茫茫IP地址中找到需要的服務呢?換句話來說,是否有一種提供唯一入口的機制,來完成對Pod的訪問,而無需關心訪問到具體是哪個Pod(who care :happy:)? > > Kubernetes 提供了這種機制,稱之為 Service。 ### Service概念 Service服務是Kubernetes裡的核心資源物件之一,從名稱上來看,理解其為一個”服務“也不為過,Service的作用是為相同標識的一系列Pod提供唯一的訪問地址。 > Service使用的唯一地址稱為ClusterIP,僅當在叢集內的容器才能通過此IP訪問到Service 它具體實現對一系列Pod繫結,需要再引入Label的概念,才能做出解答。 ### Label概念 Kubernetes 提供了Label(標籤)來對Pod、Service、RC、Node等進行標記。相當於打標籤,Label可以是一組KV鍵值對,也可以是一個set 一個資源物件可以定義任意數量的Label,同一個Label可以新增到任意數量的資源物件上。通常由定義資源物件時新增,建立後亦可動態新增或刪除。 ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620123903294-109764052.jpg) ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620123932902-1782116128.jpg) ### Service如何動態繫結Pods? 原來,在定義 Pod 時,設定一系列 Label 標籤,Service 建立時定義了 Label Selector(Label Selector 可以類比為對 Label 進行 SQL 的 where 查詢),kube-proxy 程序通過 Service的Label Selector 來選擇對應的 Pod,自動建立每個 Service 到對應 Pod 的請求轉發路由表,從而實現 Service 的智慧負載均衡機制。 ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620162518779-1756951607.jpg) 小結:Pod是K8s最小的執行單元,包含一個Pause容器與多個業務容器,每個Pod中容器共享Pod IP,容器之間可直接作用Pod IP通訊;Label是一種標籤,它將標籤打在Pod上時,Service可以通過定義Label Selector(Label查詢規則)來選擇Pod,具體實現路由表建立的是kube-proxy ## 部署應用實踐(Minikube) 安裝kubectl需要安裝成本地服務,這裡是debian10,更多參考https://developer.aliyun.com/mirror/kubernetes ```bash sudo su - apt-get update && apt-get install -y apt-transport-https curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - cat </etc/apt/sources.list.d/kubernetes.list deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main EOF apt-get update apt-get install -y kubelet kubectl exit ``` 下載安裝Minikube(阿里雲修改版): ```bash curl -Lo minikube-linux-amd64-1.11.0-aliyuncs http://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/v1.11.0/minikube-linux-amd64 sudo install minikube-linux-amd64-1.11.0-aliyuncs /usr/local/bin/minikube ``` > 使用魔改版是因為官方程式碼裡有些地方寫死了地址,而國內無法訪問 部署k8s叢集: ```bash minikube start --driver docker --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --kubernetes-version v1.18.3 ``` ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620153717911-524847325.png) > 本地有docker時使用此driver,其他可選的虛擬化技術參考https://minikube.sigs.k8s.io/docs/drivers/ 選擇 ```bash #部署一個Pod,Pod的deployment是一種預設的無狀態多備份的部署型別 kubectl create deployment hello-minikube --image=registry.cn-hangzhou.aliyuncs.com/google_containers/echoserver:1.4 #檢視叢集中當前的Pod列表 kubectl get pods #建立的NodePort型別Service,將所有Node開放一個埠號,通過這個埠將流量轉發到Service以及下游Pods kubectl expose deployment hello-minikube --type=NodePort --port=8080 #minikube提供的特色功能,直接通過瀏覽器開啟剛才建立的Service minikube service hello-minikube ``` ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620155937048-412359598.png) 自動開啟瀏覽器訪問服務(Minikube特色功能) ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620235606000-1972383929.png) 檢視Pod的描述資訊 ```bash kubectl describe pod hello-minikube ``` ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200620161659326-1466659705.png) > 最下方可以清楚得看到K8s叢集default-scheduler成功指派我們要求的Pod在節點minikube上建立,kubelet收到資訊後,拉取映象並啟動了容器 ## 部署流程原理簡述 1. `kubectl` 傳送建立 deployment 型別、名為`hello-minikube`的Pod 請求到 `kube-apiserver` 2. `kube-apiserver` 將這條描述資訊存到 etcd 3. `kube-scheduler` 監控 etcd 得到描述資訊,監測Node負載情況,建立Pod部署描述資訊到etcd 4. 待部署Node的`kubelet`監聽到 etcd 中有自己的部署Pod資訊,取出資訊並按圖拉取業務映象,建立pause容器與業務容器(此時叢集外部無法訪問) 5. `kubectl` 執行`expose`命令,同時將建立Service與NodePort資訊存到etcd中 6. 各節點`kube-proxy`監聽到etcd變化,建立邏輯上的Service與路由資訊,開闢NodePort 7. 當請求到達`<任意Node節點IP>:` 時,根據路由錶轉發到指定的Service上,負載均衡到Pod,提供服務 叢集外部訪問: ![](https://img2020.cnblogs.com/blog/1149398/202006/1149398-20200621004737866-1074205814.png) **參考** - https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/ - https://kubernetes.io/docs/concepts/services-networking/ - https://minikube.sigs.k8s.io/docs/start/ - https://minikube.sigs.k8s.io/docs/handbook/controls/ - 《Kubernetes權威指南》第 4 版 > 行文過程中難免出現錯誤,還請讀者評論幫忙改正,大家共同進步,在此感謝 轉載請註明出處,文章中概念引入《Kubernetes權威指南》很多,侵權改。