本活動在微信公眾號【我的小碗湯】上舉行,有送書活動!這里參與答題不能參與到送書活動哦!
昨日考題
通過命令行,使用nginx鏡像創(chuàng)建一個(gè)pod并手動調(diào)度到節(jié)點(diǎn)名為node1121節(jié)點(diǎn)上,Pod的名稱為cka-1121,答題最好附上,所用命令、創(chuàng)建Pod所需最精簡的yaml;如果評論有限制,請把注意點(diǎn)列出,主要需列出手動調(diào)度怎么做?
注意:手動調(diào)度是指不需要經(jīng)過kube-scheduler去調(diào)度。
昨日答案
將名稱為cka-1121的Pod,調(diào)度到節(jié)點(diǎn)node1121:
apiVersion: v1
kind: Pod
metadata:
name: cka-1121
labels:
app: cka-1121
spec:
containers:
- name: cka-1121
image: busybox
command: ['sh', '-c', 'echo Hello CKA! && sleep 3600']
nodeName: node1121
昨日解析
官網(wǎng)中調(diào)度器地址:
https://kubernetes.io/docs/concepts/scheduling/kube-scheduler/
調(diào)度器命令行參數(shù):
https://kubernetes.io/docs/reference/command-line-tools-reference/kube-scheduler/
調(diào)度器kube-scheduler分為預(yù)選、優(yōu)選、pod優(yōu)先級搶占、bind階段;
預(yù)選:從podQueue的待調(diào)度隊(duì)列中彈出需要調(diào)度的pod,先進(jìn)入預(yù)選階段,預(yù)選函數(shù)來判斷每個(gè)節(jié)點(diǎn)是否適合被該P(yáng)od調(diào)度。
優(yōu)選:從預(yù)選篩選出的滿足的節(jié)點(diǎn)中選擇出最優(yōu)的節(jié)點(diǎn)。
pod優(yōu)先級搶占:如果預(yù)選和優(yōu)選調(diào)度失敗,則會嘗試將優(yōu)先級低的pod剔除,讓優(yōu)先級高的pod調(diào)度成功。
bind:上述步驟完成后,調(diào)度器會更新本地緩存,但最后需要將綁定結(jié)果提交到etcd中,需要調(diào)用Apiserver的Bind接口完成。
以下k8s源碼版本為1.13.2
我們?nèi)ゲ榭磌ube-scheduler源碼,調(diào)度器通過list-watch機(jī)制,監(jiān)聽集群內(nèi)Pod的新增、更新、刪除事件,調(diào)用回調(diào)函數(shù)。指定nodeName后將不會放入到未調(diào)度的podQueue隊(duì)列中,也就不會走上面這幾個(gè)階段。具體可以來到pkg\scheduler\factory\factory.go源碼中的NewConfigFactory函數(shù)中:

