K8S 實戰(九)| 控制器 DaemonSet - 將守護進程容器化

語言: CN / TW / HK

前言

Deployment 管理的 Pod 允許在一個節點上運行多個副本。

當需要在節點上運行收集日誌或者執行監控任務的容器時,顯然不適合啟動多個 Pod 副本。

這種場景下,我們可以啟用 DaemonSet 控制器來管理 Pod。

Daemon Pod 的特點

  1. Pod 運行在集羣中的全部或者部分節點上
  2. 每個節點上只能有一個這樣的 Pod
  3. 當集羣中加入了新節點,Pod 會自動在新節點上創建
  4. 當節點被從集羣中移除後,節點上 Pod 會自動被回收掉

Daemon Pod 適用的場景

  1. 網絡插件的 Agent
  2. 存儲插件的 Agent
  3. 監控任務的 Agent
  4. 收集日誌的 Agent

DaemonSet

創建一個 DS

cat daemonset.yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # this toleration is to have the daemonset runnable on master nodes
      # remove it if your masters can't run pods
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers


# kubectl apply -f daemonset.yaml
daemonset.apps/fluentd-elasticsearch created

查看

[[email protected] ~]# kubectl get ds --namespace kube-system
NAME                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                 AGE
fluentd-elasticsearch   6         6         6       6            6           <none>                        11m

目前集羣中有 3 個 master,3 個 worker,一共 6 個節點,可以看到 6 個節點上都運行了該 node

工作流程

DaemonSet Controller,從 Etcd 裏獲取所有的 Node 列表,然後遍歷所有的 Node。

然後檢查當前這個 Node 上是不是有一個攜帶了 name=fluentd-elasticsearch 標籤的 Pod 在運行。

而檢查的結果,大概有這麼三種情況:

  1. Node 上沒有這種 Pod,那麼就意味着要在這個 Node 上創建這個 Pod;
  2. Node 上有這種 Pod,但是數量大於 1,那就説明要把多餘的 Pod 從這個 Node 上刪除掉;
  3. 只有一個這種 Pod,説明這個節點是正常的。

重要參數

spec.affinity.nodeAffinity

通過命令

# kubectl edit pod fluentd-elasticsearch-22g5r --namespace=kube-system

可以看到 DaemonSet 自動給 Pod 增加了參數

spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchFields:
          - key: metadata.name
            operator: In
            values:
            - master03

限制了該 Pod 只能運行在 master03 這個 Node 上

tolerations

同樣通過上面的命令,可以看到有參數

  tolerations:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
  - effect: NoSchedule
    key: node.kubernetes.io/disk-pressure

意味着可以容忍所有標記有如下“污點”的 Node,可以在這些 Node 上運行 master/not-ready/unreachable/disk-pressure

正常情況下,如果 Node 上被標記了這些“污點”,Pod 被禁止調度到這樣的 Node 上運行

但 DaemonSet 給 Pod 加上了 tolerations,使 Pod 可以忽略這些污點,從而成功將 Pod 調度到“污點”節點上

如果節點有故障導致 Pod 啟動失敗,DaemonSet 會一直嘗試,直到 Pod 成功啟動

僅在部分節點運行 Pod

可以在 YAML 中手工指定 .spec.template.spec.affinity,這樣 Pod 會運行在指定的 Node 上

nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchFields:
      - key: metadata.name
        operator: In
        values:
        - target-host-name

如果沒有指定該參數,那麼 Pod 會運行在所有 Node 上

DaemonSet 優點

我們也可以自己寫一個守護進程來執行類似的工作,使用 DaemonSet Pod 有哪些優點呢。

  1. DaemonSet Pod 自帶自身監控功能,省去了我們自己再寫一個針對守護進程的監控程序的工作
  2. DaemonSet Pod 不管運行什麼任務,都是統一的語言和管理方式
  3. DaemonSet Pod 自帶了資源限制功能,避免了守護進程長時間運行佔用過多資源對宿主機造成影響

結束語

DaemonSet 傾向於精確控制 Pod 運行在哪些機器上,確保這些機器上都有這個 Pod 在運行。

而 Deployment 更適合於管理離用户更近的無狀態類 Pod,比如 Web 服務。

它們的共同點是,都不希望自己管理的 Pod 終止,Pod 出現問題後可以自愈。

聯繫我

微信公眾號:IT奮鬥的青年