本文內容
本文致力於介紹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收到信息后,拉取鏡像並啟動了容器
部署流程原理簡述
初始化,kubelet、kube-scheduler-manager、kube-controller-manager、kube-proxy向注冊kube-apiserver自身信息,監聽kube-apiserver的watch接口
kubectl
發送創建 deployment 類型、名為hello-minikube
的Pod 請求到kube-apiserver
kube-apiserver
將這條描述信息存到 etcd,再將事件發送給kube-scheduler
kube-scheduler
收到事件,調用kube-apiserver的API ,監測Node負載情況,創建Pod部署描述信息到etcd,kube-apiserver返回此事件給kubelet- 待部署Node的
kubelet
收到kube-apiserver的事件,獲得Pod信息,取出信息並拉取業務鏡像,創建pause容器與業務容器(此時集群外部無法訪問) kubectl
執行expose
命令,將請求發送到kube-apiserver,將創建Service與NodePort信息存到etcd中- 各節點
kube-proxy
收到事件,創建邏輯上的Service與路由信息,開辟NodePort - 當請求到達
<任意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權威指南》很多,侵權改。