kubernetes学习笔记-存储卷管理

kubernetes学习笔记-存储卷管理

容器内部的磁盘文件是较为脆弱的,生产中往往由于某些不可抗因素,如pod被迫下限kubelet重新生产干净的pod导致原容器的重要文件被删除,或者容器被重新调度后,在新的宿主机找不到原来的文件等等问题,因此kubernetes根据不同情况提供了不同的持久卷来满足我们的需求。

参考blog:
https://www.cnblogs.com/xzkzzz/p/9633308.html

volume的定义

kubernetes内置了很多存储类型,用户可以通过 kubectl explain pods.spec.volumes 来查看支持的存储卷

hostPath  主机目录
emptyDir  空目录(pod销毁也随之销毁)
rbd    分布式存储之ceph块存储
local   卷表示挂载的本地存储设备,如磁盘、分区或目录
cephfs   分布式存储之cephfs
awsElasticBlockStore  aws云存储
azureDisk   azure云存储
azureFile   azure云存储
glusterfs   分布式存储之glusterfs
downwardAPI   卷用于使向下 API 数据(downward API data)对应用程序可用。它挂载一个目录,并将请求的数据写入纯文本文件。
cinder   OpenStack 块存储
configMap   配置中心
fc  卷允许将现有的 fc 卷挂载到 pod 中。您可以使用卷配置中的 targetWWN 参数指定单个或多个目标全球通用名称(World Wide Name)。如果指定了多个 WWN,则 targetWWN 期望这些 WWN 来自多路径连接。
flexVolume 抽象的存储服务,存储服务的管理软件
flocker  是一款开源的集群容器数据卷管理器。它提供了由各种存储后端支持的数据卷的管理和编排。
gcePersistentDisk   谷歌云上
gitRepo  卷是一个可以演示卷插件功能的示例。它会挂载一个空目录并将 git 存储库克隆到您的容器中。
iscsi  iscsi 卷允许将现有的 iSCSI卷挂载到容器中。不像 emptyDir,删除 Pod 时 iscsi 卷的内容将被保留,卷仅仅是被卸载。这意味着 iscsi 卷可以预先填充数据,并且这些数据可以在 pod 之间“切换”。
nfs   nfs Nas存储
persistentVolumeClaim 卷用于将 PersistentVolume 挂载到容器中。PersistentVolumes 是在用户不知道特定云环境的细节的情况下“声明”持久化存储(例如 GCE PersistentDisk 或 iSCSI 卷)的一种方式。
photonPersistentDisk
portworxVolume  是一个与 Kubernetes 一起,以超融合模式运行的弹性块存储层
projected 卷将几个现有的卷源映射到同一个目录中
quobyte  卷允许将现有的 Quobyte 卷挂载到容器中。
scaleIO  ScaleIO 是一个基于软件的存储平台,可以使用现有的硬件来创建可扩展的共享块网络存储集群
secret   加密文件
storageos  动态存储
vsphereVolume 配置了 vSphere Cloud Provider 的 Kubernetes

pod可以选择一个或多个不同类型的存储进行进行挂载,与docker不同的是只有当pod被删除时,volume才会被清理,并且数据的删除取决于Volume的具体类型和回收策略。

用户可以通过 kubectl explain pod.spec.containers.volumeMounts 查看系统支持的挂载类型

  • mountPath 挂载路径
  • name 指定挂载的volumes名称
  • readOnly 是否只读挂载
  • subPath 是否挂载子路径

emptyDir存储类型

查看说明:kubectl explain pod.spec.volumes.emptyDir

  • medium 指定媒介类型 disk Memory 两种
  • sizeLimit 现在资源使用情况

emptyDir的生命周期和pod生命周期相同,pod被删除对应的emptyDir也会被清理。

示例:同一个pod中的两个容器挂载同一个目录

apiVersion: v1
kind: Pod
metadata:
  name: emptydir-demo
  namespace: default
  labels:
    name: emptydir-demo
