日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

21丨容器化守护进程的意义:DaemonSet

發(fā)布時(shí)間:2024/9/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 21丨容器化守护进程的意义:DaemonSet 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
你好,我是張磊。今天我和你分享的主題是:容器化守護(hù)進(jìn)程的意義之 DaemonSet。在上一篇文章中,我和你詳細(xì)分享了使用 StatefulSet 編排“有狀態(tài)應(yīng)用”的過程。從中不難看出,StatefulSet 其實(shí)就是對(duì)現(xiàn)有典型運(yùn)維業(yè)務(wù)的容器化抽象。也就是說,你一定有方法在不使用 Kubernetes、甚至不使用容器的情況下,自己 DIY 一個(gè)類似的方案出來。但是,一旦涉及到升級(jí)、版本管理等更工程化的能力,Kubernetes 的好處,才會(huì)更加凸現(xiàn)。比如,如何對(duì) StatefulSet 進(jìn)行“滾動(dòng)更新”(rolling update)?很簡單。你只要修改 StatefulSet 的 Pod 模板,就會(huì)自動(dòng)觸發(fā)“滾動(dòng)更新”:$ kubectl patch statefulset mysql --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"mysql:5.7.23"}]' statefulset.apps/mysql patched在這里,我使用了 kubectl patch 命令。它的意思是,以“補(bǔ)丁”的方式(JSON 格式的)修改一個(gè) API 對(duì)象的指定字段,也就是我在后面指定的“spec/template/spec/containers/0/image”。這樣,StatefulSet Controller 就會(huì)按照與 Pod 編號(hào)相反的順序,從最后一個(gè) Pod 開始,逐一更新這個(gè) StatefulSet 管理的每個(gè) Pod。而如果更新發(fā)生了錯(cuò)誤,這次“滾動(dòng)更新”就會(huì)停止。此外,StatefulSet 的“滾動(dòng)更新”還允許我們進(jìn)行更精細(xì)的控制,比如金絲雀發(fā)布(Canary Deploy)或者灰度發(fā)布,這意味著應(yīng)用的多個(gè)實(shí)例中被指定的一部分不會(huì)被更新到最新的版本。這個(gè)字段,正是 StatefulSet 的 spec.updateStrategy.rollingUpdate 的 partition 字段。比如,現(xiàn)在我將前面這個(gè) StatefulSet 的 partition 字段設(shè)置為 2:$ kubectl patch statefulset mysql -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":2}}}}'statefulset.apps/mysql patched其中,kubectl patch 命令后面的參數(shù)(JSON 格式的),就是 partition 字段在 API 對(duì)象里的路徑。所以,上述操作等同于直接使用 kubectl edit 命令,打開這個(gè)對(duì)象,把 partition 字段修改為 2。這樣,我就指定了當(dāng) Pod 模板發(fā)生變化的時(shí)候,比如 MySQL 鏡像更新到 5.7.23,那么只有序號(hào)大于或者等于 2 的 Pod 會(huì)被更新到這個(gè)版本。并且,如果你刪除或者重啟了序號(hào)小于 2 的 Pod,等它再次啟動(dòng)后,也會(huì)保持原先的 5.7.2 版本,絕不會(huì)被升級(jí)到 5.7.23 版本。StatefulSet 可以說是 Kubernetes 項(xiàng)目中最為復(fù)雜的編排對(duì)象,希望你課后能認(rèn)真消化,動(dòng)手實(shí)踐一下這個(gè)例子。而在今天這篇文章中,我會(huì)為你重點(diǎn)講解一個(gè)相對(duì)輕松的知識(shí)點(diǎn):DaemonSet。顧名思義,DaemonSet 的主要作用,是讓你在 Kubernetes 集群里,運(yùn)行一個(gè) Daemon Pod。 所以,這個(gè) Pod 有如下三個(gè)特征:這個(gè) Pod 運(yùn)行在 Kubernetes 集群里的每一個(gè)節(jié)點(diǎn)(Node)上;每個(gè)節(jié)點(diǎn)上只有一個(gè)這樣的 Pod 實(shí)例;當(dāng)有新的節(jié)點(diǎn)加入 Kubernetes 集群后,該 Pod 會(huì)自動(dòng)地在新節(jié)點(diǎn)上被創(chuàng)建出來;而當(dāng)舊節(jié)點(diǎn)被刪除后,它上面的 Pod 也相應(yīng)地會(huì)被回收掉。這個(gè)機(jī)制聽起來很簡單,但 Daemon Pod 的意義確實(shí)是非常重要的。我隨便給你列舉幾個(gè)例子:各種網(wǎng)絡(luò)插件的 Agent 組件,都必須運(yùn)行在每一個(gè)節(jié)點(diǎn)上,用來處理這個(gè)節(jié)點(diǎn)上的容器網(wǎng)絡(luò);各種存儲(chǔ)插件的 Agent 組件,也必須運(yùn)行在每一個(gè)節(jié)點(diǎn)上,用來在這個(gè)節(jié)點(diǎn)上掛載遠(yuǎn)程存儲(chǔ)目錄,操作容器的 Volume 目錄;各種監(jiān)控組件和日志組件,也必須運(yùn)行在每一個(gè)節(jié)點(diǎn)上,負(fù)責(zé)這個(gè)節(jié)點(diǎn)上的監(jiān)控信息和日志搜集。更重要的是,跟其他編排對(duì)象不一樣,DaemonSet 開始運(yùn)行的時(shí)機(jī),很多時(shí)候比整個(gè) Kubernetes 集群出現(xiàn)的時(shí)機(jī)都要早。這個(gè)乍一聽起來可能有點(diǎn)兒奇怪。但其實(shí)你來想一下:如果這個(gè) DaemonSet 正是一個(gè)網(wǎng)絡(luò)插件的 Agent 組件呢?這個(gè)時(shí)候,整個(gè) Kubernetes 集群里還沒有可用的容器網(wǎng)絡(luò),所有 Worker 節(jié)點(diǎn)的狀態(tài)都是 NotReady(NetworkReady=false)。這種情況下,普通的 Pod 肯定不能運(yùn)行在這個(gè)集群上。所以,這也就意味著 DaemonSet 的設(shè)計(jì),必須要有某種“過人之處”才行。為了弄清楚 DaemonSet 的工作原理,我們還是按照老規(guī)矩,先從它的 API 對(duì)象的定義說起。apiVersion: apps/v1kind: DaemonSetmetadata:name: fluentd-elasticsearchnamespace: kube-systemlabels:k8s-app: fluentd-loggingspec:selector:matchLabels:name: fluentd-elasticsearchtemplate:metadata:labels:name: fluentd-elasticsearchspec:tolerations:- key: node-role.kubernetes.io/mastereffect: NoSchedulecontainers:- name: fluentd-elasticsearchimage: k8s.gcr.io/fluentd-elasticsearch:1.20resources:limits:memory: 200Mirequests:cpu: 100mmemory: 200MivolumeMounts:- name: varlogmountPath: /var/log- name: varlibdockercontainersmountPath: /var/lib/docker/containersreadOnly: trueterminationGracePeriodSeconds: 30volumes:- name: varloghostPath:path: /var/log- name: varlibdockercontainershostPath:path: /var/lib/docker/containers這個(gè) DaemonSet,管理的是一個(gè) fluentd-elasticsearch 鏡像的 Pod。這個(gè)鏡像的功能非常實(shí)用:通過 fluentd 將 Docker 容器里的日志轉(zhuǎn)發(fā)到 ElasticSearch 中。可以看到,DaemonSet 跟 Deployment 其實(shí)非常相似,只不過是沒有 replicas 字段;它也使用 selector 選擇管理所有攜帶了 name=fluentd-elasticsearch 標(biāo)簽的 Pod。而這些 Pod 的模板,也是用 template 字段定義的。在這個(gè)字段中,我們定義了一個(gè)使用 fluentd-elasticsearch:1.20 鏡像的容器,而且這個(gè)容器掛載了兩個(gè) hostPath 類型的 Volume,分別對(duì)應(yīng)宿主機(jī)的 /var/log 目錄和 /var/lib/docker/containers 目錄。顯然,fluentd 啟動(dòng)之后,它會(huì)從這兩個(gè)目錄里搜集日志信息,并轉(zhuǎn)發(fā)給 ElasticSearch 保存。這樣,我們通過 ElasticSearch 就可以很方便地檢索這些日志了。需要注意的是,Docker 容器里應(yīng)用的日志,默認(rèn)會(huì)保存在宿主機(jī)的 /var/lib/docker/containers/{{. 容器 ID}}/{{. 容器 ID}}-json.log 文件里,所以這個(gè)目錄正是 fluentd 的搜集目標(biāo)。那么,DaemonSet 又是如何保證每個(gè) Node 上有且只有一個(gè)被管理的 Pod 呢?顯然,這是一個(gè)典型的“控制器模型”能夠處理的問題。DaemonSet Controller,首先從 Etcd 里獲取所有的 Node 列表,然后遍歷所有的 Node。這時(shí),它就可以很容易地去檢查,當(dāng)前這個(gè) Node 上是不是有一個(gè)攜帶了 name=fluentd-elasticsearch 標(biāo)簽的 Pod 在運(yùn)行。而檢查的結(jié)果,可能有這么三種情況:沒有這種 Pod,那么就意味著要在這個(gè) Node 上創(chuàng)建這樣一個(gè) Pod;有這種 Pod,但是數(shù)量大于 1,那就說明要把多余的 Pod 從這個(gè) Node 上刪除掉;正好只有一個(gè)這種 Pod,那說明這個(gè)節(jié)點(diǎn)是正常的。其中,刪除節(jié)點(diǎn)(Node)上多余的 Pod 非常簡單,直接調(diào)用 Kubernetes API 就可以了。但是,如何在指定的 Node 上創(chuàng)建新 Pod 呢?如果你已經(jīng)熟悉了 Pod API 對(duì)象的話,那一定可以立刻說出答案:用 nodeSelector,選擇 Node 的名字即可。nodeSelector:name: <Node 名字 >沒錯(cuò)。不過,在 Kubernetes 項(xiàng)目里,nodeSelector 其實(shí)已經(jīng)是一個(gè)將要被廢棄的字段了。因?yàn)?#xff0c;現(xiàn)在有了一個(gè)新的、功能更完善的字段可以代替它,即:nodeAffinity。我來舉個(gè)例子:apiVersion: v1kind: Podmetadata:name: with-node-affinityspec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: metadata.nameoperator: Invalues:- node-geektime在這個(gè) Pod 里,我聲明了一個(gè) spec.affinity 字段,然后定義了一個(gè) nodeAffinity。其中,spec.affinity 字段,是 Pod 里跟調(diào)度相關(guān)的一個(gè)字段。關(guān)于它的完整內(nèi)容,我會(huì)在講解調(diào)度策略的時(shí)候再詳細(xì)闡述。而在這里,我定義的 nodeAffinity 的含義是:requiredDuringSchedulingIgnoredDuringExecution:它的意思是說,這個(gè) nodeAffinity 必須在每次調(diào)度的時(shí)候予以考慮。同時(shí),這也意味著你可以設(shè)置在某些情況下不考慮這個(gè) nodeAffinity;這個(gè) Pod,將來只允許運(yùn)行在“metadata.name”是“node-geektime”的節(jié)點(diǎn)上。在這里,你應(yīng)該注意到 nodeAffinity 的定義,可以支持更加豐富的語法,比如 operator: In(即:部分匹配;如果你定義 operator: Equal,就是完全匹配),這也正是 nodeAffinity 會(huì)取代 nodeSelector 的原因之一。備注:其實(shí)在大多數(shù)時(shí)候,這些 Operator 語義沒啥用處。所以說,在學(xué)習(xí)開源項(xiàng)目的時(shí)候,一定要學(xué)會(huì)抓住“主線”。不要顧此失彼。所以,我們的 DaemonSet Controller 會(huì)在創(chuàng)建 Pod 的時(shí)候,自動(dòng)在這個(gè) Pod 的 API 對(duì)象里,加上這樣一個(gè) nodeAffinity 定義。其中,需要綁定的節(jié)點(diǎn)名字,正是當(dāng)前正在遍歷的這個(gè) Node。當(dāng)然,DaemonSet 并不需要修改用戶提交的 YAML 文件里的 Pod 模板,而是在向 Kubernetes 發(fā)起請(qǐng)求之前,直接修改根據(jù)模板生成的 Pod 對(duì)象。這個(gè)思路,也正是我在前面講解 Pod 對(duì)象時(shí)介紹過的。此外,DaemonSet 還會(huì)給這個(gè) Pod 自動(dòng)加上另外一個(gè)與調(diào)度相關(guān)的字段,叫作 tolerations。這個(gè)字段意味著這個(gè) Pod,會(huì)“容忍”(Toleration)某些 Node 的“污點(diǎn)”(Taint)。而 DaemonSet 自動(dòng)加上的 tolerations 字段,格式如下所示:apiVersion: v1kind: Podmetadata:name: with-tolerationspec:tolerations:- key: node.kubernetes.io/unschedulableoperator: Existseffect: NoSchedule這個(gè) Toleration 的含義是:“容忍”所有被標(biāo)記為 unschedulable“污點(diǎn)”的 Node;“容忍”的效果是允許調(diào)度。備注:關(guān)于如何給一個(gè) Node 標(biāo)記上“污點(diǎn)”,以及這里具體的語法定義,我會(huì)在后面介紹調(diào)度器的時(shí)候做詳細(xì)介紹。這里,你可以簡單地把“污點(diǎn)”理解為一種特殊的 Label。而在正常情況下,被標(biāo)記了 unschedulable“污點(diǎn)”的 Node,是不會(huì)有任何 Pod 被調(diào)度上去的(effect: NoSchedule)。可是,DaemonSet 自動(dòng)地給被管理的 Pod 加上了這個(gè)特殊的 Toleration,就使得這些 Pod 可以忽略這個(gè)限制,繼而保證每個(gè)節(jié)點(diǎn)上都會(huì)被調(diào)度一個(gè) Pod。當(dāng)然,如果這個(gè)節(jié)點(diǎn)有故障的話,這個(gè) Pod 可能會(huì)啟動(dòng)失敗,而 DaemonSet 則會(huì)始終嘗試下去,直到 Pod 啟動(dòng)成功。這時(shí),你應(yīng)該可以猜到,我在前面介紹到的DaemonSet 的“過人之處”,其實(shí)就是依靠 Toleration 實(shí)現(xiàn)的。假如當(dāng)前 DaemonSet 管理的,是一個(gè)網(wǎng)絡(luò)插件的 Agent Pod,那么你就必須在這個(gè) DaemonSet 的 YAML 文件里,給它的 Pod 模板加上一個(gè)能夠“容忍”node.kubernetes.io/network-unavailable“污點(diǎn)”的 Toleration。正如下面這個(gè)例子所示:...template:metadata:labels:name: network-plugin-agentspec:tolerations:- key: node.kubernetes.io/network-unavailableoperator: Existseffect: NoSchedule在 Kubernetes 項(xiàng)目中,當(dāng)一個(gè)節(jié)點(diǎn)的網(wǎng)絡(luò)插件尚未安裝時(shí),這個(gè)節(jié)點(diǎn)就會(huì)被自動(dòng)加上名為node.kubernetes.io/network-unavailable的“污點(diǎn)”。而通過這樣一個(gè) Toleration,調(diào)度器在調(diào)度這個(gè) Pod 的時(shí)候,就會(huì)忽略當(dāng)前節(jié)點(diǎn)上的“污點(diǎn)”,從而成功地將網(wǎng)絡(luò)插件的 Agent 組件調(diào)度到這臺(tái)機(jī)器上啟動(dòng)起來。這種機(jī)制,正是我們?cè)诓渴?Kubernetes 集群的時(shí)候,能夠先部署 Kubernetes 本身、再部署網(wǎng)絡(luò)插件的根本原因:因?yàn)楫?dāng)時(shí)我們所創(chuàng)建的 Weave 的 YAML,實(shí)際上就是一個(gè) DaemonSet。這里,你也可以再回顧一下第 11 篇文章《從 0 到 1:搭建一個(gè)完整的 Kubernetes 集群》中的相關(guān)內(nèi)容。至此,通過上面這些內(nèi)容,你應(yīng)該能夠明白,DaemonSet 其實(shí)是一個(gè)非常簡單的控制器。在它的控制循環(huán)中,只需要遍歷所有節(jié)點(diǎn),然后根據(jù)節(jié)點(diǎn)上是否有被管理 Pod 的情況,來決定是否要?jiǎng)?chuàng)建或者刪除一個(gè) Pod。只不過,在創(chuàng)建每個(gè) Pod 的時(shí)候,DaemonSet 會(huì)自動(dòng)給這個(gè) Pod 加上一個(gè) nodeAffinity,從而保證這個(gè) Pod 只會(huì)在指定節(jié)點(diǎn)上啟動(dòng)。同時(shí),它還會(huì)自動(dòng)給這個(gè) Pod 加上一個(gè) Toleration,從而忽略節(jié)點(diǎn)的 unschedulable“污點(diǎn)”。當(dāng)然,你也可以在 Pod 模板里加上更多種類的 Toleration,從而利用 DaemonSet 實(shí)現(xiàn)自己的目的。比如,在這個(gè) fluentd-elasticsearch DaemonSet 里,我就給它加上了這樣的 Toleration:tolerations:- key: node-role.kubernetes.io/mastereffect: NoSchedule這是因?yàn)樵谀J(rèn)情況下,Kubernetes 集群不允許用戶在 Master 節(jié)點(diǎn)部署 Pod。因?yàn)?#xff0c;Master 節(jié)點(diǎn)默認(rèn)攜帶了一個(gè)叫作node-role.kubernetes.io/master的“污點(diǎn)”。所以,為了能在 Master 節(jié)點(diǎn)上部署 DaemonSet 的 Pod,我就必須讓這個(gè) Pod“容忍”這個(gè)“污點(diǎn)”。在理解了 DaemonSet 的工作原理之后,接下來我就通過一個(gè)具體的實(shí)踐來幫你更深入地掌握 DaemonSet 的使用方法。備注:需要注意的是,在 Kubernetes v1.11 之前,由于調(diào)度器尚不完善,DaemonSet 是由 DaemonSet Controller 自行調(diào)度的,即它會(huì)直接設(shè)置 Pod 的 spec.nodename 字段,這樣就可以跳過調(diào)度器了。但是,這樣的做法很快就會(huì)被廢除,所以在這里我也不推薦你再花時(shí)間學(xué)習(xí)這個(gè)流程了。首先,創(chuàng)建這個(gè) DaemonSet 對(duì)象:$ kubectl create -f fluentd-elasticsearch.yaml需要注意的是,在 DaemonSet 上,我們一般都應(yīng)該加上 resources 字段,來限制它的 CPU 和內(nèi)存使用,防止它占用過多的宿主機(jī)資源。而創(chuàng)建成功后,你就能看到,如果有 N 個(gè)節(jié)點(diǎn),就會(huì)有 N 個(gè) fluentd-elasticsearch Pod 在運(yùn)行。比如在我們的例子里,會(huì)有兩個(gè) Pod,如下所示:$ kubectl get pod -n kube-system -l name=fluentd-elasticsearchNAME? ? ? ? ? ? ? ? ? ? ? ? ? READY? ?? STATUS? ? RESTARTS?? AGEfluentd-elasticsearch-dqfv9?? 1/1? ? ?? Running?? 0? ? ? ? ? 53mfluentd-elasticsearch-pf9z5?? 1/1? ? ?? Running?? 0? ? ? ? ? 53m而如果你此時(shí)通過 kubectl get 查看一下 Kubernetes 集群里的 DaemonSet 對(duì)象:$ kubectl get ds -n kube-system fluentd-elasticsearchNAME? ? ? ? ? ? ? ? ? ? DESIRED?? CURRENT?? READY? ?? UP-TO-DATE?? AVAILABLE?? NODE SELECTOR?? AGEfluentd-elasticsearch?? 2? ? ? ?? 2? ? ? ?? 2? ? ? ?? 2? ? ? ? ? ? 2? ? ? ? ?? <none>? ? ? ? ? 1h備注:Kubernetes 里比較長的 API 對(duì)象都有短名字,比如 DaemonSet 對(duì)應(yīng)的是 ds,Deployment 對(duì)應(yīng)的是 deploy。就會(huì)發(fā)現(xiàn) DaemonSet 和 Deployment 一樣,也有 DESIRED、CURRENT 等多個(gè)狀態(tài)字段。這也就意味著,DaemonSet 可以像 Deployment 那樣,進(jìn)行版本管理。這個(gè)版本,可以使用 kubectl rollout history 看到:$ kubectl rollout history daemonset fluentd-elasticsearch -n kube-systemdaemonsets "fluentd-elasticsearch"REVISION? CHANGE-CAUSE1? ? ? ?? <none>接下來,我們來把這個(gè) DaemonSet 的容器鏡像版本到 v2.2.0:$ kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=k8s.gcr.io/fluentd-elasticsearch:v2.2.0 --record -n=kube-system這個(gè) kubectl set image 命令里,第一個(gè) fluentd-elasticsearch 是 DaemonSet 的名字,第二個(gè) fluentd-elasticsearch 是容器的名字。這時(shí)候,我們可以使用 kubectl rollout status 命令看到這個(gè)“滾動(dòng)更新”的過程,如下所示:$ kubectl rollout status ds/fluentd-elasticsearch -n kube-systemWaiting for daemon set "fluentd-elasticsearch" rollout to finish: 0 out of 2 new pods have been updated...Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 0 out of 2 new pods have been updated...Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 1 of 2 updated pods are available...daemon set "fluentd-elasticsearch" successfully rolled out注意,由于這一次我在升級(jí)命令后面加上了–record 參數(shù),所以這次升級(jí)使用到的指令就會(huì)自動(dòng)出現(xiàn)在 DaemonSet 的 rollout history 里面,如下所示:$ kubectl rollout history daemonset fluentd-elasticsearch -n kube-systemdaemonsets "fluentd-elasticsearch"REVISION? CHANGE-CAUSE1? ? ? ?? <none>2? ? ? ?? kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=k8s.gcr.io/fluentd-elasticsearch:v2.2.0 --namespace=kube-system --record=true有了版本號(hào),你也就可以像 Deployment 一樣,將 DaemonSet 回滾到某個(gè)指定的歷史版本了。而我在前面的文章中講解 Deployment 對(duì)象的時(shí)候,曾經(jīng)提到過,Deployment 管理這些版本,靠的是“一個(gè)版本對(duì)應(yīng)一個(gè) ReplicaSet 對(duì)象”。可是,DaemonSet 控制器操作的直接就是 Pod,不可能有 ReplicaSet 這樣的對(duì)象參與其中。那么,它的這些版本又是如何維護(hù)的呢?所謂,一切皆對(duì)象!在 Kubernetes 項(xiàng)目中,任何你覺得需要記錄下來的狀態(tài),都可以被用 API 對(duì)象的方式實(shí)現(xiàn)。當(dāng)然,“版本”也不例外。Kubernetes v1.7 之后添加了一個(gè) API 對(duì)象,名叫ControllerRevision,專門用來記錄某種 Controller 對(duì)象的版本。比如,你可以通過如下命令查看 fluentd-elasticsearch 對(duì)應(yīng)的 ControllerRevision:$ kubectl get controllerrevision -n kube-system -l name=fluentd-elasticsearchNAME? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? CONTROLLER? ? ? ? ? ? ? ? ? ? ? ? ? ?? REVISION?? AGEfluentd-elasticsearch-64dc6799c9?? daemonset.apps/fluentd-elasticsearch?? 2? ? ? ? ? 1h而如果你使用 kubectl describe 查看這個(gè) ControllerRevision 對(duì)象:$ kubectl describe controllerrevision fluentd-elasticsearch-64dc6799c9 -n kube-systemName:? ? ? ?? fluentd-elasticsearch-64dc6799c9Namespace:? ? kube-systemLabels:? ? ?? controller-revision-hash=2087235575name=fluentd-elasticsearchAnnotations:? deprecated.daemonset.template.generation=2kubernetes.io/change-cause=kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=k8s.gcr.io/fluentd-elasticsearch:v2.2.0 --record=true --namespace=kube-systemAPI Version:? apps/v1Data:Spec:Template:$ Patch:? replaceMetadata:Creation Timestamp:? <nil>Labels:Name:? fluentd-elasticsearchSpec:Containers:Image:? ? ? ? ? ? ? k8s.gcr.io/fluentd-elasticsearch:v2.2.0Image Pull Policy:? IfNotPresentName:? ? ? ? ? ? ?? fluentd-elasticsearch...Revision:? ? ? ? ? ? ? ? ? 2Events:? ? ? ? ? ? ? ? ? ? <none>就會(huì)看到,這個(gè) ControllerRevision 對(duì)象,實(shí)際上是在 Data 字段保存了該版本對(duì)應(yīng)的完整的 DaemonSet 的 API 對(duì)象。并且,在 Annotation 字段保存了創(chuàng)建這個(gè)對(duì)象所使用的 kubectl 命令。接下來,我們可以嘗試將這個(gè) DaemonSet 回滾到 Revision=1 時(shí)的狀態(tài):$ kubectl rollout undo daemonset fluentd-elasticsearch --to-revision=1 -n kube-systemdaemonset.extensions/fluentd-elasticsearch rolled back這個(gè) kubectl rollout undo 操作,實(shí)際上相當(dāng)于讀取到了 Revision=1 的 ControllerRevision 對(duì)象保存的 Data 字段。而這個(gè) Data 字段里保存的信息,就是 Revision=1 時(shí)這個(gè) DaemonSet 的完整 API 對(duì)象。所以,現(xiàn)在 DaemonSet Controller 就可以使用這個(gè)歷史 API 對(duì)象,對(duì)現(xiàn)有的 DaemonSet 做一次 PATCH 操作(等價(jià)于執(zhí)行一次 kubectl apply -f “舊的 DaemonSet 對(duì)象”),從而把這個(gè) DaemonSet“更新”到一個(gè)舊版本。這也是為什么,在執(zhí)行完這次回滾完成后,你會(huì)發(fā)現(xiàn),DaemonSet 的 Revision 并不會(huì)從 Revision=2 退回到 1,而是會(huì)增加成 Revision=3。這是因?yàn)?#xff0c;一個(gè)新的 ControllerRevision 被創(chuàng)建了出來。總結(jié)在今天這篇文章中,我首先簡單介紹了 StatefulSet 的“滾動(dòng)更新”,然后重點(diǎn)講解了本專欄的第三個(gè)重要編排對(duì)象:DaemonSet。相比于 Deployment,DaemonSet 只管理 Pod 對(duì)象,然后通過 nodeAffinity 和 Toleration 這兩個(gè)調(diào)度器的小功能,保證了每個(gè)節(jié)點(diǎn)上有且只有一個(gè) Pod。這個(gè)控制器的實(shí)現(xiàn)原理簡單易懂,希望你能夠快速掌握。與此同時(shí),DaemonSet 使用 ControllerRevision,來保存和管理自己對(duì)應(yīng)的“版本”。這種“面向 API 對(duì)象”的設(shè)計(jì)思路,大大簡化了控制器本身的邏輯,也正是 Kubernetes 項(xiàng)目“聲明式 API”的優(yōu)勢所在。而且,相信聰明的你此時(shí)已經(jīng)想到了,StatefulSet 也是直接控制 Pod 對(duì)象的,那么它是不是也在使用 ControllerRevision 進(jìn)行版本管理呢?沒錯(cuò)。在 Kubernetes 項(xiàng)目里,ControllerRevision 其實(shí)是一個(gè)通用的版本管理對(duì)象。這樣,Kubernetes 項(xiàng)目就巧妙地避免了每種控制器都要維護(hù)一套冗余的代碼和邏輯的問題。思考題我在文中提到,在 Kubernetes v1.11 之前,DaemonSet 所管理的 Pod 的調(diào)度過程,實(shí)際上都是由 DaemonSet Controller 自己而不是由調(diào)度器完成的。你能說出這其中有哪些原因嗎?

總結(jié)

以上是生活随笔為你收集整理的21丨容器化守护进程的意义:DaemonSet的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。