1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Kubernetes Pod 刪除操作源碼解析

        共 6110字,需瀏覽 13分鐘

         ·

        2022-04-13 07:31

        比如現(xiàn)在我有一個(gè)更新策略為 Recreate 的應(yīng)用,然后執(zhí)行刪除命令,如下所示:

        ????kubectl?get?pods
        NAME????????????????????READY???STATUS????RESTARTS????????AGE
        minio-875749785-sv5ns???1/1?????Running???1?(2m52s?ago)???42h
        ????kubectl?delete?pod?minio-875749785-sv5ns
        pod?"minio-875749785-sv5ns"?deleted

        在刪除之前在另外一個(gè)終端觀察應(yīng)用狀態(tài):

        ????kubectl?get?pods?-w
        NAME????????????????????READY???STATUS??????????????RESTARTS?????????AGE
        minio-875749785-sv5ns???1/1?????Running?????????????1?(2m46s?ago)???42h
        minio-875749785-sv5ns???1/1?????Terminating?????????1?(2m57s?ago)???42h
        minio-875749785-h2j2b???0/1?????Pending?????????????0???????????????0s
        minio-875749785-h2j2b???0/1?????Pending?????????????0???????????????0s
        minio-875749785-h2j2b???0/1?????ContainerCreating???0???????????????0s
        minio-875749785-sv5ns???0/1?????Terminating?????????1?(2m59s?ago)???42h
        minio-875749785-sv5ns???0/1?????Terminating?????????1?(2m59s?ago)???42h
        minio-875749785-sv5ns???0/1?????Terminating?????????1?(2m59s?ago)???42h
        minio-875749785-h2j2b???0/1?????Running?????????????0???????????????17s
        minio-875749785-h2j2b???1/1?????Running?????????????0???????????????30s

        從上面的過程可以看到當(dāng)我們執(zhí)行 kubectl delete 命令后 Pod 變成了 Terminating 狀態(tài),然后才消失。接下來我們會(huì)從代碼角度來介紹下刪除 Pod 的整體流程。

        這里我們以 v1.22.8 版本的 Kubernetes 為例進(jìn)行說明,其他版本不保證代碼完全一致,但是整體思路是一致的。

        刪除狀態(tài)

        我們可以根據(jù) kubectl 操作后看到的狀態(tài)來進(jìn)行跟蹤,上面的格式化結(jié)果是通過代碼 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/printers/internalversion/printers.go#L88-L102 實(shí)現(xiàn)的,如下所示:

        對(duì)于 Pod 的輸出結(jié)果是通過 printPod 函數(shù)獲取的,代碼位于:https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/printers/internalversion/printers.go#L756-L840,其中有一段代碼提到了 Terminating 值,是在 pod.DeletionTimestamp != nil 的情況下變成該狀態(tài)的,如下所示:

        也就是說當(dāng)執(zhí)行刪除操作的時(shí)候,會(huì)設(shè)置 Pod 的 DeletionTimestamp 屬性,這個(gè)時(shí)候就會(huì)顯示成 Terminating 狀態(tài)。

        當(dāng)執(zhí)行刪除操作的時(shí)候,會(huì)向 apiserver 發(fā)送一次 DELETE 請求:

        I0408?11:25:33.002155???42938?round_trippers.go:435]?curl?-v?-XDELETE??-H?"Content-Type:?application/json"?-H?"User-Agent:?kubectl/v1.22.7?(darwin/amd64)?kubernetes/b56e432"?-H?"Accept:?application/json"?'https://192.168.0.111:6443/api/v1/namespaces/default/pods/minio-875749785-sv5ns'
        I0408?11:25:33.037245???42938?round_trippers.go:454]?DELETE?https://192.168.0.111:6443/api/v1/namespaces/default/pods/minio-875749785-sv5ns?200?OK?in?35?milliseconds

        接收到刪除請求的處理器位于代碼 https://github.com/kubernetes/kubernetes/blob/v1.22.8/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go#L986,如下所示:

        BeforeDelete 函數(shù)中判斷是否需要優(yōu)雅刪除,判斷的標(biāo)準(zhǔn)是 DeletionGracePeriodSeconds 值是否為 0,不為零則認(rèn)為是優(yōu)雅刪除,apiserver 不會(huì)立即將這個(gè)對(duì)象從 etcd 中刪除,否則直接刪除。對(duì)于 Pod 而言,默認(rèn) DeletionGracePeriodSeconds 為 30 秒,因此這里不會(huì)被立刻刪除掉,而是將 DeletionTimestamp 設(shè)置為當(dāng)前時(shí)間,DeletionGracePeriodSeconds 設(shè)置為默認(rèn)值 30 秒。代碼位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go#L93-L159,在該函數(shù)中會(huì)設(shè)置 DeletionTimestamp 的值,如下所示:

        上面的代碼驗(yàn)證了當(dāng)執(zhí)行刪除操作的時(shí)候,apiserver 會(huì)先設(shè)置 Pod 的 DeletionTimestamp 屬性為當(dāng)前時(shí)間加上優(yōu)雅刪除寬限時(shí)長的時(shí)間點(diǎn),設(shè)置了該屬性后,我們客戶端格式化過后看到的就是 Terminating 狀態(tài)了。

        優(yōu)雅刪除

        由于 Pod 中涉及到其他很多資源,比如 sandbox 容器、volume 卷等等,在刪除后都需要進(jìn)行回收,而刪除 Pod 最終也是去刪除對(duì)應(yīng)的容器,這個(gè)就需要 Pod 所在節(jié)點(diǎn)的 kubelet 來完成清理了。kubelet 首先同樣會(huì)一直 watch 我們的 Pod,當(dāng) Pod 的刪除時(shí)間更新后,自然就會(huì)接收到事件,然后進(jìn)行相應(yīng)的清理工作。

        kubelet 對(duì) Pod 的處理主要在 syncLoop 函數(shù)中,會(huì)去調(diào)用和事件相關(guān)的處理函數(shù) syncLoopIteration,代碼位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kubelet.go#L2040-L2079 中,如下所示:

        當(dāng)執(zhí)行刪除操作的時(shí)候,apiserver 首先會(huì)更新 Pod 中的 DeletionTimestamp 屬性,這個(gè)改變對(duì)于 kubelet 來說屬于更新操作,所以會(huì)對(duì)應(yīng) kubetypes.UPDATE 操作,會(huì)調(diào)用 HandlePodUpdates 函數(shù)進(jìn)行更新。

        HandlePodUpdates 中會(huì)調(diào)用 dispatchWork 將 Pod 刪除分配給具體的 worker 處理,podWorker 是具體的執(zhí)行者,也就是每次 Pod 需要更新都會(huì)發(fā)送給 podWorker。

        dispatchWork 方法會(huì)調(diào)用 UpdatePod 函數(shù)對(duì) Pod 進(jìn)行刪除,代碼位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/pod_workers.go#L540-L765,在該函數(shù)中會(huì)通過一個(gè) channel 傳遞 Pod 信息,在一個(gè) goroutine 中調(diào)用 managePodLoop 函數(shù)進(jìn)行處理,該函數(shù)中會(huì)調(diào)用 syncTerminatingPod/syncPod 方法來進(jìn)行刪除操作。

        最終都會(huì)調(diào)用 killPod 函數(shù)去執(zhí)行刪除 Pod:

        killPod 函數(shù)中會(huì)調(diào)用容器運(yùn)行時(shí)去停止該 Pod 中的容器,代碼位于https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kubelet_pods.go#L856-L868:

        容器運(yùn)行時(shí)的 KillPod 方法位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kuberuntime/kuberuntime_manager.go#L969-L998,如下所示:

        killPodWithSyncResult 方法中首先調(diào)用函數(shù) killContainersWithSyncResult 殺掉所有運(yùn)行的容器,然后刪除 Pod 的 sandbox。

        在該函數(shù)中,利用多個(gè) goroutine 來對(duì) Pod 中的每一個(gè)容器進(jìn)行刪除,刪除容器的方法是 killContainer,在該函數(shù)中首先會(huì)執(zhí)行 pre-stop 這個(gè) hooks(如果存在的話),然后才停止容器,代碼位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kuberuntime/kuberuntime_container.go#L660-L736。

        首先獲取優(yōu)雅刪除的寬限時(shí)間:

        其中 TerminationGracePeriodSeconds 可以在資源清單文件中進(jìn)行設(shè)置,默認(rèn)為 30 秒,這個(gè)時(shí)間是,給 Pod 發(fā)出關(guān)閉指令后會(huì)給應(yīng)用發(fā)送 SIGTERM 信號(hào),程序只需要捕獲 SIGTERM 信號(hào)并做相應(yīng)處理即可。也就是 Pod 接收到 SIGTERM 信號(hào)后,應(yīng)用能夠優(yōu)雅關(guān)閉的時(shí)間。該時(shí)間是由 apiserver 設(shè)置的,前面已經(jīng)分析過。

        如果配置了 pre-stop hook 并且還有足夠的時(shí)間,則會(huì)執(zhí)行該 hook,pre-stop 主要是為了業(yè)務(wù)在容器刪除前前,能夠優(yōu)雅的停止,比如資源回收等操作:

        最后才會(huì)真正去調(diào)用底層容器運(yùn)行時(shí)來停止容器:

        容器刪掉后回到前面的 killPodWithSyncResult 函數(shù)中,接下來就會(huì)去調(diào)用運(yùn)行時(shí)服務(wù)的 StopPodSandbox 函數(shù)停止 sandbox 容器,也就是 pause 容器。

        //?Stop?all?sandboxes?belongs?to?same?pod
        for?_,?podSandbox?:=?range?runningPod.Sandboxes?{
        ????if?err?:=?m.runtimeService.StopPodSandbox(podSandbox.ID.ID);?err?!=?nil?&&?!crierror.IsNotFound(err)?{
        ????????killSandboxResult.Fail(kubecontainer.ErrKillPodSandbox,?err.Error())
        ????????klog.ErrorS(nil,?"Failed?to?stop?sandbox",?"podSandboxID",?podSandbox.ID)
        ????}
        }

        到這里 kubelet 就完成了對(duì) Pod 的優(yōu)雅刪除,但是這并沒有結(jié)束。

        同步狀態(tài)

        對(duì)于優(yōu)雅刪除一開始在 apiserver 只是給 Pod 設(shè)置了 DeletionTimestamp 屬性,然后 kubelet watch 來更新后去完成了 Pod 的優(yōu)雅刪除,但是現(xiàn)在服務(wù)端中還有 Pod 的記錄,并沒有真正去刪除。

        在 kubelet 啟動(dòng)的時(shí)候同時(shí)還去啟動(dòng)了一個(gè) statusManager 的同步循環(huán),該 Manager 是 kubelet pod 狀態(tài)的真實(shí)來源,應(yīng)該與最新的 v1.PodStatus 保持同步,它還將更新同步回 apiserver,也就是當(dāng)優(yōu)雅刪除完成后我們還將通過該管理器將狀態(tài)同步回 apiserver。

        狀態(tài)管理器在與 apiserver 進(jìn)行狀態(tài)同步的時(shí)候會(huì)去調(diào)用該管理器下面的 syncPod 方法進(jìn)行處理,代碼位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/status/status_manager.go#L149-L181,如下所示:

        在該方法中會(huì)判斷 Pod 是否已經(jīng)優(yōu)雅停止了,代碼位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/status/status_manager.go#L583-L652,如下所示:

        比如會(huì)判斷是否還有容器在運(yùn)行、volumes 是否還沒有清理、pod cgroup 還沒清空等等,如果 canBeDeleted 返回 true,則表示 pod 已經(jīng)優(yōu)雅的停止了,那么這個(gè)時(shí)候就可以向 apiserver 發(fā)送 Delete 請求,再次刪除 Pod 了。

        不過這一次的設(shè)置的 GracePeriodSeconds 為 0,表示要強(qiáng)制刪除 Pod 了,到這里 apiserver 會(huì)再次收到 DELETE 請求,與第一次不同的是,這次是強(qiáng)制刪除 Pod,會(huì)去 etcd 中刪除 Pod 對(duì)象了。

        這個(gè)時(shí)候 kubelet 會(huì)接受到 REMOVE 的事件,調(diào)用 HandlePodRemoves 函數(shù)去進(jìn)行處理:

        首先會(huì)去調(diào)用 deletePod 函數(shù)去停掉關(guān)聯(lián)的 pod worker,然后還會(huì)調(diào)用 probeManager 去移除 Pod 相關(guān)的探針 prober worker,到這里就表示 Pod 徹底從節(jié)點(diǎn)上刪除了。

        瀏覽 85
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            韩国三级hd高清中字 | 操女人的骚逼 | 日日夜夜逼 | www.乱伦.com | 私人玩物极品女神 | 国产欧美日韩另类 | 国产免费拔擦拔擦8x高清 | 久久久天堂国产精品女人 | 免费绳艺捆绑紧缚av网站入口 | 大香蕉欧美在线 |