持久化存储概念介绍

【官方】https://kubernetes.io/zh/docs/concepts/storage/volumes

将容器内数据卷挂载到宿主机上,实现数据存储,避免因为容器销毁导致的数据丢失

我们想要使用存储卷,需要经历如下步骤
1、定义pod的volume,这个volume指明它要关联到哪个存储上的
2、在容器中要使用volumemounts挂载对应的存储

【执行命令查看-常用的持久化方式】
kubectl explain pods.spec.volumes

  • List item
  • emptyDir
  • hostPath
  • nfs
  • persistentVolumeClaim
  • glusterfs
  • cephfs
  • configMap
  • secret

EmptyDir

Pod临时挂载到宿主机上的目录,容器删除,目录删除,文件删除,不会恢复。

vim pod-emptydir.yaml

## 查看本机临时目录存在的位置
# 查看pod调度到哪个节点
kubectl get pods -o wide | grep empty

# 查看pod的uid
kubectl get pods pod-empty -o yaml | grep uid

# 登录到对应主机上
tree /var/lib/kubelet/pods/38d60544-8591-468d-b70d-2a66df3a1cf6
apiVersion: v1
kind: Pod
metadata:
  name: pod-empty
spec:
  containers:
  - name: container-empty
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}
/var/lib/kubelet/pods/49d73a17-5615-44bc-aed0-ce88520e0572
├── containers
│   └── container-empty
│       └── af926089
├── etc-hosts
├── plugins
│   └── kubernetes.io~empty-dir
│       ├── cache-volume
│       │   └── ready
│       └── wrapped_default-token-dr4nt
│           └── ready
└── volumes
    ├── kubernetes.io~empty-dir
    │   └── cache-volume
    └── kubernetes.io~secret
        └── default-token-dr4nt
            ├── ca.crt -> ..data/ca.crt
            ├── namespace -> ..data/namespace
            └── token -> ..data/token

11 directories, 7 files
# 挂载目录
/var/lib/kubelet/pods/49d73a17-5615-44bc-aed0-ce88520e0572/volumes/kubernetes.io~empty-dir/cache-volume/

# 在此目录下写入一个文件hello.txt
# 进入容器查看/cache目录下,是否也有相同文件
kubectl exec -it pod-empty -- /bin/sh

HostPath

指Pod挂载宿主机上的目录或文件。容器删除目录依旧存在,数据依旧存在,重新挂载数据恢复。

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

vim pod-hostpath.yaml

# 查看pod调度到那一台机器上了
kubectl get pods -o wide

# 去对应机器下查看目录/data-test,并创建文件
# 进入指定容器,查看创建的文件是否也在容器内
kubectl exec -it test-hostpath -c test-nginx -- /bin/bash
kubectl exec -it test-hostpath -c test-tomcat -- /bin/bash
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: /data-test
      type: DirectoryOrCreate 

NFS或者分布式存储

[分布式存储方案] nfs,cephfs,glusterfs

数据可以在Pod之间共享,但是NFS单节点如果宕机了,数据也就丢失了,所以需要使用分布式存储

搭建NFS单节点服务器,详见:https://blog.csdn.net/AlgebraFly/article/details/125991396

分布式存储,待定

【注意】使用NFS挂载操作需要在工作节点物理机上安装nfs-utils

vim pod-nfs.yaml

# 字段解释
path: /data/volumes  #nfs的共享目录
server:10.11.2.58    #master1机器的ip

# 进入NFS挂载目录/data/volumes,写一个测试文件
vim index.html

# 请求一下查看结果
curl <ip>:<80>
# 进入容器中查看文件
kubectl exec -it test-nfs  -- /bin/bash
cd /usr/share/nginx/html && ls
apiVersion: v1
kind: Pod
metadata:
 name: test-nfs
spec:
 containers:
 - name: test-nginx
   image: nginx
   imagePullPolicy: IfNotPresent
   ports:
   - containerPort: 80
     protocol: TCP
   volumeMounts:
   - name: nfs-volumes
     mountPath: /usr/share/nginx/html
 volumes:
 - name: nfs-volumes
   nfs:
    path: /data/volumes
    server: 10.11.2.58

PV和PVC(重点)

概念

PersistentVolume(PV)是群集中的一块存储,由管理员配置或使用存储类动态配置。 它是集群中的资源,就像pod是k8s集群资源一样。 PV是容量插件,如Volumes,其生命周期独立于使用PV的任何单个pod。

PersistentVolumeClaim(PVC)是一个持久化存储卷,我们在创建pod时可以定义这个类型的存储卷。 它类似于一个pod。 Pod消耗节点资源,PVC消耗PV资源。

