Kubernetes 系列(六):持久化存储 PV与PVC(一)

在使用容器之后,我们需要考虑的另外一个问题就是持久化存储,怎么保证容器内的数据存储到我们的服务器硬盘上。这样容器在重建后,依然可以使用之前的数据。但是显然存储资源和 CPU 资源以及内存资源有很大不同,为了屏蔽底层的技术实现细节,让用户更加方便的使用,Kubernetes便引入了 PV 和 PVC 两个重要的资源对象来实现对存储的管理。

一、概念

PV 的全称是:PersistentVolume(持久化卷),是对底层的共享存储的一种抽象,PV 由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、NFS 等,都是通过插件机制完成与共享存储的对接。

PVC 的全称是:PersistentVolumeClaim(持久化卷声明),PVC 是用户存储的一种声明,PVC 和 Pod 比较类似,Pod 消耗的是节点,PVC 消耗的是 PV 资源,Pod 可以请求 CPU 和内存,而 PVC 可以请求特定的存储空间和访问模式。对于真正使用存储的用户不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。

但是通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。

(1)NFS

我们这里为了演示方便,决定使用相对简单的 NFS 这种存储资源,接下来我们在节点master节点(192.168.3.131)上来安装 NFS 服务端,数据目录:/data/k8s/

1. 关闭防火墙

systemctl stop firewalld.service
systemctl disable firewalld.service

2. 安装配置 nfs

yum install -y nfs-utils rpcbind

安装完成后检查一下:

rpm -qa nfs-utils rpcbind

共享目录设置权限:

首先在/data路径下新建k8s文件,然后赋予操作权限

mkdir data
mkdir k8s
chmod 755 /data/k8s/

配置 nfs,nfs 的默认配置文件在 /etc/exports 文件下,在该文件中添加下面的配置信息:

vi /etc/exports
/data/k8s  *(rw,sync,no_root_squash)

配置说明:

  • /data/k8s:是共享的数据目录
  • *:表示任何人都有权限连接,当然也可以是一个网段,一个 IP,也可以是域名
  • rw:读写的权限
  • sync:表示文件同时写入硬盘和内存
  • no_root_squash:当登录 NFS 主机使用共享目录的使用者是 root 时,其权限将被转换成为匿名使用者,通常它的 UID 与 GID,都会变成 nobody 身份

启动nfs需要向rpc注册,rpc一旦重启了,注册的文件都会丢失,向它注册的服务都需要重启。

下面我们来启动nfs,注意启动顺序,先启动rpcbind:

systemctl start rpcbind.service
systemctl enable rpcbind
systemctl status rpcbind

看到上面这样的显示就说明启动成功了。

然后启动 nfs 服务:

systemctl start nfs.service
systemctl enable nfs
systemctl status nfs

同样,看到上面这样的输出就证明NFS Server启动成功了。

另外我们还可以通过下面的命令确认下:

[[email protected] data]# rpcinfo -p|grep nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    3   tcp   2049  nfs_acl
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    3   udp   2049  nfs_acl

查看具体目录挂载权限:

[[email protected] /]# cat /var/lib/nfs/etab
/data/k8s       *(rw,sync,wdelay,hide,nocrossmnt,secure,no_root_squash,no_all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,rw,secure,no_root_squash,no_all_squash)

到这里我们就把 nfs server 给安装成功了,接下来我们在node1节点(192.168.3.132)上来安装 nfs 的客户端来验证下 nfs

关闭防火墙

systemctl stop firewalld.service
systemctl disable firewalld.service

然后安装 nfs

yum -y install nfs-utils rpcbind

安装完成后,和上面的方法一样,先启动 rpc、然后启动 nfs:

systemctl start rpcbind.service
systemctl enable rpcbind.service
systemctl start nfs.service
systemctl enable nfs.service

挂载数据目录 客户端启动完成后,我们在客户端来挂载下 nfs 测试下,首先检查下 nfs 是否有共享目录:

