k8s-数据持久化存储卷,nfs,pv/pvc,StorageClass

数据持久化-储存卷

	我们知道,Pod是由容器组成的,而容器宕机或停止之后,数据就随之丢了,那么这也就意味着我们在做Kubernetes集群的时候就不得不考虑存储的问题,而存储卷就是为了Pod保存数据而生的。存储卷的类型有很多,我们常用到一般有四种:emptyDir,hostPath,NFS以及云存储(ceph, glasterfs...)等。

官方文档

https://kubernetes.io/zh/docs/concepts/storage/volumes/#emptydir

https://kubernetes.io/zh/docs/concepts/storage/volumes/#hostpath

存储卷类型

emptyDir,hostPath,NFS以及云存储(ceph, glasterfs...)等。

1.emptyDir

		emptyDir类型的volume在pod分配到node上时被创建,kubernetes会在node上自动分配一个目录,因此无需指定宿主机node上对应的目录文件。这个目录的初始内容为空,当Pod从node上移除时,emptyDir中的数据会被永久删除。
emptyDir Volume主要用于某些应用程序无需永久保存的临时目录.
作用:
1.用于容器间分享文件   
2.用于创建临时目录
注:emptyDir不能够用来做数据持久化

例子1:

kind: Deployment
apiVersion: apps/v1
metadata:
  name: emptydir
spec:
  selector:
    matchLabels:
      app: emptydir
  template:
    metadata:
      labels:
        app: emptydir
    spec:
      containers:
        - name: nginx
          image: nginx
          volumeMounts:  ## 挂载
            - mountPath: /usr/share/nginx/nginx  ## 挂在目录
              name: test-emptydir  # 存储卷名称
      volumes: ## 创建存储卷
        - name: test-emptydir # 创建存储卷名称
          emptyDir: {}

2.hostpath

https://kubernetes.io/zh/docs/concepts/storage/volumes/#hostpath

警告:
HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath。 当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。

如果通过 AdmissionPolicy 限制 HostPath 对特定目录的访问, 则必须要求 volumeMounts 使用 readOnly 挂载以使策略生效。

hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。

例如,hostPath 的一些用法有:

  • 运行一个需要访问 Docker 内部机制的容器;可使用 hostPath 挂载 /var/lib/docker 路径。
  • 在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys
  • 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。

除了必需的 path 属性之外,用户可以选择性地为 hostPath 卷指定 type

支持的 type 值如下:

取值 行为
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory 在给定路径上必须存在的目录。
FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File 在给定路径上必须存在的文件。
Socket 在给定路径上必须存在的 UNIX 套接字。
CharDevice 在给定路径上必须存在的字符设备。
BlockDevice 在给定路径上必须存在的块设备。

当使用这种类型的卷时要小心,因为:

  • HostPath 卷可能会暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字), 可用于容器逃逸或攻击集群的其他部分。

  • 具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同 而在不同节点上有不同的行为。

  • 下层主机上创建的文件或目录只能由 root 用户写入。你需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath

hostPath 配置示例:****

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # 宿主上目录位置
      path: /data
      # 此字段为可选
      type: Directory
      
注意: FileOrCreate 模式不会负责创建文件的父目录。 如果欲挂载的文件的父目录不存在,Pod 启动会失败。 为了确保这种模式能够工作,可以尝试把文件和它对应的目录分开挂载,如 FileOrCreate 配置 所示。

hostPath FileOrCreate 配置示例

apiVersion: v1
kind: Pod
metadata:
  name: test-webserver
spec:
  containers:
  - name: test-webserver
    image: k8s.gcr.io/test-webserver:latest
    volumeMounts:
    - mountPath: /var/local/aaa
      name: mydir
    - mountPath: /var/local/aaa/1.txt
      name: myfile
  volumes:
  - name: mydir
    hostPath:
      # 确保文件所在目录成功创建。
      path: /var/local/aaa
      type: DirectoryOrCreate
  - name: myfile
    hostPath:
      path: /var/local/aaa/1.txt
      type: FileOrCreate

3.pv/pvc(推荐使用)

nfs官方文档

nfs官方文档:https://kubernetes.io/zh/docs/concepts/storage/volumes/#nfs

作用

动态存储,网络存储。动态生成存储卷

安装测试nfs

1. 在所有节点上安装nfs(所有节点)
		yum -y install nfs-utils rpcbind
