Kubernetes的持久化存储

  • 前言
  • 卷的类型
  • emptyDir
  • emptyDir的用法
  • hostPath
  • hostPath的用法
  • PersistentVolume(PV)和PersistentVolumeClaim(PVC)
  • 概念
  • 静态PV和动态PV
  • 静态PV
  • 动态PV
  • 绑定
  • 持久卷声明的保护
  • 持久卷类型
  • PV的访问模式
  • 回收策略
  • 状态
  • 持久化演示说明--NFS
  • 安装NFS服务器
  • 部署PV
  • 创建服务并使用PVC
  • 关于StatefulSet


前言

容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet会重启它,但是容器中的文件将会丢失----容器以干净的状态(镜像最初的状态)重新启动。其次在Pod中同时运行多个容器是,这些容器之间通常需要共享文件。Kubernetes中的Volume抽象就很好的解决了这些问题。
Kubernetes中的卷有明确的寿命,与封装它的Pod相同。所以,卷的生命比Pod中的所有容器都长,当这个容器重启时数据仍然得以保存。当然,当Pod不再存在时,卷也不复存在。Kubernetes支持多种类型的卷,Pod也可以同时使用任意数量的卷。

卷的类型

Kubernetes支持以下类型的卷:

  • awsElasticBlockStore azureDisk azureFile cephfs csi downwardAPI emptyDir
  • fc flocker gcePersistentDisk gitRepo glusterfs hostPath iscsi local nfs
  • persistentVolumeClaim projected portworxVolume quobyte rbd scaleIO secret
  • storageos vsphereVolume

emptyDir

当Pod被分配给节点时,首先会创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字,它最初是空的。Pod中的容器可以读取和写入emptyDir卷中的相同文件。尽管该卷可以挂载到每个容器中的相同或者不同路径上。当出于任何原因从节点中删除Pod时,emptyDir中的数据将被永久删除。

注意: 容器崩溃不会从节点移除Pod,因此emptyDir卷中的数据在容器崩溃时是安全的。

emptyDir的用法

  • 暂存空间,例如基于磁盘的合并序列
  • 用作长时间计算崩溃恢复时的检查点
  • Web服务器容器提供数据时,保存内容管理容器提取的文件
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

hostPath

hostPath卷将主机节点的文件系统中的文件或者目录挂载到集群中

hostPath的用法

  • 运行需要访问的Docker内部的容器;使用/var/lib/docker的hostPath
  • 在容器中运行cAdvisor;使用/dev/cgroup的hostPath
  • 允许Pod指定给定的hostPath是否应该在Pod运行前存在,是否应该创建,以及它应该以什么形式存在

除了所需的path属性外,用户还可以为hostPath卷指定type


行为

空字符串(默认)用于向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查。

DirectoryOrCreate

如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。

Directory

给定的路径下必须存在目录

FileOrCreate

如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。

File

给定的路径下必须存在文件

Socket

给定的路径下必须存在 UNIX 套接字

CharDevice

给定的路径下必须存在字符设备

BlockDevice

给定的路径下必须存在块设备

使用hostPath卷需要注意的是:

  • 由于每个节点上的文件都不同,具有相同配置的Pod在不同节点上的行为可能会有所不同
  • 当Kubernetes按照计划添加资源感知调度时,将无法考虑hostPath使用的资源
  • 在底层主机上创建的文件或者目录只能由root写入。管理员需要在特权容器中以root身份运行进程,或修改主机上的文件权限以便写入hostPath卷
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # 本机的目录
      path: /data
      # 类型可以随意选择
      type: Directory

PersistentVolume(PV)和PersistentVolumeClaim(PVC)

概念

PV是由管理员设置的存储,它是集群的一部分。就像就节点是集群中的资源一样,PV也是集群中的资源。PV是volume的卷插件,但具有独立于使用PV的Pod的生命周期。此API对象包含存储实现的细节,即NFS、iSCSI、或特定的云供应商的存储系统.

PVC是用户存储的请求。它与Pod相似。Pod消耗节点资源,PVC消耗PV资源.Pod可以请求特定级别的资源,例如CPU和内存。声明可以请求特定的大小和访问方式(例如,可以读/写一次或者 只读多次模式挂载)

静态PV和动态PV

静态PV

集群管理员创建一些PV。他们带有可供集群用户使用的实际存储的细节。他们存在于Kubernetes API中,可用于消费

动态PV

当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试动态地为PVC创建卷。此配置基于StorageClasses:PVC必须请求[存储类],并且管理员必须创建并配置该类才能进行动态创建。声明该类为 “” 可以有效地禁止其动态配置
如果要启用基于存储级别的动态存储配置,集群管理员需要启用API Server上的 DefaultStorageClass[准入控制器]。在API Server组件的 "–admission-control"的有序列表中插入DefaultStorageClass

绑定

master中的控制环路监视新的PVC,寻找匹配大的PV,并将他们绑定在一起。如果为新的PVC动态调配PV,则该环路将始终将该PV绑定到PVC。负责,用户总会得到他们所请求的存储,但是容量可能超出要求的数量。一旦PV和PVC绑定后,PVC绑定时排他性的,不管他们时如何绑定的。PVC跟PV绑定是一对一的映射。

持久卷声明的保护

PVC保护的目的是确保由Pod正在使用的PVC不会从系统中移除,因为如果被移除的话可能会导致数据丢失

