volume:持久化存储卷,可以对数据进行持久化存储

查看k8s支持哪些存储

[root@master ~]# kubectl explain pods.spec.volumes
常用的如下:
emptyDir
hostPath
nfs
persistentVolumeClaim
glusterfs
cephfs
configMap

我们想要使用存储卷,需要经历如下步骤

(1)定义pod的volume,这个volume指明它要关联到哪个存储上的

(2)在容器中要使用volume mounts(挂载存储)

1、EmptyDir临时目录

emptyDir类型的Volume在Pod分配到Node上时被创建,Kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。当Pod从Node上移除时,emptyDir中的数据会被永久删除。emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等,生产一般不使用

[root@master ~]# vim emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test-container
    image: nginx
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - emptyDir:
     {}
    name: cache-volume
[root@master ~]# kubectl get pod
NAME       READY   STATUS    RESTARTS   AGE
test-pod   1/1     Running   0          4s

2、hostPath Volume

使容器可以使用宿主机上的目录或文件,在pod被删除,这个目录还是存在的,不会被删除。

hostpath存储卷缺点:pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失

这里volumeMounts:下的name是下面创建的volumes的名字

apiVersion: v1
kind: Pod
metadata:
  name: test-hostpath
spec:
  containers:
  - name: test-nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /test-nginx
      name: test-volume
  - name: test-tomcat
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /test-tomcat
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /data1			#节点上需要有这个目录
      type: DirectoryOrCreate
[root@master ~]# kubectl apply -f hostpath.yaml
pod/test-hostpath created
[root@master ~]# kubectl get pod
NAME            READY   STATUS    RESTARTS   AGE
test-hostpath   2/2     Running   0          2s
[root@master ~]# kubectl describe pod test-hostpath
Containers:
  test-nginx:
      /test-nginx from test-volume (rw)
Volumes:
  test-volume:
    Type:          HostPath (bare host directory volume)
    Path:          /data1

此时,进入容器查看目录里的内容是空的

[root@master ~]# kubectl exec -it test-hostpath -c test-nginx -- /bin/bash
root@test-hostpath:/# ls /test-nginx/

我们在pod节点的/data1目录创建文件hello,再次进入容器查看,两个容器都有hello

[root@node1 ~]# touch /data1/hello
[root@master ~]# kubectl exec -it test-hostpath -c test-nginx -- /bin/bash
root@test-hostpath:/# ls /test-nginx/
hello
[root@master ~]# kubectl exec -it test-hostpath -c test-tomcat -- /bin/bash
bash-4.4# ls /test-tomcat/
hello

3、NFS

安装NFS,你也可以声明多个NFS的挂载目录共享出去,这里只设置了一个。

master上安装
yum install nfs-utils -y
mkdir /data/volumes -pv 
cat /etc/exports
/data/volumes 192.168.1.0/24(rw,no_root_squash)
exportfs -arv
systemctl start nfs
在node1上挂载:
yum install nfs-utils -y
mount -t nfs 192.168.0.0:/data/volumes /mnt

创建pod

vim nfs.yaml
apiVersion: v1
kind: Pod
metadata:
 name: test-nfs-volume
spec:
 containers:
 - name: test-nfs
   image: nginx
   ports:
   - containerPort: 80
     protocol: TCP
   volumeMounts:
   - name: nfs-volumes
     mountPath: /usr/share/nginx/html
 volumes:
 - name: nfs-volumes
   nfs:
     path: /data/volumes
     server: 192.168.1.11
[root@master ~]# kubectl apply -f nfs.yaml
[root@master ~]# kubectl get pod -owide
NAME      		READY   STATUS    RESTARTS    AGE   IP     		   NODE     
test-nfs-volume  1/1   Running   	0     	  61s   10.244.1.70   node1   
[root@master ~]# curl 10.244.1.70
<center><h1>403 Forbidden</h1></center>     #空的目录
[root@master ~]# echo haha> /data/volumes/index.html
[root@master ~]# curl 10.244.1.70
haha

4、PV PVC

PersistentVolume(PV)是群集中的一块存储,是群集中的资源。其生命周期独立于使用PV的任何单个pod。

PersistentVolumeClaim(PVC)是一个持久化存储卷,创建pod时可以定义这个类型的存储卷。

(1)pv的供应方式

**静态的:**集群管理员创建许多PV。它们存在于Kubernetes API中,可供使用。

**动态的:**当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,群集可能会尝试为PVC专门动态配置卷。此配置基于StorageClasses:PVC必须请求存储类,管理员必须已创建并配置该类,以便进行动态配置。常用

(2)绑定 用户创建pvc并指定需要的资源和访问模式,匹配找到可用pv绑定。

(3)使用

a)需要找一个存储服务器,把它划分成多个存储空间;
b)k8s管理员可以把这些存储空间定义成多个pv;
c)在pod中使用pvc类型的存储卷之前需要先创建pvc,通过定义需要使用的pv的大小和对应的访问模式,找到合适的pv;
d)pvc被创建之后,就可以当成存储卷来使用了,我们在定义pod时就可以使用这个pvc的存储卷
e)pvc和pv它们是一 一对应的关系,pv如果被被pvc绑定了,就不能被其他pvc使用了;
f)我们在创建pvc的时候,应该确保和底下的pv能匹配绑定,否则pvc就会处于pending状态。

(4)回收策略

