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奮鬥的青年