[[email protected] ~]# showmount -e 192.168.3.131
Export list for 192.168.3.131:
/data/k8s *

然后我们在客户端上新建目录:

mkdir -p /root/course/kubeadm/data

将 nfs 共享目录挂载到上面的目录:

mount -t nfs 192.168.3.131:/data/k8s /root/course/kubeadm/data

挂载成功后,在客户端上面的目录中新建一个文件,然后我们观察下 nfs 服务端的共享目录下面是否也会出现该文件:

touch /root/course/kubeadm/data/test.txt

然后在 nfs 服务端查看(注意是服务端哦,我这里是master节点 192.168.3.131):

[[email protected] /]# ls -ls /data/k8s/
总用量 0
0 -rw-r--r--. 1 root root 0 8月  10 23:10 test.txt

如果上面出现了 test.txt 的文件,那么证明我们的 nfs 挂载成功了。

(2)PV

有了上面的 NFS 共享存储,下面我们就可以来使用 PV 和 PVC 了。PV 作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略等关键信息,下面我们来新建一个 PV 对象,使用 nfs 类型的后端存储,1G 的存储空间,访问模式为 ReadWriteOnce,回收策略为 Recyle,对应的 YAML 文件如下:(pv1-demo.yaml)

apiVersion: v1
kind: PersistentVolume
metadata:
  name:  pv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /data/k8s
    server: 192.168.3.131

Kubernetes 支持的 PV 类型有很多,比如常见的 Ceph、GlusterFs、NFS,甚至 HostPath也可以,不过 HostPath 我们之前也说过仅仅可以用于单机测试,更多的支持类型可以前往 Kubernetes PV 官方文档进行查看,因为每种存储类型都有各自的特点,所以我们在使用的时候可以去查看相应的文档来设置对应的参数。

然后同样的,直接使用 kubectl 创建即可:

[[email protected] pv]# kubectl create -f pv1-demo.yaml
persistentvolume/pv1 created
[[email protected] pv]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    1Gi        RWO            Recycle          Available                                   8s

我们可以看到 pv1 已经创建成功了,状态是 Available,表示 pv1 就绪,可以被 PVC 申请。我们来分别对上面的属性进行一些解读。

Capacity(存储能力)

一般来说,一个 PV 对象都要指定一个存储能力,通过 PV 的 capacity属性来设置的,目前只支持存储空间的设置,就是我们这里的 storage=1Gi,不过未来可能会加入 IOPS、吞吐量等指标的配置。

AccessModes(访问模式)

AccessModes 是用来对 PV 进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:

  • ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载
  • ReadOnlyMany(ROX):只读权限,可以被多个节点挂载
  • ReadWriteMany(RWX):读写权限,可以被多个节点挂载

注意:一些 PV 可能支持多种访问模式,但是在挂载的时候只能使用一种访问模式,多种访问模式是不会生效的。

persistentVolumeReclaimPolicy(回收策略)

