kubernetes(四)Storage

1.Volume

On-disk files in a Container are ephemeral, which presents some problems for non-trivial applications when running in Containers. First, when a Container crashes, kubelet will restart it, but the files will be lost - the Container starts with a clean state. Second, when running Containers together in a Pod it is often necessary to share files between those Containers. The Kubernetes Volume abstraction solves both of these problems

https://kubernetes.io/docs/concepts/storage/volumes/

容器和 Pod都是短暂的。它们的生命周期可能很短,会被频繁地销毁和创建。
容器销毁时,保存在容器内部文件系统中的数据都会被清除。
为了持久化保存容器的数据,可以使用 Kubernetes Volume。

Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留下来,可以用于下次创建容器时恢复数据。

本质上,Kubernetes Volume 是一个目录,这一点与 Docker Volume 类似。当 Volume 被 mount 到 Pod,Pod 中的所有容器都可以访问这个 Volume。Kubernetes Volume 也支持多种类型,包括 emptyDir、hostPath等。

hostPath Volume 的作用是将 宿主机的文件系统中已经存在的目录 mount 给 Pod 的容器。

1)定义一个Pod,里面包含两个不同的container,将container里的路径映射到宿主机上

apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - name: volume-pod           # mount 的volume name
      mountPath: /nginx-volume   # 容器内的路径
  - name: busybox-container
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
    volumeMounts:
    - name: volume-pod
      mountPath: /busybox-volume
  volumes:
  - name: volume-pod
    hostPath:
      path: /tmp/volume-pod      # 宿主机上的路径

2)查看pod的运行情况

3)在运行的worker节点w2看下对应的路径下的数据是否共享

通过docker的命令进入容器中

缺点:数据保存在节点上,容器迁移至其它节点数据会丢失。

两个container是共用pod的ip和网络,他们里面的hosts文件也是一样的,我们想修改对应的hosts文件肯定也不会直接在里面修改,这样会导致两个文件不同步

一般想修改container中的存储或者网络的内容,不要在container层面修改,而是直接在pod中修改
比如下面修改一下网络

 spec:
 hostNetwork: true
 hostPID: true
 hostAliases: 
   - ip: "192.168.56.61"
  hostnames: 
     - "test.chenpp.com" 
 containers:
   - name: nginx-container
  image: nginx

2.PersistentVolume

2.1基本概念

The PersistentVolume subsystem provides an API for users and administrators that abstracts details of how storage is provided from how it is consumed. 

A PersistentVolume (PV) is a piece of storage in the cluster that has been provisioned by an administrator or dynamically provisioned using Storage Classes.

A PersistentVolumeClaim (PVC) is a request for storage by a user.  Pods consume node resources and PVCs consume PV resources. Pods can request specific levels of resources (CPU and Memory). Claims can request specific size and access modes (e.g., they can be mounted once read/write or many times read-only).

普通Volume和使用它的Pod之间是一种静态绑定关系,Volume是定义在Pod的yaml文件里,Volume 是Pod的附加属性,我们无法单独创建一个Volume,因为它不是一个独立的k8s资源对象。

而Persistent Volume (PV)是一个单独的K8S资源对象,所以我们可以直接创建一个PV。它不和Pod直接发生绑定,而是通过Persistent Volume Claim(PVC,持久化存储声明)来实现动态绑定。在Pod里面定义PVC,然后PVC会根据Pod的要求(CPU,内存,access modesden)去自动绑定符合条件的PV供Pod使用

PVC一般通过存储大小和access mode来匹配对应的PV,进行绑定。也就是PVC负责请求PV的大小和访问方式,然后Pod中就可以直接使用PVC;如果没有匹配成功,Pod就会处于Pending状态。

PV的access mode:

  • ReadWriteOnce:最基本的方式,可读写,但只支持被单个Pod挂载。
  • ReadOnlyMany: 支持以只读的方式被多个Pod挂载。
  • ReadWriteMany:支持以读写的方式被多个Pod共享。

PV的状态

  • Available:表示当前的pv没有被任何pvc绑定
  • Bound:表示已经被pvc挂载
  • Released:当前没有pvc在绑定该pv, 并且该pv不能使用,需要管理员手工释放才可以被其他pvc使用
  • Failed:资源回收失败

PV回收策略

  • Retain:表示删除PVC的时候,PV不会一起删除,而是变成Released状态等待管理员手动清理
  • Recycle:在Kubernetes新版本就不用了,采用动态PV的方式来替代
  • Delete:表示删除PVC的时候,PV也会一起删除,同时也删除PV所指向的实际存储空间

注意:目前只有NFS和HostPath支持Recycle策略。AWS EBS、GCE PD、Azure Disk和Cinder支持Delete策略

#PV的定义
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 5Gi          # 存储空间大小
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce       # 只允许一个Pod进行独占式读写操作
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp            # 远端服务器的目录
    server: 172.17.0.2    # 远端的服务器
---
#PVC的定义
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:             # 用于匹配对应的PV,只有满足selector条件的PV才能被该PVC bound
    matchLabels:        # 匹配的PV需要有对应的label标签
      release: "stable"
    matchExpressions:   # 用表达式匹配的标签
      - {key: environment, operator: In, values: [dev]}

#在Pod使用PVC来定义volume
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

