kubernetes基础组件原理
kubelet 的工作核心,就是一個(gè)控制循環(huán)SyncLoop,驅(qū)動(dòng)這個(gè)控制循環(huán)運(yùn)行的事件,包括四種:
1.Pod?更新事件
2.Pod?生命周期變化
3.kubelet?本身設(shè)置的執(zhí)行周期
4.定時(shí)的清理事件
kubelet 還負(fù)責(zé)維護(hù)著很多其他的子控制循環(huán),比如 Volume Manager、Image Manager、Node Status Manager 等等,這些控制循環(huán)的責(zé)任,就是通過控制器模式,完成 kubelet 的某項(xiàng)具體職責(zé)。
例如:Node Status Manager,就負(fù)責(zé)響應(yīng) Node 的狀態(tài)變化,然后將 Node 的狀態(tài)收集起來,并通過 Heartbeat 的方式上報(bào)給 APIServer。CPU Manager,就負(fù)責(zé)維護(hù)該 Node 的 CPU 核的信息,以便在 Pod 通過 cpuset 的方式請求 CPU 核的時(shí)候,能夠正確地管理 CPU 核的使用量和可用量。
kubelet 通過 Watch 機(jī)制,監(jiān)聽了與自己相關(guān)的 Pod 對象的變化:
這個(gè) Watch 的過濾條件是該 Pod 的 nodeName 字段與自己相同,kubelet 會(huì)把這些 Pod 的信息緩存在自己的內(nèi)存里。
當(dāng)一個(gè) Pod 完成調(diào)度、與一個(gè) Node 綁定起來之后, 這個(gè) Pod 的變化就會(huì)觸發(fā) kubelet 在控制循環(huán)里注冊的 Handler,也就是上圖中的 HandlePods 部分。
通過檢查該 Pod 在 kubelet 內(nèi)存里的狀態(tài),kubelet 就能夠判斷出這是一個(gè)新調(diào)度過來的 Pod,從而觸發(fā) Handler 里 ADD 事件對應(yīng)的處理邏輯。(備注:在具體的處理過程當(dāng)中,kubelet 會(huì)啟動(dòng)一個(gè)名叫 Pod Update Worker 的、單獨(dú)的 Goroutine 來完成對 Pod 的處理工作。)
CRI是Container Runtime Interface(容器運(yùn)行時(shí)接口)的簡寫,CRI解耦了kubelet與容器運(yùn)行時(shí),讓kubelet無需重新編譯就可以支持多種容器運(yùn)行時(shí),kubelet將通過CRI接口來跟第三方容器運(yùn)行時(shí)進(jìn)行通信,來操作容器與鏡像。實(shí)現(xiàn)了 CRI 接口的容器運(yùn)行時(shí)通常稱為 CRI shim, 這是一個(gè) gRPC Server,監(jiān)聽在本地的 unix socket ?上;而 kubelet 作為 gRPC 的客戶端來調(diào)用 CRI 接口,來進(jìn)行Pod ?和容器、鏡像的生命周期管理。另外,容器運(yùn)行時(shí)需要自己負(fù)責(zé)管理容器的網(wǎng)絡(luò),推薦使用 CNI。
CAdvisor
集成在 Kubelet 中的容器監(jiān)控工具,用于收集本節(jié)點(diǎn)和容器的監(jiān)控信息。
oomWatcher
kubelet的oomwatcher從cadvisor監(jiān)聽事件,如果出現(xiàn)了system oom則記錄一個(gè)event事件。 對于容器的oom狀態(tài),k8s使用docker的狀態(tài)State.OOMKilled判斷是否經(jīng)歷oom事件。
GCManager
垃圾回收是 kubelet 的一個(gè)有用功能,它將清理未使用的鏡像和容器。 Kubelet 將每分鐘對容器執(zhí)行一次垃圾回收,每五分鐘對鏡像執(zhí)行一次垃圾回收。
不建議使用外部垃圾收集工具,因?yàn)檫@些工具可能會(huì)刪除原本期望存在的容器進(jìn)而破壞 kubelet 的行為。
CPUManager
默認(rèn)情況下,kubelet 使用CFS配額來執(zhí)行 Pod 的 CPU 約束。 當(dāng)節(jié)點(diǎn)上運(yùn)行了很多 CPU 密集的 Pod 時(shí),工作負(fù)載可能會(huì)遷移到不同的 CPU 核, 這取決于調(diào)度時(shí) Pod 是否被扼制,以及哪些 CPU 核是可用的。 許多工作負(fù)載對這種遷移不敏感,因此無需任何干預(yù)即可正常工作。
ProberManager
ProberManager 實(shí)現(xiàn)對容器的健康檢查。目前有三種 probe 探針:
liveness: 讓Kubernetes知道你的應(yīng)用程序是否健康,如果你的應(yīng)用程序不健康,Kubernetes將刪除Pod并啟動(dòng)一個(gè)新的替換它(與RestartPolicy有關(guān))。Liveness 探測可以告訴 Kubernetes 什么時(shí)候通過重啟容器實(shí)現(xiàn)自愈。
readiness: readiness與liveness原理相同,不過Readiness探針是告訴 Kubernetes 什么時(shí)候可以將容器加入到 Service 負(fù)載均衡中,對外提供服務(wù)。
startupProbe:1.16開始支持的新特性,檢測慢啟動(dòng)容器的狀態(tài)。
Kubelet 定期調(diào)用容器中的探針來診斷容器的健康狀況。 包含如下三種實(shí)現(xiàn)方式:
ExecAction:在容器內(nèi)部執(zhí)行一個(gè)命令,如果該命令的退出狀態(tài)碼為 0,則表明容器健康;
TCPSocketAction:通過容器的 IP 地址和端口號執(zhí)行 TCP 檢查,如果端口能被訪問,則表明容器健康;
HTTPGetAction:通過容器的 IP 地址和端口號及路徑調(diào)用 HTTP GET 方法,如果響應(yīng)的狀態(tài)碼大于等于 200 且小于 400,則認(rèn)為容器狀態(tài)健康。
StatusManager
StatusManager 的主要功能是將 pod 狀態(tài)信息同步到 apiserver,statusManage 并不會(huì)主動(dòng)監(jiān)控 pod 的狀態(tài),而是提供接口供其他 manager 進(jìn)行調(diào)用。比如 probeManager。probeManager 會(huì)定時(shí)去監(jiān)控 pod 中容器的健康狀況,一旦發(fā)現(xiàn)狀態(tài)發(fā)生變化,就調(diào)用 statusManager 提供的方法更新 pod 的狀態(tài)。
EvictionManager
EvictionManager 會(huì)監(jiān)控資源的使用情況,并使用驅(qū)逐機(jī)制防止計(jì)算和存儲(chǔ)資源耗盡。
VolumeManager
volumeManager通過actualStateOfWorld和desiredStateOfWorld來表明當(dāng)前的volume掛載狀態(tài)和期望的volume掛載狀態(tài)。然后由desiredStateOfWorldPopulator維護(hù)desireedStateOfWorld和podManager的一致性;由reconcile維護(hù)actualStateOfWorld和desiredStateOfWorld的一致性及磁盤volume掛載和actualStateOfWorld的一致性。通過這些機(jī)制,volumeManager完成了volume掛載生命周期的管理。
PluginManager
PluginManager 可以用將系統(tǒng)硬件資源發(fā)布到kubelet。
podworker,其功能就是處理當(dāng)前節(jié)點(diǎn)被調(diào)度pod的聲明周期的,也就是說你建了一個(gè)pod,然后調(diào)度器將這個(gè)pod調(diào)度到某個(gè)節(jié)點(diǎn)上面了,那么kubelet就需要去工作了,它的工作就是啟動(dòng)這個(gè)pod,用容器運(yùn)行時(shí)去啟動(dòng),也就是將進(jìn)程拉起來,放到某個(gè)namespace下面去,通過cgroup對資源做限制,通過網(wǎng)絡(luò)插件將網(wǎng)絡(luò)配置好。
kubectl
常用命令格式
創(chuàng)建:kubectl run <name> --image=<image> 或者 kubectl create -f manifest.yaml
查詢:kubectl get <resource>
更新 kubectl set 或者 kubectl patch
刪除:kubectl delete <resource> <name> 或者 kubectl delete -f manifest.yaml
查詢 Pod IP:kubectl get pod <pod-name> -o jsonpath='{.status.podIP}'
容器內(nèi)執(zhí)行命令:kubectl exec -ti <pod-name> sh
容器日志:kubectl logs [-f] <pod-name>
導(dǎo)出服務(wù):kubectl expose deploy <name> --port=80
自定義輸出列
比如,查詢所有 Pod 的資源請求和限制:
Kubectl?get pods --all-namespaces -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,"CPU(requests)":.spec.containers[*].resources.requests.cpu,"CPU(limits)":.spec.containers[*].resources.limits.cpu,"MEMORY(requests)":.spec.containers[*].resources.requests.memory,"MEMORY(limits)":.spec.containers[*].resources.limits.memory
日志查看
# Return snapshot logs from pod nginx with only one container
kubectl logs nginx
# Return snapshot of previous terminated ruby container logs from pod web-1
kubectl logs -p -c ruby web-1
# Begin streaming the logs of the ruby container in pod web-1
kubectl logs -f -c ruby web-1
連接到一個(gè)正在運(yùn)行的容器
kubectl attach 123456-7890 -c ruby-container -i -t
在容器內(nèi)部執(zhí)行命令
# Get output from running 'date' from pod 123456-7890, using the first container by default
??kubectl exec 123456-7890 date
??# Get output from running 'date' in ruby-container from pod 123456-7890
??kubectl exec 123456-7890 -c ruby-container date
??# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890
??# and sends stdout/stderr from 'bash' back to the client
??kubectl exec 123456-7890 -c ruby-container -i -t -- bash -il
Options:
??-c, --container='': Container name. If omitted, the first container in the pod will be chosen
??-p, --pod='': Pod name
??-i, --stdin=false: Pass stdin to the container
??-t, --tty=false: Stdin is a TT
端口轉(zhuǎn)發(fā)
kubectl patch
kubectl get?pv,pvc -o wide
kubectl get pod,svc,ingress
Kubernetes Service ?定義了這樣一種抽象:一個(gè) ?Pod ?的邏輯分組,一種可以訪問它們的策略 —— 通常稱為微服務(wù)。 這一組 ?Pod ?能夠被 ?Service ?訪問到,通常是通過 ?Label Selector
Service 在 K8s 中有以下四種類型
1.ClusterIp:默認(rèn)類型,自動(dòng)分配一個(gè)僅 Cluster 內(nèi)部可以訪問的虛擬 IP
2.NodePort:在 ClusterIP 基礎(chǔ)上為 Service 在每臺(tái)機(jī)器上綁定一個(gè)端口,這樣就可以通過 : NodePort 來訪問該服務(wù)
3.LoadBalancer:在 NodePort 的基礎(chǔ)上,借助 cloud provider 創(chuàng)建一個(gè)外部負(fù)載均衡器,并將請求轉(zhuǎn)發(fā)到: NodePort
4.ExternalName:把集群外部的服務(wù)引入到集群內(nèi)部來,在集群內(nèi)部直接使用。沒有任何類型代理被創(chuàng)建,這只有 kubernetes 1.7 或更高版本的 kube-dns 才支持
apiVersion: v1
kind: Service
metadata:
??name: my-service
spec:
??selector:
????app: MyApp
??ports:
????- protocol: TCP
??????port: 80
??????targetPort: 9376
上述配置創(chuàng)建一個(gè)名稱為 “my-service” 的?Service?對象,它會(huì)將請求代理到使用 TCP 端口 9376,并且具有標(biāo)簽?"app=MyApp"?的?Pod?上。 Kubernetes 為該服務(wù)分配一個(gè) IP 地址(有時(shí)稱為 “集群IP” ),該 IP 地址由服務(wù)代理使用。
endpoint
Endpoint是kubernetes中的一個(gè)資源對象,存儲(chǔ)在etcd中,用來記錄一個(gè)service對應(yīng)的所有pod的訪問地址,它是根據(jù)service配置文件中selector描述產(chǎn)生的。
????一個(gè)service由一組pod組成,這些pod通過Endpoint暴露出來,Endpoints是實(shí)現(xiàn)實(shí)際服務(wù)的端點(diǎn)集合。換句話說,service和pod之間的聯(lián)系是通過endpoints實(shí)現(xiàn)的。
kube-proxy 目前支持三種工作模式:userspace、iptables、ipvs
userspace模式下,kube-proxy會(huì)為每一個(gè)Service創(chuàng)建一個(gè)監(jiān)聽端口,發(fā)向Cluster IP的請求被Iptables規(guī)則重定向到kube-proxy監(jiān)聽的端口上,kube-proxy根據(jù)LB算法選擇一個(gè)提供服務(wù)的pod并和其建立鏈接,以將請求轉(zhuǎn)發(fā)到Pod上。
該模式下,kube-proxy充當(dāng)了一個(gè)四層負(fù)責(zé)均衡器的角色,由于kube-proxy運(yùn)行在userspace中,在進(jìn)行轉(zhuǎn)發(fā)處理時(shí)會(huì)增加內(nèi)核和用戶空間之間的數(shù)據(jù)拷貝,雖然比較穩(wěn)定,但是效率比較低。
iptables模式下,kube-proxy為service后端的每個(gè)Pod創(chuàng)建對應(yīng)的iptables規(guī)則,直接將發(fā)向Cluster IP的請求重定向到一個(gè)Pod IP。
?該模式下,kube-proxy不承擔(dān)四層負(fù)責(zé)均衡器的角色,只負(fù)責(zé)創(chuàng)建iptables規(guī)則。該模式的優(yōu)點(diǎn)是較userspace模式效率更高,但不能提供靈活的LB策略,當(dāng)后端Pod不可用時(shí)也無法進(jìn)行重試。
pvs模式和iptables模式類似,kube-proxy監(jiān)控Pod的變化并創(chuàng)建相應(yīng)的ipvs規(guī)則,ipvs相對iptables轉(zhuǎn)發(fā)效率更高。除此之外,ipvs支持更多的LB算法。
Kubernetes Controller內(nèi)擁有許多的控制器類型,用來控制pod的狀態(tài)、行為、副本數(shù)量等等,控制器通過Pod的標(biāo)簽來控制Pod ,從而實(shí)現(xiàn)對應(yīng)用的運(yùn)維,如伸縮、升級等。
常用的控制器類型如下:
ReplicationController 、ReplicaSet、Deployment:無狀態(tài)服務(wù),保證在任意時(shí)間運(yùn)行Pod指定的副本數(shù)量,能夠保證Pod總是可用的,支持滾動(dòng)更新、回滾。典型用法:web服務(wù)。
DaemonSet:確保集群內(nèi)全部(或部分)node節(jié)點(diǎn)上都分配一個(gè)pod,如果新加node節(jié)點(diǎn),也會(huì)自動(dòng)再分配對應(yīng)的pod。典型用法:filebeat日志收集、prometheus資源監(jiān)控。
StatefulSet:有狀態(tài)服務(wù),如各種數(shù)據(jù)存儲(chǔ)系統(tǒng)。StatefullSet內(nèi)的服務(wù)有著穩(wěn)定的持久化存儲(chǔ)和網(wǎng)絡(luò)標(biāo)識(shí),有序部署,有序伸縮。
Job:只運(yùn)行一次的作業(yè)。
CronJob:周期性運(yùn)行的作業(yè)。典型用法:數(shù)據(jù)庫定時(shí)備份。
Horizontal Pod Autoscaling(HPA):按照期望的pod的cpu或內(nèi)存來自動(dòng)伸縮pod數(shù)量。
Pod是通過Controller實(shí)現(xiàn)應(yīng)用的運(yùn)維,比如彈性伸縮,滾動(dòng)升級等
Pod 和 Controller之間是通過label標(biāo)簽來建立關(guān)系,同時(shí)Controller又被稱為控制器工作負(fù)載
Scheduler是 Kubernetes 的調(diào)度器,屬于核心組件,主要的任務(wù)是把定義的 Pod 分配到集群的節(jié)點(diǎn)上,聽起來非常簡單,但是有很多要考慮的問題:
公平:如果保證每個(gè)節(jié)點(diǎn)都能被分配資源
資源高效利用: 集群所有資源最大化被使用
效率:調(diào)度的性能更好,能夠盡快地對大批量的 Pod 完成調(diào)度工作
靈活:允許用戶根據(jù)自己的需求控制調(diào)度的邏輯
Scheduler 提供的調(diào)度流程分為預(yù)選 (Predicates) 和優(yōu)選 (Priorities) 兩個(gè)步驟:
預(yù)選,K8S會(huì)遍歷當(dāng)前集群中的所有?Node,篩選出其中符合要求的 Node 作為候選
優(yōu)選,K8S將對候選的 Node 進(jìn)行打分
第一階段:預(yù)選
預(yù)選的作用,是找到滿足條件的節(jié)點(diǎn),如具有SSD硬盤,系統(tǒng)內(nèi)存大于某個(gè)值,去掉不滿足條件的節(jié)點(diǎn)。以下是幾個(gè)比較重要的策略:
防止過度提交
反親和
親和
污染和容忍
第二階段:優(yōu)選
預(yù)選可能找到多個(gè)滿足條件的node, 優(yōu)選階段將按照一些規(guī)則對其進(jìn)行打分并匯總,打分高者最后會(huì)被選中。以下是幾個(gè)優(yōu)選的策略:
節(jié)點(diǎn)漫延
反親和
親和
打分后線性相加,得到最后的總分,分高的node將會(huì)被選中。
現(xiàn)在再來看 Kubernetes 從一開始就提供的東西:描述各種資源需求的標(biāo)準(zhǔn) API。例如,
描述 pod、container 等計(jì)算需求?的 API;
描述 service、ingress 等虛擬網(wǎng)絡(luò)功能?的 API;
描述 volumes 之類的持久存儲(chǔ)?的 API;
甚至還包括 service account 之類的服務(wù)身份?的 API 等等。
用戶創(chuàng)建一個(gè)資源分兩個(gè)步驟:
第一步是將對應(yīng)請求發(fā)送給apiserver,通過apiserver把對應(yīng)資源定義的信息存放在etcd中;第二個(gè)步驟是對應(yīng)資源類型的控制器通過apiserver從etcd中讀取對應(yīng)資源的定義,將其創(chuàng)建出來
k8s上,資源的類型有很多,比如pod,service,PersistentVolume,PersistentVolumeClaim等等,這些都是一些基礎(chǔ)的資源類型
k8s上擴(kuò)展資源類型的方式有三種
第一種是crd,crd是k8s內(nèi)建的資源類型,該類型資源主要用來創(chuàng)建用戶自定義資源類型的資源;即通過crd資源,可以將用戶自定義資源類型轉(zhuǎn)換為k8s上資源類型;
第二種是自定義apiserver;這種方式要比第一種方式要復(fù)雜一點(diǎn),需要用戶手動(dòng)開發(fā)程序?qū)崿F(xiàn)對應(yīng)功能的apiserver,讓其用戶創(chuàng)建自定義類型資源能夠通過自定義apiserver實(shí)現(xiàn);
第三種方式就是修改現(xiàn)有k8sapiserver,讓其支持對應(yīng)用戶自定義資源類型
自定義控制器
自定義資源類型我們可以使用crd資源實(shí)現(xiàn),也可以使用自定義apiserver或修改原有apiserver代碼實(shí)現(xiàn)
自定義控制器也是同樣的邏輯,使用自定義控制器的目的也是讓對應(yīng)自定義類型資源能夠被自定義控制器監(jiān)聽,一旦對應(yīng)資源發(fā)生變動(dòng),它能夠?qū)⑵湓趉8s上創(chuàng)建出來,并一直保持和用戶期望的狀態(tài)吻合;自定義控制器和自定義資源類型可以分開實(shí)現(xiàn),也可以合并在一起實(shí)現(xiàn),即自定義控制器程序能夠自動(dòng)創(chuàng)建crd資源,讓其對應(yīng)自定義類型資源能夠被k8s識(shí)別并將其創(chuàng)建出來;具體是分開實(shí)現(xiàn)還是合并在一起實(shí)現(xiàn),取決開發(fā)自定義控制器程序員
crd資源是k8s上的標(biāo)準(zhǔn)資源之一,它的定義主要有apiVersion,kind,metadata,spec和status;其中kind類型為CustomResourceDefinition,apiVersion是apiextensions.k8s.io/v1;這兩個(gè)是固定格式;spec字段是用來定義對應(yīng)指定資源類型資源的相關(guān)屬性
CRD:用來聲明用戶的自定義資源,例如它是 namespace-scope 還是 cluster-scope 的資源、有哪些字段等等,K8s 會(huì)自動(dòng)根據(jù)這個(gè)定義生成相應(yīng)的 API;
CRD 是資源類型定義,具體的資源叫 CR。
Operator 框架:“operator” 在這里的字面意思是“承擔(dān)運(yùn)維任務(wù)的程序”, 它們的基本邏輯都是一樣的:時(shí)刻盯著資源狀態(tài),一有變化馬上作出反應(yīng)(也就是 reconcile 邏輯)。
控制器的目的是讓 CRD 定義的資源達(dá)到我們預(yù)期的一個(gè)狀態(tài),要達(dá)到我們定義的狀態(tài),我們需要監(jiān)聽觸發(fā)事件。觸發(fā)事件的概念是從硬件信號產(chǎn)生?中斷?的機(jī)制衍生過來的,
其產(chǎn)生一個(gè)電平信號時(shí),有水平觸發(fā)(包括高電平、低電平),也有邊緣觸發(fā)(包括上升沿、下降沿觸發(fā)等)。
水平觸發(fā) : 系統(tǒng)僅依賴于當(dāng)前狀態(tài)。即使系統(tǒng)錯(cuò)過了某個(gè)事件(可能因?yàn)楣收蠏斓袅?#xff09;,當(dāng)它恢復(fù)時(shí),依然可以通過查看信號的當(dāng)前狀態(tài)來做出正確的響應(yīng)。
邊緣觸發(fā) : 系統(tǒng)不僅依賴于當(dāng)前狀態(tài),還依賴于過去的狀態(tài)。如果系統(tǒng)錯(cuò)過了某個(gè)事件(“邊緣”),則必須重新查看該事件才能恢復(fù)系統(tǒng)。
Kubernetes 的 API 和控制器都是基于水平觸發(fā)的,可以促進(jìn)系統(tǒng)的自我修復(fù)和周期調(diào)協(xié)。
其 API 實(shí)現(xiàn)方式(也是我們常說的聲明式 API)是:控制器監(jiān)視資源對象的實(shí)際狀態(tài),并與對象期望的狀態(tài)進(jìn)行對比,然后調(diào)整實(shí)際狀態(tài),使之與期望狀態(tài)相匹配。
總結(jié)
以上是生活随笔為你收集整理的kubernetes基础组件原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP站内搜索代码#
- 下一篇: Python3新特性 类型注解 以及