k8s series 12: 存储

540 阅读7分钟

这是我参与更文挑战的第9天,活动详情查看: 更文挑战

   k8s环境中,不管是deployment还是daemonset还是其他控制器对象,最终启动的容器还是pod,pod在运行中会产生临时数据,如果pod重启,数据会丢失。对于无状态应用,是可以接受的,但有状态pod就不行了,会导致大故障,所以持久化存储至关重要,那k8s中的存储又是怎么样的了

主要概念

    k8s中有4个重要概念: Volume(卷)、PersistentVolume(持久卷)、PersistentVolumeClaim(PVC)、StorageClass(存储类)

架构图

Volume

  volume是最基础的使用方式,其底层可以是不同类型的存储方案,默认支持列表(不断增加中)

awsElasticBlockStoreazureDiskazureFilecephfscinderconfigMapdownwardAPIemptyDirfc (fibre channel)flocker (deprecated)gcePersistentDiskgitRepo (deprecated)glusterfshostPathiscsilocalnfs

PV持久卷

 持久卷是集群中的一块存储,可以提前配置,或使用storageclass 动态创建,pv独立于pod生命周期,pod重启,pv可继续存在

回收策略:
Retain(保留) --手动回收
Delete (删除) --关联的存储资产 如 AWS EBS、GCE PD、Azure Disk和OpenStack Cinder卷将被删除
当前只有NFS和HostPath支持回收策略。 AWS EBS、GCE PD 、Azure Disk 和Cinder卷支持删除策略

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

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

PVC持久卷认领

 消费PV,从PV处申请卷,PV上的存储单元

例子:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs1
  nfs:
    path: /nfsdata1
    server: 192.168.78.136
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc004
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs1

StorageClass存储类

storage class相当于为提供了一组接口,可以按策略配置,来动态创建PV和服务各种底层存储,如GlusterFS

每个 StorageClass 都包含 provisionerparametersreclaimPolicy 字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到

官方参考:  kubernetes.io/docs/concep…

例子:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: glusterfs-storageclass
  namespace: default
parameters:
  resturl: "http://ip:8080"
  clusterid: "xxxxxxxxxx"
  restauthenabled: "true"             #若heketi开启认证此处也必须开启auth认证
  restuser: "admin"
  secretName: "glusterfs-secret"      #name/namespace与secret资源中定义一致
  secretNamespace: "default"
  volumetype: "replicate:2"
provisioner: kubernetes.io/glusterfs
reclaimPolicy: Delete
allowVolumeExpansion: true

实战部署

nfs安装

在centos7上

yum install nfs-utils rpcbind -y

配置

mkdir -p /data/nfs
chmod 755 /data/nfs

vi /etc/exports
-
/data/nfs     *(rw,sync,no_root_squash,no_all_squash)
-

systemctl enable rpcbind
systemctl enable nfs-server
systemctl start rpcbind
systemctl start nfs-server
#查看nfs信息
showmount -e localhost  

配置释义

ro                  只读访问  
rw                  读写访问sync 所有数据在请求时写入共享  
async nfs           在写入数据前可以响应请求  
secure nfs          通过1024以下的安全TCP/IP端口发送  
insecure nfs        通过1024以上的端口发送  
wdelay              如果多个用户要写入nfs目录,则归组写入(默认)  
no_wdelay           如果多个用户要写入nfs目录,则立即写入,当使用async时,无需此设置。      
hide                在nfs共享目录中不共享其子目录  
no_hide             共享nfs目录的子目录  
subtree_check       如果共享/usr/bin之类的子目录时,强制nfs检查父目录的权限(默认)  
no_subtree_check    和上面相对,不检查父目录权限  
all_squash          共享文件的UID和GID映射匿名用户anonymous,适合公用目录。  
no_all_squash       保留共享文件的UID和GID(默认)  
root_squash         root用户的所有请求映射成如anonymous用户一样的权限(默认)  
no_root_squas       root用户具有根目录的完全管理访问权限  
anonuid=xxx         指定nfs服务器/etc/passwd文件中匿名用户的UID  
anongid=xxx         指定nfs服务器/etc/passwd文件中匿名用户的GID 

以nfs为底层实际存储,来部署一个zookeeper集群

创建PVPVC

PV 作为存储资源,主要包括存储能力、访问模式、回收策略、存储类型

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv1
  labels:
    app: nfs
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  nfs:
   path: /data/nfs/pv1
   server: ip

