DaemonSet
DaemonSet 保证在每个 Node 上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。典型的应用包括:
  • 日志收集,比如 fluentd,logstash 等
  • 系统监控,比如 Prometheus Node Exporter,collectd,New Relic agent,Ganglia gmond 等
  • 系统程序,比如 kube-proxy, kube-dns, glusterd, ceph 等

API 版本对照表

Kubernetes 版本
Deployment 版本
v1.5-v1.6
extensions/v1beta1
v1.7-v1.15
apps/v1beta1
v1.8-v1.15
apps/v1beta2
v1.9+
apps/v1
使用 Fluentd 收集日志的例子:
1
apiVersion: apps/v1
2
kind: DaemonSet
3
metadata:
4
name: fluentd-elasticsearch
5
namespace: kube-system
6
labels:
7
k8s-app: fluentd-logging
8
spec:
9
selector:
10
matchLabels:
11
name: fluentd-elasticsearch
12
template:
13
metadata:
14
labels:
15
name: fluentd-elasticsearch
16
spec:
17
tolerations:
18
- key: node-role.kubernetes.io/master
19
effect: NoSchedule
20
containers:
21
- name: fluentd-elasticsearch
22
image: gcr.io/google-containers/fluentd-elasticsearch:1.20
23
resources:
24
limits:
25
memory: 200Mi
26
requests:
27
cpu: 100m
28
memory: 200Mi
29
volumeMounts:
30
- name: varlog
31
mountPath: /var/log
32
- name: varlibdockercontainers
33
mountPath: /var/lib/docker/containers
34
readOnly: true
35
terminationGracePeriodSeconds: 30
36
volumes:
37
- name: varlog
38
hostPath:
39
path: /var/log
40
- name: varlibdockercontainers
41
hostPath:
42
path: /var/lib/docker/containers
Copied!

滚动更新

v1.6 + 支持 DaemonSet 的滚动更新,可以通过 .spec.updateStrategy.type 设置更新策略。目前支持两种策略
  • OnDelete:默认策略,更新模板后,只有手动删除了旧的 Pod 后才会创建新的 Pod
  • RollingUpdate:更新 DaemonSet 模版后,自动删除旧的 Pod 并创建新的 Pod
在使用 RollingUpdate 策略时,还可以设置
  • .spec.updateStrategy.rollingUpdate.maxUnavailable, 默认 1
  • spec.minReadySeconds,默认 0

回滚

v1.7 + 还支持回滚
1
# 查询历史版本
2
$ kubectl rollout history daemonset <daemonset-name>
3
4
# 查询某个历史版本的详细信息
5
$ kubectl rollout history daemonset <daemonset-name> --revision=1
6
7
# 回滚
8
$ kubectl rollout undo daemonset <daemonset-name> --to-revision=<revision>
9
# 查询回滚状态
10
$ kubectl rollout status ds/<daemonset-name>
Copied!

指定 Node 节点

DaemonSet 会忽略 Node 的 unschedulable 状态,有两种方式来指定 Pod 只运行在指定的 Node 节点上:
  • nodeSelector:只调度到匹配指定 label 的 Node 上
  • nodeAffinity:功能更丰富的 Node 选择器,比如支持集合操作
  • podAffinity:调度到满足条件的 Pod 所在的 Node 上

nodeSelector 示例

首先给 Node 打上标签
1
kubectl label nodes node-01 disktype=ssd
Copied!
然后在 daemonset 中指定 nodeSelector 为 disktype=ssd
1
spec:
2
nodeSelector:
3
disktype: ssd
Copied!

nodeAffinity 示例

nodeAffinity 目前支持两种:requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution,分别代表必须满足条件和优选条件。比如下面的例子代表调度到包含标签 kubernetes.io/e2e-az-name 并且值为 e2e-az1 或 e2e-az2 的 Node 上,并且优选还带有标签 another-node-label-key=another-node-label-value 的 Node。
1
apiVersion: v1
2
kind: Pod
3
metadata:
4
name: with-node-affinity
5
spec:
6
affinity:
7
nodeAffinity:
8
requiredDuringSchedulingIgnoredDuringExecution:
9
nodeSelectorTerms:
10
- matchExpressions:
11
- key: kubernetes.io/e2e-az-name
12
operator: In
13
values:
14
- e2e-az1
15
- e2e-az2
16
preferredDuringSchedulingIgnoredDuringExecution:
17
- weight: 1
18
preference:
19
matchExpressions:
20
- key: another-node-label-key
21
operator: In
22
values:
23
- another-node-label-value
24
containers:
25
- name: with-node-affinity
26
image: gcr.io/google_containers/pause:2.0
Copied!

podAffinity 示例

podAffinity 基于 Pod 的标签来选择 Node,仅调度到满足条件 Pod 所在的 Node 上,支持 podAffinity 和 podAntiAffinity。这个功能比较绕,以下面的例子为例:
  • 如果一个 “Node 所在 Zone 中包含至少一个带有 security=S1 标签且运行中的 Pod”,那么可以调度到该 Node
  • 不调度到 “包含至少一个带有 security=S2 标签且运行中 Pod” 的 Node 上
1
apiVersion: v1
2
kind: Pod
3
metadata:
4
name: with-pod-affinity
5
spec:
6
affinity:
7
podAffinity:
8
requiredDuringSchedulingIgnoredDuringExecution:
9
- labelSelector:
10
matchExpressions:
11
- key: security
12
operator: In
13
values:
14
- S1
15
topologyKey: failure-domain.beta.kubernetes.io/zone
16
podAntiAffinity:
17
preferredDuringSchedulingIgnoredDuringExecution:
18
- weight: 100
19
podAffinityTerm:
20
labelSelector:
21
matchExpressions:
22
- key: security
23
operator: In
24
values:
25
- S2
26
topologyKey: kubernetes.io/hostname
27
containers:
28
- name: with-pod-affinity
29
image: gcr.io/google_containers/pause:2.0
Copied!

静态 Pod

除了 DaemonSet,还可以使用静态 Pod 来在每台机器上运行指定的 Pod,这需要 kubelet 在启动的时候指定 manifest 目录:
1
kubelet --pod-manifest-path=/etc/kubernetes/manifests
Copied!
然后将所需要的 Pod 定义文件放到指定的 manifest 目录中。
注意:静态 Pod 不能通过 API Server 来删除,但可以通过删除 manifest 文件来自动删除对应的 Pod。
最近更新 2yr ago