Kubernetes 作業管理之 DaemonSet


本文是對 Kubernetes 作業管理中的容器化守護進程相關設計的理解,由於 DaemonSet 這個知識點相對較爲容易理解,所以主要是作的張磊在極客時間上《深入剖析 Kubernetes》課程的筆記。



Why(爲什麼要有 DaemonSet)

使用場景:

  1. 各種網絡插件的 Agent 組件,都必須運行在每一個節點上,用來處理這個節點上的容器網絡;
  2. 各種存儲插件的 Agent 組件,也必須運行在每一個節點上,用來在這個節點上掛載遠程存儲目錄,操作容器的 Volume 目錄;
  3. 各種監控組件和日誌組件,也必須運行在每一個節點上,負責這個節點上的監控信息和日誌蒐集。

What(DaemonSet 是什麼)

一句話:在 Kubernetes 集羣中的每一個節點中運行一個 Daemon Pod

How(DaemonSet 如何保證每個 Node 上有且只有一個被管理的 Pod)

DaemonSet 會保證每個 Node 上有且只有一個被管理的 Pod,是利用“控制器模型”原理實現。

原理: DaemonSet Controller,首先從 Etcd 裏獲取所有的 Node 列表,然後遍歷所有的 Node。這時,它就可以很容易地去檢查,當前這個 Node 上是不是有一個攜帶了指定標籤的 Pod 在運行。有多餘 Pod 的話就調用 Kubernetes API 刪除;沒有這種 Pod 的話就利用 Pod 來創建一個。

有2個點:
DaemonSet Controller 會在創建 Pod 的時候,自動在這個 Pod 的 API 對象裏,加上一個 nodeAffinity 定義。其中,需要綁定的節點名字,正是當前正在遍歷的這個 Node。
此外,DaemonSet 還會給這個 Pod 自動加上另外一個與調度相關的字段,叫作 tolerations。這個字段意味着這個 Pod,會“容忍”(Toleration)某些 Node 的“污點”(Taint)。
具體可以看最後的“使用實例”。

另外,DaemonSet 控制器操作的直接就是 Pod,沒有 ReplicaSet 這樣的對象參與其中,所以,它的版本維護是使用 API 對象的方式實現,名爲 ControllerRevision。
這個 ControllerRevision 對象,實際上會保存某一版本對應的完整的 DaemonSet 的 API 對象。並且,在 Annotation 字段保存了創建這個對象所使用的 kubectl 命令。
DaemonSet Controller 回滾版本實際上就是使用這個歷史 API 對象,對現有的 DaemonSet 做一次 PATCH 操作(等價於執行一次 kubectl apply -f “舊的 DaemonSet 對象”)

使用實例

實例:部署一個 DaemonSet 管理 fluentd-elasticsearch 鏡像的 Pod。通過 fluentd 將 Docker 容器裏的日誌轉發到 ElasticSearch 中。

1、創建 DaemonSet 對象

$ kubectl create -f fluentd-elasticsearch.yaml

實際過程分爲2步:

(1)用戶提交 YAML

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector: # 使用 selector 選擇管理所有攜帶了 name=fluentd-elasticsearch 標籤的 Pod
    matchLabels:
      name: fluentd-elasticsearch
  template:  # 這些 Pod 的模板,也是用 template 字段定義的
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations: # 爲了能在 Master 節點上部署 DaemonSet 的 Pod,我就必須讓這個 Pod“容忍”這個“污點”
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch # 管理的是一個 fluentd-elasticsearch 鏡像的 Pod
        image: k8s.gcr.io/fluentd-elasticsearch:1.20 # 定義了一個使用 fluentd-elasticsearch:1.20 鏡像的容器
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts: # 這個容器掛載了兩個 hostPath 類型的 Volume,分別對應宿主機的 /var/log 目錄和 /var/lib/docker/containers 目錄
        - 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