2.配置nfs
[root@sg-14 opt]# vi /etc/exports
/data/k8s  *(rw,sync,no_root_squash)  # 允许共享的ip和目录
/home/jeff  192.168.0.216(rw,sync,no_root_squash)  # 允许共享的ip和目录
/nfs/v1/  192.168.0.216(rw,no_root_squash)
/nfs/v2/  192.168.0.216(rw,no_root_squash)
/nfs/v3/  192.168.0.216(rw,no_root_squash)
/nfs/v4/  192.168.0.216(rw,no_root_squash)
/nfs/v5/  192.168.0.216(rw,no_root_squash)
/nfs/v6/  192.168.0.216(rw,no_root_squash)
/nfs/v7/  192.168.0.216(rw,no_root_squash)
/nfs/v8/  192.168.0.216(rw,no_root_squash)
/nfs/v9/  192.168.0.216(rw,no_root_squash)
/nfs/v10/ 192.168.0.216(rw,no_root_squash)


[root@sg-14 opt]# systemctl enable --now nfs
[root@sg-14 opt]# mkdir -pv /nfs/v{1..10}
[root@sg-14 opt]# cd /nfs/
[root@sg-14 opt]# systemctl restart rpcbind.service && systemctl restart nfs.service
3.测试k8s使用nfs
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs
spec:
  selector:
    matchLabels:
      app: nfs
  template:
    metadata:
      labels:
        app: nfs
    spec:
      nodeName: sg-16  # 指定部署机器
      containers:
        - name: nginx
          image: nginx
          volumeMounts:  # 挂载容器内部目录
            - mountPath: /home/test
              name: nfs
      volumes: ## 存储卷
        - name: nfs
          nfs:
            path: /nfs/v1  # master上目录
            server: 192.168.0.214  # master机器ip
    
4. 使用pv/pvc来管理nfs
#########################################################################################
#  1、部署MySQL集群
#     1、创建命名空间
#     2、创建service提供负载均衡
#     3、使用控制器部署MySQL实例
###
#  2、部署Discuz应用
#     1、创建命名空间
#     2、创建Service提供负载均衡(Headless Service)
#     3、创建服务并挂载代码
#     4、创建Ingress,用于域名转发(https)
###
#  3、服务之间的互连
#     1、Discuz连接MySQL  --->  mysql.mysql.svc.cluster.local
#########################################################################################

pv/pvc管理nfs

官方文档

https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/#reclaim-policy

pv/pvc解释

注:pv是集群级资源,pvc是名称空间级资源

PVC和PV的设计,类似“接口”和“实现”的思想,开发者只知道使用“接口”PVC,运维人员负责给“接口”绑定具体的实现PV,说白了PVC就是一种特殊的Volume存储卷
PVC和PV的实现原理
PVC:描述 Pod想要使用的持久化属性,比如存储大小、读写权限等
PV:描述一个具体的Volume属性,比如Volume的类型、挂载目录、远程存储服务器地址等

1. PV 的访问模式(accessModes)

模式 解释
ReadWriteOnce(RWO) 可读可写,但只支持被单个节点挂载。
ReadOnlyMany(ROX) 只读,可以被多个节点挂载。
ReadWriteMany(RWX) 多路可读可写。这种存储可以以读写的方式被多个节点共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在 PVC 绑定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。

2. PV 的回收策略(persistentVolumeReclaimPolicy)

策略 解释
Retain 不清理, 保留 Volume(需要手动清理)
Recycle 删除数据,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支持)
Delete 删除存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)

3. PV 的状态

状态 解释
Available 可用。
Bound 已经分配给 PVC。
Released PVC 解绑但还未执行回收策略。
Failed 发生错误。

4.创建pv

kind: PersistentVolume
apiVersion: v1
metadata:
  name: pv001
  labels:
    app: pv001
spec:
  nfs:
    path: /nfs/v2  # master机器共享目录
    server: 192.168.0.214  # master机器
  capacity:
    storage: 20Gi  # 指定存储卷大小
  persistentVolumeReclaimPolicy: Retain  # 回收策略
  accessModes: # 访问模式,支持缩写
    - "ReadWriteMany"
    - "ReadWriteOnce"
    
kubectl apply -f pv.yaml
[root@sg-14 nfs]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv001   20Gi       RWO,RWX        Retain           Available                                   7s

STATUS状态:无

5.pvc插件

官方文档

https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/#access-modes

pvc使用pv-创建pvc

---
# 创建pv
kind: PersistentVolume
apiVersion: v1
metadata:
  name: pv001
  labels:
    app: pv001
