前言:
在集群部署中,由于节点数量不定,那么如果我们需要对每个节点中都运行一个守护进程、日志收集进程等情况时,在k8s中如何实现呢?
通过了解DaemonSet 资源可以实现上述情况。
一、Kubernetes 中资源对象
在k8s中有很多资源对象,以下列举的内容都是 k8s 中相关对象的对象,这些对象都可以在 yaml 文件中作为一种 API 类型来配置。
| 类别 | 名称 |
| 工作负载型资源对象 | Pod、Replicaset、ReplicationController、Deployments、StatefulSets、DaemonSet、Job、CronJob |
| 服务发现及负载均衡 | Service、Ingress |
| 配置与存储 | Volume、Persistent Volume、CSl 、 configMap、Secret |
| 集群资源 | Namespace、Node、Role、ClusterRole、RoleBinding、ClusterRoleBinding |
| 元数据资源 | HPA、PodTemplate、LimitRang |
前面已经对:Pod、Replicaset、Deployments、Service有了一定了解,接下来继续对DaemonSet对象进行学习
二、什么是DaemonSet ?
DaemonSet:用于确保全部(或者某些)节点上运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
DaemonSet 的一些典型用法:
- 在每个节点上运行集群守护进程
- 在每个节点上运行日志收集守护进程
- 在每个节点上运行监控守护进程
一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个 DaemonSet。 一个稍微复杂的用法是为同一种守护进程部署多个 DaemonSet;每个具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。
总结:DaemonSet 保证每个一个节点上都运行一个定义的Pod副本。
三、DaemonSet Spec 的定义
a)必填字段:
与其他k8s资源定义一样:DaemonSet 需要 apiVersion、kind 和 metadata字段。
DaemonSet 对象的名称必须是一个合法的 DNS 子域名
DNS子域名:
-
- 不能超过253个字符
- 只能包含小写字母、数字,以及'-' 和 '.'
- 须以字母数字开头
- 须以字母数字结尾
b)Pod模板定义:
.spec 中唯一必需的字段是 .spec.template。
.spec.template 是一个 Pod 模板。 除了它是嵌套的,因而不具有 apiVersion 或 kind 字段之外,它与 Pod 具有相同的 schema。
除了 Pod 必需字段外,在 DaemonSet 中的 Pod 模板必须指定合理的标签(查看 Pod 选择算符)。
在 DaemonSet 中的 Pod 模板必须具有一个值为 Always 的 RestartPolicy。 当该值未指定时,默认是 Always。
Pod 选择算符
.spec.selector 字段表示 Pod 选择算符,它与 Job 的 .spec.selector 的作用是相同的。
从 Kubernetes 1.8 开始,您必须指定与 .spec.template 的标签匹配的 Pod 选择算符。 用户不指定 Pod 选择算符时,该字段不再有默认值。 选择算符的默认值生成结果与 kubectl apply 不兼容。 此外,一旦创建了 DaemonSet,它的 .spec.selector 就不能修改。 修改 Pod 选择算符可能导致 Pod 意外悬浮,并且这对用户来说是费解的。
spec.selector 是一个对象,如下两个字段组成:
-
-
matchLabels- 与 ReplicationController 的.spec.selector的作用相同。 -
matchExpressions- 允许构建更加复杂的选择器,可以通过指定 key、value 列表以及将 key 和 value 列表关联起来的 operator。
-
当上述两个字段都指定时,结果会按逻辑与(AND)操作处理。
如果指定了 .spec.selector,必须与 .spec.template.metadata.labels 相匹配。 如果与后者不匹配,则 DeamonSet 会被 API 拒绝。
c)仅在某些节点上运行 Pod
如果指定了 .spec.template.spec.nodeSelector,DaemonSet 控制器将在能够与 Node 选择算符 匹配的节点上创建 Pod。
如果根本就没有指定,则 DaemonSet 控制器将在所有节点上创建 Pod。
d)通信方式
DaemonSet 中的 Pod 进行通信的几种可能模式如下:
-
-
推送(Push):配置 DaemonSet 中的 Pod,将更新发送到另一个服务,例如统计数据库。 这些服务没有客户端。
-
NodeIP 和已知端口:DaemonSet 中的 Pod 可以使用
hostPort,从而可以通过节点 IP 访问到 Pod。客户端能通过某种方法获取节点 IP 列表,并且基于此也可以获取到相应的端口。 -
DNS:创建具有相同 Pod 选择算符的 无头服务, 通过使用
endpoints资源或从 DNS 中检索到多个 A 记录来发现 DaemonSet。 -
Service:创建具有相同 Pod 选择算符的服务,并使用该服务随机访问到某个节点上的 守护进程(没有办法访问到特定节点)。
-
四、DaemonSet 调度策略/更新策略
a)调度策略
通常情况下,通过DaemonSet创建的的Pod应该调度到那个节点是通过Kubernetes调度策略决定的,然而,当这个Pod被创建的时候,运行在那个节点上其实已经被提前决定了,所以它会忽略调度器。因此:
-
- DaemonSet控制器并不在乎Node的unschedulable字段;
- 即使调度器没有启动,DaemonSet控制器都可以创建Pod;
但是可以通过以下方法来让Pod运行到指定的Node上:
-
- nodeSelector:只调度到匹配指定label的Node上;
- nodeAffinity:功能更丰富的Node选择器,比如支持集合操作;
- podAffinity:调度到满足条件的Pod所在的Node上;
b)DaemonSet 有两种更新策略:
-
OnDelete: 使用
OnDelete更新策略时,在更新 DaemonSet 模板后,只有当你手动删除老的 DaemonSet pods 之后,新的 DaemonSet Pod 才会被自动创建。跟 Kubernetes 1.6 以前的版本类似。 -
RollingUpdate: 默认的更新策略。使用
RollingUpdate更新策略时,在更新 DaemonSet 模板后, 老的 DaemonSet pods 将被终止,并且将以受控方式自动创建新的 DaemonSet pods。 更新期间,最多只能有 DaemonSet 的一个 Pod 运行于每个节点上
五、DaemonSet 示例
a)创建一个收集日志的DaemonSet,使用filebeat收集日志,通过filebeat收集日志传给redis。
# 创建Redis环境 apiVersion: apps/v1 kind: Deployment metadata: name: redis namespace: default spec: replicas: 1 selector: matchLabels: app: redis role: cachedb template: metadata: labels: app: redis role: cachedb spec: containers: - name: redis image: redis:5.0.5-alpine ports: - name: redis containerPort: 6379 --- # 创建服务 apiVersion: v1 kind: Service metadata: name: redis namespace: default spec: type: ClusterIP selector: app: redis role: cachedb ports: - port: 6379 --- # 创建守护进程集合:filebeat-收集日志 apiVersion: apps/v1 kind: DaemonSet metadata: name: filebeat-ds namespace: default spec: selector: matchLabels: app: filebeat role: logstorage template: metadata: labels: app: filebeat role: logstorage spec: containers: - name: filebeat image: ikubernetes/filebeat:5.6.5-alpine env: - name: REDIS_HOST value: redis.default.svc.cluster.local
b)执行命令:
//应用yaml kubectl apply -f redis-filebeat.yaml
c)查看运行情况
# 1. 查看Pod创建情况 kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-669qx 1/1 Running 0 56m filebeat-ds-grthz 1/1 Running 0 53m redis-84d7cdf88b-v4n8q 1/1 Running 0 46m # 2. 查看服务状态 kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE redis ClusterIP 10.100.160.198 <none> 6379/TCP 63m # 3. 进入filebeat中,添加日志记录 kubectl exec -it filebeat-ds-grthz -- /bin/bash cd /var/log/containers/ echo "测试日志" > a.log # 4. 进入redis中查看 kubectl exec -it redis-84d7cdf88b-v4n8q -- /bin/sh /data # redis-cli -h redis.default.svc.cluster.local -p 6379 redis.default.svc.cluster.local:6379> KEYS * 1) "filebeat"
总结:
本篇简单的学习了用于创建守护进程的DaemonSet资源对象,接下来就还将继续对StatefulSets资源进行学习。