2.2 Pod中使用PVC实战

使用nginx做持久化存储演示,使用NFS:network file system网络文件系统,是FreeBSD支持的文件系统中的一种,允许网络中的计算机之间通过TCP/IP网络共享资源

(1)master节点搭建nfs,目录为/nfs/data

#在master上安装NFS
yum install -y nfs-utils
# 创建nfs目录
mkdir -p /nfs/data/
# 授予权限
chmod -R 777 /nfs/data
# 编辑export文件
vi /etc/exports
/nfs/data *(rw,no_root_squash,sync)
# 使得配置生效
exportfs -r
# 查看生效
exportfs
# 启动rpcbind、nfs服务
systemctl restart rpcbind && systemctl enable rpcbind
systemctl restart nfs && systemctl enable nfs
# 查看rpc服务的注册情况
rpcinfo -p localhost
# showmount测试
showmount -e 192.168.56.51

#在所有Node上安装客户端
yum -y install nfs-utils
systemctl start nfs && systemctl enable nfs

测试nfs安装搭建成功

(2)创建PV&PVC&Nginx

#在nfs服务器创建所需要的目录
mkdir -p /nfs/data/nginx

#定义yaml
# 定义PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv
spec:
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 200Mi
  nfs:
    path: /nfs/data/nginx     
    server: 192.168.56.51
    
---
# 定义PVC,用于消费PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 200Mi
  
---
# 定义Pod,指定需要使用的PVC
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels: 
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: cppnginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-persistent-storage
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-persistent-storage
        persistentVolumeClaim:
          claimName: nginx-pvc

创建资源后查看pv,pvc
kubectl get pv,pvc

(3)验证持久化存储
在/nfs/data/nginx新建文件hello.html,写上内容 " hello!"

3.StorageClass

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

PV一般是运维人员来创建的,开发只需操作PVC就可以了,但是集群中可能会需要很多的PV,提前创建大量PV显然不可取,而运维如果每次都手动处理创建PV也是一件很繁琐的事情,所以就有了动态创建PV的概念。动态供给的关键就是StorageClass,它的作用就是创建PV模板。

Each StorageClass contains the fields provisionerparameters, and reclaimPolicy, which are used when a PersistentVolume belonging to the class needs to be dynamically provisioned.


StorageClass里面需要定义PV属性比如存储类型、大小等,和创建PV需要的插件。
使用StorageClass,用户提交PVC,PVC里面指定存储类型,如果匹配定义的StorageClass,则会为其自动创建PV并进行绑定。这样一来运维只需要提前定义好PV的模板就可以了,可以为PVC指定storageClassName属性,标识其匹配的PV需要归属于哪一个StorageClass

1.对于PV或者StorageClass一次只能创建一种对应的后端存储
2.一个Pod可以使用多个PVC,一个PVC也可以给多个Pod使用
3.一个PVC只能绑定一个PV,一个PV也只能对应一种后端存储

Provisioner:
Storage classes have a provisioner that determines what volume plugin is used for provisioning PVs. This field must be specified.

Provisioner决定了创建pv需要使用的volume插件,但是NFS这种类型,K8s中默认是没有Provisioner插件的,需要自己创建

https://github.com/kubernetes-incubator/external-storage/tree/master/nfs(nfs插件)

#StorageClass的定义
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate

#有了StorageClass,PVC里就可以使用storageClass代替PV
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim1
spec:
accessModes:
    - ReadWriteMany
resources:
 requests:
    storage: 1Mi
  storageClassName: nfs

(1)准备好NFS服务器,创建持久化需要的目录  path: /nfs/data/chenpp

   server: master 192.168.56.51

(2)根据rbac.yaml文件创建资源
   https://github.com/kubernetes-incubator/external-storage/blob/master/nfs/deploy/kubernetes/rbac.yaml
   rbac: Role Based Access Control 角色权限控制,用于授权
  创建nfs插件与api-server交互和创建storageclass的权限
   kubectl apply -f rbac.yaml

(3)根据deployment.yaml文件创建ServiceAccount和Deployment(nfs插件)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nfs-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: example.com/nfs
            - name: NFS_SERVER
              value: 192.168.56.51 
            - name: NFS_PATH
              value: /nfs/data/chenpp
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.56.51
            path: /nfs/data/chenpp

(4)根据class.yaml创建StorageClass

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: example-nfs
provisioner: example.com/nfs

 (5)根据pvc.yaml创建PVC资源

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi
  # 这个名字要和上面创建的storageclass名称一致
  storageClassName: example-nfs

(6)根据nginx-pod创建资源

kind: Pod
apiVersion: v1
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
      - name: my-pvc
        mountPath: "/usr/chenpp"
  restartPolicy: "Never"
  volumes:
    - name: my-pvc
      persistentVolumeClaim:
        claimName: my-pvc

启动Pod之后,查看K8s的PV资源,可以看到有新的pv生成

对于通过StorageClass生成的pv,会在nfs的目录下生成一个挂载目录来持久化数据

如果创建一个新的pvc,那么就会在目录下生成一个新的挂载目录

发布了47 篇原创文章 · 获赞 12 · 访问量 5085

猜你喜欢

转载自blog.csdn.net/qq_35448165/article/details/103375726