spec:
  containers:
  - name: emptydir-demo
    image: nginx
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: emptydir-v
      mountPath: /usr/share/nginx/html/
  - name: busybox
    image: busybox
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: emptydir-v
      mountPath: /data/
    command:
    - "/bin/sh"
    - "-c"
    - "while true; do echo $(date) >> /data/index.html; sleep 2; done"
  volumes:
  - name: emptydir-v
    emptyDir: {}

查看这个pod并访问nginx主页

kubectl describe pod emptydir-demo
curl 10.212.0.45

hostPath存储类型

查看说明:kubectl explain pod.spec.volumes.hostPath

  • path 指定宿主机的路径
  • type DirectoryOrCreate 宿主机上不存在创建此目录 Directory 必须存在挂载目录 FileOrCreate 宿主机上不存在挂载文件就创建 File 必须存在文件

apiVersion: v1
kind: Pod
metadata:
  name: host-dir-demo
  namespace: default
  labels:
    name: host-dir-demo
spec:
  containers:
  - name: host-dir-demo
    image: nginx
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: host-dir
      mountPath: /usr/share/nginx/html/
  volumes:
  - name: host-dir
    hostPath:
      path: /data/pod/nginx
      type: DirectoryOrCreate

我们现在尝试一下使用subPath仅仅挂载html目录

apiVersion: v1
kind: Pod
metadata:
  name: host-dir-demo
  namespace: default
  labels:
    name: host-dir-demo
spec:
  containers:
  - name: host-dir-demo
    image: nginx
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: host-dir
      mountPath: /usr/share/nginx/html/
      subPath: html
  volumes:
  - name: host-dir
    hostPath:
      path: /data/pod/nginx
      type: DirectoryOrCreate

查看一下宿主机的目录结构

[abc@abc nginx]# tree
.
├── html
└── index.html

1 directory, 1 file

可以看到在原来的宿主机目录下单独生成了新的挂载目录

NFS存储类型

查看说明: kubectl explain pod.spec.volumes.nfs

  • path 源目录
  • readOnly 是否只读 默认false
  • server NFS服务地址

安装NFS服务

yum install nfs-utils  rpcbind -y   
#nfs-utils:NFS主程序,rpcbind:PRC主程序,客户端和服务器都必须安装。
#启动RPC bind服务
 systemctl start rpcbind
#服务端修改配置文件
/opt/nfs/data1     192.168.163.0/24(rw,no_root_squash)      client-A.ctos.zu(rw,sync)
#[共享目录]   [客户端地址1(权限)]        [客户端地址2(权限)]
#检查一下配置文件
exportfs -rv
#启动NFS服务
systemctl start nfs

启动nginx容器挂载NFS目录

apiVersion: v1
kind: Pod
metadata:
  name: nfs-dir-demo
  namespace: default
  labels:
    name: nfs-dir-demo
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: nfs-dir
      mountPath: /usr/share/nginx/html/
  volumes:
  - name: nfs-dir
    nfs:
      server: 192.168.163.252
      path: /opt/nfs/data1

PV资源

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

查询方式: kubectl explain pv.spec

  1. accessModes 访问模式
    • ReadWriteOnce(RWO) 单节点读写
    • ReadOnlyMany(ROX) 多节点只读
    • ReadWriteMany(RWX) 多节点读写
  2. capacity 定义pv使用多少资源

PV的API字段说明 kubectl explain pods.spec.volumes

PVC的API字段说明 kubectl explain pods.spec.volumes.persistentVolumeClaim

SC的字段说明 kubectl explain sc

定义一个基于NFS格式的PV

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-1
  labels:
    name: pv-nfs-1
spec:
  nfs:
    path: /opt/nfs/data1
    server: 192.168.163.252
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi

查看PV资源

kubectl get pv 

PVC资源

