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;

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