spec:
  nfs:
    path: /nfs/v2  # master机器共享目录
    server: 192.168.0.214  # master机器
  capacity:
    storage: 20Gi  # 指定存储卷大小
  persistentVolumeReclaimPolicy: Retain  # 回收策略
  accessModes: # 访问模式,支持缩写
    - "ReadWriteMany"
    - "ReadWriteOnce"
---
# 创建名称空间
apiVersion: v1
kind: Namespace
metadata:
  name: mysql 
  labels:
    app: test-Namespace
---
# 创建pvc存储卷
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1  # 存储卷名字
  namespace: mysql # 指定名称空间,pvc是名称空间级资源
spec:
  accessModes:  # 访问模式
    - "ReadWriteMany"
  resources:
    requests:
      storage: "6Gi"
      
kubectl apply -f pvc.yaml
[root@sg-14 nfs]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   REASON   AGE
pv001   20Gi       RWO,RWX        Retain           Bound    default/pvc1                           47m

[root@sg-14 nfs]# kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc1   Bound    pv001    20Gi       RWO,RWX                       2m22s

状态:Bound CLAIM:default/pvc1

pv-pvc.yaml 使用nfs

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pv-pvc-mysql
  namespace: mysql # 指定名称空间
spec:
  replicas: 3 # 部署个数
  selector:
    matchLabels:
      app: pv-pvc
  template:
    metadata:
      labels:
        app: pv-pvc
    spec:
      containers:
        - name: mysql
          image: mysql:5.7 
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
          volumeMounts:  # 挂载容器内部目录
            - mountPath: /var/lib/mysql
              name: pv-pvc
      volumes: ## 存储卷master
        - name: pv-pvc
          persistentVolumeClaim:
            claimName: pvc1  # 指定存储卷名字
            
kubectl apply -f pv-pvc.yaml
此时:所有的容器/var/lib/mysql目录和master的/nfs/v2实现共享


kubectl exec -it npv-pvc-f76d748dd-ps7rs -- bash  # 进入容器
mysql -u root -p # 登陆数据库

4.StorageClass

​ 在一个大规模的Kubernetes集群里,可能有成千上万个PVC,这就意味着运维人员必须实现创建出这个多个PV,此外,随着项目的需要,会有新的PVC不断被提交,那么运维人员就需要不断的添加新的,满足要求的PV,否则新的Pod就会因为PVC绑定不到PV而导致创建失败。而且通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,kubernetes根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。

4.1定义StorageClass

​ 每一个存储类都包含provisioner、parameters和reclaimPolicy这三个参数域,当一个属于某个类的PersistentVolume需要被动态提供时,将会使用上述的参数域。

# 下载helm
wget https://get.helm.sh/helm-v3.3.4-linux-amd64.tar.gz

# 解压
tar xf helm-v3.3.4-linux-amd64.tar.gz
# 安装
mv linux-amd64/helm /usr/local/bin/

# 验证
helm version

# 添加阿里云镜像仓库
helm repo add ali-stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

# 添加官方仓库
helm repo add stable https://kubernetes-charts.storage.googleapis.com/

# 添加微软云helm仓库
helm repo add azure http://mirror.azure.cn/kubernetes/charts/

# 下载nfs
helm pull ckotzbauer/nfs-client-provisioner

### 解压
[root@k8s-m-01 /opt]# tar -xf nfs-client-provisioner-1.0.2.tgz 

### 修改values.yaml
[root@k8s-m-01 /opt]# cd nfs-client-provisioner/
[root@k8s-m-01 /opt/nfs-client-provisioner]# vim values.yaml 
nfs:
  server: 192.168.0.214
  path: /nfs/v6 
storageClass:
  accessModes: ReadWriteMany  ## 修改访问类型
  reclaimPolicy: Retain  ## 修改回收策略

### 安装nfs-client
[root@k8s-m-01 /opt/nfs-client-provisioner]# helm install nfs-client ./
NAME: nfs-client
LAST DEPLOYED: Wed Dec  8 11:38:02 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

[root@sg-14 nfs-client-provisioner]# kubectl get sc

案例:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  namespace: default
  name: test-nfs
  labels:
    app: test-nfs
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nfs-client
  resources:
    requests:
      storage: 8Gi
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: test-nfs-storageclass
  namespace: default
  labels:
    app: test-nfs
spec:
  selector:
    matchLabels:
      app: test-nfs
  template:
    metadata:
      labels:
        app: test-nfs
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: test-nfs
      volumes:
        - name: test-nfs
          persistentVolumeClaim:
            claimName: test-nfs

posted @ 2021-12-01 17:38  Jeff的技术栈  阅读(1082)  评论(0编辑  收藏  举报
回顶部