## 注意
1.PV是群集中的资源。 PVC是对这些资源的请求。
2.PV被释放之后,不可再重复使用,无论是何种形式的操作,直到他被删除为止

【pv的供应方式】
1.静态
集群管理员创建了许多PV。它们包含可供群集用户使用的实际存储的详细信息。它们存在于Kubernetes API中,可供使用。
2.动态
当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,群集可能会尝试为PVC专门动态配置卷。此配置基于StorageClasses,PVC必须请求存储类,管理员必须创建并配置该类,以便进行动态配置。

【绑定】
用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态
【使用】
a)需要找一个存储服务器,把它划分成多个存储空间;
b)k8s管理员可以把这些存储空间定义成多个pv;
c)在pod中使用pvc类型的存储卷之前需要先创建pvc,通过定义需要使用的pv的大小和对应的访问模式,找到合适的pv;
d)pvc被创建之后,就可以当成存储卷来使用了,我们在定义pod时就可以使用这个pvc的存储卷;
e)pvc和pv它们是一一对应的关系,pv如果被pvc绑定了,就不能被其他pvc使用了;
f)我们在创建pvc的时候,应该确保和底下的pv能绑定,如果没有合适的pv,那么pvc就会处于pending状态。
【回收策略】
当Pod删除后,Pod与PVC就绑定解除了,PVC绑定的PV卷也解除了绑定,此时PV的处理方式有:
Retain   保留(当删除pvc的时候,pv仍然存在,处于released状态,但是它不能被其他pvc绑定使用)
Recycle  回收(不推荐使用,1.15可能被废弃了)
Delete   删除(删除pvc时即会从Kubernetes中移除PV)

资源清单

## 【1】创建NFS共享目录
mkdir /data/volume_test/v{1,2,3,4,5,6,7,8,9,10} -p
vim /etc/exports

/data/volumes 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v1 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v2 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v3 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v4 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v5 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v6 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v7 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v8 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v9 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v10 10.11.2.0/24(rw,no_root_squash)

# 重新加载配置
exportfs -arv
## 【2】PV 资源清单文件
vim pv-test.yaml
kubectl apply -f pv-test.yaml 
kubectl get pv
# 初始化完成后,状态是Available
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v1
spec:
  capacity:
    storage: 1Gi                #pv的存储空间容量
  accessModes: ["ReadWriteOnce"]
  nfs:
    path: /data/volume_test/v1  #把nfs的存储空间创建成pv
    server: 10.11.2.58          #nfs服务器的地址
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v2
spec:
  capacity:
      storage: 20Mi
  accessModes: ["ReadWriteMany"]
  nfs:
    path: /data/volume_test/v2
    server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v3
spec:
  capacity:
      storage: 30Mi
  accessModes: ["ReadOnlyMany"]
  nfs:
    path: /data/volume_test/v3
    server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v4
spec:
  capacity:
      storage: 40Mi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v4
    server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v5
spec:
  capacity:
      storage: 50Mi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v5
    server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v6
spec:
  capacity:
      storage: 60Mi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v6
    server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v7
spec:
  capacity:
      storage: 70Mi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v7
    server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v8
spec:
  capacity:
      storage: 80Mi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v8
    server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v9
spec:
  capacity:
      storage: 90Mi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v9
    server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v10
spec:
  capacity:     
      storage: 100Mi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v10  
    server: 10.11.2.58
## 字段解释
# kubectl explain pv.spec.nfs
path	<string> -required-
readOnly	<boolean>
server	<string> -required-

# kubectl explain pv.spec.capacity
设置PV容量

# kubectl explain pv.spec.accessModes
设置PV访问模式
ReadWriteOnce
卷可以被一个节点以读写方式挂载。也允许运行在同一节点上的多个 Pod 访问卷。
ReadOnlyMany
卷可以被多个节点以只读方式挂载。
ReadWriteMany
卷可以被多个节点以读写方式挂载。
ReadWriteOncePod
卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用ReadWriteOncePod 访问模式。
## 【3】PVC 资源清单文件
vim pvc-test.yaml
kubectl apply -f pvc-test.yaml

kubectl get pv
kubectl get pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 20M
## 字段解释
# kubectl explain pvc.spec
accessModes  <[]string>         # 同PV的accessModes
dataSource   <Object>           
resources    <Object>           # 要求挂载的PV的资源最小值
selector     <Object>
storageClassName     <string>
volumeMode   <string>
volumeName   <string>

# kubectl explain pvc.spec.resources
limits       <map[string]string>  #类似于Pod资源的限制
requests     <map[string]string>
## 【4】创建Pod,挂载PVC
vim pod-test-pvc.yaml
kubectl apply -f pod-test-pvc.yaml

