Job资源对象,与k8s存储
注意,如果容器内执行任务有误,会根据容器的重启策略操作容器,不过这里的容器重启策略只能是: Never和 OnFailure。.spec.suspend: 挂起,该字段也是可选的,如果设置为true,后续所有执行都会被挂起,它对开始执行的job。而错过了被调度的时间,那么错过执行时间的job将被认为是失败的。.spec.jobTemplate:Job模板,必需字段,指定需要运行的任务,格式同job

apiVersion
查看可用的apiversion命令:kubectl api-versions
k8s官方将apiversion分成了三个大类型,alpha、beta、stable。
Alpha: 未经充分测试,可能存在bug,功能可能随时调整或删除。
Beta: 经过充分测试,功能细节可能会在未来进行修改。
Stable: 稳定版本,将会得到持续支持。
常用apiversion:
v1: Kubernetes API的稳定版本,包含很多核心对象:pod、service等。
apps/v1: 包含一些通用的应用层的api组合,如:Deployments, RollingUpdates, ReplicaSets, Daemonset。
batch/v1: 包含与批处理和类似作业的任务相关的对象,如:job、cronjob。
autoscaling/v1: 允许根据不同的资源使用指标自动调整容器。
添加apiVersion库:
vim /etc/kubernetes/manifests/kube-apiserver.yaml
在yaml文件中command指令下添加:
- --runtime-config=batch/v2alpha1=true
然后重启kubelet服务,重新识别api yaml文件内容即可。
systemctl restart kubelet
kubectl api-versions
===========================================
Job资源对象:
服务类的Pod容器:RC、RS、DS、Deployment(Pod内运行的服务,要持续运行)
工作类的Pod容器:Job--->执行一次,或者批量执行处理程序,完成之后退出容器。
特殊说明:
spec.template格式同Pod
restartPolicy仅支持Never或onFailure
单个Pod时,默认Pod成功运行后Job即结束
.spec.completions标志Job结束需要成功运行的Pod个数,默认为1
.spec.parallelism标志并行运行的Pod的个数,默认为1
.spec.activeDeadlineSeconds标志失败Pod的重试最大时间,超时间不会继续重试
举例:
运行job,计算2000位的圆周率
---yaml
kind: Job
apiVersion: batch/v1
metadata:
name: pi
spec:
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
imagePullPolicy: IfNotPresent
command: ["perl","-Mbignum=bpi","-wle","print bpi(2000)"]
restartPolicy: Never
查看容器日志结果:
kubectl logs -f pi-j5j4n
运行job,发送简单信息
---yaml
kind: Job
apiVersion: batch/v1
metadata:
name: test-job
spec:
template:
metadata:
name: test-job
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command: ["echo","hello k8s job!"]
restartPolicy: Never
注意,如果容器内执行任务有误,会根据容器的重启策略操作容器,不过这里的容器重启策略只能是: Never和 OnFailure。
提高Job的执行效率:
我们可以在Job.spec字段下加上**parallelism**选项。表示同时运行多少个Pod执行任务。
我们可以在Job.spec字段下加上**completions**选项。表示总共需要完成Pod的数量。
举例将上述Job任务进行更改。提示,更改Job任务的时候,需要先将原来的Job资源对象删除
PS:
---yaml
kind: Job
apiVersion: batch/v1
metadata:
name: test-job1
spec:
parallelism: 2
completions: 8
template:
metadata:
name: test-job
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command: ["echo","hello k8s job!"]
restartPolicy: Never
Job的作用,与我们之前接触过的at有些类似,在k8s集群中,如果需要用到运行一次性工作任务的需
求,那么,就可以考虑使用Job资源对象。
工作类资源对象不仅只有一个Job,还有一个和crontab十分相像的cronJob.
------------------------------------
CronJob
管理基于时间的Job,即:
在给定时间点只运行一次
周期性地在给定时间点运行
典型用法:
在给定的时间点调度Job运行
创建周期性运行的Job,例如:数据库备份、发送邮件
CronJob Spec
.spec.schedule:调度,必需字段,指定任务运行周期
.spec.jobTemplate:Job模板,必需字段,指定需要运行的任务,格式同job
.spec.startingDeadlineSeconds:启动Job的期限(秒级别),该字段是可选的。如果因为任何原因
而错过了被调度的时间,那么错过执行时间的job将被认为是失败的。如果没有指定,则没有期限。
.sec.concurrencyPolicy: 并发策略,该字段也是可选的。它指定了如何处理CronJob创建的Job的并发执行。
只允许指定下面策略中的一种:
Allow (默认):允许并发job
Forbid: 禁止并发运行,如果前一个还没有完成,则直接跳过下一个
Replace: 取消当前正在运行的job,用一个新的来替换
.spec.suspend: 挂起,该字段也是可选的,如果设置为true,后续所有执行都会被挂起,它对开始执行的job
不起作用。默认值为false。
.spec.successfulJobsHistoryLimit和.spec.failedJobsHistoryLimit: 历史限制,可选字段,它们指定了可
以保留多少完成和失败的job。默认设置为3和1,如果值为0,相关类型的job完成后不被保留。
---yaml
kind: CronJob
apiVersion: batch/v1beta1
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command: ["echo","hello cronjob!"]
restartPolicy: OnFailure
此时查看Pod的状态,会发现,每分钟都会运行一个新的Pod来执行命令规定的任务。
K8s存储
Volume: 数据卷
kubernetes Pod中多个容器访问的共享目录。volume被定义在pod上,被这个pod的多个容器
挂载到相同或不同的路径下。volume的生命周期与pod的生命周期相同,pod内的容器停止和
重启时一般不会影响volume中的数据。所以一般volume被用于持久化pod产生的数据。
volume类型:
emptyDir
hostPath
gcePersistentDisk
awsElasticBlockStore
nfs
iscsi
flocker
glusterfs
rbd
cephfs
gitRepo
secret
persistentVolumeClaim
downwardAPI
azureFileVolume
azureDisk
vsphereVolume
Quobyte
-----------------------------------------
emptyDir:
emptyDir的生命周期与所属的pod相同。
pod删除时,其emptyDir中的数据也会被删除。
emptyDir类型的volume在pod分配到node上时被创建,kubernetes会在node上自动分配一个目录,因此无需指定宿主机node上对应的目录文件。
emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。
注:一般用于容器数据卷共享,不能做持久化数据存储。
//写一个emptyDir.yaml的文件。
---yaml
kind: Pod
apiVersion: v1
metadata:
name: producer-consumer
spec:
containers:
- name: producer
image: busybox
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /producer_dir
name: shared-volume
args:
- /bin/sh
- -c
- echo "hello world" > /producer_dir/hello.txt ; sleep 30000
- name: consumer
image: busybox
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /consumer_dir
name: shared-volume
args:
- /bin/sh
- -c
- cat /consumer_dir/hello.txt ;sleep 30000
volumes:
- name: shared-volume
emptyDir: {}
总结:
根据上述yaml文件分析,volumes是指k8s的存储方案.容器内volumeMounts使用的是volumes内定义的存储,所以现在可以理解为,volumes定义的dockerHost上的目录或文件,分别挂载到了producer(/producer_dir)和consumer(/consumer_dir)这个两个容器的对应目录。那么安装这个方法,我们可以判断出,在consumer这个容器的/consumer_dir目录下,应该也会有一个hello.txt的文件。
//验证,查看conumer容器的日志。
[root@master volume]# kubectl logs producer-consumer consumer
hello world
//查看一个Pod运行在了那个Node节点上
[root@master volume]# kubectl get pod -o wide
//到对应Node节点上查看该容器的详细信息(Mounts)
[root@node01 ~]# docker inspect 413d5dbd0239
...
"Mounts": [
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/82a382ce-78aa-48f1-933b-685ce2ba7a3d/volumes/kubernetes.io~empty-dir/shared-volume",
"Destination": "/producer_dir",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
PS: 查看到该容器的Mounts字段,等于是运行docker容器的时候使用这么一条命令:
docker run -v /producer_dir busybox
emptyDir的使用场景:如果Pod的被删除,那么数据也会被删除,不具备持久化。Pod内的容器,需要
共享数据卷的时候,使用的临时数据卷。
-----------------------------------------
HostPath
hostPath卷将主机节点的文件系统中的文件或目录挂载到集群中。
相对于emtpyDir来说,hostPath就等于运行容器是使用的命令:
docker run -v /host/path:/container/path
除了path属性之外,用户还可以指定type:
空 空字符串(默认),挂载hostPath卷之前不会执行任何检查
DirectoryOrCreate 如果指定的位置没有目录,将创建空目录,权限755,与kubelet具有相同的所有权
Directory 指定的位置必须存在目录
FileOrCreate 如果指定的位置没有文件,将创建空文件,权限644,与kubelet具有相同的所有权
File 指定的位置必须存在文件
Socket 指定的位置必须存在Unix套接字
CharDevice 指定的位置必须存在字符设备
BlockDevice 指定的路径下必须存在块设备
//这里没有创建新的yaml文件,直接将emptyDir.yaml文件的volumes字段更改为:hostPath.
[root@node01 volume]#
...
volumes:
- name: shared-volume
hostPath:
path: "/data/hostPath"
type: DirectoryOrCreate
注:对比emptyDIR,hostPath具有持久性:即容器删除,数据卷还在
=================================
PV、PVC
PV: Persistent(持久的、稳固的)Volume
由管理员设置的存储,是集群的一部分,就像node节点一样,PV也是集群的资源。PV是volume之类的卷插件,但独立于使用PV的pod的生命周期。此api对象包含存储实现的细节,即nfs、iscsi、ceph或云存储等。
是k8s集群的外部存储系统,一般是设定好的存储空间(文件系统中的一个目录)。
PVC: PersistentvolumeClaim(声明、申请)
是用户存储的请求,它与pod相似。pod消耗节点资源,PVC消耗PV资源。pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(只读/读写)。
如果应用需要用到持久化的时候,可以直接向PV申请空间。
基于NFS服务来创建的PV:
//3台节点都安装nfs-工具包和rpc-bind服务。
[root@master ~]# yum install nfs-utils rpcbind -y
//这里准备将NFS服务部署在master节点上,需要在master节点上提前规划好共享的目录
[root@master ~]# mkdir /nfsdata
[root@master ~]# vim /etc/exports
/nfsdata *(rw,sync,no_root_squash)
[root@master ~]# systemctl start rpcbind
[root@master ~]# systemctl enable rpcbind
[root@master ~]# systemctl start nfs-server
[root@master ~]# systemctl enable nfs-server
[root@master ~]# showmount -e
//创建pv1.yaml文件
---yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata
server: 192.168.8.10
PV所支持的访问模式:
ReadWriteOnce: PV能以read-write的模式mount到单个节点。(命令模式:RWO)
ReadOnlyMany: PV能以read-only 的模式mount到多个节点。(命令模式:ROX)
ReadWriteMany: PV能以read-write的模式Mount到多个节点。(命令模式:RWX)
PV状态:
Available(可用):一块空闲资源还没有被任何声明绑定
Bound(绑定):卷已经被声明绑定
Released(已释放):声明被删除,但是资源还未被集群重新声明
Failed(失败):该卷的自动回收失败
PV空间的回收策略:persistentVolumeReclaimPolicy
Recycle: 回收,会清除数据,自动回收(最新k8s版本已不支持)。
Retain: 保留,需要手动清理回收。
Delete: 删除,关联的存储资产(AWS EBS,GCE PD,Azure Disk和Openstack Cinder卷)将被删除
注:只有nfs和hostPath支持回收策略,AWS EBS,GCE PD,Azure Disk和Cinder支持删除策略
关于pv所支持的访问模式的理解:
读写方面: 如果是可以读写的,则认为,Pod可以在挂载的路径下,执行读写操作。如果是只读的,那么Pod就只能够读取PV共享目录下的数据了。
节点方面:所谓挂载到单个或者多个节点,指的是Kuberntes的工作节点(node节点)
验证结果(不完全正确):
1)kubernetes官方表示,ReadOnly是以只读的方式挂载,但实际的验证结果仍需要在挂载时指定其挂
载类型为ReadOnly: true,才可以实现只读。
2)这里所说的挂载至单节点或多节点,和官方描述不一致。具体实现方法,有待进一步验证。
官网描述: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
重要提醒!
每个卷只能同一时刻只能以一种访问模式挂载,即使该卷能够支持 多种访问模式。例如,一个 GCEPersistentDisk 卷可以被某节点以 ReadWriteOnce 模式挂载,或者被多个节点以ReadOnlyMany 模式挂载,但不可以同时以两种模式挂载。
//创建一个PVC,向刚才的PV申请使用空间,注意,这里PV与PVC的绑定,通过storageClassName和accessModes这两个字段共同决定。
---yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc1
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs
resources:
requests:
storage: 1Gi
总结:
1. 当系统中的pv被绑定之后,就不会被其他的PVC绑定了。
2. 如果系统中有多个能够满足pvc要求的pv,那么,系统会自动选择一个符合pvc申请空间大小的PV,进行绑定,尽量不浪费存储空间。
//创建一个Pod,来使用上述PVC。
kind: Pod
apiVersion: v1
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- sleep 30000
volumeMounts:
- mountPath: "/data"
name: mydata
volumes:
- name: mydata
persistentVolumeClaim:
claimName: pvc1
=======================================
PV的空间回收
当回收策略为recycle
[root@master ~]# kubectl get pv,pvc
// 验证dockerhost上PV上存放的数据
[root@master ~]# ls /nfsdata/
test.txt
//删除Pd资源,PVC
[root@master ~]# kubectl delete pod pod1
pod "pod1" deleted
[root@master ~]# kubectl delete pvc pvc1
persistentvolumeclaim "pvc1" deleted
//查看PV的过程,Released(释放)--->Available(可用)。
[root@master ~]# kubectl get pv
//验证,数据依然被删除
[root@master ~]# ls /nfsdata
无数据
PS: 在释放空间的过程中,其实K8S生成了一个新的Pod,由这个Pod执行删除数据的操作。
-------------------------------------
当回收策略为: Retain
...
persistentVolumeReclaimPolicy: Retain //更改回收策略为保留
//重新运行pvc1,pod资源,然后在Pod内,创建对应的资源,再尝试删除PVC,和Pod,验证PV目录
下,数据是否还会存在?
[root@master ~]# kubectl apply -f pvc1.yaml
[root@master ~]# kubectl apply -f pod.yaml
[root@master ~]# kubectl exec pod1 touch /data/test.txt
[root@master ~]# ls /nfsdata/
test.txt
//再次删除Pod,PVC,验证PV目录下存放的数据
[root@master ~]# kubectl delete pod pod1
[root@master ~]# kubectl delete pvc pvc1
[root@master ~]# ls /nfsdata/
test.txt
//修复状态released为 Available
[root@master ~]# kubectl edit pv pv1
删除 claimRef: 字段
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: pvc1
namespace: default
resourceVersion: "111021"
uid: d7ef17f9-ad63-4907-a277-0e172496e1ec
================================================
PV,PVC的运用
现在部署一个MySQL服务,并且将MySQL的数据进行持久化存储。
1、创建PV,PVC
vim mysql-pv.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: mysql-pv
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 1Gi
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata/mysql-pv
server: 192.168.8.10
vim mysql-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs
resources:
requests:
storage: 1Gi
[root@master MySQL]# mkdir /nfsdata/mysql-pv
[root@master MySQL]# kubectl apply -f mysql-pv.yaml
[root@master MySQL]# kubectl apply -f mysql-pvc.yaml
[root@master MySQL]# kubectl get pv,pvc
2、部署MySQL
vim mysql.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: 123.com
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: mysql-pvc
---
kind: Service
apiVersion: v1
metadata:
name: mysql
spec:
type: NodePort
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
nodePort: 31306
3、在MySQL数据库中添加数据
[root@master ~]# kubectl exec -it mysql-6fccccd487-5q2dt -- mysql -uroot -p123.com
mysql> SHOW DATABASES; //查看当前的库。
mysql> CREATE DATABASE TEST; //创建test库。
mysql> USE TEST; //选择使用test库。
mysql> CREATE TABLE my_id(id int(4)); //创建my_id表
mysql> INSERT my_id values (9527); //往my_id表中,插入数据。
mysql> SELECT * FROM my_id; //查看my_id表中所有数据
4、模拟MySQ服务器节点故障
k8s集群会生产一个新的Pod,验证这个Pod内是否有之前数据。
//先查看运行MySQL服务的Pod,在哪个节点,然后将该节点挂起,我们知道k8s肯定会在另外一个节点重新生成一个Pod
[root@master ~]# kubectl get pod -o wide
//新生成Pod后,同样进入Pod验证数据是否会会存在,
[root@master MySQL]# kubectl exec -it mysql-5d86c64fc9-p7hv6 -- mysql -u root -p123.com
mysql> show databases;
mysql> use TEST;
mysql> show tables;
mysql> select * from my_id;
更多推荐



所有评论(0)