<xmp id="63nn9"><video id="63nn9"></video></xmp>

<xmp id="63nn9"></xmp>

<wbr id="63nn9"><ins id="63nn9"></ins></wbr>

<wbr id="63nn9"></wbr><video id="63nn9"><ins id="63nn9"><table id="63nn9"></table></ins></video>

【Kubernetes】K8s筆記(九):DaemonSet 守護進程集

kubernetes DaemonSet docs

0. Deployment 有哪些不足

Deployment 能夠創建任意多個的 Pod 實例,并且維護這些 Pod 的正常運行,保證應用始終處于可用狀態。Deployment 并不關心 Pod 在哪些節點上運行,只要 Pod 的數量足夠,應用程序應該會正常工作。

但是有些業務是和運行環境相關的,它們并非完全獨立于系統運行,而是與主機存在綁定關系,必須依附于節點才能產生價值:

  • 網絡應用如 kube-proxy,節點不運行這個 Pod 就無法加入 Kubernetes 網絡

  • 監控應用如 Prometheus,節點需要運行這個 Pod 報告節點運行狀態

  • 日志應用如 Fluentd,節點需要運行這個 Pod 來收集日志

  • 安全應用,每個節點都要有一個 Pod 來執行安全審計、入侵檢查、漏洞掃描等工作

這些業務如果用 Deployment 來部署就不太合適了,因為 Deployment 所管理的 Pod 數量是固定的,而且可能會在集群里“漂移”,但,實際的需求卻是要在集群里的每個節點上都運行 Pod,也就是說 Pod 的數量與節點數量保持同步。

所以,Kubernetes 就定義了新的 API 對象 DaemonSet,它在形式上和 Deployment 類似,都是管理控制 Pod,但管理調度策略卻不同。

DaemonSet 確保全部(或者某些)節點上運行一個 Pod 的副本。 當有節點加入集群時, 也會為他們新增一個 Pod 。 當有節點從集群移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod。

1. 使用 YAML 描述 DaemonSet 對象

使用命令 kubectl api-resources 可以知道它的簡稱是 ds。Kubernetes 不提供自動創建 DaemonSet YAML 樣板的功能,我們只能去 DaemonSet 的文檔頁面獲取一個 DaemonSet 的 YAML 模板。我們把它拷貝下來,再去掉多余的部分,就可以做成自己的一份樣板文件:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: redis-ds
  labels:
    app: redis-ds

spec:
  selector:
    matchLabels:
      name: redis-ds

  template:
    metadata:
      labels:
        name: redis-ds
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - containerPort: 6379

這個 DaemonSet 對象的名字是 redis-ds,鏡像是 redis:5-alpine。

spec 部分,DaemonSet 也有 selector 字段,匹配 template 里 Pod 的 labels 標簽,這和 Deployment 對象幾乎一模一樣。

DaemonSet 在 spec 里沒有 replicas 字段,意味著它不會在集群里創建多個 Pod 副本,而是要在每個節點上只創建出一個 Pod 實例。也就是說,DaemonSet 僅僅是在 Pod 的部署調度策略上和 Deployment 不同,其他的都是相同的,某種程度上我們也可以把 DaemonSet 看做是 Deployment 的一個特例。

所以我們只需要用 kubectl create 先創建出一個 Deployment 對象,然后把 kind 改成 DaemonSet,再刪除 spec.replicas 就行了。

2. 在 Kubernetes 里使用 DaemonSet

現在,讓我們執行命令 kubectl apply,把 YAML 發送給 Kubernetes,讓它創建 DaemonSet 對象,再用 kubectl get 查看對象的狀態:

$ kubectl apply -f redis-ds.yaml 
daemonset.apps/redis-ds created
l$ kubectl get ds
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
redis-ds   1         1         0       1            0           <none>          12s
$ kubectl get ds
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
redis-ds   1         1         1       1            1           <none>          15s
$ kubectl get pod -o wide 
NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE      NOMINATED NODE   READINESS GATES
redis-ds-ktmrm             1/1     Running   0          22s   10.10.1.26   worker1   <none>           <none>

雖然我們沒有指定 DaemonSet 里 Pod 要運行的數量,但它自己就會去查找集群里的節點,在節點里創建 Pod。因為我們的實驗環境里有一個 Master 一個 Worker,而 Master 默認是不跑應用的,所以 DaemonSet 就只生成了一個 Pod,運行在了“worker”節點上。

按照 DaemonSet 的本意,應該在每個節點上都運行一個 Pod 實例才對,但 Master 節點卻被排除在外了,這就不符合我們當初的設想了。

為了應對 Pod 在某些節點的“調度”和“驅逐”問題,它定義了兩個新的概念:污點(taint)容忍度(toleration)。

3. Taint 和 Toleration

“污點”是 Kubernetes 節點的一個屬性,它的作用也是給節點“貼標簽”,但為了不和已有的 labels 字段混淆,就改成了 taint。

