目录

1. 使用emptyDir卷

2. hostpath卷

3.网络存储(NAS)

4. 持久卷和(PV)、持久卷声明(PVC)和存储类(StorageClass)


本章展示k8s使用存储卷将外部存储挂载到pod容器内,实现数据临时存储或持久化存储。

1. 使用emptyDir卷

apiVersion : v1 
kind: Pod 
metadata: 
        name: gitrepo-volume-pod
spec:
        containers: 
        - image: nginx:alpine 
          name: web-server 
          volumeMounts:
          - name : html 
            mountPath: /usr/share/nginx/html 
            readOnly: true 
          ports: 
          - containerPort: 80 
            protocol: TCP
        volumes:
        - name : html
          emptyDir: {}

emptyDir用于在同一个pod中运行的多个容器之间共享文件,也可以被单个容器用于将数据临时写入磁盘,例如执行排序操作时,没有那么多内存够用。

emptyDir的声明周期与pod相关联,pod删除后,卷的内容会丢失。

emptyDir的实际存储是pod所在节点的磁盘,其性能取决于节点的磁盘类型,通过如下配置可以在内存上创建emptyDir.

volumes:
        - name : html
          emptyDir: 
                medium: Memory

2. hostpath卷

hostpath卷指向pod所在节点的文件目录,在同一个节点上运行的pod同时挂载同一个目录可以共享文件,pod将需要持久化的内容输出到挂载路径下,pod删除后其中的内容不会丢失,pod重建时再次自动挂载,真正实现了持久化的卷。

 缺点是由于pod删除重建无法保证每次都在同一个节点上,因此pod跨节点时无法保证内容同步。通常hostpath用在单节点集群的持久化,或者需要读取或写入系统文件时才使用。

3.网络存储(NAS)

网络存储类型有很多,例如谷歌的GCE持久磁盘,AWS弹性块存储等,常用的有NFS。

...
volumes:
        - name: share-nfs
          nfs:
            path: /nfs-share
            server: 172.10.25.45
...

使用网络存储避免了挂载固定节点的弊端,任何pod或pod漂移到任何节点,都可以同步、共享、持久化内容。

4. 持久卷和(PV)、持久卷声明(PVC)和存储类(StorageClass)

这个一开始不太好理解,多看看就明白了

为什么需要持久卷

不管是hostpath还是NFS,都需要开发人员了解集群中真实的存储结构并且知道服务器地址和路径,这违背了k8s的基础理念,开发人员不需要掌握基础设施的具体状态,并且能使应用程序在云服务商之间能够自由迁移。

理想情况下,应用程序只要告诉k8s需要多大存储,然后由k8s自动分配给应用程序,就像声明cpu和内存一样,应用层不需要知道基础设施的细节。

持久卷的目的是从底层存储技术解耦pod。

如何使用持久卷

1. 管理员创建持久卷(PV)->开发人员创建持久卷声明(PVC)->PVC自动寻找满足声明需求的PV并绑定->将PVC作为存储卷挂载到pod

2. 还有一种方式不用手动创建PV,先创建存储类(StorageClass),用户创建PVC时指定StorageClass,系统根据StorageClass自动创建PV.

手动模式:

 

创建持久卷(PV)时指定其大小和可支持的访问模式。

创建持久卷声明(PVC)时指定所需要的最低容量要求和访问模式,k8s将找到可匹配的持久卷(PV)并将其绑定到持久卷声明(PVC).

持久卷声明可以当做pod的一个卷来使用,其他用户不能使用相同的持久卷,除非先删除持久卷声明绑定来释放.

持久卷的存储类型有多种,以nfs为例:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 1Gi
  nfs:
    path: /nfs-share/nginx-pv
    server: 172.162.22.43
  persistentVolumeReclaimPolicy: Retain

持久卷不属于任何命名空间,它跟节点一样是集群层面的资源,而持久卷声明是属于命名空间的.

 

访问模式(accessModes)的种类有:

  • RWO --ReadWriteOnce--仅允许单个节点挂载读写

  • ROX--ReadOnlyMany--允许多个节点挂载只读

  • RWX--ReadWriteMany--允许多个节点挂载读写

回收策略(persistentVolumeReclaimPolicy)有三种:

  • Retain--保留--PV在PVC与其解除绑定后,保留其中的内容,并且不会再与其他PVC绑定.

  • Recyle--回收--PVC与PV解绑后,PV清空存储的内容,等待新的PVC与其绑定

  • Delete--删除--PVC与PV解绑后,PV标记为Failed,不可再用,并删除存储的内容

