【 云原生 | kubernetes 】资源对象 - 容器化守护进程之Daemonset

时间:2022-10-15 16:55:03

【 云原生 | kubernetes 】资源对象 - 容器化守护进程之Daemonset

DaemonSet简述

DaemonSet对象确保所有(或部分)节点运行一个Pod的副本。随着节点被添加到集群中,Pods也被添加到集群中。当节点从集群中移除时,这些Pods将被垃圾收集。删除一个DaemonSet将清除它创建的Pods。

守护进程(daemon进程)是一种特殊的进程,它随着系统的启动而启动,随着系统的关闭而关闭。也有部分在特定情况下才启动,完成任务后自动结束进程

使用场景

DaemonSet这个机制听起来很简单,但对我们有很多帮助作用,各种和节点有关的插件,我们都可以使用Daemon对象来部署,例子:

  • 各种网络插件,都必须运行在每一个节点,来保持各个节点上Pod的联通,比如:calico,flannel
  • 各种存储插件,必须运行在每一个节点,挂载远程存储目录,操控容器Volume目录,比如:rook-ceph
  • 各种监控和日志采集,典型的例子:node-exporter

【 云原生 | kubernetes 】资源对象 - 容器化守护进程之Daemonset

还有一个稍微复杂的用法,为同一种守护进程部署多个 DaemonSet;每个具有不同的标志, 但是对不同硬件可能有不同的内资源需求。

创建DaemonSet

1.编写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:
        - 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

这个DaemonSet管理的是镜像为fluentd的Pod,从yaml中可以看出DaemonSet和Deployment也是是分相似的,只是没有replicas,刚刚我们讲了DaemonSet会根据节点自动伸缩Pod。也使用selector选择管理携带 name:fluentd-elasticsearch 标签的Pod。

2.运行DaemonSet

[root@ycloud ~]# kubectl apply -f daemonset.yaml 
daemonset.apps/fluentd-elasticsearch created
[root@ycloud ~]# kubectl get po -n kube-system -owide
NAME                              READY   STATUS    RESTARTS   AGE   IP                NODE                                 NOMINATED NODE   READINESS GATES
fluentd-elasticsearch-6976r       1/1     Running   0          85s   192.168.234.207   10.0.0.1   <none>           <none>
fluentd-elasticsearch-7hldk       1/1     Running   0          85s   192.168.245.147   10.0.0.2   <none>           <none>
fluentd-elasticsearch-gpq4x       1/1     Running   0          85s   192.168.132.190   10.0.0.3    <none>           <none>

在 DaemonSet 中的 Pod 模板必须具有一个值为 AlwaysRestartPolicy。 当该值未指定时,默认是 Always

Fluentd是一个开源的通用日志采集和分发系统,可以从多个数据源采集日志,并将日志过滤和加工后分发到多种存储和处理系统。

Daemon Pod调度

之前的文章中详细讲了对Pod的调度,已经熟悉的同学,一定会想起用,

1.NodeSelector定向调度

apiVersion: v1
kind: Pod
...
spec:
 nodeSelector:
   disktype: ssd

2.通过亲和性匹配节点来创建Pod

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd  

pod会被调度到携带 disktype: ssd 标签的Pod上

requiredDuringSchedulingIgnoredDuringExecution,硬请求,必须满足; preferredDuringSchdulingIgnoredDuringExecution, 软请求,不一定满足,优先调度到满足指定规则的node

如果根本就没有指定调度,则 DaemonSet Controller 将在所有节点上创建 Pod。

3.容忍和污点

DaemonSet 自动添加 tolerations,定义容忍的污点,在有此污点的节点上也可以调度。

apiVersion: v1
kind: Pod
metadata:
  name: toleration
spec:
  tolerations:
  - key: node.kubernetes.io/unschedulable
    operator: Exists
    effect: NoSchedule

容忍携带 unschedulable 污点的Node。容忍是允许调度,如果节点上添加了污点,被调度对象没有进行"容忍",就不会被调度。

也可以这么认为,把污点当作一个label,携带对应的容忍就会选择调度,这样应该好理解一点

滚动更新

我们来把这个 DaemonSet 的容器镜像版本到 v2.5.3

[root@ycloud ~]# kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=quay.io/fl
uentd_elasticsearch/fluentd:v2.5.3 -n kube-system --record                                              daemonset.apps/fluentd-elasticsearch image updated 

添加–record 参数,指令就会自动添加在 DaemonSet 的 rollout history 里面

也可查询历史操作记录

