在k8s中为什么要做数据持久化?

  当在Kubernetes中部署应用程序时,数据通常存储在容器内部的文件系统中。然而,
容器的生命周期是临时的,当容器被删除或重新启动时,容器内的数据也会丢失。 
  为了解决这个问题,需要在Kubernetes中实现数据持久化。数据持久化是将数据保存到持久化存
储介质(如磁盘)上,以便在容器被重新创建或迁移到其他节点时仍然可用。


数据持久化的场景包括:
1、数据存储:许多应用程序需要保存用户生成的数据,如文件、图片、日志等。通过数据持久化,可
以确保这些数据在容器销毁或重启后仍然存在。 
2、数据共享:在某些情况下,多个容器或Pod可能需要访问和共享相同的数据。通过将数据存储在
持久化卷中,可以使多个容器之间共享数据,实现数据一致性和共享访问。 
3、数据备份和恢复:持久化存储解决方案通常提供数据备份和恢复机制,以防止数据丢失。这对于保
护重要数据、应对故障或恢复到先前的状态非常重要。 
4、数据迁移和扩展:在Kubernetes集群中,可能需要扩展应用程序到多个节点或迁移到其他集群。
通过将数据存储在持久化卷中,可以方便地将数据与应用程序一起迁移到新的环境,无需担心数据丢失。 
5、数据安全:某些行业或应用程序对数据的安全性有严格的要求。持久化存储解决方案通常提供数据
加密和访问控制功能,以确保数据在传输和存储过程中的安全性。 

k8s持久化存储方案-emptyDir

  在Kubernetes中,EmptyDir是一种卷(Volume),它提供了一个空目录来供容器使用。EmptyDir
卷在Pod级别上创建,与Pod的生命周期绑定。EmptyDir卷在Pod被删除或重新启动时会被清空,因
此它不是持久化的存储解决方案。


EmptyDir 卷的使用场景包括: 
1. 临时文件共享:如果多个容器需要在同一个Pod中进行临时文件共享,EmptyDir卷是一个简便
的解决方案。容器可以将文件写入EmptyDir卷,并且其他容器可以读取和修改这些文件。当Pod
被删除或重启时,EmptyDir卷中的文件会被清空。 
2. 共享数据:某些应用程序可能需要在容器之间共享一些中间结果或临时数据。EmptyDir卷可以
作为容器之间的临时数据交换机制。容器可以将数据写入EmptyDir卷,其他容器可以读取和处
理这些数据,从而实现数据共享和协作。 
3. 缓存:EmptyDir卷可以用作容器的缓存存储。某些应用程序可能需要将频繁访问的数据缓存到
本地存储中,以提高性能。EmptyDir卷提供了一个临时的、高速的存储介质来存储缓存数据,
提供快速的读取和写入操作。

当在Kubernetes中使用存储卷(Volume),需要经历以下步骤: 
1. 定义Pod的Volume:在Pod的配置中定义一个Volume,指定它要关联到哪个存储上。可以
使用不同类型的Volume,如EmptyDir、HostPath、PersistentVolumeClaim等,具体选
择取决于需求。 
2. 在容器中使用Volume Mounts:在Pod的配置中,为每个容器定义Volume Mounts,将
Volume 挂载到容器内部的指定路径上。这样容器就能够访问和操作Volume中的数据。 
3. 通过Volume实现数据持久化和共享:一旦Volume被挂载到容器中,容器就可以将数据写入
Volume 或从Volume中读取数据。这使得数据能够在容器的生命周期内持久存在,并且可以被
其他容器共享和访问。



root@ubuntu0:~/matedata/volumes# cat emptydir.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: xpp
  labels:
    app: v1
spec:
  containers:
  - name: pod-xp
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /cache  #挂在到容器下的/cache  也就是在这个目录下产生的数据会产生到容器下的  /cache 下  那临时目录需要去对应被调度的机器上找
      name: cache-volume
  volumes:
  - emptyDir: {}  #{}表示临时目录,可以不用指定大小
    name: cache-volume  #卷的名字

