【概念介绍】
学习了监管离线任务的API对象job/cronjob,监管在线任务的API对象deployment。今天学习做好守护任务的API对象DaemonSet。它会在 Kubernetes 集群的每个节点上都运行一个 Pod,就好像是 Linux 系统里的“守护进程”(Daemon)。
为什么不能用deployment来做守护任务呢,它不是也可以确保一定跑起来哪些pod么?可是我们跑pod,最终目的是为了运行我们的服务应用,有些服务应用并不适合在某些节点运行起来,甚至不能运行,那么这个pod running了,也就没有实际意义了。又比如,有些pod应该在每个节点都运行,这个需要被保证,而不只是总pod数对了就行,比如下面几个应用的pod:
1、网络应用(如 kube-proxy),必须每个节点都运行一个 Pod,否则节点就无法加入 Kubernetes 网络;
2、监控应用(如 Prometheus),必须每个节点都有一个 Pod 用来监控节点的状态,实时上报信息;
3、日志应用(如 Fluentd),必须在每个节点上运行一个 Pod,才能够搜集容器运行时产生的日志数据;
4、安全应用,同样的,每个节点都要有一个 Pod 来执行安全审计、入侵检查、漏洞扫描等工作。
这些业务如果用 Deployment 来部署就不太合适了,因为 Deployment 所管理的 Pod 数量是固定的,而且可能会在集群里“漂移”,简单说,就是只要pod运行数目对了,在哪儿运行的我就不管啦~但,实际的需求却是要在集群里的每个节点上都运行 Pod。
所以,Kubernetes 就定义了新的 API 对象 DaemonSet,它在形式上和 Deployment 类似,都是管理控制 Pod,但管理调度策略却不同。DaemonSet 的目标是在集群的每个节点上运行且仅运行一个 Pod,就好像是为节点配上一只“看门狗”,忠实地“守护”着节点,这就是 DaemonSet 名字的由来。
【如何使用 YAML 描述 DaemonSet】
DaemonSet 和 Deployment 都属于在线业务,所以它们也都是“apps”组,使用命令 kubectl api-resources 可以知道它的简称是 ds ,YAML 文件头信息应该是:
apiVersion: apps/v1 kind: DaemonSet metadata: name: xxx-ds
但是Kubernetes 不提供自动创建 DaemonSet YAML 样板的功能,也就是说,我们不能用命令 kubectl create 直接创建出一个 DaemonSet 对象。只能通过官网找到YAML示例,拷贝下来,如下:
apiVersion: apps/v1 kind: DaemonSet metadata: name: redis-ds labels: app: redis-ds spec: selector: matchLabels: name: redis-ds template: metadata: labels: name: redis-ds spec: containers: - image: redis:5-alpine name: redis ports: - containerPort: 6379
针对这个YAML中一些重要参数的说明:
1、DaemonSet 对象的名字是 redis-ds,镜像是 redis:5-alpine;
2、DaemonSet 相比deployment,在 spec 里没有 replicas 字段,意味着它不会在集群里创建多个 Pod 副本,而是要在每个节点上只创建出一个 Pod 实例;
除此之外,daemonset和deplyment的yaml没有什么不同,这也说明他们的工作方式是非常类似的,仅仅实在部署调度策略上不太相同,一个是重视pod的数目,一个是重视每个节点是否都运行了需要的pod。所以把daemonset理解为是deployment的特例,也是非常合理的。Chrono老师也特意画了针对这两种API对象的YAML退避图:
了解了区别之后,那么这里就有一个用create创建ds yaml样板间的方式:用 kubectl create 先创建出一个 Deployment 对象,然后把 kind 改成 DaemonSet,再删除 spec.replicas 就行了~如下,箭头处修改为DaemonSet,红框三个地方删除即可。
正确yml如下,可以复制使用:
apiVersion: apps/v1 kind: DaemonSet metadata: creationTimestamp: null labels: app: redis-ds name: redis-ds spec: selector: matchLabels: app: redis-ds template: metadata: creationTimestamp: null labels: app: redis-ds spec: containers: - image: redis:5-alpine name: redis resources: {}
kubectl apply -f ds.yml创建daemonset对象,get一下看看:
图上有几个点要注意:
1、虽然我们没有指定 DaemonSet 里 Pod 要运行的数量,但它自己就会去查找集群里的节点,会在每个节点里创建 Pod;
2、因为我们的实验环境里只有一个 Master 一个 Worker,而 Master 默认是不跑应用的,所以 DaemonSet 就只生成了一个 Pod,运行在了“worker”节点上。但是这是怎么做到只在worker运行的呢?这是通过污点(taint)和容忍度(toleration)来实现的。describe node可以看到这个node的taint,describe pod的时候可以看到toleration。每个pod对于taint的容忍不一样,包含在容忍度列表的taint,打这个taint的节点,就可以运行pod,否则就不可以运行。如果一定要在master上运行这个pod,有两个思路:
1)去除master的taint,命令如下。但非常不建议如此,master去掉taint意味着以后所有pod都能在其上运行,这会影响master性能;
kubectl taint node master node-role.kubernetes.io/master:NoSchedule-
2)在pod的容忍度列表增加master的taint。在pod的yml文件里,增加容忍度列表,然后重新kubectl apply -f ds.yml一下,部署ds
tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule operator: Exists
完整的yml是这样的:
apiVersion: apps/v1 kind: DaemonSet metadata: creationTimestamp: null labels: app: redis-ds name: redis-ds spec: selector: matchLabels: app: redis-ds template: metadata: creationTimestamp: null labels: app: redis-ds spec: tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule operator: Exists containers: - image: redis:5-alpine name: redis resources: {}
重新部署ds,会看到在master和worker上都运行起来了这个pod:
【静态pod】
还有一种pod,也有YAML来描述,也会跑在容器运行时上,但是不受k8s管控,不与apiserver,scheduler有任何交互,所以是静态的。只能通过kubelet管理。这类静态pod的YAML文件默认存在节点的 /etc/kubernetes/manifests 目录下,它是 Kubernetes 的专用目录。
从上图可以看到,Kubernetes 的 4 个核心组件 apiserver、etcd、scheduler、controller-manager 原来都以静态 Pod 的形式存在的,这也是为什么它们能够先于 Kubernetes 集群启动的原因。(是说之前为啥这几个pod早早就running了,解惑了!)
如果你有一些 DaemonSet 无法满足的特殊的需求,可以考虑使用静态 Pod,编写一个 YAML 文件放到这个目录里,节点的 kubelet 会定期检查目录里的文件,发现变化就会调用容器运行时创建或者删除静态 Pod。
标签:kubernetes,chrono,--,redis,节点,Pod,DaemonSet,pod,ds From: https://www.cnblogs.com/1234roro/p/17012604.html