[root@ycloud ~]# kubectl rollout history  ds/fluentd-elasticsearch -n kube-system
daemonset.apps/fluentd-elasticsearch 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=quay.io/fluentd_elasticsearch/fluentd:v2.5.3 --namespace=kube-system --record=true

滚动更新和Deployment相似,可以了解这篇文章,不同点是,Deployment直接控制的ReplicaSet对象,DaemonSet对象之间控制的Pod对象

我们可以通过 controllerrevision ,查看是否更新,回滚时通过REVISION,回滚到旧版本

[root@ycloud ~]# kubectl get controllerrevision -n kube-system -l name=fluentd-elasticsearchNAME                               CONTROLLER                             REVISION   AGE
fluentd-elasticsearch-84d7969c85   daemonset.apps/fluentd-elasticsearch   1          18m
fluentd-elasticsearch-86d54b564b   daemonset.apps/fluentd-elasticsearch   2          10m

controllerrevision 专门用来记录 Controller 对象的版本

可以查看下controllervision 的描述信息

[root@ycloud ~]# kubectl describe controllerrevision fluentd-elasticsearch-86d54b564b -n kube-system
Name:         fluentd-elasticsearch-86d54b564b
Namespace:    kube-system
Labels:       controller-revision-hash=86d54b564b
              name=fluentd-elasticsearch
Annotations:  deprecated.daemonset.template.generation: 2
              kubernetes.io/change-cause:
                kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=quay.io/fluentd_elasticsearch/fluentd:v2.5.3 --namespace=kube-system --re...
API Version:  apps/v1
Data:
  Spec:
    Template:
      $patch:  replace
      Metadata:
        Creation Timestamp:  <nil>
        Labels:
          Name:  fluentd-elasticsearch
      Spec:
        Containers:
          Image:              quay.io/fluentd_elasticsearch/fluentd:v2.5.3
          Image Pull Policy:  IfNotPresent
          Name:               fluentd-elasticsearch
          Resources:
            Limits:
              Memory:  200Mi
            Requests:
              Cpu:                     100m
              Memory:                  200Mi
          Termination Message Path:    /dev/termination-log
          Termination Message Policy:  File
          Volume Mounts:
            Mount Path:  /var/log
            Name:        varlog
            Mount Path:  /var/lib/docker/containers
            Name:        varlibdockercontainers
            Read Only:   true
        Dns Policy:      ClusterFirst
        Restart Policy:  Always
        Scheduler Name:  default-scheduler
        Security Context:
        Termination Grace Period Seconds:  30
        Tolerations:
          Effect:  NoSchedule
          Key:     node-role.kubernetes.io/master
        Volumes:
          Host Path:
            Path:  /var/log
            Type:  
          Name:    varlog
          Host Path:
            Path:  /var/lib/docker/containers
            Type:  
          Name:    varlibdockercontainers
Kind:              ControllerRevision
Metadata:
  Creation Timestamp:  2022-10-03T14:11:16Z
  Managed Fields:
    API Version:  apps/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:data:
      f:metadata:
        f:annotations:
          .:
          f:deprecated.daemonset.template.generation:
          f:kubectl.kubernetes.io/last-applied-configuration:
          f:kubernetes.io/change-cause:
        f:labels:
          .:
          f:controller-revision-hash:
          f:name:
        f:ownerReferences:
          .:
          k:{"uid":"a6ae6104-d0ee-4dc2-bf72-650016927fd5"}:
      f:revision:
    Manager:    kube-controller-manager
    Operation:  Update
    Time:       2022-10-03T14:11:16Z
  Owner References:
    API Version:           apps/v1
    Block Owner Deletion:  true
    Controller:            true
    Kind:                  DaemonSet
    Name:                  fluentd-elasticsearch
    UID:                   a6ae6104-d0ee-4dc2-bf72-650016927fd5
  Resource Version:        36359613
  UID:                     4a56423a-ddbe-49ca-82e3-14ce24d2e194
Revision:                  2
Events:                    <none>

可以看到,ControllerRevision其实就是DaemonSet 控制器每个版本创建的

接下来进行回滚动作

[root@ycloud ~]# kubectl rollout undo daemonset fluentd-elasticsearch --to-revision=1 -n kube-system
daemonset.apps/fluentd-elasticsearch rolled back
[root@ycloud ~]# kubectl get ds -n kube-system -oyaml|grep image
        - image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
          imagePullPolicy: IfNotPresent

可以看到镜像已经从v2.5.3替换到2.5.2,回滚成功。

结论

我们了解了,DeamonSet对象会确保每个节点都运行一个Pod,如果我们对 node 打上”污点“,DaemonSet会自动添加tolerations,确保该节点可以运行该Pod。这才是DaemonSet对象的精髓所在。