(2)Daemon Controller 自動補充 YAML

  • 補充 nodeAffinity:是 Pod 裏跟調度相關的一個字段
apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution: # 這個 nodeAffinity 必須在每次調度的時候予以考慮
        nodeSelectorTerms:
        - matchExpressions: # 這個 Pod,將來只允許運行在“metadata.name”是“node-geektime”的節點上
          - key: metadata.name
            operator: In
            values:
            - node-geektime
  • 補充 tolerations :這個字段意味着這個 Pod,會“容忍”(Toleration)某些 Node 的“污點”(Taint)
apiVersion: v1
kind: Pod
metadata:
  name: with-toleration
spec:
  tolerations:
  - key: node.kubernetes.io/unschedulable # “容忍”所有被標記爲 unschedulable“污點”的 Node;“容忍”的效果是允許調度。
    operator: Exists
    effect: NoSchedule

2、查看 DaemonSet 對象 及相關對象

$ kubectl get pod -n kube-system -l name=fluentd-elasticsearch
NAME                          READY     STATUS    RESTARTS   AGE
fluentd-elasticsearch-dqfv9   1/1       Running   0          53m
fluentd-elasticsearch-pf9z5   1/1       Running   0          53m

$ kubectl get ds -n kube-system fluentd-elasticsearch
NAME                    DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
fluentd-elasticsearch   2         2         2         2            2           <none>          1h

3、版本管理

# 查看版本情況
$ kubectl rollout history daemonset fluentd-elasticsearch -n kube-system
daemonsets "fluentd-elasticsearch"
REVISION  CHANGE-CAUSE
1         <none>

# 升級鏡像
$ kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=k8s.gcr.io/fluentd-elasticsearch:v2.2.0 --record -n=kube-system

# 查看“滾動更新”的過程
$ kubectl rollout status ds/fluentd-elasticsearch -n kube-system
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: 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

# 在升級命令後面加上了–record 參數,使用到的指令就會自動出現在 DaemonSet 的 rollout history 裏面
$ kubectl rollout history daemonset fluentd-elasticsearch -n kube-system
daemonsets "fluentd-elasticsearch"
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=k8s.gcr.io/fluentd-elasticsearch:v2.2.0 --namespace=kube-system --record=true

# 以 ControllerRevision 方式查看版本
$ kubectl get controllerrevision -n kube-system -l name=fluentd-elasticsearch
NAME                               CONTROLLER                             REVISION   AGE
fluentd-elasticsearch-64dc6799c9   daemonset.apps/fluentd-elasticsearch   2          1h

# 查看某個 ControllerRevision 對象版本詳細信息
$ kubectl describe controllerrevision fluentd-elasticsearch-64dc6799c9 -n kube-system
Name:         fluentd-elasticsearch-64dc6799c9
Namespace:    kube-system
Labels:       controller-revision-hash=2087235575
              name=fluentd-elasticsearch
Annotations:  deprecated.daemonset.template.generation=2
              kubernetes.io/change-cause=kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=k8s.gcr.io/fluentd-elasticsearch:v2.2.0 --record=true --namespace=kube-system
API Version:  apps/v1
Data:
  Spec:
    Template:
      $ Patch:  replace
      Metadata:
        Creation Timestamp:  <nil>
        Labels:
          Name:  fluentd-elasticsearch
      Spec:
        Containers:
          Image:              k8s.gcr.io/fluentd-elasticsearch:v2.2.0
          Image Pull Policy:  IfNotPresent
          Name:               fluentd-elasticsearch
...
Revision:                  2
Events:                    <none>

# 回滾到 Revision=1 時的狀態
$ kubectl rollout undo daemonset fluentd-elasticsearch --to-revision=1 -n kube-system
daemonset.extensions/fluentd-elasticsearch rolled back

參考:
《深入剖析Kubernetes | 極客時間》張磊,容器編排和Kubernetes作業管理 21

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章