一、DaemonSet概述
DaemonSet即守护进程集,与守护进程类似。DaemonSet确保在符合匹配条件的节点上部署运行一个Pod
当有新的节点加入时,也会为新节点添加Pod,同样当节点从集群移除时,运行的Pod也会被收回,而删除DaemonSet会删除DaemonSet创建的所有Pod
下面是使用DaemonSet的一些场景:
- 运行集群存储的daemon:例如每个节点上运行Clusterd、Ceph(分布式存储)等
- 每个节点运行日志收集的daemon:例如Fluentd、Logstash等
- 每个节点运行监控的daemon:例如Prometheus Node Exporter、Collectd、Datadog等
- 每个节点运行的网络插件的dameon:例如Flannel、Calico等
DaemonSet的主要特征:
- 创建的Pod运行在K8S集群的每一个节点上
- 每个节点只会存在一个DaemonSet创建的Pod实例
- 如果有新节点
在部署K8S时,其实已经创建了两个DaemonSet,分别是flannel和proxy
[root@master test]# kubectl get daemonsets.apps -A NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE kube-system kube-flannel-ds 2 2 2 2 2 <none> 11d kube-system kube-proxy 2 2 2 2 2 kubernetes.io/os=linux 11d
- 注意
从1.6开始,DaemonSet控制器将不会再把Pod调度到主节点上。
这是因为主节点上有node-role.kubernetes.io/master及NoSchedule污点,而Pod没有容忍该污点,所以不会调度到主节点上。
官方已经不建议,那么如果没有必要就不要向主机调度Pod了,除非是出于监控或者指标收集等原因。
二、DaemonSet定义
- 创建一个DaemonSet的yaml大致如下,这是Prometheus部署时使用的node-exporter用于监控节点信息
--- apiVersion: apps/v1 kind: DaemonSet metadata: name: node-exporter namespace: kube-system labels: k8s-app: node-exporter spec: selector: matchLabels: k8s-app: node-exporter template: metadata: labels: k8s-app: node-exporter spec: containers: - image: prom/node-exporter name: node-exporter ports: - containerPort: 9100 protocol: TCP name: http --- apiVersion: v1 kind: Service metadata: labels: k8s-app: node-exporter name: node-exporter namespace: kube-system spec: ports: - name: http port: 9100 nodePort: 31672 protocol: TCP type: NodePort selector: k8s-app: node-exporter
其中必须字段:
和其他所有的K8S资源配置相同,必须字段有:apiVersion、kind、metadata、spec
Pod模板:
spec唯一需要的字段是spec.template,除了必须字段外,在DaemonSet中的Pod模板必须指定合理的标签。并且还需要具有一个RestartPolicy(重启策略),默认策略是Always
注释:spec.template是一个Pod模板,与Pod具有相同的配置方式,但是她并没有apiVersion和kind字段
Pod Selector:
Pod Selector代表的字段是spec.selector,与其他资源的spec.selector字段作用相同。spec.selector表示一个对象,由如下两个字段组成:
matchLabels:用于匹配符合条件的Pod
matchExpressions:允许构建更加复杂的Selector
如果上面的两个字段同时指定是,结果表示的是逻辑与(AND)的关系
注意:spec.selector必须与spec.template.metadata.labels相匹配,如果没有指定,默认是等价的,如果这两个的配置不匹配,则会被API拒绝,也就会报错
三、创建DaemonSet
- 下面创建一个nginx的DaemonSet
[root@master test]# cat nginx.yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: nginx spec: selector: matchLabels: run: nginx template: metadata: labels: run: nginx spec: containers: - name: nginx image: nginx:1.15.2 ports: - containerPort: 80 name: nginx dnsPolicy: ClusterFirst restartPolicy: Always tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule —————————————————————————————————————————————————————————————————————————————— 添加'容忍'即可使DaemonSet可以在主节点上创建Pod,字段是'spec.template.spec.tolerations' tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule ——————————————————————————————————————————————————————————————————————————————
这里有一个字段spec.template.spec.dnsPolicy,这个字段可以指定DNS策略
- 无策略(None):清除Pod预设的DNS配置,当dnsPolicy设置成这个值时,K8S不会为Pod预先加载任何逻辑用于判定得到的DNS配置
- 默认预设(Default):设置为这个值时,Pod里面的DNS配置会继承宿主机上的配置,该Pod的DNS配置与宿主机的完全相同
- 集群优先(ClusterFirst):与Default策略相反,设置为这个值时,会预先使用Kube-dns或者CoreDNS的信息当作预设参数写到创建Pod的DNS配置中
- ClusterFirstWithHostNet:设置为这个值时,宿主机会与K8S共存,共同使用hostNetwork与kube-dns作为创建Pod的预设配置
创建
[root@master test]# kubectl apply -f nginx.yaml daemonset.apps/nginx created [root@master test]# kubectl get node #先看一下,这里有两个节点 NAME STATUS ROLES AGE VERSION master Ready master 11d v1.18.0 node Ready <none> 11d v1.18.0 [root@master test]# kubectl get pods #因为添加了容忍,所以两个节点都创建pod了 NAME READY STATUS RESTARTS AGE nginx-krr85 1/1 Running 0 3m19s nginx-q7wz9 1/1 Running 0 3m19s
四、DaemonSet指定节点部署Pod
- 如果指定了
spec.template.spec.nodeSelector
字段,那么DaemonSet控制器将在与Node Selector(节点选择器)
匹配的节点上创建Pod,例如:
只想部署Pod到磁盘为SSD的节点上
- 如果想要指定节点部署Pod,我们需要提前给节点定义
标签Label
,例如:
containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: #此字段同样适用于其他资源控制器 disktype: ssd
注意:这个标签名称、标签值都是自定义的
- 下面通过添加节点标签指定pod运行的节点
[root@master ~]# kubectl label node node ds=true #节点名称叫node node/node labeled [root@master ~]# kubectl get node --show-labels | grep ds=true #可以看到标签加了一个ds=true node Ready <none> 13d v1.18.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ds=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=node,kubernetes.io/os=linux
- 下面修改yaml文件
[root@master test]# cat nginx.yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: nginx spec: selector: matchLabels: run: nginx template: metadata: labels: run: nginx spec: containers: - name: nginx image: nginx:1.15.2 ports: - containerPort: 80 name: nginx dnsPolicy: ClusterFirst restartPolicy: Always tolerations: #容忍不能去掉,不然master无法创建pod - key: node-role.kubernetes.io/master effect: NoSchedule nodeSelector: #添加node的标签选择器 ds: "true" #与刚才添加的标签相同
- 重新生成
[root@master test]# kubectl apply -f nginx.yaml daemonset.apps/nginx configured [root@master test]# kubectl get pods -o wide #可以看到这次只有一个node节点的了了 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-mgmx8 1/1 Running 0 22s 10.244.1.63 node <none> <none>
- 给master也添加标签
[root@master test]# kubectl label node master ds=true node/master labeled [root@master test]# kubectl get pods -o wide #可以看到两个节点都创建了 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-5kl24 1/1 Running 0 47s 10.244.1.65 node <none> <none> nginx-mwz4w 1/1 Running 0 3s 10.244.0.6 master <none> <none>
- 去除标签
[root@master test]# kubectl label node node ds- #去掉标签 ds- ,- 就是删除的意思 node/node labeled [root@master test]# kubectl get pods -o wide #可以看到node节点的pod被删除了 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-mwz4w 1/1 Running 0 57s 10.244.0.6 master <none> <none>
五、DaemonSet更新策略
通过上面的添加、删除标签,我们可以知道,在修改节点标签后,DaemonSet会立即向新匹配的节点上添加Pod,同时也会删除不匹配节点上的Pod
在K8S1.6版本之后,可以在DaemonSet上执行滚动更新,而之后的K8S也将支持节点的可控更新
DaemonSet有两种更新策略:
OnDelete:使用此策略时,在更新DaemonSet之后,需要手动删除旧的DaemonSet创建的Pod,然后新的Pod才会被自动创建,与K8S1.6版本之前的方法类似
RollingUpdate:这是默认的更新策略,使用此策略时,在更新DaemonSet之后,旧的Pod将会被自动终止,并且以受控方式自动创建一个新的Pod,更新期间,最多只能有DaemonSet’的一个Pod运行在每个节点上,也就是说每个节点运行的Pod最多只能有一个
查看已经创建的DaemonSet的更新方式:
#查看.spec.updateStrategy.type 字段,可以看到是RollingUpdate更新策略 [root@master test]# kubectl get ds nginx -o yaml 。。。。。。 spec: 。。。。。。 updateStrategy: rollingUpdate: maxUnavailable: 1 #最大不可用pod数量 type: RollingUpdate #使用的更新策略 。。。。。。