Kubernetes 中存储使用介绍(PV、PVC和StorageClass)

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 在 Kubernetes 中的应用,都是以 Pod 的形式运行的,当我们要是在 Kubernetes 上运行一些需要存放数据的应用时,便需要关注应用存放的数据是否安全可靠。因为 Pod 是有生命周期的,那么也就是说当 Pod 被删除或重启后,Pod 里面所运行的数据也会随之消失。

Kubernetes 中存储使用介绍



一、基本介绍


1.Volume 类型

2.PV 和 PVC 绑定条件

3.StorageClass


二、使用介绍


1.创建 PV

2.创建 PVC

3.创建 StorageClass


一、基本介绍



在 Kubernetes 中的应用,都是以 Pod 的形式运行的,当我们要是在 Kubernetes 上运行一些需要存放数据的应用时,便需要关注应用存放的数据是否安全可靠。因为 Pod 是有生命周期的,那么也就是说当 Pod 被删除或重启后,Pod 里面所运行的数据也会随之消失。


因此,K8s 引入了 Volume(数据卷)的概念,使我们可以通过挂载的方式,将 Pod 内所需要存放的数据,挂载到宿主机的目录中。这样,我们便可以防止 Pod 内所运行的数据因为 Pod 的删除/重启而丢失。


1.Volume 类型


  • emptyDir:临时目录,用于 Pod 内多容器共享目录,并不适用于需要保存数据的应用,因为 emptyDir 和 Pod 的生命周期相同。
  • hostPath:主机目录,可以保证运行应用的数据不被丢失,但是需要将 Pod 每次都调度到同一台主机上。
  • nfs:共享目录,可以保证运行应用的数据不被丢失。


以上三种是较为常见的数据卷,同时,我们还可以通过配置 PV、PVC、StorageClass 来保证数据的持久化存储。


PV 的全称: PersistentVolume(持久化卷),是对底层共享存储的一种抽象,将共享存储定义为一种资源,它属于集群级别资源,不属于任何命名空间。PV 由管理员进行创建和配置,与共享存储的具体实现直接相关。


PVC 的全称: PersistentVolumeClaim(持久化卷声明),用来描述 Pod 对于 PV 存储的要求,以此来分配到合适的 PV 上。


Pod、PV、PVC 关系: 一个 Pod 可以挂载 n 个 PVC,同样一个 PVC 也可以给 n 个 Pod 提供服务。但是,一个 PVC 只能绑定一个 PV,一个 PV 只能对应一种后端存储。


image.png


2.PV 和 PVC 绑定条件


  1. PV 的存储大小和权限需要满足 PVC 所提供的要求;
  2. PV 和 PVC 的 StorageClassName 需要相同(如果没有指定 StorageClassName,则默认为空)


注意: 要是当我们创建的 Pod 挂载的 PVC 没有和 PV 绑定成功,那么 Pod 将会一直处于 Pending 状态。


3.StorageClass


Kubernetes 提供了一种能够自动管理 PV 的机制,叫做 StorageClass(可以说是 PV 的模板,能够自动的创建 PV)


二、使用介绍



准备工作:


[root@k8s-master01 ~]# yum -y install nfs-utils rpcbind
[root@k8s-master01 ~]# echo "/app *(rw,sync,no_root_squash)" > /etc/exports
[root@k8s-master01 ~]# mkdir /app
[root@k8s-master01 ~]# systemctl start rpcbind nfs


1.创建 PV


[root@k8s-master01 ~]# vim test-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs
spec:
  capacity:
    storage: 2Gi            # 存储容量为 2Gi
  accessModes:
  - ReadWriteOnce
  nfs:
    path: /app
    server: 192.168.1.1
[root@k8s-master01 ~]# kubectl create -f test-pv.yaml


image.png


Access Modes 访问模式:


image.png


  • 需要注意的是,accessModes 只能针对于块存储来做限制,‘像 NFS 这类的文件系统是支持这样配置的,但是限制不了。


Reclaim Policy 回收策略:


  • Delete(删除):当 PVC 被删除时,PV 同样会被删除。
  • Retain(保留):当 PVC 被删除时,PV 并不会被删除,需要手动进行删除。
  • Recycle(回收):当 PVC 被删除时,PV 上的数据也会随之删除,以便和新的 PVC 进行绑定(已被遗弃)


2.创建 PVC


1)创建


[root@k8s-master01 ~]# cat <<END > test-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
END
[root@k8s-master01 ~]# kubectl create -f test-pvc.yaml


  • 上面 PVC 的配置表示:希望被分配到一个具有 2Gi 空间的磁盘,并且只允许我一个 PVC 进行读写。


2)查看


[root@k8s-master01 ~]# kubectl get pv,pvc


image.png


PV,PVC 绑定状态:


image.png


3)创建 Pod


[root@k8s-master01 ~]# cat <<END > test-web.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-web
spec:
  containers:
  - name: nginx
    image: nginx:1.21.0
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    persistentVolumeClaim:
      claimName: test-pvc
END
[root@k8s-master01 ~]# kubectl create -f test-web.yaml


  • 这里需要注意,Pod 所运行在的主机,需要安装 nfs-utils 包,不然挂载 NFS 时会出现问题。


验证: 在挂载目录下创建个 index.html 文件,查看是否挂载成功(尽量不要挂载有用的目录,因为挂载后会进行覆盖)


[root@k8s-master01 ~]# echo "Hello" > /app/index.html


image.png


3.创建 StorageClass


1)创建 RBAC 授权文件


[root@k8s-master01 ~]# cat <<END > external-storage-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-clusterrole
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-clusterrole
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: default
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
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io
END
[root@k8s-master01 ~]# kubectl create -f external-storage-rbac.yaml


