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;