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

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

本文內容

本文致力於介紹K8s一些基礎概念與串聯部署應用的主體流程,使用Minikube實操

基礎架構概念回顧

溫故而知新,上一節【K8S學習筆記】初識K8S 及架構組件 我們學習了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的組成示意圖:

為什麼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重新調度到其他節點上。

細心的讀者是否發現:

當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可以添加到任意數量的資源對象上。通常由定義資源對象時添加,創建后亦可動態添加或刪除。

Service如何動態綁定Pods?

原來,在定義 Pod 時,設置一系列 Label 標籤,Service 創建時定義了 Label Selector(Label Selector 可以類比為對 Label 進行 SQL 的 where 查詢),kube-proxy 進程通過 Service的Label Selector 來選擇對應的 Pod,自動建立每個 Service 到對應 Pod 的請求轉發路由表,從而實現 Service 的智能負載均衡機制。

小結: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

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 <<EOF >/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(阿里雲修改版):

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集群:

minikube start --driver docker --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --kubernetes-version v1.18.3

本地有docker時使用此driver,其他可選的虛擬化技術參考https://minikube.sigs.k8s.io/docs/drivers/ 選擇

#部署一個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
#獲取暴露 Service 的 URL 以查看 Service 的詳細信息:
minikube service hello-minikube --url
#minikube提供的特色功能,直接通過瀏覽器打開剛才創建的Service的外部訪問地址
minikube service hello-minikube

自動打開瀏覽器訪問服務(Minikube特色功能)

提示:這張圖中的request-uri的解釋是不正確的,但是與 <minikube這個唯一Node的IP>:<NodePort><Service的ClusterIP>:<ServicePort>都不是完全匹配的,不大理解這塊提示,有緣人希望可解我所惑,在此先行感謝

查看Pod的描述信息

kubectl describe pod hello-minikube

最下方可以清楚得看到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>:<NodePort> 時,根據路由錶轉發到指定的Service上,負載均衡到Pod,提供服務

集群外部訪問:

參考

  • 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權威指南》很多,侵權改。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

FB行銷專家,教你從零開始的技巧