CronJob
CronJob用于以时间为基准周期性地执行任务,这些自动化任务和运行在Linux或UNIX系统上的CronJob一样。CronJob对于创建定期和重复任务非常有用,例如执行备份任务、周期性调度程序接口、发送电子邮件等。
对于Kubernetes 1.8以前的版本,需要添加–runtime-config=batch/v2alpha1=true参数至APIServer中,然后重启APIServer和Controller Manager用于启用API,对于1.8以后的版本无须修改任何参数,可以直接使用,本节的示例基于1.8以上的版本。
创建CronJob
创建CronJob有两种方式,一种是直接使用kubectl创建,一种是使用yaml文件创建。
使用kubectl创建CronJob的命令如下:
kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"
对应的yaml文件如下:
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
查看创建的CronJob:
kubectl get cj
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 0 <none> 5s
等待1分钟可以查看执行的任务(Jobs):
kubectl get jobs
NAME COMPLETIONS DURATION AGE
hello-1558779360 1/1 23s 32s
CronJob每次调用任务的时候会创建一个Pod执行命令,执行完任务后,Pod状态就会变成Completed,如下所示:
kubectl get po
NAME READY STATUS RESTARTS AGE
hello-1558779360-jcp4r 0/1 Completed 0 37s
可以通过logs查看Pod的执行日志:
kubectl logs -f hello-1558779360-jcp4r
Sat May 25 10:16:23 UTC 2019
Hello from the Kubernetes cluster
如果要删除CronJob,直接使用delete即可:
kubectl delete cronjob hello
可用参数的配置
定义一个CronJob的yaml文件如下:
apiVersion: v1
items:
- apiVersion: batch/v1beta1
kind: CronJob
metadata:
labels:
run: hello
name: hello
namespace: default
spec:
concurrencyPolicy: Allow
failedJobsHistoryLimit: 1
jobTemplate:
metadata:
creationTimestamp: null
spec:
template:
metadata:
creationTimestamp: null
labels:
run: hello
spec:
containers:
- args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
image: busybox
imagePullPolicy: Always
name: hello
resources: {
}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: OnFailure
schedulerName: default-scheduler
securityContext: {
}
terminationGracePeriodSeconds: 30
schedule: '*/1 * * * *'
successfulJobsHistoryLimit: 3
suspend: false
其中各参数的说明如下,可以按需修改:
schedule:调度周期,和Linux一致,分别是分时日月周。
restartPolicy:重启策略,和Pod一致。
concurrencyPolicy:并发调度策略。可选参数如下:
Allow:允许同时运行多个任务。
Forbid:不允许并发运行,如果之前的任务尚未完成,新的任务不会被创建。
Replace:如果之前的任务尚未完成,新的任务会替换的之前的任务。
suspend:如果设置为true,则暂停后续的任务,默认为false。
successfulJobsHistoryLimit:保留多少已完成的任务,按需配置。
failedJobsHistoryLimit:保留多少失败的任务。
相对于Linux上的计划任务,Kubernetes的CronJob更具有可配置性,并且对于执行计划任务的环境只需启动相对应的镜像即可。比如,如果需要Go或者PHP环境执行任务,就只需要更改任务的镜像为Go或者PHP即可,而对于Linux上的计划任务,则需要安装相对应的执行环境。此外,Kubernetes的CronJob是创建Pod来执行,更加清晰明了,查看日志也比较方便。可见,Kubernetes的CronJob更加方便和简单。
Taint和Toleration
Taint能够使节点排斥一类特定的Pod,Taint和Toleration相互配合可以用来避免Pod被分配到不合适的节点,比如Master节点不允许部署系统组件之外的其他Pod。每个节点上都可以应用一个或多个Taint,这表示对于那些不能容忍这些Taint的Pod是不会被该节点接受的。如果将Toleration应用于Pod上,则表示这些Pod可以(但不要求)被调度到具有匹配Taint的节点上。
查看当前运行的pod
[root@k8s-master01 ~]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-67948c7d6b-j69x8 2/2 Running 0 12s 172.18.195.13 k8s-master03 <none> <none>
nginx-67948c7d6b-tv5kn 2/2 Running 0 12s 172.25.244.202 k8s-master01 <none> <none>
给k8s-master01节点增加一个Taint:
[root@k8s-master01 ~]# kubectl taint nodes k8s-master01 key=value:NoSchedule
node/k8s-master01 tainted
编辑deploy
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "2"
creationTimestamp: "2022-11-18T06:58:00Z"
generation: 2
labels:
app: nginx
name: nginx
namespace: default
resourceVersion: "186842"
uid: e28f1958-af97-41ef-aebf-bdc3c0d7fbce
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx
resources: {
}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt
name: share-volume
- command:
- sh
- -c
- sleep 3600
image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx2
resources: {
}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /mnt
name: share-volume
dnsPolicy: ClusterFirst
nodeSelector: # 添加节点指认(部署该节点上)
kubernetes.io/hostname: k8s-master01
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {
}
terminationGracePeriodSeconds: 30
volumes:
- emptyDir: {
}
name: share-volume
查看结果:
[root@k8s-master01 ~]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-546f4f9cfc-lf6dj 0/2 Pending 0 3m41s <none> <none> <none> <none>
nginx-67948c7d6b-j69x8 2/2 Running 0 14m 172.18.195.13 k8s-master03 <none> <none>
nginx-67948c7d6b-tv5kn 2/2 Running 0 14m 172.25.244.202 k8s-master01 <none> <none>
[root@k8s-master01 ~]# kubectl describe po nginx-546f4f9cfc-lf6dj
Name: nginx-546f4f9cfc-lf6dj
Namespace: default
Priority: 0
Node: <none>
Labels: app=nginx
pod-template-hash=546f4f9cfc
Annotations: <none>
Status: Pending
IP:
IPs: <none>
Controlled By: ReplicaSet/nginx-546f4f9cfc
Containers:
nginx:
Image: nginx:1.15.2
Port: <none>
Host Port: <none>
Environment: <none>
Mounts:
/opt from share-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bt9dx (ro)
nginx2:
Image: nginx:1.15.2
Port: <none>
Host Port: <none>
Command:
sh
-c
sleep 3600
Environment: <none>
Mounts:
/mnt from share-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bt9dx (ro)
Conditions:
Type Status
PodScheduled False
Volumes:
share-volume:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
kube-api-access-bt9dx:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: