BenjaminYang In solitude, where we are least alone

Pod 数据持久化(数据卷与数据持久化卷)

1.Volume

volume使用说明

  • Kubernetes中的Volume提供了在容器中挂载外部存储的能力
  • Pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可 以使用相应的Volume

 

volume的分类

大致可以分为三类

 

volume 官网:https://kubernetes.io/docs/concepts/storage/volumes/

 

emptyDir

创建一个空卷,挂载到Pod中的容器。Pod删除该卷也会被删除。

应用场景:Pod中容器之间数据共享

read-write-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: write
    image: centos
    command: ["bash","-c","for i in {1..100};do echo $i>> /data/hello;sleep 1;done"]
    volumeMounts:
    - name: data
      mountPath: /data
  - name: read
    image: centos
    command: ["bash","-c","tail -f /data/hello"]
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    emptyDir: {}

两个pod 共用本地存储。

image.png

image.png

去 k8s-node2 查看映射在宿主机 上的目录,这个就是 pod 共享的目录

image.png

hostPath

挂载Node文件系统上文件或者目录到Pod中的容器,pod删除后宿主机上的目录不会被清除

应用场景:Pod中容器需要访问宿主机文件

hostpath.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 36000
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    hostPath:
      path: /tmp
      type: Directory  

pod被调度到 k8s-node2  容器中的/data 目录 映射到宿主机的/tmp目录

image.png

image.png

反之如果在宿主机的/tmp目录下创建文件 在容器中的 /data 目录一样可以看到。

但是如果 重建pod调度到 非之前的节点,那么之前pod 的数据就会看不到了。

 

NFS

部署nfs:

#nfs服务端
yum install nfs-utils -y
编辑 /etc/exports 
增加内容 /opt/nfs *(rw,no_root_squash)
mkdir /opt/nfs
systemctl start nfs;systemctl enable nfs;systemctl status nfs
#nfs客户端
mount -t nfs 192.168.31.65:/opt/nfs /mnt  #192.168.31.65是server端    

验证nfs共享存储:

在任意客户端的 挂载目录创建个 123文件

image.png

在其他客户端的 /mnt  或者服务端的 /opt/nfs 都可以看到

image.png

image.png

 

测试k8s中使用nfs存储

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers: 
      - name: nginx
        image: nginx
        volumeMounts: 
        - name: wwwroot
          mountPath: /usr/share/nginx/html
        ports: 
        - containerPort: 80
      volumes: 
      - name: wwwroot
        nfs:
          server: 192.168.31.65
          path: /opt/nfs

 

image.png

向 /opt/nfs  目录下创建 test.html 内容为hello test 作为 nginx的首页文件

如果是再nfs client端操作 是 /mnt目录

cd /root/learn/
echo 'hello test' >/mnt/test.html

请求首页进行验证

image.png

当我们重建一个pod 是否有效?

image.png

answer is 有效

image.png

使用nfs 网络共享存储的优势是即使pod 重建后调度到其他node上 依旧可以保留之前的数据。

 

2.PersistentVolume

  • PersistentVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理
  • PersistentVolumeClaim(PVC):让用户不需要关心具体的Volume实现细节

为什么会有pv和pvc这个概念:

image.png

对于 nfs server的 地址 挂载路径 用户不关心,那么是否可以将这资源抽象出来,将这些存储资源划分给集群管理,定义个名称或者标记,用户直接使用。

pv静态供给

提前申请好 多个pv形成一个pv池子 供pod从pv池里选取存储容量合适的pv申请成pvc 。

image.png

Kubernetes支持持久卷的存储插件: https://kubernetes.io/docs/concepts/storage/persistent-volumes/

 

向存储池申请3个pv

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /opt/nfs/pv001
    server: 192.168.31.65
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /opt/nfs/pv002
    server: 192.168.31.65
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
spec:
  capacity:
    storage: 30Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /opt/nfs/pv003
    server: 192.168.31.65

image.png

pv对应的各个字段的含义

  • NAME: pv的名称
  • CAPACITY: pv的容量
  • ACCESS MODES: 访问策略

ReadWriteOnce  – RWO - ReadWriteOnce一人读写

ReadOnlyMany  – ROX - ReadOnlyMany 多人只读

ReadWriteMany – RWX - ReadWriteMany多人读写

  • RECLAIM POLICY: 

用户删除PVC释放对PV的占用后,系统根据PV的"reclaim policy"决定对PV执行何种回收操作。 目前,"reclaim policy"有三种方式:Retained、Recycled、Deleted。

 

官网描述:

PersistentVolumes 可以有多种回收策略,包括 “Retain”、”Recycle” 和 “Delete”。对于动态配置的 PersistentVolumes 来说,默认回收策略为 “Delete”。这表示当用户删除对应的 PersistentVolumeClaim 时,动态配置的 volume 将被自动删除。如果 volume 包含重要数据时,这种自动行为可能是不合适的。那种情况下,更适合使用 “Retain” 策略。使用 “Retain” 时,如果用户删除 PersistentVolumeClaim,对应的 PersistentVolume 不会被删除。相反,它将变为 Released 状态,表示所有的数据可以被手动恢复。

 

Recycle策略

当 PVC pvc001 被删除后,我们发现 Kubernetes 启动了一个新 Pod recycler-for-pv001,这个 Pod 的作用就是清除 PV pv001 的数据。此时 pv001的状态为 Released,表示已经解除了与 pvc001的 Bound,正在清除数据,不过此时还不可用。

当数据清除完毕,pv001的状态重新变为 Available,此时则可以被新的 PVC 申请。

 

Retain策略

当绑定再pv上的pvc被删除后,并不会启动一个 recycler-for-xxx 的pod来回收pv,删除pvc后pv的状态直接变为released,虽然pvc被删除了,但是pv上的数据得到了保留,此时pv状态一直是Released的不能被其他pvc 绑定,如果想要这个pv重新被使用只有删除该pv 重建,重建后的pv状态重新变成Available再次可以被其他pvc 绑定使用。

 

Delete策略

只有使用了 动态pv的才可以支持该策略,而且pv动态供给默认使用该模式,删除pvc时同时删除与之绑定的pv,共享存储里之前pv的数据将会被归档,当pv 和pvc重新创建后会重新生成一个新目录。

之前目录将重命名为 archived-xxxxxxxxxx     xxxxxxx代表删除pvc之前的名称

 

  • STATUS :pv的状态
  • CLAIM:   与pv绑定的pvc名称
  • STORAGECLASS: 存储插件类型

 

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
    volumeMounts:
      - name: www
        mountPath: /usr/share/nginx/html
  volumes:
    - name: www
      persistentVolumeClaim:
        claimName: my-pvc

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

image.png

 

image.png

如果pv,pvc一直处于Terminating

 

kubectl patch pv pv001 -p '{"metadata":{"finalizers":null}}'
kubectl patch pvc my-pvc -p '{"metadata":{"finalizers": []}}' --type=merge

 

 

pv动态供给

Kubernetes支持持久卷的存储插件: https://kubernetes.io/docs/concepts/storage/persistent-volumes/

image.png

Dynamic Provisioning机制工作的核心在于StorageClass的API对象。

StorageClass声明存储插件,用于自动创建PV

 

k8s支持动态供给的存储插件

https://kubernetes.io/docs/concepts/storage/storage-classes/

 

 

社区开发nfs 支持动态供给的存储插件 https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client/deploy

image.png

 

实现动态pv供给需要解决的问题:

1.创建共享目录

2.创建pv

3.pv使用哪个存储后端(ip)

 

这些步骤将会由 支持pv动态供给的插件自动化完成

 

部署nfs动态供给支持插件

rbac.yaml

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

 

class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "true"

 

deployment.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
---
kind: Deployment
apiVersion: apps/v1 
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      imagePullSecrets:
      - name: myregistry
      containers:
        - name: nfs-client-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/benjamin-learn/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.31.65 
            - name: NFS_PATH
              value: /opt/nfs
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.31.65 
            path: /opt/nfs

 

image.png

 

pv动态供给示例

dynamic-pv-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
    volumeMounts:
      - name: www
        mountPath: /usr/share/nginx/html
  volumes:
    - name: www
      persistentVolumeClaim:
        claimName: my-pvc

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  storageClassName: "managed-nfs-storage"
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

 

image.png

 

进入my-pod 容器创建 index.html

image.png

default-my-pvc-pvc-f5ce89a7-b566-44df-affe-8221f13db74f 这个目录由插件自动完成创建

image.png

 

这样就可以完成了 自动pv供给,不需要再 手动申请pv

posted @ 2020-03-09 09:04  benjamin杨  阅读(1879)  评论(0编辑  收藏  举报