DaemonSet 控制器:概念、原理
1.1 DaemonSet 概述
DaemonSet 控制器能够确保 k8s 集群所有的节点都运行一个相同的 pod 副本,当向 k8s 集群中增
加 node 节点时,这个 node 节点也会自动创建一个 pod 副本,当 node 节点从集群移除,这些 pod 也 会自动删除;删除 Daemonset 也会删除它们创建的 pod
1. 2 Daemonset 工作原理:如何管理 Pod?
daemonset 的控制器会监听 kuberntes 的 daemonset 对象、pod 对象、node 对象,这些被监 听的对象之变动,就会触发 syncLoop 循环让 kubernetes 集群朝着 daemonset 对象描述的状态进行 演进。
1.3 Daemonset 典型的应用场景
在集群的每个节点上运行存储,比如:glusterd 或 ceph。
在每个节点上运行日志收集组件,比如:flunentd 、 logstash、filebeat 等。
在每个节点上运行监控组件,比如:Prometheus、 Node Exporter 、collectd 等。
1.4 DaemonSet 与 Deployment 的区别
Deployment 部署的副本 Pod 会分布在各个 Node 上,每个 Node 都可能运行好几个副本。 DaemonSet 的不同之处在于:每个 Node 上最多只能运行一个副本。
DaemonSet 资源清单文件编写技巧
kubectl explain ds
apiVersion <string> #当前资源使用的 api 版本,跟 VERSION: app/v1保持一致
kind <string> #资源类型,跟 KIND: DaemonSet 保持一致
metadata<Object> #元数据,定义 DaemonSet 名字的
spec <Object> #定义容器的
status <Object> #状态信息,不能改
DaemonSet 的 spec 字段kubectl explain ds.spec
FIELDS:
minReadySeconds <integer> #当新的 pod 启动几秒种后,再 kill 掉旧的 pod。 revisionHistoryLimit <integer> #历史版本
selector <Object> -required- #用于匹配 pod 的标签选择器
template <Object> -required-
#定义 Pod 的模板,基于这个模板定义的所有 pod 是一样的
updateStrategy #daemonset 的升级策略
#查看 DaemonSet 的 spec.template 字段如何定义?
#对于 template 而言,其内部定义的就是 pod,pod 模板是一个独立的对象
kubectl explain ds.spec.template
KIND: DaemonSet
VERSION: apps/v1
RESOURCE: template <Object>
FIELDS:
metadata <Object>
spec <Object>
FIELDS:
metadata <Object>
DaemonSet 部署日志收集组件 fluentd
把 fluentd-2-5-1.tar.gz 上传到 所有节点上.
#编写一个 DaemonSet 资源清单
cat daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
k8s-app: fluentd-logging
name: fluentd-elasticsearch
namespace: kube-system
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
name: fluentd
labels:
name: fluentd-elasticsearch
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: god/fluentd:v2.5.1
resources:
limits:
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
更新
kubectl apply -f daemonset.yaml
指定 kube-system名称空间
kubectl get daemonset -n kube-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
calico-node 3 3 3 3 3 kubernetes.io/os=linux 18d
fluentd-elasticsearch 3 3 3 3 3 <none> 3m9s
kube-proxy 3 3 3 3 3 kubernetes.io/os=linux 18d
kubectl get pods -n kube-system
万一没有fluentd-elasticsearch的话,看daemonset详细信息或者重启kubelet
systemctl restart Kubelet 重启对pod没有影响。跟apiserver交互的
kubectl describe daemonset fluentd-elasticsearch -n kube-system
kubectl get pods -n kube-system -o wide
#通过上面可以看到在 k8s 的三个节点均创建了 fluentd 这个 pod
#pod 的名字是由控制器的名字-随机数组成的
#资源清单详细说明
apiVersion: apps/v1 #DaemonSet 使用的 api 版本
kind: DaemonSet # 资源类型
metadata:
name: fluentd-elasticsearch #资源的名字
namespace: kube-system #资源所在的名称空间
labels:
k8s-app: fluentd-logging. #资源具有的标签
spec:
selector: #标签选择器
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels: # 基于这回模板定义的 pod 具有的标签
name: fluentd-elasticsearch
spec:
tolerations: #定义容忍度
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers: #定义容器
- name: fluentd-elasticsearch
image: god/fluentd:v2.5.1
resources: #资源配额
limits:
memory: 200Mi
requests:
cpu: 100m memory: 200Mi
volumeMounts: - name: varlog
mountPath: /var/log #把本地的/var/log目录挂在到容器
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers #把/var/lib/docker/containers/挂载到容器里
readOnly: true #挂载目录是只读权限
terminationGracePeriodSeconds: 30 #优雅的关闭服务
volumes:
- name: varlog hostPath:
path: /var/log #基于本地目录创建一个卷
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers #基于本地目录创建一个卷
Daemonset 管理 pod:滚动更新
#DaemonSet 实现 pod 的滚动更新
#查看 daemonset 的滚动更新策略
kubectl explain ds.spec.updateStrategy
#查看 rollingUpdate 支持的更新策略
kubectl explain ds.spec.updateStrategy.rollingUpdate
KIND: DaemonSet
VERSION: apps/v1
RESOURCE: rollingUpdate <Object>
DESCRIPTION:
Rolling update config params. Present only if type = "RollingUpdate".
Spec to control the desired behavior of daemon set rolling update.
#上面表示 rollingUpdate 更新策略只支持 maxUnavailabe,先删除在更新;因为我们不支持一 个节点运行两个 pod,因此需要先删除一个,在更新一个。
vim daemonset.yaml
kubectl apply -f daemonset.yaml
查看名称空间# kubectl get daemonset -n kube-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
calico-node 3 3 3 3 3 kubernetes.io/os=linux 18d
fluentd-elasticsearch 3 3 2 1 2 <none> 53m
kube-proxy 3 3 3 3 3 kubernetes.io/os=linux 18d
就绪只有2个,可能是控制节点没有
排错思路看describe和logs
kubectl describe pods fluentd-elasticsearch-dvl8g -n kube-system
kubectl logs fluentd-elasticsearch-dvl8g -n kube-system #在查看日志
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (2: No such file or directory)
2021/05/16 11:44:04 [emerg] 1#1: open() "/var/log/nginx/error.log" failed (2: No such file or directory)
#更新镜像版本,可以按照如下方法:
kubectl set image daemonsets fluentd-elasticsearch=ikubernetes/filebeat:5.6.6- alpine -n kube-system
Job 和 CronJob 控制器:概念、原理
Job 控制器用于管理 Pod 对象运行一次性任务,比方说我们对数据库备份,可以直接在 k8s 上启动
一个 mysqldump 备份程序,也可以启动一个 pod,这个 pod 专门用来备份用的,备份结束 pod 就可 以终止了,不需要重启,而是将 Pod 对象置于"Completed"(完成)状态,若容器中的进程因错误而终 止,则需要按照重启策略配置确定是否重启,对于 Job 这个类型的控制器来说,需不需要重建 pod 就看 任务是否完成,完成就不需要重建,没有完成就需要重建 pod。 Job 控制器的 Pod 对象的状态转换
Job 三种使用场景:
1、非并行任务:只启一个 pod,pod 成功,job 正常结束
2、并行任务同时指定成功个数:.spec.completions 为指定成功个数,可以指定也可以不指 定.spec.parallelism(指定>1,会有多个任务并行运行)。当成功个数达到.spec.completions, 任务结束。
3、有工作队列的并行任务:.spec.completions 默认为 1,.spec.parallelism 为大于 0 的整数。 此时并行启动多个 pod,只要有一个成功,任务结束,所有 pod 结束
CronJob 概念、原理
CronJob 跟 Job 完成的工作是一样的,只不过 CronJob 添加了定时任务能力可以指定时间,实现周期性运行。Job,CronJob 和 Deployment,DaemonSet 显著区别在于不需要持续在后台运行 Deployment 主要用于管理无状态的应用(kubernetes 集群有一些 pod,某一个 pod 出现故障, 删除之后会重新启动一个 pod,那么 kubernetes 这个集群中 pod 数量就正常了,更多关注的是群体,这就是无状态应用)。
使用场景:
1、在给定时间点只运行一次。
2、在给定时间点周期性地运行。
CronJob 的典型用法如下:
1、在给定的时间点调度 Job 运行。
2、创建周期性运行的 Job,例如数据库备份、发送邮件
Job 控制器:资源清单编写
#查看 Job 资源对象由哪几部分组成
kubectl explain Job
Job represents the configuration of a single job. FIELDS:
apiVersion #当前 Job 的 api 版本
kind #指定当前的资源类型
metadata <Object> #元数据,定义资源的名字和所在名称空间
spec <Object> #查看 Job 下的 spec 字段
kubectl explain Job.spec
FIELDS:
activeDeadlineSeconds #
通过指定job存活时间,来结束一个job。当
job 运行时间达到 activeDeadlineSeconds 指定的时间后,job 会停止由它启动的所有任务 (如:pod),并设置 job 的状态为 failed
backoffLimit #job 建议指定 pod 的重启策略为 never, 如:.spec.template.spec.restartPolicy = "Never",然后通过 job 的 backoffLimit 来指 定失败重试次数,在达到 backoffLimit 指定的次数后,job 状态设置为 failed(默认为 6 次)
completions <integer> #指定 job 启动的任务(如:pod)成功运行 completions 次,job 才算成功结束
manualSelector <boolean>
parallelism <integer> #指定 job 同时运行的任务(如:pod)个数,Parallelism 默认为 1,如果设置为 0,则 job 会暂定
selector。<object>
template <object>. -required-
ttlSecondsAfterFinished<integer> #默认情况下,job 异常或者成功结束后,包括
job 启动的任务(pod),都不会被清理掉,因为你可以依据保存的 job 和 pod,查看状态、
日志,以及调试等。这些用户可以手动删除,用户手动删除 job,job controller 会级联删除 对应的 pod,除了手动删除,通过指定参数 ttlSecondsAfterFinished 也可以实现自动删除 job,以及级联的资源,如:pod。如果设置为 0,job 会被立即删除。如果不指定,job 则 不会被删除
#查看 Job 下的 spec.template 字段
#template 为定义 Pod 的模板,Job 通过模板创建 Pod
kubectl explain Job.spec.template.spec
restartPolicy #重启策略,对于 Job,只能设置为 Never 或者OnFailure。对于其他 controller(比如 Deployment)可以设置为 Always 。
使用Job创建一个一次性任务
vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: my-busybox-job
spec:
completions: 6
parallelism: 3
backoffLimit: 6
template:
spec:
restartPolicy: Never
containers:
- name: my-container-job
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh','-c']
args: ['echo "Welcome xuexi"; sleep 60 ; echo "Next to Meet you"']
更新
kubectl apply -f job.yaml
查看 Job 状态:
kubectl get Job
kubectl get job
NAME COMPLETIONS DURATION AGE
my-busybox-job 3/6 79s 79s
#查看 pod 状态
kubectl get pods
kubectl logs my-busybox-job-9lzkc
Welcome xuexi
Next to Meet you
#动态查看 pod 状态
kubectl get pods -w
kubectl logs my-busybox-job-xmlcb
Welcome xuexi
Next to Meet you
#资源清单文件详细解读
apiVersion: batch/v1
kind: Job
metadata:
name: my-busybox-job spec:
ttlSecondsAfterFinished: 20
completions: 6 # Job 成功完成 Pod 的总数
parallelism: 3 #并行执行的 pod 数量是 3 次
backoffLimit: 6
template: spec:
restartPolicy: Never #. 重启策略默认
pod的重启策略restartpolicy:pod在遇到故障之后重启的动作有:
1.always:当容器退出时,总是重启容器,默认策略
2.onfailure:当容器异常退出(退出状态码非0)时,重启容器
3.nerver:当容器退出时,从不重启容器
使用CronJob创建周期性的定时任务
cat cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- data; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
更新
kubectl apply -f cronjob.yaml
kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 0 <none> 39s
#从命令的结果可以看出,CronJob 还没有调度或运行任何 Job。观察大概一分钟,等待 CronJob 创建:
kubectl get jobs --watch
NAME COMPLETIONS DURATION AGE
hello-1621232340 1/1 1s 62s
hello-1621232400 1/1 2s 2s
my-busybox-job 6/6 2m5s 20m
#现在可以看到由 hello 这个 cronjob 调度的一个正在运行的 job。
kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 0 62s 3m41s
#可以看到 hello 这个 CronJob 成功地在 LAST SCHEDULE 中指定的时间点调度了一个作 业。当前有 0 个活动作业,这意味着该作业已经完成或失败。
kubectl get pods | grep hello
hello-1621232400-qm5w6 0/1 Completed 0 2m24s
hello-1621232460-dm56x 0/1 Completed 0 83s
hello-1621232520-6rfxb 0/1 Completed 0 23s
kubectl logs hello-1621232640-z4vw5
Mon May 17 06:24:09 UTC 2021
Hello from the Kubernetes cluster