参数说明:

  • capacity:持久卷资源和容量的描述,存储大小是唯一可设置或请求的资源。 
  • accessMode:访问模式,有ReadWriteOnce,ReadOnlyMany,ReadWriteMany。其中: ReadWriteOnce:表示具有读写权限,但是只能被一个node挂载一次 ReadOnlyMany:表示具有只读权限,可以被多个node多次挂载 ReadWriteMany:表示具有读写权限,可以被多个node多次挂载 
  • persistentVolumeReclaimPolicy: 回收策略,也就是释放持久化卷时的策略,其有以下几种: Retain:保留数据,如果要清理需要手动清理数据,默认的策略; Delete:删除,将从Kubernetes中删除PV对象,以及外部基础设施中相关的存储资产,比如AWS EBS, GCE PD, Azure Disk, 或Cinder volume; Recycle:回收,清楚PV中的所有数据,相当于执行rm -rf /pv-volume/*; 
  • NFS  存储类型,还支持众多,比如常用的Ceph和GlusterFS

*注 目前只有 NFS 和 HostPath 两种类型支持回收策略。持久化应用基本配Retain 

创建PV

pv.yaml

PV的状态说明:

  • Available(可用):表示可用状态,还未被任何 PVC 绑定

  • Bound(已绑定):表示 PVC 已经被 PVC 绑定

  • Released(已释放):PVC 被删除,但是资源还未被集群重新声明

  • Failed(失败): 表示该 PV 的自动回收失败

PVC挂载PV,实际PV的申请者,也有访问模式,资源请求,挂载类型等

PVC创建时会自动绑定到PV,但是一个PVC只能绑定一个PV(因为我们访问模式定义的ReadWriteOnce),且容量不能大于PV,如果是只读只写的PV可以被多个PVC挂载,但是访问模式要和PV一样

如果有默认的存储类,PVC会自动绑定到存储类,这时需要selector来选择labels

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc1
spec:
  selector:
    matchLabels:
      app: nfs
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

参数说明:

  • accessModes:主要定义卷所应该拥有的访问模式

  • resources:主要定义卷应该拥有的最小资源

  • selector:定义绑定卷的标签查询

  • dataSource:定义如果提供者具有卷快照功能,就会创建卷,并将数据恢复到卷中,反之不创建

  • storageClassName:定义的storageClass的名字(如果PV有定义或SC有定义的)

  • volumeMode:定义卷的类型

  • volumeName:需要绑定的PV的名称链接

创建PVC

kubectl apply -f pvc.yaml
kubectl get pv,pvc

pvpvc总结: 

  • Pod声明了PVC,K8S会找一个PV配对,如果没有PV,就去找对应的StorageClass,帮它创建一个PV,然后和PVC完成绑定,就是Bound,如果都没有,就是PENGDING

创建StorageClass

    官方sigs组织有一个repo专门来提供配置以及教程:  github.com/kubernetes-…

其中覆盖比较全面,且没有排序,想正确安装使用也得爬爬坑,当然github也有repo整理排序的,但是这个SC是根据host来创建,也可以参考一下:  github.com/adonaicosta…

接下来开始部署sc

k8s所有节点安装nfs客户端(其他存储服务差不多,如果直接挂载的基本都要在k8s 节点安装客户端)

yum -y install nfs-utils

创建rbac

apiVersion: v1
kind: Namespace
metadata:
  name: dmp-storage-class
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: dmp-storage-class
---
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: dmp-storage-class
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
  namespace: dmp-storage-class
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
  namespace: dmp-storage-class
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: dmp-storage-class
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

创建nfs-client

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  namespace: dmp-storage-class
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          imagePullPolicy: IfNotPresent
          #请替换成quay.io/external_storage/nfs-client-provisioner:latest
          image: harbor-test.libaogo.cn/dev/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes/
          env:
            - name: PROVISIONER_NAME
              value: go.libaigo.com/nfs            - name: NFS_SERVER
              value: ip
            - name: NFS_PATH
              value: /data/nfs/pv4
      volumes:
        - name: nfs-client-root
          nfs:
            server: ip
            path: /data/nfs/pv4

创建SC

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: dmp-nfs-storage  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: go.libaigo.com/nfs # or choose another name, must match deployment's env PROVISIONER_NAME'
reclaimPolicy: Retain
parameters:
  archiveOnDelete: "false"

创建PVC

匹配对应存储类,会自动创建PV

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sc-test
  labels:
    app: sc-test
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: dmp-nfs-storage
  resources:
    requests:
      storage: "5Gi"

执行以下命令或在目录执行 kubectl apply -f ./

kubectl apply -f rbac.yaml
kubectl apply -f deployment-nfs-client.yaml
kubectl apply -f StorageClass-nfs-yaml
kubectl apply -f pvc.yaml

查看结果

以deployment方式部署的nfs-client

在rancher存储类的中的PV

总结: 

  •  StorageClass 支持众多存储类型

  •  StorageClass 根据Type 可以实现动态PV,实现动态扩容

  •  StorageClass 非常灵活,根据不同Type 实现不同功能

  •  StorageClass 根据Type 实现数据高可用,高冗余