Kubernetes 作业管理之 DaemonSet


本文是对 Kubernetes 作业管理中的容器化守护进程相关设计的理解,由于 DaemonSet 这个知识点相对较为容易理解,所以主要是作的张磊在极客时间上《深入剖析 Kubernetes》课程的笔记。


文章目录

    • Why(为什么要有 DaemonSet)
    • What(DaemonSet 是什么)
    • How(DaemonSet 如何保证每个 Node 上有且只有一个被管理的 Pod)
    • 使用实例
      • 1、创建 DaemonSet 对象
      • 2、查看 DaemonSet 对象 及相关对象
      • 3、版本管理


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                     1h

3、版本管理

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

# 升级镜像
$ 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         
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:  
        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:                    

# 回滚到 Revision=1 时的状态
$ kubectl rollout undo daemonset fluentd-elasticsearch --to-revision=1 -n kube-system
daemonset.extensions/fluentd-elasticsearch rolled back

参考:
《深入剖析Kubernetes | 极客时间》张磊,容器编排和Kubernetes作业管理 21

你可能感兴趣的:(Kubernetes,理解笔记)