创建持久卷声明(PVC):

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: "" # 存储类指定为空会从现有的的pv寻找绑定,否则会根据默认					   # storageClass自动创建

查看PVC,可以看到已经与前面创建的nginx-pv是Bound状态.

sudo kubectl get pvc
输出:
--------------------------------------------------------------------
NAME        STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nginx-pvc   Bound    nginx-pv   1Gi        RWO                           28s

查看PV,发现绑定到default/nginx-pvc,其中default是命名空间,nginx-pvc是持久卷声明的名称.

sudo kubectl get pv
输出:
---------------------------------------------------------------------
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                        STORAGECLASS                   REASON   AGE
nginx-pv                                   1Gi        RWO            Retain           Bound    default/nginx-pvc                                                                    85m

在pod中使用持久卷声明

apiVersion : v1 
kind: Pod 
metadata: 
        name: nginx-volume-pod
spec:
        containers: 
        - image: nginx:alpine 
          name: web-server 
          volumeMounts:
          - name : html 
            mountPath: /usr/share/nginx/html 
            readOnly: true 
          ports: 
          - containerPort: 80 
            protocol: TCP
        volumes:
        - name : html
          persistentVolumeClaim: 
                claimName: nginx-pvc

进入pod,可以看到被挂载的持久卷中的内容:

sudo kubectl exec -it nginx-volume-pod sh
df
---------------------------------------------------------------
Filesystem           1K-blocks      Used Available Use% Mounted on
172.162.22.43:/nfs-share/nginx-pv
                     151892992  84325376  67567616  56% /usr/share/nginx/html

下图展示了pod直接使用挂载,和通过持久卷挂载存储的对比

 

通过使用持久卷和持久卷声明,pod和pvc可以在不同集群间迁移,因为他们不再涉及任何特定依赖于基础设施的内容.

回收持久卷

(策略为Retain的持久卷需手动回收,策略为Recycle和Delete的可自动回收.)

删除pvc后,由于先前设置的PV回收策略是Retain(保留),所以pv不会删除,状态变为Realeased

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM 
nginx-pv                                   1Gi        RWO            Retain           Released   default/nginx-pvc                                                                    121m

再次创建pvc时,该pv不会被绑到新的pvc(因为Reatin),新的pvc处于pending状态,如果PV的回收策略是Recycle,那么再次创建PVC时,PV会再次绑定

$ sudo kubectl get pvc
NAME        STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nginx-pvc   Pending                                                     10s

这时如果希望继续使用,只能删除和重建PV,重新创建PV稍作等待后PVC又与之自动绑定了.

使用存储类(StorageClass)动态自动创建持久卷

StorageClass(下面简称sc)和PV类似,不属于命名空间,是集群级别的资源

创建sc需要置备程序provisioner,就是一个插件,如果没有的话需要提前配置

创建sc:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nginx-sc
parameters:
  archiveOnDelete: 'false'
provisioner: nfs-nfs-base
reclaimPolicy: Delete
volumeBindingMode: Immediate

使用sc创建两个pvc,nginx-pvc 和 nginx-pvc1

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
  storageClassName: nginx-sc

查看pvc和pv

$ sudo kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nginx-pvc    Bound    pvc-0c0cbb27-b149-46f5-b10c-4b72340e6e75   100Mi      RWO            nginx-sc       3m19s
nginx-pvc1   Bound    pvc-f137a7c5-511b-4295-8e5a-a9b3dc19184f   100Mi      RWO            nginx-sc       101s
$ sudo kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                        STORAGECLASS                   REASON   AGE
pvc-0c0cbb27-b149-46f5-b10c-4b72340e6e75   100Mi      RWO            Delete           Bound    default/nginx-pvc                            nginx-sc                                108s
pvc-f137a7c5-511b-4295-8e5a-a9b3dc19184f   100Mi      RWO            Delete           Bound    default/nginx-pvc1                           nginx-sc                                10s

可以看到PV已经自动创建,并且容量和访问策略跟PVC声明的一致。它的回收策略是Delete,因此删除PVC时,PV会自动删除.

使用StorageClass的好处在于,声明时通过名称引用的,只要StorageClass的名称不变,便可以在不同集群间随意移植。

Logo

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

更多推荐