Kubernetes之持久化

一、前言

前面我们接触了Kubernetes的搭建,安装和核心组件,现在我们就聊聊Kubernetes的持久化存储方面的事情。

通过前面的文章我们知道,当pod挂了以后,deployment会根据pod的yml文件的配置重新创建一定数量的pod来维持数量。如果我们没有持久化的方案,那么pod中的数据就会丢失,新创建的pod无法共用之前的数据。

二、Volumes

Kubernetes作为一个成熟的产品,其肯定会考虑这个问题的。Kubernetes提供了Volume来用于持久化存储。关于Volume请看官网:https://kubernetes.io/docs/concepts/storage/volumes/。
在这里插入图片描述
通过官网的大致介绍,我们知道Volumes有不同的类型,下面我就介绍j几种基本和常用的Volumes。

(一)Host类型的Volume

在这里插入图片描述
通过官网的介绍我们可以看到,Host类型的Volumes是使用pod的所在节点的文件夹或者文件来跟pod中container的文件进行关联,其实也就是挂载的意思。

我们可以自己尝试实践一下,在Pod中定义Volume,然后pod中再定义两个container,都使用pod的vlolume。

1、创建pod

pod的yml文件如下:

apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - name: volume-pod
      mountPath: /nginx-volume
  - name: testVolume-container
    image: testVolume
    volumeMounts:
    - name: volume-pod
      mountPath: /test-volume
  volumes:
  - name: volume-pod
    hostPath:
      path: /tmp/volume-pod 

上面的yml应该都能看懂,设置了pod的vloume,名字叫做volume-pod,路径是pod所在主机的/tmp/volume-pod,然后定义的两个container都使用这个volume,对应的路径是container内部各自的路径。它们是通过volumes的name进行关联使用的。

运行命令:kubectl apply -f volume-pod.yml

2、创建文件并校验contianer中是否有

(1)在pod所属节点的/tmp/volume-pod路径下随便创建一个文件
(2)分别进入两个container中,然后分别检查/nginx-volume和/test-volume是否有这个文件,可以使用:docker exec -it containerid sh进入到container中。

这里就说一下实践的结果,就不截图了,可以发现在这两个container中能看到pod的volume配置目录下新建的文件。

3、分别查看容器里的hosts文件

使用:docker exec -it containerid cat /etc/hosts命令,可以看到pod的hosts文件和container的hosts文件都是一样的。

因此,一般修改container中存储或者网络方面的内容,不要在container中改,直接在pod中改就能同步。

4、结论

host类型的Volume本地配置的共享文件或者文件夹。
其实也可以使用deployment创建一个pod并配置vloume路径,然后启动pod以后添加文件然后手动销毁当前pod,deployment由于你设置了pod副本的数量,新建pod的volume还是有该文件,因为是共享的。

5、问题

上面我们发现pod中的container共享volume,即使pod挂了数据也不会丢失。但是问题来了,如果pod所在的机器挂了,数据还是会丢失。那我们的volume关联的目录能不能是其他机器或者是其他服务器,这样就算当前机器挂了数据也不会丢失,于是就有了PersistentVolume。

(二)PersistentVolume

官网的地址:https://kubernetes.io/docs/concepts/storage/persistent-volumes/

PersistentVolume又可以简称为PV,我们可以在pv的yml文件中定义我们需要的volume大小以及是否被读写等配置。配置文件如下:

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 # 远端的服务器

一般都是使用其他的服务器作为volume的目录,但是如果我们自己解决与其他服务器的通信等其他问题就太麻烦了。通过官网我们可以看到,官网通过插件的方式已经帮我们解决了其他不同类型服务器的通信等问题,但是也只是支持其列出来的那几种。
在这里插入图片描述
本质:其实说白了pv就是k8s中的资源,是volume的plugin实现,生命周期独立于pod,封装了底层存储卷实现的细节。pv通常是运维人员进行维护的。

问题:pv一般都是专业的运维人员维护的,跟不同的服务器打交道,那我们开发人员使用的时候不能自己去手动创建一个pv,然后再使用吧,因此就有了PersistentVolumeClaim。