其中在構(gòu)建pod資源對象新增、更新、刪除的回調(diào)函數(shù)時(shí),分已被調(diào)度的和未被調(diào)度的回調(diào)。
已被調(diào)度的回調(diào):
已被調(diào)度的pod根據(jù)FilterFunc中定義的邏輯過濾,nodeName不為空,返回true時(shí),將會走Handler中定義的AddFunc、UpdateFunc、DeleteFunc,這個(gè)其實(shí)最終不會加入到podQueue中,但需要加入到本地緩存中,因?yàn)檎{(diào)度器會維護(hù)一份節(jié)點(diǎn)上pod列表的緩存。
// scheduled pod cache 已被調(diào)度的
args.PodInformer.Informer().AddEventHandler(
cache.FilteringResourceEventHandler{
FilterFunc: func(obj interface{}) bool {
switch t := obj.(type) {
case *v1.Pod:
//nodeName不為空,返回true;且返回true時(shí)將被走AddFunc、UpdateFunc、DeleteFunc,這個(gè)其實(shí)最終不會加入到podQueue中
return assignedPod(t)
case cache.DeletedFinalStateUnknown:
if pod, ok := t.Obj.(*v1.Pod); ok {
return assignedPod(pod)
}
runtime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, c))
return false
default:
runtime.HandleError(fmt.Errorf("unable to handle object in %T: %T", c, obj))
return false
}
},
Handler: cache.ResourceEventHandlerFuncs{
AddFunc: c.addPodToCache,
UpdateFunc: c.updatePodInCache,
DeleteFunc: c.deletePodFromCache,
},
},
)
未被調(diào)度的回調(diào):
未被調(diào)度的pod根據(jù)FilterFunc中定義的邏輯過濾,nodeName為空且pod的SchedulerName和該調(diào)度器的名稱一致時(shí)返回true;返回true時(shí),將會走Handler中定義的AddFunc、UpdateFunc、DeleteFunc,這個(gè)最終會加入到podQueue中。
// unscheduled pod queue 沒有被調(diào)度的
args.PodInformer.Informer().AddEventHandler(
cache.FilteringResourceEventHandler{
FilterFunc: func(obj interface{}) bool {
switch t := obj.(type) {
case *v1.Pod:
//nodeName為空且pod的SchedulerName和該調(diào)度器的名稱一致時(shí)返回true;且返回true時(shí)將被加入到pod queue
return !assignedPod(t) && responsibleForPod(t, args.SchedulerName)
case cache.DeletedFinalStateUnknown:
if pod, ok := t.Obj.(*v1.Pod); ok {
return !assignedPod(pod) && responsibleForPod(pod, args.SchedulerName)
}
runtime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, c))
return false
default:
runtime.HandleError(fmt.Errorf("unable to handle object in %T: %T", c, obj))
return false
}
},
Handler: cache.ResourceEventHandlerFuncs{
AddFunc: c.addPodToSchedulingQueue,
UpdateFunc: c.updatePodInSchedulingQueue,
DeleteFunc: c.deletePodFromSchedulingQueue,
},
},
)
手動調(diào)度適用場景:
- 調(diào)度器不工作時(shí),可設(shè)置nodeName臨時(shí)救急 ;
- 可以封裝成自己的調(diào)度器;
擴(kuò)展點(diǎn):
- 過去幾個(gè)版本的Daemonset都是由controller直接指定pod的運(yùn)行節(jié)點(diǎn),不經(jīng)過調(diào)度器。
- 直到1.11版本,DaemonSet的pod由scheduler調(diào)度才作為alpha特性引入
昨天的留言中,有人提到static Pod,這種其實(shí)也屬于節(jié)點(diǎn)固定,但這種Pod局限很大,比如:不能掛載configmaps和secrets等,這個(gè)由Admission Controllers控制。
下面簡單說一下靜態(tài)Pod:
靜態(tài)Pod官網(wǎng)說明:
https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/
靜態(tài) pod指在特定的節(jié)點(diǎn)上直接通過 kubelet守護(hù)進(jìn)程進(jìn)行管理,APIServer無法管理。它沒有跟任何的控制器進(jìn)行關(guān)聯(lián),kubelet 守護(hù)進(jìn)程對它進(jìn)行監(jiān)控,如果崩潰了,kubelet 守護(hù)進(jìn)程會重啟它。Kubelet 通過APIServer為每個(gè)靜態(tài) pod 創(chuàng)建 鏡像 pod,這些鏡像 pod 對于 APIServer是可見的(即kubectl可以查詢到這些Pod),但是不受APIServer控制。
具體static pod yaml文件放到哪里,需要在kubelet配置中指定,先找到kubelet配置文件:
systemctl status kubelet

找到config.yaml文件:

里面指定了staticPodPath:

kubeadm安裝的集群,master節(jié)點(diǎn)上的kube-apiserver、kube-scheduler、kube-controller-manager、etcd就是通過static Pod方式部署的:

今日考題
通過命令行,創(chuàng)建兩個(gè)deployment。
- 需要集群中有2個(gè)節(jié)點(diǎn) ;
- 第1個(gè)deployment名稱為cka-1122-01,使用nginx鏡像,有2個(gè)pod,并配置該deployment自身的pod之間在節(jié)點(diǎn)級別反親和;
- 第2個(gè)deployment名稱為cka-1122-02,使用nginx鏡像,有2個(gè)pod,并配置該deployment的pod與第1個(gè)deployment的pod在節(jié)點(diǎn)級別親和;
最好提交最精簡的deployment yaml,如果評論被限制,請?zhí)峤环从H和性配置塊yaml,也可多次評論提交
作者簡介
作者:小碗湯,一位熱愛、認(rèn)真寫作的小伙,目前維護(hù)原創(chuàng)公眾號:『我的小碗湯』,專注于寫golang、docker、kubernetes等知識等提升硬實(shí)力的文章,期待你的關(guān)注。轉(zhuǎn)載說明:務(wù)必注明來源(注明:來源于公眾號:我的小碗湯, 作者:小碗湯)
作者簡潔
作者:小碗湯,一位熱愛、認(rèn)真寫作的小伙,目前維護(hù)原創(chuàng)公眾號:『我的小碗湯』,專注于寫go語言、docker、kubernetes、java等開發(fā)、運(yùn)維知識等提升硬實(shí)力的文章,期待你的關(guān)注。轉(zhuǎn)載說明:務(wù)必注明來源(注明:來源于公眾號:我的小碗湯,作者:小碗湯)