当我们创建pod时如果使用pvc做为存储卷,那么它会和pv绑定,当删除pod,pvc和pv绑定就会解除,解除之后和pvc绑定的pv卷里的数据需要怎么处理,目前,卷可以Retain保留、Recycle 回收(不推荐使用,1.15可能被废弃了)、Delete删除。

Retain

当删除pvc的时候,pv仍然存在,处于released状态,但是它不能被其他pvc绑定使用,里面的数据还是存在的,当我们下次再使用的时候,数据还是存在的,这个是默认的回收策略,管理员能够通过下面的步骤手工回收存储卷:

1)删除PV:在PV被删除后,在外部设施中相关的存储资产仍然还在;
2)手工删除遗留在外部存储中的数据;
3)手工删除存储资产,如果需要重用这些存储资产,则需要创建新的PV。

Delete

删除pvc时即会从Kubernetes中移除PV,也会从相关的外部设施中删除存储资产,例如AWS EBS, 或者Cinder存储卷。

创建NFS

[root@master ~]# mkdir /data/volume_test/v{1,2,3,4,5} -p
[root@master ~]# vim /etc/exports
/data/volume_test/v1 192.168.1.11/24(rw,no_root_squash)
/data/volume_test/v2 192.168.1.11/24(rw,no_root_squash)
/data/volume_test/v3 192.168.1.11/24(rw,no_root_squash)
/data/volume_test/v4 192.168.1.11/24(rw,no_root_squash)
/data/volume_test/v5 192.168.1.11/24(rw,no_root_squash)
[root@master ~]# exportfs -arv
[root@master ~]# systemctl start nfs
[root@master ~]# showmount -e

创建PVC

```

apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v1
spec:
  capacity:
    storage: 1Gi
  accessModes: ["ReadWriteOnce"]
  nfs:
    path: /data/volume_test/v1
    server: master
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v2
spec:
  capacity:
      storage: 2Gi
  accessModes: ["ReadWriteMany"]
  nfs:
    path: /data/volume_test/v2
    server: master
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v3
spec:
  capacity:
      storage: 3Gi
  accessModes: ["ReadOnlyMany"]
  nfs:
    path: /data/volume_test/v3
    server: master
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v4
spec:
  capacity:
      storage: 4Gi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v4
    server: master
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v5
spec:
  capacity:
      storage: 5Gi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v5
    server: master
[root@master ~]# kubectl apply -f pv.yaml
[root@master ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   
v1     1Gi        RWO            Retain           Available                     
v2     2Gi        RWX            Retain           Available                     
v3     3Gi        ROX            Retain           Available                     
v4     4Gi        RWO,RWX        Retain           Available                     
v5     5Gi        RWO,RWX        Retain           Available

创建PVC

[root@master ~]# vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 2Gi
[root@master ~]# kubectl apply -f pvc.yaml
persistentvolumeclaim/my-pvc created
[root@master ~]# kubectl get pvc
NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc   Bound    v2       2Gi        RWX                           1s

创建pod

[root@master ~]# vim pod-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: nginx-html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nginx-html
    persistentVolumeClaim:
      claimName: my-pvc
[root@master ~]# kubectl apply -f pod-pvc.yaml
[root@master ~]# kubectl get pod -owide
NAME      READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED 
pod-pvc   1/1     Running   0          12s   10.244.1.74   node1   <none>       
[root@master ~]# curl 10.244.1.74
<head><title>403 Forbidden</title></head>
[root@master ~]# echo hello >/data/volume_test/v2/index.html
[root@master ~]# curl 10.244.1.74
hello

(1)我们每次创建pvc的时候,需要事先有划分好的pv,可能不方便,那么可以在创建pvc的时候直接动态创建一个pv这个存储类,pv事先是不存在的

(2)pvc和pv绑定,如果使用默认的回收策略retain,那么删除pvc之后,pv会处于released状态,我们想要继续使用这个pv,需要手动删除pv,kubectl delete pv pv_name,删除pv,不会删除pv里的数据,当我们重新创建pvc时还会和这个最匹配的pv绑定,数据还是原来数据,不会丢失。

[root@master ~]# kubectl delete pod pod-pvc
[root@master ~]# kubectl delete pvc my-pvc
[root@master ~]# kubectl delete pv v2
[root@master ~]# ls /data/volume_test/v2/
index.html
[root@master ~]# kubectl apply -f pv2.yaml
[root@master ~]# kubectl apply -f pvc.yaml
persistentvolumeclaim/my-pvc created
[root@master ~]# kubectl apply -f pod-pvc.yaml
[root@master ~]# kubectl get pod -owide
NAME      READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED 
pod-pvc   1/1     Running   0          14s   10.244.1.75   node1   <none>       
[root@master ~]# curl 10.244.1.75
hello

pvc的匹配:满足所需空间及条件(pvc需求2Gi、ReadWriteMany即是RWX),这里选择了V4。

[root@master ~]# kubectl delete pod pod-pvc
[root@master ~]# kubectl delete pvc my-pvc
[root@master ~]# kubectl delete pv v2
[root@master ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM            
v1     1Gi        RWO            Retain           Available                     
v3     3Gi        ROX            Retain           Available                     
v4     4Gi        RWO,RWX        Retain           Available     
v5     5Gi        RWO,RWX        Retain           Available                     
[root@master ~]# kubectl apply -f pvc.yaml
[root@master ~]# kubectl get pvc
NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc   Bound    v4       4Gi        RWO,RWX                       9s
[root@master ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS       CLAIM           
v4     4Gi        RWO,RWX        Retain           Bound       default/my-pvc   
v1     1Gi        RWO            Retain           Available