(三)PersistentVolumeClaim

官网的地址:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims

1、何为PersistentVolumeClaim

PersistentVolumeClaim又可以简称为PVC,我们可以设计一个pvc绑定pv,然后把pvc交给pod使用。运维同学会创建各种类型的pv,然后我们利用pvc匹配满足要求的pv(根据所需空间大小和访问模式进行匹配的),跟pv进行一一绑定,然后pv的状态就会变成Bound。

也就是pvc负责请求pv的大小和访问方式,然后pod中就可以直接使用pvc。
注意: pvc通常是由开发人员进行维护的。

下面就是官网给的pvc的yml文件:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

2、Pod中如何使用PVC

可以看官网的介绍:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#claims-as-volumes

具体的yml文件如下:

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

相信大家都能看懂吧,在volumes下配置persistentVolumeClaim的名字即可。

3、Pod中使用PVC的具体实践

我们就创建一个Nginx的pod然后使用nfs服务器上的文件,下面是具体的实践步骤:

3.1、搭建nfs服务器

nfs(network file system):网络文件系统,是FreeBSD支持的文件系统中的一种,允许网络中的计算机之间通过 TCP/IP网络共享资源。

上面我们pv选择了nfs服务器,那么我们就搭建nfs的服务器。

3.1.1、选择一个服务安装nfs,可以是master节点也可以是额外的服务器
# 安装nfs 
yum install -y nfs-utils 
# 创建nfs目录 
mkdir -p /nfs/data/ 
mkdir -p /nfs/data/mysql 
# 授予权限 
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 master-ip
3.1.2、在所有使用nfs的节点上安装客户端
yum -y install nfs-utils 
systemctl start nfs && systemctl enable nfs
3.2、创建pv&pvc&Nginx
3.2.1、在nfs服务器上创建所需要存储文件的目录
mkdir -p /nfs/data/nginx
3.2.2、定义PV、PVC、Nginx的文件

我们不用一个个去创建,在一个yml文件中就能创建三个,最好的步骤是先创建被调用方再创建调用方

# 定义PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv
spec:
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 2Gi    
  nfs:
    path: /nfs/data/nginx     
    server: xxx.xxx.xxx.xxx
    
---
# 定义PVC,用于消费PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
  
---
# 定义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: mysql
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-persistent-storage
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-persistent-storage
        persistentVolumeClaim:
          claimName: nginx-pvc
3.2.3、根据yml文件创建资源并查看
kubectl apply -f nginx-pv-demo.yaml 
kubectl get pv,pvc 
kubectl get pods -o wide
3.2.4、测试持久化存储

(1)在nfs的服务器/nfs/data/nginx的路径下创建一个test.html,写入一些内容;
(2)运行:kubectl get pods -o wide 得到nginx-pod的ip地址;
(3)再运行:curl nginx-pod-ip/test.html访问对应ip下的这个html就能看到返回的结果跟我们写入的是否一样;
(4)也可以运行:kubectl exec -it nginx-pod bash然后进入入/usr/share/nginx/html目录查看其下是否有test.html以及其内容是否一致;
(5)也可以运行:kubectl delete pod nginx-pod删除当前pod,然后deployment会创建新的pod;
(6)然后再查看新的新nginx-pod的ip并访问新的ip下的test.html看是否有;

3.3、流程图解

在这里插入图片描述
其实就是Pod访问PVC,然后PVC访问PV,PV访问存储服务器,我们创建的时候一般是从被调用者开始往调用者创建。

4、问题

问题:我们创建满足我们需求的pv然后跟pod关联,但是我们不能创建一大堆的pv,等我们需要的时候就会自动关联,这样太浪费资源了。因此就出现了StorageClass。

(四)StorageClass

1、何为StorageClass