2)创建 Deployment 文件


[root@k8s-master01 ~]# cat <<END > external-storage-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  namespace: default
spec:
  replicas: 1
  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
          image: quay.io/external_storage/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: tianya/nfs
            - name: NFS_SERVER
              value: 192.168.1.1
            - name: NFS_PATH
              value: /app
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.1.1
            path: /app
END
[root@k8s-master01 ~]# kubectl create -f external-storage-deploy.yaml


3)创建 StorageClass 资源文件


[root@k8s-master01 ~]# cat <<END > external-storage-class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-storageclass
provisioner: tianya/nfs
END
[root@k8s-master01 ~]# kubectl create -f external-storage-class.yaml


  • 上面的 provisioner 配置要和 Deployment 里的 PROVISIONER_NAME 变量值相同。


4)验证


[root@k8s-master01 ~]# cat <<END > test-storage-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-storage-pvc
spec:
  storageclassName: nfs-client-storageclass
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 4Gi
END
[root@k8s-master01 ~]# cat <<END > test-storage-pvc.yaml


问题: 创建完 PVC 后,一直处于 Pending 状态,通过查看 PVC 信息发现,输出:waiting for a volume to be created, either by external provisioner "tianya/nfs" or manually created by system administrator 报错。


原因是因为: 在 Kubernetes 的 1.20 以上版本,默认禁用了 SelfLink 功能。但是由于 nfs-client-privisioner 服务需要依赖此功能。所以,需要在 apiserver 的配置文件中开启此功能。


[root@k8s-master01 ~]# vim /etc/systemd/system/kube-apiserver.service


  • 增加:--feature-gates=RemoveSelfLink=false 配置。


查看:


image.png


创建 Pod,并挂载新的 PVC 进行验证:


[root@k8s-master01 ~]# cat <<END > test-storage-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-web
spec:
  containers:
  - name: test-web
    image: nginx:1.21.0
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    persistentVolumeClaim:
      claimName: test-storage-pvc
END
[root@k8s-master01 ~]# kubectl create -f test-storage-pod.yaml   


image.png


  • 上面的 /app/default-test-storage-pvc-pvc-dcc38edd-72a5-4d50-8199-0d277c9ba3f9/ 是 StorageClass 自动创建的 PV 目录。


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3月前
|
JSON Kubernetes Shell
【Azure K8S | AKS】在不丢失文件/不影响POD运行的情况下增加PVC的大小
【Azure K8S | AKS】在不丢失文件/不影响POD运行的情况下增加PVC的大小
|
3月前
|
Kubernetes Shell Perl
【Azure K8S|AKS】进入AKS的POD中查看文件,例如PVC Volume Mounts使用情况
【Azure K8S|AKS】进入AKS的POD中查看文件,例如PVC Volume Mounts使用情况
|
3月前
|
存储 Kubernetes 容器
Kubernetes 存储选项:持久化卷与存储类
【8月更文第29天】随着容器化的普及,越来越多的应用程序需要持久化数据以保持状态信息。Kubernetes 提供了一套完整的解决方案来管理和配置持久化存储,包括持久卷 (Persistent Volume, PV)、持久卷声明 (Persistent Volume Claim, PVC) 和存储类 (StorageClass)。本文将详细介绍这些概念,并通过实际示例来演示如何在 Kubernetes 中配置存储。
288 1
|
3月前
|
存储 Kubernetes Go
【Azure K8S | AKS】在AKS集群中创建 PVC(PersistentVolumeClaim)和 PV(PersistentVolume) 示例
【Azure K8S | AKS】在AKS集群中创建 PVC(PersistentVolumeClaim)和 PV(PersistentVolume) 示例
|
2月前
|
存储 Kubernetes 测试技术
k8s使用pvc,pv,sc关联ceph集群
文章介绍了如何在Kubernetes中使用PersistentVolumeClaim (PVC)、PersistentVolume (PV) 和StorageClass (SC) 来关联Ceph集群,包括创建Ceph镜像、配置访问密钥、删除默认存储类、编写和应用资源清单、创建资源以及进行访问测试的步骤。同时,还提供了如何使用RBD动态存储类来关联Ceph集群的指南。
144 7
|
3月前
|
存储 Kubernetes 容器
k8s创建NFS动态存储
k8s创建NFS动态存储
|
23天前
|
JSON Kubernetes 容灾
ACK One应用分发上线:高效管理多集群应用
ACK One应用分发上线,主要介绍了新能力的使用场景
|
24天前
|
Kubernetes 持续交付 开发工具
ACK One GitOps:ApplicationSet UI简化多集群GitOps应用管理
ACK One GitOps新发布了多集群应用控制台,支持管理Argo CD ApplicationSet,提升大规模应用和集群的多集群GitOps应用分发管理体验。
|
1月前
|
Kubernetes Cloud Native 云计算
云原生之旅:Kubernetes 集群的搭建与实践
【8月更文挑战第67天】在云原生技术日益成为IT行业焦点的今天,掌握Kubernetes已成为每个软件工程师必备的技能。本文将通过浅显易懂的语言和实际代码示例,引导你从零开始搭建一个Kubernetes集群,并探索其核心概念。无论你是初学者还是希望巩固知识的开发者,这篇文章都将为你打开一扇通往云原生世界的大门。
122 17
|
1月前
|
Kubernetes 应用服务中间件 nginx
搭建Kubernetes v1.31.1服务器集群,采用Calico网络技术
在阿里云服务器上部署k8s集群,一、3台k8s服务器,1个Master节点,2个工作节点,采用Calico网络技术。二、部署nginx服务到k8s集群,并验证nginx服务运行状态。
471 1