我这里指定的 PV 的回收策略为 Recycle,目前 PV 支持的策略有三种:

  • Retain(保留)- 保留数据,需要管理员手工清理数据
  • Recycle(回收)- 清除 PV 中的数据,效果相当于执行 rm -rf /thevoluem/*
  • Delete(删除)- 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务,比如 ASW EBS。

不过需要注意的是,目前只有 NFS 和 HostPath 两种类型支持回收策略。当然一般来说还是设置为 Retain 这种策略保险一点。

状态

一个 PV 的生命周期中,可能会处于4中不同的阶段:

  • Available(可用):表示可用状态,还未被任何 PVC 绑定
  • Bound(已绑定):表示 PV 已经被 PVC 绑定
  • Released(已释放):PVC 被删除,但是资源还未被集群重新声明
  • Failed(失败): 表示该 PV 的自动回收失败

我们平时真正使用的资源其实是 PVC,就类似于我们的服务是通过 Pod 来运行的,而不是 Node,只是 Pod 跑在 Node 上而已,所以接下来我们就来给大家讲解下 PVC 的使用方法。

(2)PVC

(我们需要在所有节点安装 nfs 客户端程序,安装方法和上面的安装方法一样的。必须在所有节点都安装 nfs 客户端,否则可能会导致 PV 挂载不上的问题)

新建 PVC

同样的,我们来新建一个数据卷声明,我们来请求 1Gi 的存储容量,访问模式也是 ReadWriteOnce,YAML 文件如下:(pvc-nfs.yaml)

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-nfs
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

我们可以看到我们这里的声明方法几乎和新建 PV 是一样的,在新建 PVC 之前,我们可以看下之前创建的 PV 的状态:

[[email protected] pvc]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    1Gi        RWO            Recycle          Available                                   9m18s

我们可以看到当前 pv-nfs 是在 Available 的一个状态,所以这个时候我们的 PVC 可以和这个 PV 进行绑定:

[[email protected] pvc]# kubectl create -f pvc-nfs.yaml
persistentvolumeclaim/pvc-nfs created
[[email protected] pvc]# kubectl get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-nfs   Bound    pv1      1Gi        RWO                           13s

我们可以看到 pvc-nfs 创建成功了,状态是 Bound 状态了,这个时候我们再看下 PV 的状态呢:

[[email protected] pvc]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pv1    1Gi        RWO            Recycle          Bound    default/pvc-nfs                           10m

同样我们可以看到 PV 也是 Bound 状态了,对应的声明是 default/pvc-nfs,就是 default 命名空间下面的 pvc-nfs,证明我们刚刚新建的 pvc-nfs 和我们的 pv-nfs 绑定成功了。

有的同学可能会觉得很奇怪,我们并没有在 pvc-nfs 中指定关于 pv 的什么标志,它们之间是怎么就关联起来了的呢?其实这是系统自动帮我们去匹配的,他会根据我们的声明要求去查找处于 Available 状态的 PV,如果没有找到的话那么我们的 PVC 就会一直处于 Pending 状态,找到了的话当然就会把当前的 PVC 和目标 PV 进行绑定,这个时候状态就会变成 Bound 状态了。

使用 PVC

上面我们已经知道怎么创建 PV 和 PVC 了,现在我们就来使用下我们的 PVC,这里我们使用 nginx 的镜像来测试下:(nfs-pvc-deploy.yaml)

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nfs-pvc
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nfs-pvc
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
      volumes:
      - name: www
        persistentVolumeClaim:
          claimName: pvc-nfs

---

apiVersion: v1
kind: Service
metadata:
  name: nfs-pvc
  labels:
    app: nfs-pvc
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: web
  selector:
    app: nfs-pvc

我们这里使用 nginx 镜像,将容器的 /usr/share/nginx/html 目录通过 volume 挂载到名为 pvc2-nfs 的 PVC 上面,然后创建一个 NodePort 类型的 Service 来暴露服务:

[[email protected] pvc]# kubectl create -f nfs-pvc-deploy.yaml
deployment.extensions/nfs-pvc created
service/nfs-pvc created
[[email protected] pvc]# kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
nfs-pvc-69f44b5958-92pp6        1/1     Running   0          12s
nfs-pvc-69f44b5958-cclhm        1/1     Running   0          12s
nfs-pvc-69f44b5958-kjzbr        1/1     Running   0          12s
[[email protected] pvc]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nfs-pvc      NodePort    10.105.217.108   <none>        80:30220/TCP   32s

然后我们就可以通过任意节点的 IP:30220端口来访问我们这里的 Nginx 服务了,但是这个时候我们来访问会出现403,这是为什么?我们再去看看 nfs 共享数据目录下面有没有数据呢?

我们发现并没有任何数据,这是因为我们把容器目录/user/share/nginx/html和挂载到了pvc-nfs这个 PVC 上面,这个 PVC 就是对应着我们上面的 nfs 的共享数据目录的,该目录下面还没有任何数据,所以我们访问就出现了403,现在我们在/data/k8s这个目录下面新建一个 index.html 的文件:

[[email protected] pvc]# echo "<h1>Hello Kubernetes~</h1>" >> /data/k8s/index.html
[[email protected] pvc]# ls /data/k8s
index.html  test.txt

我们可以看到共享数据目录中已经有一个 index.html 的文件了,由于我们挂载了 pvc-nfs 到上面的 nginx 容器中去,是不是这个时候容器目录/user/share/nginx/html下面也有index.html这个文件了啊?所以这个时候我们再来访问下服务,任一节点IP:30220

现在是不是正常了啊,但是我们可以看到我们容器中的数据是直接放到共享数据目录根目录下面的,如果以后我们又有一个新的 nginx 容器也做了数据目录的挂载,是不是就会有冲突了啊,所以这个时候就不太好区分了,这个时候我们可以在 Pod 中使用一个新的属性:subPath,该属性可以来解决这个问题,我们只需要更改上面的 Pod 的 YAML 文件即可:

...
volumeMounts:
- name: www
  subPath: nginxpvc-test
  mountPath: /usr/share/nginx/html
...

更改完 YAML 文件后,我们重新更新即可:

[[email protected] pvc]# kubectl apply -f nfs-pvc-deploy.yaml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
deployment.extensions/nfs-pvc configured
service/nfs-pvc unchanged

更新完后,我们再去看看 nfs 的数据共享目录:

[[email protected] pvc]# ls /data/k8s/
index.html  nginxpvc-test  test.txt
[[email protected] pvc]# ls /data/k8s/nginxpvc-test/

我们可以预想到现在我们访问上面的服务,又会得到403的结果,因为nginxpvc-test目录下面还没有任何文件。

我们把根目录下面的 index.html 文件一到到 nginxpvc-test 目录下便又可以访问了:

到这里我们就算完整的使用了一次 PVC 了,现在我们再来验证下我们的数据是否会丢失,怎么验证?首先我们把上面的 Deployment 删除掉,这样是不是他下面管理的3个 Pod 也会被一起删除掉啊:

[[email protected] pvc]# kubectl delete deployment nfs-pvc
deployment.extensions "nfs-pvc" deleted

Deployment 被删除掉了,但是 nfs 的数据共享目录下面的数据呢?

[[email protected] pvc]# ls /data/k8s/nginxpvc-test/
index.html

还在吧?当然了如果不在了,我们用他就没有任何意义了吧,现在我们再来重新创建上面的 Deployment,看看访问服务还能得到上面的正常输出结果吗:

[[email protected] pvc]# kubectl create -f nfs-pvc-deploy.yaml
deployment.extensions/nfs-pvc created
Error from server (AlreadyExists): error when creating "nfs-pvc-deploy.yaml": services "nfs-pvc" already exists

可以看到 nfs-pvc 这个 Deployment 创建成功了,由于 Service 我们之前没有删除掉,所以这里提示已经存在,我们忽略就可以了,现在同样我们用任一节点 IP:30220来访问我们这里的服务,是不是依然可以在页面上看到Hello Kubernetes~这里的输出信息啊,这证明我们的数据持久化是成功的吧

原文地址:https://www.cnblogs.com/weiBlog/p/11333345.html

时间: 2024-10-28 10:10:04

Kubernetes 系列(六):持久化存储 PV与PVC(一)的相关文章

使用Ceph集群作为Kubernetes的动态分配持久化存储

使用Docker快速部署Ceph集群 , 然后使用这个Ceph集群作为Kubernetes的动态分配持久化存储. Kubernetes集群要使用Ceph集群需要在每个Kubernetes节点上安装ceph-common

2个Kubernetes使用同一个Ceph存储达到Kubernetes间持久化数据迁移

2个Kubernetes使用同一个Ceph存储达到Kubernetes间持久化数据迁移 [TOC] 当前最新Kubernetes稳定版为1.14.现在为止,还没有不同Kubernetes间持久化存储迁移的方案.但根据Kubernetes pv/pvc绑定流程和原理,只要 "存储"-->"PV"-->"PVC" 的绑定关系相同,即可保证不同间Kubernetes可挂载相同的存储,并且里面是相同数据. 1. 环境 原来我的Kubernet

kubernetes持久化存储,静态存储【pv】,动态存储【StorageClass】(5)

在开始介绍k8s持久化存储前,我们有必要了解一下k8s的emptydir和hostpath.configmap以及secret的机制和用途 1.EmptydirEmptyDir是一个空目录,他的生命周期和所属的 Pod 是完全一致的,pod删掉目录消失 2.HostpathHostpath会把宿主机上的指定卷加载到容器之中,如果 Pod 发生跨主机的重建,其内容就难保证了 3.ConfigmapConfigMap跟Secrets类似,但是ConfigMap可以更方便的处理不包含敏感信息的字符串.

Kubernetes 系列(七):持久化存储StorageClass

前面的课程中我们学习了 PV 和 PVC 的使用方法,但是前面的 PV 都是静态的,什么意思?就是我要使用的一个 PVC 的话就必须手动去创建一个 PV,我们也说过这种方式在很大程度上并不能满足我们的需求,比如我们有一个应用需要对存储的并发度要求比较高,而另外一个应用对读写速度又要求比较高,特别是对于 StatefulSet 类型的应用简单的来使用静态的 PV 就很不合适了,这种情况下我们就需要用到动态 PV,也就是我们今天要讲解的 StorageClass. 创建 Provisioner 要使

k8s存储数据持久化,emptyDir,hostPath,基于Nfs服务的PV,PVC

在docker和K8S中都存在容器是有生命周期的,因此数据卷可以实现数据持久化. 数据卷解决的主要问题: 1.数据持久性:当我们写入数据时,文件都是暂时性的存在,当容器崩溃后,host就会将这个容器杀死,然后重新从镜像创建容器,数据就会丢失. 2.数据共享:在同一个Pod中运行容器,会存在共享文件的需求. 数据卷的类型: 1.emptyDiremptyDir数据卷类似于docker数据持久化的docker manager volume,该数据卷初分配时,是一个空目录,同一个Pod中的容器可以对该

Kubernetes中的PV和PVC是啥

引入了一组叫作Persistent Volume Claim(PVC)和Persistent Volume(PV)的API对象,大大降低了用户声明和使用持久化Volume的门槛. 在Pod的Volumes中,只要声明类型是persistentVolumeClaim,指定PVC的名字,当创建这个PVC对象,k8s就自动为它绑定一个符合条件的Volume,这个Volume,从PV来 PVC和PV的设计,类似"接口"和"实现"的思想,开发者只知道使用"接口&qu

k8s数据持久化之statefulset的数据持久化,并自动创建PV与PVC

一:Statefulset StatefulSet是为了解决有状态服务的问题,对应的Deployment和ReplicaSet是为了无状态服务而设计,其应用场景包括:1.稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现2.稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现3.有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依

Kubernetes 中的pv和pvc

原文地址:http://www.cnblogs.com/leidaxia/p/6485646.html 持久卷 PersistentVolumes 本文描述了 Kubernetes 中的 PersistentVolumes.要求读者有对卷 (volumes) 所有了解. 简介 存储管理跟计算管理是两个不同的问题.PersistentVolume 子系统,对存储的供应和使用做了抽象,以 API 形式提供给管理员和用户使用.要完成这一任务,我们引入了两个新的 API 资源:PersistentVol

Longhorn:实现Kubernetes集群的持久化存储

Longhorn项目是Rancher Labs推出的开源的基于云和容器部署的分布式块存储新方式.Longhorn遵循微服务的原则,利用容器将小型独立组件构建为分布式块存储,并使用容器编排来协调这些组件,形成弹性分布式系统. 自2017年4月Longhorn项目发布以来,人们对在Kubernetes集群上运行Longhorn存储就产生了极大的兴趣.近日,Longhorn v0.2版本发布了,它可支持任何Kubernetes集群的持久化存储实现! Why Longhorn 如今,基于云和容器的部署规