和“污點”相對的,就是 Pod 的“容忍度”,顧名思義,就是 Pod 能否“容忍”污點。

Kubernetes 在創建集群的時候會自動給節點 Node 加上一些“污點”,方便 Pod 的調度和部署。你可以用 kubectl describe node 來查看 Master 和 Worker 的狀態:

$ kubectl describe node k8s-master
Name:               k8s-master
Roles:              control-plane
···
Taints:             node-role.kubernetes.io/control-plane:NoSchedule
···

$ kubectl describe node worker1
Name:               worker1
Roles:              <none>
···
Taints:             <none>
···

可以看到,Master 節點默認有一個 taint,名字是 node-role.kubernetes.io/master,它的效果是 NoSchedule,也就是說這個污點會拒絕 Pod 調度到本節點上運行,而 Worker 節點的 taint 字段則是空的。這正是 Master 和 Worker 在 Pod 調度策略上的區別所在,通常來說 Pod 都不能容忍任何“污點”,所以加上了 taint 屬性的 Master 節點也就會無緣 Pod 了。

兩種方法讓 DaemonSet 在 Master 節點(或者任意其他節點)上運行:

  • 去掉 Master 節點上的 taint,DaemonSet 自然就不需要再區分 Master/Worker

    $ kubectl taint node master node-role.kubernetes.io/master:NoSchedule-
    

    這種方法修改的是 Node 的狀態,影響面會比較大,可能會導致很多 Pod 都跑到這個節點上運行,所以我們可以保留 Node 的“污點”,為需要的 Pod 添加“容忍度”,只讓某些 Pod 運行在個別節點上,實現“精細化”調度

  • 為 Pod 添加字段 tolerations,讓它能夠“容忍”某些“污點”,就可以在任意的節點上運行了

    tolerations 是一個數組,里面可以列出多個被“容忍”的“污點”,需要寫清楚“污點”的名字、效果。比較特別是要用 operator 字段指定如何匹配“污點”,一般我們都使用 Exists,也就是說存在這個名字和效果的“污點”。
    如果我們想讓 DaemonSet 里的 Pod 能夠在 Master 節點上運行,就要寫出這樣的一個 tolerations,容忍節點的 node-role.kubernetes.io/master:NoSchedule 這個污點:

    tolerations:
    - key: node-role.kubernetes.io/control-plane
      effect: NoSchedule
      operator: Exists
    

    重新部署加上了“容忍度”的 DaemonSet:

    $ kubectl apply -f ds.yml
    
    $ kubectl get ds -o wide 
    NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE   CONTAINERS   IMAGES           SELECTOR
    redis-ds   2         2         2       2            2           <none>          53m   redis        redis:5-alpine   name=redis-ds
    

需要特別說明的是:“容忍度”并不是 DaemonSet 獨有的概念,而是從屬于 Pod,所以理解了“污點”和“容忍度”之后,你可以在 Job/CronJob、Deployment 里為它們管理的 Pod 也加上 tolerations,從而能夠更靈活地調度應用。

污點和容忍度的文檔在這里:https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/ ,有哪些污點、污點有哪些效果可以在這里找到。

4. 靜態 Pod

DaemonSet 是在 Kubernetes 里運行節點專屬 Pod 最常用的方式,但它不是唯一的方式,Kubernetes 還支持另外一種叫“靜態 Pod”的應用部署手段。

“靜態 Pod”非常特殊,它不受 Kubernetes 系統的管控,不與 apiserver、scheduler 發生關系,所以是“靜態”的。但既然它是 Pod,也必然會“跑”在容器運行時上,也會有 YAML 文件來描述它,而唯一能夠管理它的 Kubernetes 組件也就只有在每個節點上運行的 kubelet 了。

“靜態 Pod”的 YAML 文件默認都存放在節點的 /etc/kubernetes/manifests 目錄下,它是 Kubernetes 的專用目錄。

Kubernetes 的 4 個核心組件 apiserver、etcd、scheduler、controller-manager 原來都以靜態 Pod 的形式存在的,這也是它們能夠先于 Kubernetes 集群啟動的原因。

附:DaemonSet YAML

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: redis-ds
  labels:
    app: redis-ds

spec:
  selector:
    matchLabels:
      name: redis-ds

  template:
    metadata:
      labels:
        name: redis-ds
    spec:
      tolerations:
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
        operator: Exists

      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - containerPort: 6379
posted @ 2022-10-19 15:23  joexu01  閱讀(181)  評論(0編輯  收藏  舉報
人碰人摸人爱免费视频播放

<xmp id="63nn9"><video id="63nn9"></video></xmp>

<xmp id="63nn9"></xmp>

<wbr id="63nn9"><ins id="63nn9"></ins></wbr>

<wbr id="63nn9"></wbr><video id="63nn9"><ins id="63nn9"><table id="63nn9"></table></ins></video>