簡(jiǎn)介
kubernetes 是一個(gè)分布式的集群管理系統(tǒng)惭每,在每個(gè)節(jié)點(diǎn)(node)上都要運(yùn)行一個(gè) worker 對(duì)容器進(jìn)行生命周期的管理,這個(gè) worker 程序就是?kubelet。
簡(jiǎn)單地說(shuō),kubelet?的主要功能就是定時(shí)從某個(gè)地方獲取節(jié)點(diǎn)上 pod/container 的期望狀態(tài)(運(yùn)行什么容器、運(yùn)行的副本數(shù)量饥努、網(wǎng)絡(luò)或者存儲(chǔ)如何配置等等)捡鱼,并調(diào)用對(duì)應(yīng)的容器平臺(tái)接口達(dá)到這個(gè)狀態(tài)八回。
kubelet 除了這個(gè)最核心的功能之外,還有很多其他特性:
? ? * 定時(shí)匯報(bào)當(dāng)前節(jié)點(diǎn)的狀態(tài)給 apiserver驾诈,以供調(diào)度的時(shí)候使用
? ? *?鏡像和容器的清理工作缠诅,保證節(jié)點(diǎn)上鏡像不會(huì)占滿磁盤(pán)空間,退出的容器不會(huì)占用太多資源
? ? * 運(yùn)行 HTTP Server乍迄,對(duì)外提供節(jié)點(diǎn)和 pod 信息管引,如果在 debug 模式下,還包括調(diào)試信息
? ? * 等等……
集群狀態(tài)下闯两,kubelet 會(huì)從 master 上讀取信息褥伴,但其實(shí) kubelet 還可以從其他地方獲取節(jié)點(diǎn)的 pod 信息。目前 kubelet 支持三種數(shù)據(jù)源:
? ? *?本地文件
? ? *?通過(guò) url 從網(wǎng)絡(luò)上某個(gè)地址來(lái)獲取信息
? ? *?API Server:從 kubernetes master 節(jié)點(diǎn)獲取信息
從管理的對(duì)象來(lái)說(shuō)漾狼,kubelet 目前支持docker和rkt重慢,默認(rèn)情況下使用的 docker。
kubelet 主要功能
Pod 管理
在 kubernetes 的設(shè)計(jì)中逊躁,最基本的管理單位是 pod似踱,而不是 container。pod 是 kubernetes 在容器上的一層封裝稽煤,由一組運(yùn)行在同一主機(jī)的一個(gè)或者多個(gè)容器組成核芽。如果把容器比喻成傳統(tǒng)機(jī)器上的一個(gè)進(jìn)程(它可以執(zhí)行任務(wù),對(duì)外提供某種功能)酵熙,那么 pod 可以類比為傳統(tǒng)的主機(jī):它包含了多個(gè)容器轧简,為它們提供共享的一些資源。
之所以費(fèi)功夫提供這一層封裝匾二,主要是因?yàn)槿萜魍扑]的用法是里面只運(yùn)行一個(gè)進(jìn)程哮独,而一般情況下某個(gè)應(yīng)用都由多個(gè)組件構(gòu)成的庐橙。
pod 中所有的容器最大的特性也是最大的好處就是共享了很多資源,比如網(wǎng)絡(luò)空間借嗽。pod 下所有容器共享網(wǎng)絡(luò)和端口空間态鳖,也就是它們之間可以通過(guò)?localhost?訪問(wèn)和通信,對(duì)外的通信方式也是一樣的恶导,省去了很多容器通信的麻煩浆竭。
除了網(wǎng)絡(luò)之外,定義在 pod 里的 volume 也可以 mount 到多個(gè)容器里惨寿,以實(shí)現(xiàn)共享的目的邦泄。
最后,定義在 pod 的資源限制(比如 CPU 和 Memory) 也是所有容器共享的裂垦。
容器健康檢查
創(chuàng)建了容器之后顺囊,kubelet 還要查看容器是否正常運(yùn)行,如果容器運(yùn)行出錯(cuò)蕉拢,就要根據(jù)設(shè)置的重啟策略進(jìn)行處理特碳。檢查容器是否健康主要有三種方式:執(zhí)行命令,http Get晕换,和tcp連接午乓。
不管用什么方式,如果檢測(cè)到容器不健康闸准,kubelet 會(huì)刪除該容器益愈,并根據(jù)容器的重啟策略進(jìn)行處理(比如重啟,或者什么都不做)夷家。
容器監(jiān)控
kubelet 還有一個(gè)重要的責(zé)任蒸其,就是監(jiān)控所在節(jié)點(diǎn)的資源使用情況,并定時(shí)向 master 報(bào)告库快。知道整個(gè)集群所有節(jié)點(diǎn)的資源情況摸袁,對(duì)于 pod 的調(diào)度和正常運(yùn)行至關(guān)重要。
kubelet 使用?cAdvisor?進(jìn)行資源使用率的監(jiān)控缺谴。cAdvisor 是 google 開(kāi)源的分析容器資源使用和性能特性的工具但惶,在 kubernetes 項(xiàng)目中被集成到 kubelet 里,無(wú)需額外配置湿蛔。默認(rèn)情況下膀曾,你可以在?localhost:4194?地址看到 cAdvisor 的管理界面。
除了系統(tǒng)使用的 CPU阳啥,Memory添谊,存儲(chǔ)和網(wǎng)絡(luò)之外,cAdvisor 還記錄了每個(gè)容器使用的上述資源情況察迟。
代碼分析
入口程序
cmd/kublet/kubelet.go? -->? main 方法
1. 創(chuàng)建kubeletFlags數(shù)據(jù)結(jié)構(gòu)(對(duì)應(yīng)kubelet命令行參數(shù))斩狱;
2. 創(chuàng)建kubeletConfigration數(shù)據(jù)結(jié)構(gòu)耳高;
3. 創(chuàng)建kubeletServer數(shù)據(jù)結(jié)構(gòu),此數(shù)據(jù)結(jié)構(gòu)包括kubeletFlags所踊、kubeletConfigration泌枪;
4. 啟動(dòng)kubelet Configuration controller,此功能開(kāi)始配置和狀態(tài)的循環(huán)同步秕岛;
// 創(chuàng)建一個(gè)配置控制器BootstrapKubeletConfigController(defaultConfig*kubeletconfiginternal.KubeletConfiguration,dynamicConfigDir string) {
? ? ?c := dynamickubeletconfig.NewController(defaultConfig, dir)
? ? // 讀取默認(rèn)配置碌燕,并啟動(dòng)一個(gè)goroutine來(lái)更新
? ??kc, err := c.Bootstrap()
? ? return kc, c, nil
}
5. 創(chuàng)建kubeletDeps數(shù)據(jù)結(jié)構(gòu);
kubeletDeps?的名字聽(tīng)起來(lái)很奇怪继薛,其實(shí)它內(nèi)部保存了 kubelet 各個(gè)重要組件的對(duì)象修壕,之所以要把它作為參數(shù)傳遞,是為了實(shí)現(xiàn) dependency injection遏考。簡(jiǎn)單地說(shuō)慈鸠,就是把 kubelet 依賴的組件對(duì)象作為參數(shù)傳進(jìn)來(lái),這樣可以控制 kubelet 的行為灌具。比如在測(cè)試的時(shí)候青团,只要構(gòu)建 fake 的組件實(shí)現(xiàn),就能很輕松進(jìn)行測(cè)試稽亏。KubeDeps?包含的組件很多壶冒,下面列出一些:
CAdvisorInterface:提供 cAdvisor 接口功能的組件缕题,用來(lái)獲取監(jiān)控信息
DockerClientConfig:docker 客戶端截歉,用來(lái)和 docker 交互
KubeClient:apiserver 客戶端,用來(lái)和 api server 通信
Mounter:執(zhí)行 mount 相關(guān)操作
NetworkPlugins:網(wǎng)絡(luò)插件烟零,執(zhí)行網(wǎng)絡(luò)設(shè)置工作
VolumePlugins:volume 插件瘪松,執(zhí)行 volume 設(shè)置工作
TLSOptions:檢查或者生成自簽名證書(shū)和密鑰文件。
啟動(dòng)程序
cmd/kubelet/app/server.go ? -->? Run 方法
1. 判斷kubelet是否以standalone模式運(yùn)行锨阿;
2. 創(chuàng)建對(duì)象kubeClient宵睦、evnetClient,用來(lái)和 apiserver 通信墅诡。 heartbeatClient壳嚎、externalkubeClient、ContainerManager末早;并設(shè)置OOM烟馅。
3.?調(diào)用RunKubelet。 運(yùn)行 kubelet然磷,這個(gè)函數(shù)會(huì)啟動(dòng) goroutine 一直運(yùn)行郑趁,是 kubelet 核心功能執(zhí)行的地方。
RunKubelet(&s.KubeletFlags, &s.KubeletConfiguration, kubeDeps, s.RunOnce) {
? ? //?1. 初始化各個(gè)對(duì)象姿搜,比如 eventBroadcaster寡润,這樣就能給?apiserver?發(fā)送事件了
? ? makeEventRecorder(kubeDeps, nodeName)
……
? ? // 2. 通過(guò) builder 創(chuàng)建并初始化Kubelet
????builder := kubeDeps.Builder
????if builder == nil {
????????builder = CreateAndInitKubelet
? ? }
? ? 調(diào)用builder(......)
? ? // 3. 根據(jù)運(yùn)行模式捆憎,運(yùn)行?Kubelet
? ? startKubelet(k, podCfg, kubeCfg, kubeDeps)
}