# 测试文件挂载
# 创建一个index.html
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
## 注意
1、我们每次创建pvc的时候,需要事先有划分好的pv,这样可能不方便,那么可以在创建pvc的时候直接动态创建一个pv这个存储类,pv事先是不存在的

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

存储类(解决PV依存关系问题)

概念

Kubernetes提供一种自动创建PV的机制,叫StorageClass,它的作用就是创建PV的模板。k8s集群管理员通过创建Storageclass可以动态生成一个存储卷pv供k8s pvc使用。

## 注意
1. storageClass是一个K8S资源类型,它依赖于provisioner(供应商)
2. provisioner是一个自动生成PV的插件,它以将以一个k8s-pod资源的形式部署在k8s集群中,提供PVC使用
3. provisioner有多重形式,可以根据自己情况自行选择
4. Kubernetes就能够根据用户提交的PVC,找到对应的StorageClass,然后Kubernetes就会调用 StorageClass声明的存储插件,创建出需要的PV。

资源清单

## StorageClass会定义以下两部分:
1、PV的属性 ,比如存储的大小、类型等;
2、创建这种PV需要使用到的存储插件,比如Ceph、NFS等

# kubectl explain storageclass
allowVolumeExpansion	<boolean>  # 允许扩展卷
allowedTopologies	<[]Object>
apiVersion	<string>
kind	<string>
metadata	<Object>
mountOptions	<[]string>         # 如果卷插件不支持挂载选项,却指定了挂载选项,则制备操作会失败。
parameters	<map[string]string>
provisioner	<string> -required-    # 创建PV的供应商(需自己配置搭建)
reclaimPolicy	<string>           # 回收策略
volumeBindingMode	<string>       # Immediate 模式表示一旦创建了 PVC 也就完成了卷绑定和动态制备。

# kubectl explain storageclass.reclaimPolicy
指定PV的回收策略,Delete 或者 Retain,默认是Delete

# kubectl explain storageclass.allowVolumeExpansion
允许扩展卷(仅允许扩展卷,不允许缩小)
将此功能设置为true时,允许用户通过编辑相应的 PVC 对象来调整卷大小。

安装nfs provisioner

provisioner有多种,其作用是按照pvc既定的资源配置和StorageClass创建PV,以供PVC绑定使用,下面展示以NFS为存储器的nfs-client的配置使用

# 【1】到Github下载安装包镜像,上传到工作节点,并解压
docker load -i nfs-subdir-external-provisioner.tar.gz
# 创建sa账号
vim serviceaccount.yaml
kubectl apply -f serviceaccount.yaml

# 赋予sa账户角色权限
kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
## 【2】配置NFS
mkdir /data/nfs_pro -p

#把/data/nfs_pro变成nfs共享的目录
vim /etc/exports

/data/nfs_pro 192.168.40.0/24(rw,no_root_squash)

exportfs -arv
# 【3】创建nfs-provisioner资源
vim nfs-deployment.yaml
kubectl apply -f nfs-deployment.yaml
kubectl get pods
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-provisioner
spec:
  selector:
    matchLabels:
       app: nfs-provisioner
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
      - name: nfs-provisioner
        image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: nfs-client-root
          mountPath: /persistentvolumes
        env:
        - name: PROVISIONER_NAME
          value: example.com/nfs
        - name: NFS_SERVER
          value: 10.11.2.58
        - name: NFS_PATH
          value: /data/nfs_pro
      volumes:
      - name: nfs-client-root
        nfs:
          server: 10.11.2.58
          path: /data/nfs_pro

创建使用

## 【1】创建storageclass,动态供给pv
vim nfs-storageClass.yaml
kubectl get storageclass

## 结果展示
NAME   PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs    example.com/nfs   Delete          Immediate           false                  74m
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: nfs
provisioner: example.com/nfs
## 【2】创建pvc,通过storageclass动态生成pv
vim pvc-sc.yaml
kubectl get pvc
kubectl get pv

## 结果展示
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
test-claim1   Bound    pvc-47e1e175-f940-43bb-bf30-2ec1b0b7556e   30M        RWX            nfs            69m

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                 STORAGECLASS   REASON   AGE
pvc-47e1e175-f940-43bb-bf30-2ec1b0b7556e   30M        RWX            Delete           Bound       default/test-claim1   nfs                     69m
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-claim1
spec:
  accessModes:  ["ReadWriteMany"]
  resources:
    requests:
      storage: 100Mi
  storageClassName: nfs
## 【3】创建pod,挂载storageclass动态生成的pvc
vim pod-pvc-sc.yaml

## 创建文件验证文件挂载
apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc-sc
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: nfs-pvc
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nfs-pvc
    persistentVolumeClaim:
      claimName: test-claim1
Logo

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

更多推荐