DaemonSet 保证在每个 Node 上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。典型的应用包括:
- 日志收集,比如 fluentd,logstash 等
- 系统监控,比如 Prometheus Node Exporter,collectd,New Relic agent,Gangliagmond 等
- 系统程序,比如 kube-proxy, kube-dns, glusterd, ceph 等
API版本对照:
kubernetes版本 | Deployment版本 |
v1.5-v1.6 | extensions/v1beta1 |
v1.7 | apps/v1beta1 |
v1.8 | apps/v1beta2 |
v1.9 | apps/v1 |
一个Fluentd示例:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-es-v3.1.1
namespace: logging
labels:
k8s-app: fluentd-es
version: v3.1.1
addonmanager.kubernetes.io/mode: Reconcile
spec:
selector:
matchLabels:
k8s-app: fluentd-es
version: v3.1.1
template:
metadata:
labels:
k8s-app: fluentd-es
version: v3.1.1
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
priorityClassName: system-node-critical
serviceAccountName: fluentd-es
containers:
- name: fluentd-es
image: quay.io/fluentd_elasticsearch/fluentd:v3.1.0
env:
- name: FLUENTD_ARGS
value: --no-supervisor -q
resources:
limits:
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: config-volume
mountPath: /etc/fluent/config.d
ports:
- containerPort: 24231
name: prometheus
protocol: TCP
livenessProbe:
tcpSocket:
port: prometheus
initialDelaySeconds: 5
timeoutSeconds: 10
readinessProbe:
tcpSocket:
port: prometheus
initialDelaySeconds: 5
timeoutSeconds: 10
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: config-volume
configMap:
name: fluentd-es-config-v0.2.1
指定运行Node节点:
DaemonSet 会忽略 Node 的 unschedulable 状态,有两种方式来指定 Pod 只运行在指定的 Node 节点上:
- nodeSelector:只调度到匹配指定 label 的 Node 上
- nodeAffinity:功能更丰富的 Node 选择器,比如支持集合操作
- podAffinity:调度到满足条件的 Pod 所在的 Node 上
nodeSelector示例:
kubectl label nodes node1 disktype=ssd #首先给节点打上disktype标签;
在daemonset的yaml文件中指定nodeSelector,disktype=ssd
spec:
nodeSelector:
disktype: ssd
nodeAffinity 示例:
nodeAffinity 目前支持两种:requiredDuringSchedulingIgnoredDuringExecution 和preferredDuringSchedulingIgnoredDuringExecution,分别代表必须满足条件和优选条件。比如下面的例子代表调度到包含标签 kubernetes.io/e2e-az-name 并且值为e2e-az1 或 e2e-az2 的 Node 上,并且优选还带有标签 another-node-label-key=another-node-label-value 的 Node。
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: gcr.io/google_containers/pause:2.0
podAffinity 示例:
podAffinity 基于 Pod 的标签来选择 Node,仅调度到满足条件 Pod 所在的 Node 上,支持 podAffinity 和 podAntiAffinity。这个功能比较绕,以下面的例子为例:如果一个 “Node 所在 Zone 中包含至少一个带有 security=S1 标签且运行中的Pod”,那么可以调度到该 Node不调度到 “包含至少一个带有 security=S2 标签且运行中 Pod” 的 Node 上
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: failure-domain.beta.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: kubernetes.io/hostname
containers:
- name: with-pod-affinity
image: gcr.io/google_containers/pause:2.0
静态 Pod:
除了 DaemonSet,还可以使用静态 Pod 来在每台机器上运行指定的 Pod,这需要kubelet 在启动的时候指定 manifest 目录:
滚动更新:
v1.6 + 支持 DaemonSet 的滚动更新,可以通过 .spec.updateStrategy.type 设置更新策略。目前支持两种策略:
- OnDelete:默认策略,更新模板后,只有手动删除了旧的 Pod 后才会创建新的Pod
- RollingUpdate:更新 DaemonSet 模版后,自动删除旧的 Pod 并创建新的 Pod在使用 RollingUpdate 策略时,还可以设置
- spec.updateStrategy.rollingUpdate.maxUnavailable , 默认 1
- spec.minReadySeconds ,默认 0
回滚:
v1.7+版本支持回滚
# 查询历史版本
$ kubectl rollout history daemonset <daemonset-name>
# 查询某个历史版本的详细信息
$ kubectl rollout history daemonset <daemonset-name> --revision=1
# 回滚
$ kubectl rollout undo daemonset <daemonset-name> --to-revision=<revision>
# 查询回滚状态
$ kubectl rollout status ds/<daemonset-name>