注意:

  • 当Pod状态为 Pending 并且 Pod已经分配给节点或Pod为Running状态时,PVC处于活动状态。
  • 当启用PVC保护alpha功能时,如果用户删除了一个Pod正在使用的PVC,则该PVC不会被立即删除。PVC的删除将被推迟,知道PVC不再被任何Pod使用

持久卷类型

PV类型以插件形式实现。Kubernetes目前支持以下插件类型:

  • GCEPersistentDisk AWSElasticBlockStore AzureFile AzureDisk FC (Fibre Channel)
  • FlexVolume Flocker NFS iSCSI RBD (Ceph Block Device) CephFS
  • Cinder (OpenStack block storage) Glusterfs VsphereVolume Quobyte Volumes
  • **HostPath ** VMware Photon Portworx Volumes ScaleIO Volumes StorageOS

PV的访问模式

PV可以以资源提供者支持的任何方式挂载到主机上。。供应商具有不同的功能,每个PV的访问模式都将被设置为该卷支持的特定模式。例如,NFS可以支持多个读/写客户端,但特定的NFS PV可能以只读方式导出到服务器上。每个PV都有一套自己的用来描述特定功能的访问模式。

  • RWO ReadWriteOnce:该卷可以被单个节点以读/写模式挂载
  • ROX ReadOnlyMany:该卷可以被多个节点以只读模式挂载
  • RWX ReadWriteMany:该卷可以被多个节点以读/写模式挂载

注意:一个卷一次只能使用一种访问模式挂载,即使它支持很多访问模式。例如,GCEPersistentDisk 可以由单个节点作为
ReadWriteOnce 模式挂载,或由多个节点以 ReadOnlyMany 模式挂载,但不能同时挂载

Volume 插件

ReadWriteOnce

ReadOnlyMany

ReadWriteMany

AWSElasticBlockStoreAWSElasticBlockStore


-

-

AzureFile




AzureDisk


-

-

CephFS




Cinder


-

-

FC



-

FlexVolume



-

Flocker


-

-

GCEPersistentDisk



-

Glusterfs




HostPath


-

-

iSCSI



-

PhotonPersistentDisk


-

-

Quobyte




NFS




RBD



-

VsphereVolume


-

- (当 pod 并列时有效)

PortworxVolume


-


ScaleIO



-

StorageOS


-

-

回收策略

  • Retain(保留) —手动回收
  • Recycle(回收) — 基本擦除(rm -rf /thevolume/*)
  • Delete(删除) —关联的存储资源(例如 AWS EBS GCE Azure Disk 和 OpenStack Cinder卷)将被删除
    当前,只有NFS和HostPath支持回收策略。AWS EBS GCE Azure Disk 和 OpenStack Cinder卷支持删除策略

状态

卷可以处于以下的某种状态:

  • Available(可用)----一块空闲资源还没有被任何声明绑定
  • Bound(已绑定) ----卷已经被声明绑定
  • Released(已释放) ----声明被删除,但是资源没未被集群重新声明
  • Failed(失败) ----该卷的自动回收失败

kubectl get pvc
可以显示绑定到的PV的PVC的名称

持久化演示说明–NFS

安装NFS服务器

##安装nfs和rpcbind
yum -y install nfs-common nfs-utils rpcbind
##创建共享目录,修改权限
mkdir /nfsdata/{1..5}
chown nfsnobody /nfsdata -R
chmod 666 /nfsdata -R
##声明nfs配置文件
/nfsdata/1 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/2 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/3 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/4 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/5 *(rw,no_root_squash,no_all_squash,sync)
##说明 
- rw 可读写 
- no_root_squash root有完全读写权限
- no_all_squash 保留UID,GID

sync 同步刷新
##启动服务,设置开机自启动
systemctl start rpcbind
systemctl enable nfs
systemctl stert rpcbind

部署PV

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/1
    server: 192.168.2.80
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv2
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/2
    server: 192.168.2.80
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv3
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/3
    server: 192.168.2.80
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv4
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/4
    server: 192.168.2.80
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv5
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/5
    server: 192.168.2.80

###
kubectl  apply -f nfs-pv.yaml

创建服务并使用PVC

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "nfs"
      resources:
        requests:
          storage: 1Gi 
### 
kubectl apply -f nfs-pvc.yaml

kubesphere 持久卷添加数据 kubernetes 持久化存储_docker

关于StatefulSet

  • 配置Pod name的模式为 $(StatefulSet Name)+序号
  • SatefulSet为每个Pod副本创建了DNS域名,这个域名格式为:$(Pod Name).(Headless ServerName),这就意味着服务间是通过Pod域名来访问而非Pod IP,因为Pod当前所在的Node节点发生故障时,Pod会漂移到其他Node上,Pod IP会发生改变,但是Pod域名不会变化。
  • StatefulSet使用Headless服务来控制Pod的域名,这个域名的 FQDN为:kubesphere 持久卷添加数据 kubernetes 持久化存储_docker_02(namespace).svc.cluster.local 。其中”cluster.local“就是集群的域名。
  • 根据PVC,为每个Pod创建一个pvc,pvc的命令规则匹配模式:volumeClaimTemplates.name-Pod_name
  • 删除Pod不会删除其PVC,手动删除PVC将自动释放PV