官网:https://kubernetes.io/docs/concepts/storage/storage-classes/
nfs github:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs
在这里插入图片描述
从官网的介绍我们可以看到:StorageClass声明存储插件用于自动创建PV。说白了就是创建PV的模板,其中有连个重要的部分:PV的属性和创建次PV需要的插件。这样PV就可以按照Class来匹配PV,可以为PV指定storageClassName属性,标识PV归属于哪一个Class。

下面就是StorageClass的yml文件:

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可以变成如下:

kind: PersistentVolumeClaim 
apiVersion: v1 
metadata: 
  name: test-claim1 
spec: 	
  accessModes: - ReadWriteMany 
  resources: 
 	requests: 
 		storage: 1Mi 
 	storageClassName: nfs

2、何为Provisioner

StorageClass之所以能顾动态提供PV是因为Provisioner ,根据官网我们可以看出k8s提供了多种类型的Provisioner,但是发现我们上面使用的nfs的Provisioner是没有的,需要自己创建。nfs的Provisioner插件github有人开源提供了,等会我们实践的时候具体讲解。

上面我们提供的官方给的StorageClass的yml文件可以看出是用的AWSElasticBlockStore的Provisioner。
在这里插入图片描述

3、StorageClass实践

因为之前我们使用的都是nfs服务器,现在我们依然使用nfs服务器,虽然k8s官方没有提供nfs的Provisioner插件的,但是github上有人已经开源了。
开源地址:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs

以下需要的yml文件都可以在上面github的开源地址中的/deploy/kubernetes文件夹下找到,我没有写的就是可以直接去github上拿来直接用的,有些进行了一些改动,会把改动以后的yml给出的。

3.3、准备好NFS服务器

可以使用上面pod中使用pvc实践中创建nfs服务器的步骤准备好nfs服务器,并确保nfs可以正常工作,同事创建持久化存储的目录。

mkdir -p /nfs/data/nginx
3.2根据rbac.yaml文件创建资源
kubectl apply -f rbac.yaml
3.3根据deployment.yaml文件创建资源
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: xxx.xxx.xx.xx #nfs服务器地址
            - name: NFS_PATH
              value: /nfs/data/nginx
      volumes:
        - name: nfs-client-root
          nfs:
            server: xxx.xxx.xx.xx #nfs服务器地址 
            path: /nfs/data/nginx
kubectl apply -f deployment.yaml
3.4根据class.yaml创建资源
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: example-nfs
provisioner: example.com/nfs
kubectl apply -f class.yaml
3.5根据pvc.yaml创建资源
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi
  # 这个名字要和上面创建的storageclass名称一致
  storageClassName: example-nfs
kubectl apply -f my-pvc.yaml
kubectl get pvc
3.6根据nginx-pod创建资源
kind: Pod
apiVersion: v1
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
      - name: my-pvc
        mountPath: "/usr/test"
  restartPolicy: "Never"
  volumes:
    - name: my-pvc
      persistentVolumeClaim:
        claimName: my-pvc
kubectl apply -f nginx-pod.yaml 
kubectl exec -it nginx bash 
cd /usr/test # 进行同步数据测试

4、StorageClass总结

1)对于PV或者StorageClass只能对应一种后端存储;
2)对于手动的情况,一般我们会创建很多的PV,等有PVC需要使用的时候就可以直接使用了;
3)对于自动的情况,那么就由StorageClass来自动管理创建;
4)如果Pod想要使用共享存储,一般会在创建PVC,PVC中描述了想要什么类型的后端存储、空间等,K8s从而会匹配对应 的PV,如果没有匹配成功,Pod就会处于Pending状态。Pod中使用只需要像使用volumes一样,指定名字就可以使用了;
5)一个Pod可以使用多个PVC,一个PVC也可以给多个Pod使用;
6) 一个PVC只能绑定一个PV,一个PV只能对应一种后端存储;

流程图如下:
在这里插入图片描述

(五) PV的状态和回收策略

5.1、PV的状态

Available:表示当前的pv没有被绑定;
Bound:表示已经被pvc挂载;
Released:pvc没有在使用pv, 需要管理员手工释放pv;
Failed:资源回收失败;

5.2、PV回收策略

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

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

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值