查看说明:kubectl explain pvc.spec

  • accessModes 访问模式 是递延pv的accessModes的子集,例如:pv中accessModes 定义[“ReadWriteMany”,“ReadWriteOnce”],pvc中的也只能定义[“ReadWriteMany”,“ReadWriteOnce”] 或其中的一个。
  • resources 资源限制
  • selector  标签选择器
  • storageClassName 动态存储名称
  • volumeMode 后端存储卷的模式
  • volumeName 指定卷(pv)的名称

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

虽然 PersistentVolumeClaims 允许用户使用抽象存储资源,但用户需要具有不同性质(例如性能)的 PersistentVolume 来解决不同的问题。集群管理员需要能够提供各种各样的 PersistentVolume,这些PersistentVolume 的大小和访问模式可以各有不同,但不需要向用户公开实现这些卷的细节。对于这些需求,StorageClass 资源可以实现。

创建PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-1
  namespace: default
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 1.5Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc-1
  namespace: default
  labels:
    name: pod-pvc-1
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: pv-nfs
      mountPath: /usr/share/nginx/html/
  volumes:
  - name: pv-nfs
    persistentVolumeClaim:
      claimName: pvc-nfs-1

StorageClass存储方式

前面的 PV 都是静态的,所以导致当我要使用的一个 PVC 的话就必须手动去创建一个 PV,当pvc申请的时候不一定有满足pvc要求的pv,那怎么办呢?kubernetes为 为管理员提供了描述存储 “class(类)” 的方法(StorageClass)

要使用 StorageClass,我们就得安装对应的自动配置程序,比如我们这里存储后端使用的是 nfs,那么我们就需要使用到一个 nfs-client 的自动配置程序,我们也叫它 Provisioner,这个程序使用我们已经配置好的 nfs 服务器,来自动创建持久卷,也就是自动帮我们创建 PV。

  • 自动创建的 PV 以${namespace}-${pvcName}-${pvName}这样的命名格式创建在 NFS 服务器上的共享数据目录中
    
  • 而当这个 PV 被回收后会以archieved-${namespace}-${pvcName}-${pvName}这样的命名格式存在 NFS 服务器上。
    

创建对应的SA并绑定

kind: ServiceAccount
apiVersion: v1
metadata:
  name: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

新建的一个名为 nfs-client-provisioner 的ServiceAccount,然后绑定了一个名为 nfs-client-provisioner-runner 的ClusterRole,而该ClusterRole声明了一些权限,其中就包括对persistentvolumes的增、删、改、查等权限,所以我们可以利用该ServiceAccount来自动创建 PV。

创建NFS-CLINET帮助我们动态创建PV资源

kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
spec:
  selector:
    matchLabels:
      app: nfs-client-provisioner
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              value: 192.168.163.252        #nfs服务器
            - name: NFS_PATH
              value: /opt/nfs/data2     #共享目录
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.163.252       #nfs服务器
            path: /opt/nfs/data2        #共享目录

将nfs配置成storageclass,安装对应的自动配置程序nfs-client,可以自动创建持久卷(pv)。
每当创建storageclass时,就会在kubernetes里面自动创建pvnfs目录下自动创建文件夹,省去手动创建的繁琐。

创建存储类:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs #---动态卷分配者名称,必须和上面创建的"provisioner"变量中设置的Name一致
parameters:
  archiveOnDelete: "true" #---设置为"false"时删除PVC不会保留数据,"true"则保留数据

查看一下刚才创建的SC

kubectl get sc

创建一个基于SC的PVC

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
  annotations:
    volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"  #---需要与上面创建的storageclass的名称一致
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 200Mi

启动一个pod绑定我们刚才创建的PVC

kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: busybox:1.24
    command:
      - "/bin/sh"
    args:
      - "-c"
      - "touch /mnt/SUCCESS && exit 0 || exit 1"
    volumeMounts:
      - name: nfs-pvc
        mountPath: "/mnt"
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim           #我们定义的pvc

查看创建的PV和PVC

kubectl get pv,pvc

你可能感兴趣的:(容器)