K8S 实战(九)| 控制器 DaemonSet - 将守护进程容器化

1,184 阅读3分钟

前言

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

查看

[root@master01 ~]# 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奋斗的青年