如何去对应的机器上找临时目录,他被调度到ubuntu2  上了,那就去ubuntu2 上去找
root@ubuntu0:~/matedata/volumes# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE   IP              NODE      NOMINATED NODE   READINESS GATES
default-55cdb47c4-zl2x9   1/1     Running   0          12h   10.244.25.164   ubuntu1   <none>           <none>
xpp                       1/1     Running   0          13s   10.244.152.98   ubuntu2   <none>           <none>
root@ubuntu0:~/matedata/volumes# 
查看对应的uuid,然后去对应的机器上找
root@ubuntu0:~/matedata/volumes#  kubectl get pods xpp  -o yaml | grep uid
  uid: 6f0ce328-63f5-436d-95f7-2612c8ae750a

root@ubuntu2:~# tree /var/lib/kubelet/pods/6f0ce328-63f5-436d-95f7-2612c8ae750a/
/var/lib/kubelet/pods/6f0ce328-63f5-436d-95f7-2612c8ae750a/
|-- containers
|   `-- pod-xp
|       `-- 0b0ad86f
|-- etc-hosts
|-- plugins
|   `-- kubernetes.io~empty-dir
|       |-- cache-volume
|       |   `-- ready
|       `-- wrapped_kube-api-access-m25b5
|           `-- ready
`-- volumes
    |-- kubernetes.io~empty-dir
    |   `-- cache-volume   #就在这个目录下,在这个目录下创建的数据,容器内对应的/cache也会有数据
    `-- kubernetes.io~projected
        `-- kube-api-access-m25b5
            |-- ca.crt -> ..data/ca.crt
            |-- namespace -> ..data/namespace
            `-- token -> ..data/token

11 directories, 7 files

hostPath

hostPath 是 Kubernetes 中的一种卷类型,它将主机节点上的文件或目录挂载到容器中。使用 
hostPath,可以将主机节点上的文件系统路径直接映射到容器的文件系统中。这种方式在某些情况下非常
有用,但也需要谨慎使用,因为它具有一些潜在的限制和风险。



以下是 hostPath 的一些关键特点和适用场景:
1. 直接访问主机文件系统:hostPath 卷允许容器直接访问主机节点上的文件系统。这对于需要访
问主机节点上的特定文件或目录的应用程序非常有用。例如,某些日志收集器可能需要访问主机
上的日志文件。 
2. 主机依赖性:hostPath 卷的挂载是与特定主机节点紧密关联的,因此在调度 Pod 时需要特别
注意。如果 Pod 被调度到另一个主机节点上,它将无法访问之前挂载的主机文件系统。 
3. 危险性:hostPath 卷的使用需要谨慎,因为容器可以访问主机节点上的任何文件或目录,包括
敏感的系统文件。此外,如果多个 Pod 使用相同的 hostPath 卷并且并发写入同一个文件,可
能会导致冲突和数据损坏。 
4. 开发和测试环境:hostPath 卷特别适用于开发和测试环境,因为它可以方便地将主机节点上的
文件或目录映射到容器中,从而加快开发和测试工作流程。

需要注意的是,hostPath 卷并不适合生产环境中的大多数用例。在生产环境中,建议使用更可靠和
弹性的持久化存储方案,例如网络存储卷(NFS)、云提供商的块存储或对象存储等。  


root@ubuntu0:~# kubectl explain pods.spec.volumes.hostPath
KIND:     Pod
VERSION:  v1

RESOURCE: hostPath <Object>


root@ubuntu0:~/matedata/volumes# cat hostpath.yaml 
apiVersion: v1 
kind: Pod 
metadata: 
  name: test-hostpath 
spec: 
  containers: 
  - image: nginx 
    imagePullPolicy: IfNotPresent 
    name: test-nginx 
    volumeMounts: 
    - mountPath: /test-nginx 
      name: test-volume 
  - image: nginx 
    imagePullPolicy: IfNotPresent 
    name: test-tomcat 
    volumeMounts: 
    - mountPath: /test-tomcat 
      name: test-volume 
  volumes: 
  - name: test-volume 
    hostPath: 
      path: /data1 
      type: DirectoryOrCreate
# DirectoryOrCreate 表示本地有/data1 目录,就用本地的,本地没有就会在pod调度到的节点自
动创建一个 
root@ubuntu0:~/matedata/volumes# mkdir /data1
root@ubuntu0:~/matedata/volumes# kubectl apply -f hostpath.yaml 
pod/test-hostpath created
root@ubuntu0:~/matedata/volumes# kubectl get pods -owide
NAME            READY   STATUS    RESTARTS      AGE   IP               NODE      NOMINATED NODE   READINESS GATES
test-hostpath   2/2     Running   3 (28s ago)   52s   10.244.152.101   ubuntu2   <none>           <none>
机器是调度到ubuntu2这台机器上,去ubuntu2这台机器上看看有没有创建/data1目录
root@ubuntu2:~# ls /data1/
root@ubuntu2:~# 
root@ubuntu2:~# cd /data1/
root@ubuntu2:/data1# mkdir aa

#测试存储卷是否可以正常使用,登录到nginx容器
root@ubuntu0:~/matedata/volumes# kubectl exec -it test-hostpath -c test-nginx -- /bin/bash 
root@test-hostpath:/#  cd /test-nginx/ 
root@test-hostpath:/test-nginx# ls
aa

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

NFS

NFS(Network File System)是一种网络文件系统协议,它允许不同计算机之间共享文件和目录。
在 Kubernetes(k8s)中,NFS 是一种常见的持久化存储方案,用于将网络共享的存储卷挂载到容器中。



下面是 NFS 的基本介绍和常见应用场景:
1. 基本原理:NFS 允许将存储资源(文件或目录)通过网络共享给其他计算机。NFS 服务器将存
储资源公开为共享,并将其挂载到客户端计算机上。客户端可以像访问本地文件系统一样访问这
些共享资源。 
2. 持久化存储方案:在 Kubernetes 中,NFS 可以作为持久化存储方案使用。它可以提供可靠的
存储,并在容器被重新调度到不同的节点时保持数据的一致性。 
3. 分布式访问:NFS 允许多个客户端同时访问共享资源。这使得它非常适合那些需要多个容器或 
Pod 共享数据的场景,例如数据库系统或分布式文件共享。 
4. 跨平台兼容性:NFS 是一种跨平台的文件系统协议,支持在不同操作系统之间进行文件共享。这
使得它成为在混合操作系统集群中实现持久化存储的理想选择。 
5. 灵活性:NFS 提供了对存储资源的灵活访问和管理。管理员可以根据需求创建和配置 NFS 服务
器,设置共享权限以及实施访问控制策略。 
6. 备份和恢复:NFS 具备备份和恢复数据的能力。通过使用备份工具和策略,可以对 NFS 共享的
数据进行定期备份,以防止数据丢失或损坏。 

常见的应用场景包括: 
• 数据库持久化:NFS 可用于挂载数据库文件,确保数据库的持久性和数据一致性,并提供跨多个
数据库节点的共享访问。 
• 分布式文件共享:多个容器或 Pod 可以通过挂载相同的 NFS 共享来实现文件共享和协作,如
共享配置文件、日志目录等。 
• 文件存储和共享:NFS 可以用作共享存储,供团队成员或应用程序之间共享文件,便于协作和数
据交换。


总结起来,NFS 是一种在 Kubernetes 中常用的持久化存储方案,可以提供可靠的存储和跨多个容
器或 Pod 的文件共享。它具有跨平台兼容性、灵活性和备份恢复能力等 


1、搭建nfs服务 
以k8s的控制节点作为NFS服务端
root@ubuntu0:~/matedata/volumes# apt install nfs-kernel-server -y
2.在宿主机创建NFS需要的共享目录
root@ubuntu0:~#  mkdir /data/volumes -pv
3.配置nfs共享服务器上的/data/volumes目录
root@ubuntu0:~# systemctl restart nfs-server
root@ubuntu0:~# tail -n1 /etc/exports 
/data/volumes *(rw,no_root_squash) 
#no_root_squash: 用户具有根目录的完全管理访问权限 
4.使NFS配置生效 
root@ubuntu0:~#  exportfs -arv
root@ubuntu0:~# systemctl restart nfs-server
5.在剩下的两台机器上也安装nfs
root@ubuntu2:/data1# apt install nfs-kernel-server -y
root@ubuntu2:/data1# systemctl restart nfs-server
root@ubuntu2:/data1# showmount -e 192.168.23.99
Export list for 192.168.23.99:
/data/volumes *
6.挂载
root@ubuntu2:/data1# mount -t nfs 192.168.23.99:/data/volumes /data1 
root@ubuntu2:/data1# df -h /data1
Filesystem                   Size  Used Avail Use% Mounted on
192.168.23.99:/data/volumes   24G   17G  5.8G  75% /data1
root@ubuntu2:/data1# 


7.创建Pod,挂载NFS共享出来的目录 
root@ubuntu0:~/matedata/volumes# cat nfs.yaml 
apiVersion: v1 
kind: Pod 
metadata: 
  name: test-nfs-volume 
spec: 
  containers: 
  - name: test-nfs 
    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    #nfs共享的目录
      server: 192.168.23.99  #nfs服务端地址
root@ubuntu0:~/matedata/volumes# kubectl apply -f nfs.yaml 
pod/test-nfs-volume created
root@ubuntu0:~/matedata/volumes# kubectl get pods -owide
NAME              READY   STATUS    RESTARTS   AGE   IP              NODE      NOMINATED NODE   READINESS GATES
test-nfs-volume   1/1     Running   0          8h    10.244.25.168   ubuntu1   <none>           <none>
root@ubuntu0:~/matedata/volumes# curl 10.244.25.168
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.17.9</center>
</body>
</html>
root@ubuntu0:~/matedata/volumes# cd /data/volumes
root@ubuntu0:/data/volumes# vim index.html
root@ubuntu0:/data/volumes# cat index.html 
hhhh
root@ubuntu0:/data/volumes# curl 10.244.25.168
hhhh

可以把pod给删除,让他调度到另一个机器上,也是能访问的






k8s 持久化存储方案-PVC

1. K8s PV 是什么? 
PersistentVolume(PV): PV 是集群中的存储资源,可以是物理存储设备、网络存储或云存储等。
PV独立于Pod存在,它们是集群级别的资源,由集群管理员进行配置和管理。PV具有持久性,即使Pod
被删除,PV中的数据也会保留。PV定义了存储的容量、访问模式和其他属性。

2.K8s PVC 是什么?
PersistentVolumeClaim(PVC):PVC是Pod对PV的申请,它表示Pod需要一定的存储资源来
满足其持久化存储需求。PVC在Pod和PV之间建立了一个抽象层,使得Pod无需关心底层存储的具体
细节。PVC定义了Pod对存储的需求,包括存储容量、访问模式等。



3.K8s PVC和PV工作原理
当创建一个PersistentVolume(PV)和PersistentVolumeClaim(PVC)时,它们之间的相互作
用和工作原理如下: 



1. PV的供应方式:
• 静态配置:集群管理员预先创建PV对象,包含了实际存储资源的详细信息。这些PV
存在于Kubernetes API中,供用户使用。 
• 动态配置:当静态PV无法匹配用户的PVC时,Kubernetes可以尝试为PVC动态地
配置PV。这基于StorageClasses,PVC必须请求存储类,并且管理员必须创建和配
置该类以进行动态配置。 
2. 绑定
• 用户创建PVC并指定所需的存储资源和访问模式。 
• 在找到可用的PV之前,PVC保持未绑定状态。
3.使用
• 首先,存储管理员创建PV,并将其划分为多个存储卷。 
• 用户在创建Pod之前创建PVC,并指定所需的PV大小和访问模式。 
• 创建PVC后,可以将其作为存储卷使用,并在Pod定义中引用该PVC。 
• PV和PVC是一对一的关系。一旦PV被某个PVC绑定,其他PVC就不能使用它。 
• 如果没有合适的PV可用,PVC将处于挂起状态,直到有一个合适的PV可用为止。 
4. 回收策略: 
• 当删除使用PVC作为存储卷的Pod时,PVC与PV的绑定将解除。 
• PV有不同的回收策略可供选择:
  • Retain(保留):删除PVC后,PV保留,并且数据仍然存在。PV不会被绑
    定到其他PVC上,可以再次使用。 
  • Recycle(回收,不推荐):删除PVC后,PV会被清空数据并准备重新使用。
    这个回收策略在Kubernetes 1.15版本后被废弃。 
  • Delete(删除):删除PVC后,PV也会从Kubernetes中移除,并且相关
    的存储资源也会被删除。

通过PV和PVC的结合使用,Kubernetes提供了一种灵活的持久化存储管理机制,使得开发者可以
轻松地申请、使用和管理存储资源,同时提供了不同的回收策略以满足不同的需求。


1、创建nfs共享目录
#在宿主机创建NFS需要的共享目录
root@ubuntu0:/data/volumes#  mkdir /data/volume_test/v{1,2} -p
2.配置nfs共享宿主机上的/data/volume_test/v1..v2目录 
root@ubuntu0:~/matedata/volumes# tail -n2 /etc/exports 
/data/volume_test/v1 *(rw,no_root_squash) 
/data/volume_test/v2 *(rw,no_root_squash) 
root@ubuntu0:~/matedata/volumes# exportfs -arv

3.如何编写pv的资源清单文件 
root@ubuntu0:~/matedata/volumes# cat pv.yaml 
apiVersion: v1 
kind: PersistentVolume 
metadata: 
    name:  v1
spec:
  capacity:
    storage: 1Gi  #pv的存储空间容量
  accessModes: ["ReadWriteOnce"]
  nfs:
    path: /data/volume_test/v1 #把nfs的存储空间创建成pv
    server: 192.168.23.99     #nfs服务器的地址 ---
---      
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v2
spec:
  capacity:
      storage: 2Gi
  accessModes: ["ReadWriteMany"]
  nfs:
    path: /data/volume_test/v2
    server: 192.168.23.99
root@ubuntu0:~/matedata/volumes# kubectl apply -f pv.yaml 
persistentvolume/v1 created
persistentvolume/v2 created
root@ubuntu0:~/matedata/volumes# kubectl get pv -owide
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE   VOLUMEMODE
v1     1Gi        RWO            Retain           Available                                   5s    Filesystem
v2     2Gi        RWX            Retain           Available                                   5s    Filesystem
#STATUS是Available,表示pv是可用的

4.创建pvc,和符合条件的pv绑定
root@ubuntu0:~/matedata/volumes# cat pvc.yaml 
apiVersion: v1 
kind: PersistentVolumeClaim 
metadata: 
  name: my-pvc 
spec: 
  accessModes: ["ReadWriteMany"] 
  resources: 
    requests: 
      storage: 2Gi 
root@ubuntu0:~/matedata/volumes# kubectl apply -f pvc.yaml 
persistentvolumeclaim/my-pvc created

查看pv,发现v2已经被绑定了
root@ubuntu0:~/matedata/volumes# kubectl get pv -owide
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM            STORAGECLASS   REASON   AGE    VOLUMEMODE
v1     1Gi        RWO            Retain           Available                                            2m8s   Filesystem
v2     2Gi        RWX            Retain           Bound       default/my-pvc                           2m8s   Filesystem
#STATUS是Bound,表示这个pv已经被my-pvc绑定了
pvc的名字-绑定到pv-绑定的是v2这个pv-pvc可使用的容量是2G


5、创建pod,挂载pvc 
root@ubuntu0:~/matedata/volumes# cat 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@ubuntu0:~/matedata/volumes# kubectl apply -f pod_pvc.yaml 
pod/pod-pvc created
root@ubuntu0:~/matedata/volumes# kubectl get pod -owide
NAME      READY   STATUS    RESTARTS   AGE   IP              NODE      NOMINATED NODE   READINESS GATES
pod-pvc   1/1     Running   0          17s   10.244.25.169   ubuntu1   <none>           <none>

进入容器内查看是否已经挂载上了
root@ubuntu0:~/matedata/volumes# kubectl exec -it pod-pvc -- bash
root@pod-pvc:/# df -h
Filesystem                          Size  Used Avail Use% Mounted on
overlay                              24G   14G  8.6G  62% /
tmpfs                                64M     0   64M   0% /dev
/dev/mapper/ubuntu--vg-ubuntu--lv    24G   14G  8.6G  62% /etc/hosts
shm                                  64M     0   64M   0% /dev/shm
192.168.23.99:/data/volume_test/v2   24G   23G     0 100% /usr/share/nginx/html


测试pod挂载PVC 是否正常: 
在绑定的v2 目录下创建文件,写入测试内容“my-pvc”
root@ubuntu0:~/matedata/volumes#  echo "my-pvc" >> /data/volume_test/v2/index.html 
root@ubuntu0:~/matedata/volumes# curl 10.244.25.169
my-pvc


测试删除pod,再重新创建pod ,挂载原先的pvc,看数据是否会丢失:
root@ubuntu0:~/matedata/volumes# kubectl delete -f pod_pvc.yaml 
pod "pod-pvc" deleted
root@ubuntu0:~/matedata/volumes# kubectl get pods -owide
NAME      READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
pod-pvc   1/1     Running   0          4s    10.244.152.102   ubuntu2   <none>           <none>
root@ubuntu0:~/matedata/volumes# curl 10.244.152.102
my-pvc


k8s存储类:storageclass

1.Kubernetes提供了StorageClass来自动创建PV,以减轻管理员的维护成本。以下是关于
Kubernetes PV、PVC和StorageClass的更新内容: 
2.PV(PersistentVolume)是Kubernetes中的持久化存储资源,而PVC(PersistentVolumeClaim)
是Pod对PV的申请。传统的PV和PVC模式需要管理员预先创建PV,然后将其与PVC进行一对一的
绑定。这种方式在大规模部署中可能导致管理复杂性和维护成本的增加。 
3.为了解决这个问题,Kubernetes引入了StorageClass机制。StorageClass是一种动态创建PV的模板。
集群管理员可以创建多个StorageClass,每个StorageClass定义了存储的类型、访问模式和其他属性。 
4.当用户创建一个PVC并指定StorageClass时,Kubernetes会自动根据该StorageClass创建一个PV,
并将其与PVC进行绑定。这样,管理员无需手动创建PV,而是根据StorageClass的定义,动态生成PV
来满足用户的存储需求。


StorageClass 提供了以下好处
1. 简化管理:StorageClass 允许管理员创建一组可重用的存储配置模板,而无需为每个 PVC 手动
创建和管理 PV。这降低了管理成本和复杂性。
2. 动态供应:使用 StorageClass,管理员可以根据需求动态创建 PV,从而自动为 PVC 提供存储
资源。这种动态供应的机制使得存储的分配更加灵活和自动化。
3. 可选性和灵活性:StorageClass 允许管理员根据存储的不同特性和需求创建不同的
StorageClass。用户可以根据自己的需求选择合适的 StorageClass,并使用相应的存储资源。



#查看定义的 storageclass 需要的字段
root@ubuntu0:~#  kubectl explain storageclass
KIND:     StorageClass
VERSION:  storage.k8s.io/v1

DESCRIPTION:
     StorageClass describes the parameters for a class of storage for which
     PersistentVolumes can be dynamically provisioned.

     StorageClasses are non-namespaced; the name of the storage class according
     to etcd is in ObjectMeta.Name.


provisioner:供应商,storageclass 需要有一个供应者,用来确定我们使用什么样的存储来创建
pv,常见的 provisioner 如下
(https://kubernetes.io/zh/docs/concepts/storage/storage-classes/

provisioner既可以由内部供应商提供,也可以由外部供应商提供,如果是外部供应商可以参考https://github.com/kubernetes-incubator/external-storage/下提供的方法创建

以NFS为例,要想使用NFS,我们需要一个nfs-client的自动装载程序,称之为provisioner,这个程序会使用我们已经配置好的NFS服务器自动创建持久卷,也就是自动帮我们创建PV。
上传镜像,并解压
allowVolumeExpansion:允许卷扩展,PersistentVolume 可以配置成可扩展。将此功能设置为true时,允许用户通过编辑相应的PVC 对象来调整卷大小。当基础存储类的allowVolumeExpansion 字段设置为true 时,以下类型的卷支持卷扩展。
此功能仅用于扩容卷,不能用于缩小卷


安装nfsprovisioner,用于配合存储类动态生成pv
root@ubuntu0:~/matedata/volumes# ansible all -m copy -a "src=/root/nfs-subdir-external-provisioner.tar.gz dest=/root"
root@ubuntu0:~/matedata/volumes# ansible all -m shell -a "ctr -n=k8s.io images import nfs-subdir-external-provisioner.tar.gz"
root@ubuntu0:~/matedata/volumes# ansible all -m shell -a "crictl image ls|grep nfs-subdir-external-provisioner"
ubuntu2 | CHANGED | rc=0 >>
registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner   v4.0.0              3beaacba3ff48       45.1MB
ubuntu1 | CHANGED | rc=0 >>
registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner   v4.0.0              3beaacba3ff48       45.1MB



1、创建运行 nfs-provisioner 需要的 sa 账号
root@ubuntu0:~/matedata/volumes# cat serviceaccount.yam 
apiVersion: v1
kind: ServiceAccount
metadata:
 name: nfs-provisioner
root@ubuntu0:~/matedata/volumes# kubectl apply -f serviceaccount.yam 
serviceaccount/nfs-provisioner created

扩展:什么是 sa?
sa 的全称是 serviceaccount。
serviceaccount 是为了方便 Pod 里面的进程调用 Kubernetes API 或其他外部服务而设计的。
指定了 serviceaccount 之后,我们把 pod 创建出来了,我们在使用这个 pod 时,这个 pod 就有了我们指定的账户的权限了。


2、对 sa 授权
root@ubuntu0:~/matedata/volumes# kubectl get sa 
NAME              SECRETS   AGE
default           1         43d
nfs-provisioner   1         25s
root@ubuntu0:~/matedata/volumes# kubectl create clusterrolebinding nfs-provisioner --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
clusterrolebinding.rbac.authorization.k8s.io/nfs-provisioner created

3、安装 nfs-provisioner 程序
root@ubuntu0:~/matedata/volumes# tail -n1 /etc/exports 
/data/nfs_pro *(rw,no_root_squash)
使配置生效
root@ubuntu0:~/matedata/volumes# exportfs -arv

4.创建 storageclass,动态供给 pv
root@ubuntu0:~/matedata/volumes# cat nfs-storageclass.yaml 
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
 name: nfs
provisioner: example.com/nfs  # 必须与 Deployment 中的 PROVISIONER_NAME 一致,因为需要有一个对应的 StorageClass 来告诉 Kubernetes 使用哪个 provisioner:
root@ubuntu0:~/matedata/volumes# kubectl apply -f nfs-storageclass.yaml 
storageclass.storage.k8s.io/nfs created
root@ubuntu0:~/matedata/volumes# kubectl get storageclass
NAME   PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs    example.com/nfs   Delete          Immediate           false                  4s

5.安装 nfs-provisioner 程序
root@ubuntu0:~/matedata/volumes# cat nfs-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: xpp
  labels:
    app: v1
spec: 
  selector: 
    matchLabels:
      app: nfs-provisioner
  replicas: 1
  strategy:  #用于将现有的pod部署成新的pod的部署策略
    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  #将 NFS 共享挂载到容器的 /persistentvolumes 路径
        env:
          - name:  PROVISIONER_NAME  # provisioner 的标识符
            value: example.com/nfs
          - name: NFS_SERVER
            value: 192.168.23.99
          - name: NFS_PATH
            value: /data/nfs_pro
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.23.99
            path: /data/nfs_pro
root@ubuntu0:~/matedata/volumes# kubectl apply -f nfs-deployment.yaml 
deployment.apps/xpp created
root@ubuntu0:~/matedata/volumes# kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
pod-pvc               1/1     Running   0          54m
xpp-c44d68dcf-fkxkk   1/1     Running   0          2m40s

#显示内容如上,说明 storageclass 创建成功了
注意:provisioner 处写的 example.com/nfs 应该跟安装 nfs provisioner 时候的 env 下的
PROVISIONER_NAME 的 value 值保持一致,如下:
env:
 - name: PROVISIONER_NAME
 value: example.com/nfs


6.创建 pvc,通过 storageclass 动态生成 pv
root@ubuntu0:~/matedata/volumes# cat claim.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim1
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs
root@ubuntu0:~/matedata/volumes# kubectl apply -f claim.yaml 
persistentvolumeclaim/test-claim1 created

#查看是否动态生成了 pv,pvc 是否创建成功,并和 pv 绑定
root@ubuntu0:~/matedata/volumes# kubectl get pvc 
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc        Bound    v2                                         2Gi        RWX                           11d
test-claim1   Bound    pvc-81a6a294-de2a-4e44-94d0-35c8a67b3a95   1Gi        RWX            nfs            29s
#通过上面可以看到 test-claim1 的 pvc 已经成功创建了,绑定的 pv 是
pvc-81a6a294-de2a-4e44-94d0-35c8a67b3a95,这个 pv 是由 storageclass 调用 nfs provisioner
自动生成的
root@ubuntu0:~/matedata/volumes# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                 STORAGECLASS   REASON   AGE
pvc-81a6a294-de2a-4e44-94d0-35c8a67b3a95   1Gi        RWX            Delete           Bound       default/test-claim1   nfs                     47s


6.创建 pod,挂载 storageclass 动态生成的 pvc
root@ubuntu0:~/matedata/volumes# cat read-pod.yaml 
kind: Pod
apiVersion: v1
metadata:
 name: read-pod
spec:
 containers:
 - name: read-pod
   image: nginx
   imagePullPolicy: IfNotPresent
   volumeMounts:
   - name: nfs-pvc
     mountPath: /usr/share/nginx/html
 restartPolicy: "Never"
 volumes:
 - name: nfs-pvc
   persistentVolumeClaim:
     claimName: test-claim1
root@ubuntu0:~/matedata/volumes# kubectl apply -f read-pod.yaml 
pod/read-pod created
root@ubuntu0:~/matedata/volumes# kubectl apply -f read-pod.yaml 
pod/read-pod created
root@ubuntu0:~/matedata/volumes# kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
pod-pvc               1/1     Running   0          65m
read-pod              1/1     Running   0          23s
xpp-c44d68dcf-fkxkk   1/1     Running   0          13m
root@ubuntu0:~/matedata/volumes# kubectl describe pods read-pod
Volumes:
  nfs-pvc:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  test-claim1
    ReadOnly:   false
  kube-api-access-qxkd8:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>

storageclass 默认的回收策略是 delete,删除 pvc,会把 pvc 以及 pvc 绑定的 pv 和 pv 对应的后
端存储目录都删除,比较危险。
生产环境回收策略用 retain,这样的话删除 pvc,不会把 pvc 绑定的 pv 和 pv 对应的后端存储目录
都删除。
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