DaemonSet控制器
DaemonSet是pod控制器的又一种实现,用于在集群中的全部节点上同时运行一份指定的pod资源副本,后续新加入集群的工作节点也会自动创建一个相关的pod对象,当从集群移除节点时,此类pod对象也将被自动回收而无需重建。当然,如果删除DaemonSet,所有和这个对象相关的Pods都会被删除。管理员也可以使用节点选择器及节点标签指定仅在部分具有特定特征的节点上运行指定的pod对象。
DaemonSet的控制器会监听kuberntes的DaemonSet对象、pod对象、node对象,这些被监听的对象的变动,就会触发syncLoop循环让kubernetes集群朝着DaemonSet对象描述的状态进行演进。
DaemonSet典型的应用场景:
1)运行集群存储的守护进程,如在每个节点上运行glusterd 或 ceph
2)在各个节点上运行日志收集守护进程,如flunentd 、 logstash、filebeat等。
3)在各个节点上运行监控系统的代理守护进程,如Prometheus Node Exporter 、collectd等。
DaemonSet 与 Deployment 的区别:
1)Deployment 部署的副本 Pod 会分布在各个 Node 上,每个 Node 都可能运行好几个副本。
2)DaemonSet 的不同之处在于:每个 Node 上最多只能运行一个副本
只有必须将pod对象运行于固定的几个节点并且需要先于其他pod启动时,才有必要使用DaemonSet控制器,否则就应该使用Deployment控制器。
1. DaemonSet资源清单文件编写说明
查看定义Daemonset资源需要的字段有哪些:
[root@k8s-master1 daemonset]# kubectl explain daemonset KIND: DaemonSet VERSION: apps/v1 DESCRIPTION: DaemonSet represents the configuration of a daemon set. FIELDS: apiVersion <string> #当前资源使用的api版本 APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources kind <string> #资源类型 Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds metadata <Object> #元数据,定义DaemonSet名字的 Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata spec <Object> #定义容器的 The desired behavior of this daemon set. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status status <Object> #状态信息,不能改 The current status of this daemon set. This data may be out of date by some window of time. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
查看DaemonSet的spec字段如何定义
[root@k8s-master1 daemonset]# kubectl explain daemonset.spec KIND: DaemonSet VERSION: apps/v1 RESOURCE: spec <Object> DESCRIPTION: The desired behavior of this daemon set. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status DaemonSetSpec is the specification of a daemon set. FIELDS: minReadySeconds <integer> #当新的pod启动几秒种后,再kill掉旧的pod The minimum number of seconds for which a newly created DaemonSet pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). revisionHistoryLimit <integer> #历史版本 The number of old history to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10. selector <Object> -required- #用于匹配pod的标签选择器 A label query over pods that are managed by the daemon set. Must match in order to be controlled. It must match the pod template's labels. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors template <Object> -required- #定义Pod的模板,基于这个模板定义的所有pod是一样的 An object that describes the pod that will be created. The DaemonSet will create exactly one copy of this pod on every node that matches the template's node selector (or on every node if no node selector is specified). More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template updateStrategy <Object> #daemonset的升级策略 An update strategy to replace existing DaemonSet pods with new pods.
2. 创建DaemonSet资源对象
DaemonSet控制器的spec字段中嵌套使用的字段同样包含了minReadySeconds,selector和template,但是它不支持replicas字段,毕竟DaemonSet并不是基于期望的副本数控制pod资源数量,而是基于节点数量。
下面资源清单文件示例中定义了一个名为fluentd-elasticsearch的DaemonSet控制器,它将在每个节点上运行一个fluentd进程以收集容器相关的日志数据。
[root@k8s-master1 daemonset]# vim daemonset-demo.yaml You have new mail in /var/spool/mail/root [root@k8s-master1 daemonset]# cat daemonset-demo.yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd labels: k8s-app: fluentd-logging spec: selector: matchLabels: name: fluentd template: metadata: labels: name: fluentd spec: tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd image: ikubernetes/fluentd:v2.5.1 imagePullPolicy: IfNotPresent resources: limits: memory: 200Mi requests: cpu: 100m memory: 200Mi
通过清单文件创建DaemonSet资源:
[root@k8s-master1 daemonset]# kubectl apply -f daemonset-demo.yaml daemonset.apps/fluentd created
与其他资源一样,也可以通过“kubectl describe”命令查看DaemonSet对象的详细信息。结果信息中,Node-Selector字段为空,表示它需要运行于集群中的每个节点上。而当前集群节点数为3,因此期望的pod副本数为3,当前也成功创建了3个相关的pod对象。
[root@k8s-master1 daemonset]# kubectl describe ds Name: fluentd Selector: name=fluentd Node-Selector: <none> Labels: k8s-app=fluentd-logging Annotations: deprecated.daemonset.template.generation: 1 Desired Number of Nodes Scheduled: 3 Current Number of Nodes Scheduled: 3 Number of Nodes Scheduled with Up-to-date Pods: 3 Number of Nodes Scheduled with Available Pods: 3 Number of Nodes Misscheduled: 0 Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed Pod Template: Labels: name=fluentd Containers: fluentd: Image: ikubernetes/fluentd:v2.5.1 Port: <none> Host Port: <none> Limits: memory: 200Mi Requests: cpu: 100m memory: 200Mi Environment: <none> Mounts: <none> Volumes: <none> Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreate 2m1s daemonset-controller Created pod: fluentd-bzbbx Normal SuccessfulCreate 2m1s daemonset-controller Created pod: fluentd-pfbv4 Normal SuccessfulCreate 2m1s daemonset-controller Created pod: fluentd-wtjf6
根据DaemonSet资源本身的意义,fluentd控制器成功创建了3个pod对象应该分别运行于集群中的每个节点之上,通过以下命令得以验证:
[root@k8s-master1 daemonset]# kubectl get ds -o wide NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR fluentd 3 3 3 3 3 <none> 6m10s fluentd ikubernetes/fluentd:v2.5.1 name=fluentd You have new mail in /var/spool/mail/root [root@k8s-master1 daemonset]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES fluentd-bzbbx 1/1 Running 0 6m12s 10.244.169.147 k8s-node2 <none> <none> fluentd-pfbv4 1/1 Running 0 6m12s 10.244.159.169 k8s-master1 <none> <none> fluentd-wtjf6 1/1 Running 0 6m12s 10.244.36.71 k8s-node1 <none> <none>
通过上面可以看到在k8s的三个节点均创建了fluentd这个pod,pod的名字是由控制器的名字-随机数组成的。
3. 更新DaemonSet对象
查看daemonset的滚动更新策略,支持RollingUpdate(滚动更新)和OnDelete(删除时更新)两种更新策略:滚动更新为默认的更新策略,工作逻辑仅支持使用maxUnavailable属性定义最大不可用pod资源副本数(默认为1),而删除时更新的方式则是在删除相应节点的pod资源后重建并更新为新版本。
[root@k8s-master1 daemonset]# kubectl explain ds.spec.updateStrategy KIND: DaemonSet VERSION: apps/v1 RESOURCE: updateStrategy <Object> DESCRIPTION: An update strategy to replace existing DaemonSet pods with new pods. DaemonSetUpdateStrategy is a struct used to control the update strategy for a DaemonSet. FIELDS: rollingUpdate <Object> Rolling update config params. Present only if type = "RollingUpdate". type <string> Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is RollingUpdate.
查看rollingUpdate支持的更新策略
[root@k8s-master1 daemonset]# kubectl explain ds.spec.updateStrategy.rollingUpdate KIND: DaemonSet VERSION: apps/v1 RESOURCE: rollingUpdate <Object> DESCRIPTION: Rolling update config params. Present only if type = "RollingUpdate". Spec to control the desired behavior of daemon set rolling update. FIELDS: maxUnavailable <string> #表示rollingUpdate更新策略只支持maxUnavailabe,先删除在更新;因为不支持一个节点运行两个pod,因此需要先删除一个,在更新一个 The maximum number of DaemonSet pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of total number of DaemonSet pods at the start of the update (ex: 10%). Absolute number is calculated from percentage by rounding up. This cannot be 0. Default value is 1. Example: when this is set to 30%, at most 30% of the total number of nodes that should be running the daemon pod (i.e. status.desiredNumberScheduled) can have their pods stopped for an update at any given time. The update starts by stopping at most 30% of those DaemonSet pods and then brings up new DaemonSet pods in their place. Once the new pods are available, it then proceeds onto other DaemonSet pods, thus ensuring that at least 70% of original number of DaemonSet pods are available at all times during the update.
例如,将此前创建的fluentd中的pod模板中的镜像更新为test/fluentd:v2.5.1,使用“set image”命令即可实现
[root@k8s-master1 daemonset]# kubectl set image daemonset fluentd fluentd=test/fluentd:v2.5.1 daemonset.apps/fluentd image updated
监控查看滚动更新过程中pod变动的过程,可以看到是先删除一个工作节点上的pod对象,再在该工作节点上更新一个pod资源,直到运行到期望的pod数量为止。
[root@k8s-master1 daemonset]# kubectl get pods -w NAME READY STATUS RESTARTS AGE fluentd-bzbbx 1/1 Running 0 21m fluentd-pfbv4 1/1 Running 0 21m fluentd-wtjf6 1/1 Running 0 21m fluentd-bzbbx 1/1 Terminating 0 21m fluentd-bzbbx 1/1 Terminating 0 21m fluentd-bzbbx 0/1 Terminating 0 21m fluentd-bzbbx 0/1 Terminating 0 21m fluentd-bzbbx 0/1 Terminating 0 21m fluentd-9c9kn 0/1 Pending 0 0s fluentd-9c9kn 0/1 Pending 0 0s fluentd-9c9kn 0/1 ContainerCreating 0 0s fluentd-9c9kn 0/1 ContainerCreating 0 3s fluentd-9c9kn 1/1 Running 0 3s fluentd-wtjf6 1/1 Terminating 0 21m fluentd-wtjf6 1/1 Terminating 0 21m fluentd-wtjf6 0/1 Terminating 0 21m fluentd-wtjf6 0/1 Terminating 0 21m fluentd-wtjf6 0/1 Terminating 0 21m fluentd-9fvqt 0/1 Pending 0 0s fluentd-9fvqt 0/1 Pending 0 1s fluentd-9fvqt 0/1 ContainerCreating 0 1s fluentd-9fvqt 0/1 ContainerCreating 0 3s fluentd-9fvqt 1/1 Running 0 4s fluentd-pfbv4 1/1 Terminating 0 21m fluentd-pfbv4 1/1 Terminating 0 21m fluentd-pfbv4 0/1 Terminating 0 21m fluentd-pfbv4 0/1 Terminating 0 21m fluentd-pfbv4 0/1 Terminating 0 21m fluentd-wfqt5 0/1 Pending 0 0s fluentd-wfqt5 0/1 Pending 0 0s fluentd-wfqt5 0/1 ContainerCreating 0 0s fluentd-wfqt5 0/1 ContainerCreating 0 2s fluentd-wfqt5 1/1 Running 0 4s
通过下面命令可以看出,fluentd控制器pod模板中的镜像文件已经完成了更新,对滚动更新策略来说,它会自动触发更新机制。也可以通过fluentd控制器的详细信息了解滚动更新的过程。由下面的命令结果也可以看出,默认滚动更新策略是一次删除一个工作节点上的pod资源,待其新版本pod资源重建完成后,再开始操作另外一个工作节点上的pod资源。
[root@k8s-master1 daemonset]# kubectl describe daemonset fluentd Name: fluentd Selector: name=fluentd Node-Selector: <none> Labels: k8s-app=fluentd-logging Annotations: deprecated.daemonset.template.generation: 2 Desired Number of Nodes Scheduled: 3 Current Number of Nodes Scheduled: 3 Number of Nodes Scheduled with Up-to-date Pods: 3 Number of Nodes Scheduled with Available Pods: 3 Number of Nodes Misscheduled: 0 Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed Pod Template: Labels: name=fluentd Containers: fluentd: Image: test/fluentd:v2.5.1 Port: <none> Host Port: <none> Limits: memory: 200Mi Requests: cpu: 100m memory: 200Mi Environment: <none> Mounts: <none> Volumes: <none> Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreate 27m daemonset-controller Created pod: fluentd-bzbbx Normal SuccessfulCreate 27m daemonset-controller Created pod: fluentd-pfbv4 Normal SuccessfulCreate 27m daemonset-controller Created pod: fluentd-wtjf6 Normal SuccessfulDelete 6m1s daemonset-controller Deleted pod: fluentd-bzbbx Normal SuccessfulCreate 5m54s daemonset-controller Created pod: fluentd-9c9kn Normal SuccessfulDelete 5m51s daemonset-controller Deleted pod: fluentd-wtjf6 Normal SuccessfulCreate 5m43s daemonset-controller Created pod: fluentd-9fvqt Normal SuccessfulDelete 5m38s daemonset-controller Deleted pod: fluentd-pfbv4 Normal SuccessfulCreate 5m24s daemonset-controller Created pod: fluentd-wfqt5
查看历史版本记录
[root@k8s-master1 daemonset]# kubectl rollout history daemonset fluentd daemonset.apps/fluentd REVISION CHANGE-CAUSE 1 <none> 2 <none>
DaemonSet控制器的滚动更新机制也可以借助minReadySeconds 字段控制滚动节奏,必要时可以执行暂停和继续操作。另外,故障的更新操作也可以进行回滚,包括回滚到revision历史记录中的任何一个指定的版本。