K8S上篇我们说了简单的配置以及临时存储

但是在实际生产中,如果有使用磁盘的需求,那么不太可能使用hostPath或者emptyDir,毕竟不是完全的持久化,在Pod死亡后也一同死亡了

这个时候,Volume的持久化就相当重要了

这种时候,对于持久化的卷,就可以考虑使用NFS GlusterFs 云厂商提供的块存储

那么我们先拿如何挂载NFS来看

对于NFS在宿主机的安装,我们稍微一说

# 在任意机器

yum install -y nfs-utils

# 执行以下命令,启动 nfs 服务;创建共享目录

mkdir -p /nfs/data

#执行命令 vi /etc/exports,创建 exports 文件,文件内容如下:

echo “/nfs/data/ *(insecure,rw,sync,no_root_squash)” > /etc/exports

#/nfs/data  172.26.248.0/20(rw,no_root_squash)

systemctl enable rpcbind

systemctl enable nfs-server

systemctl start rpcbind

systemctl start nfs-server

exportfs -r

#检查配置是否生效

exportfs

# 输出结果如下所示

/nfs/data /nfs/data

之后就创建了一个NFS的Server

如果是想使用这个NFS,可以考虑配置一个NFS的Client

#服务器端防火墙开放111、662、875、892、2049的 tcp / udp 允许,否则远端客户无法连接。

#安装客户端工具

yum install -y nfs-utils

#执行以下命令检查 nfs 服务器端是否有设置共享目录

# showmount -e $(nfs服务器的IP)

showmount -e 172.26.165.243

# 输出结果如下所示

Export list for 172.26.165.243

/nfs/data *

#执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount

mkdir /root/nfsmount

# mount -t nfs $(nfs服务器的IP):/root/nfs_root /root/nfsmount

#高可用备份的方式

mount -t nfs 172.26.165.243:/nfs/data /root/nfsmount

# 写入一个测试文件

echo “hello nfs server” > /root/nfsmount/test.txt

#在 nfs 服务器上执行以下命令,验证文件写入成功

cat /root/nfsmount/test.txt

然后是在K8S上关于NFS的挂载使用

一个Pod的yaml如下

#测试Pod直接挂载NFS了

apiVersion: v1

kind: Pod

metadata:

name: vol-nfs

namespace: default

spec:

containers:

– name: myapp

image: nginx

volumeMounts:

– name: html

mountPath: /usr/share/nginx/html/

volumes:

– name: html

nfs:

path: /nfs/data   #1000G

server: 自己的nfs服务器地址

需要注意,需要在集群上每一台服务器都安装nfs-client,从而可以mount对应的远端nfs存储到本地

其次是我们在其中的volumes声明了挂载的nfs路径,这个路径要求必须要在nfs文件夹下创建好了

比如

Nfs:

Path: ./nfs/data/nginx

这个nginx文件夹就需要创建好

从上面的nfs-client和nfs path中,就暴露了直接挂载的缺点,需要的准备工作不少

那么为了消除这个弱点,K8S提供了PV PVC StorageClass

PV是PersistentVolume 持久卷

集群中的一块存储,记录了存储背后的实现细节

PVC PersistentVolumeClain PVC

是Pod等对象对存储的请求

规定了请求的大小和请求的模式,诸如ReadWriteOnce ReadOnlyMany

StorageClass 存储累

将不同的PVC抽象成一个对象,更加抽象PVC和PV

我们将上面的手动挂载流程,套用到PV – PVC -StorageClass这个模板

首先我们创建一个PV,并且声明StorageClass

apiVersion: v1

kind: PersistentVolume

metadata:

name: pv-volume-10m

labels:

type: local

spec:

storageClassName: my-nfs-storage

capacity:

storage: 100m

accessModes:

– ReadWriteOnce

nfs:  ## 使用nfs存储系统

server: 10.170.11.8  ## 没type

path: /nfs/data/haha  ### abc文件夹提前创建

这样就会创建一个容量为100mb,模式为可读写,使用nfs,storageClass为my-nfs-storage的PV

其次是声明一个PVC绑定这个pv

并且寻一个Pod去使用这个PVC

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

name: nginx-pvc

namespace: default

labels:

app: nginx-pvc

spec:

storageClassName: my-nfs-storage  ## 存储类的名字

accessModes:

– ReadWriteOnce

resources:

requests:

storage: 50m

声明了一个PVC的请求,要求的storageClassName必须要和PV一致

这样K8S就会在storageClass中挑选最为合适的进行绑定

之后的Pod书写中加上一个volumes为PVC类型的和下面的PVC名称一致即可使用了

apiVersion: v1

kind: Pod

metadata:

name: “nginx-pvc”

namespace: default

labels:

app: “nginx-pvc”

spec:

containers:

– name: nginx-pvc

image: “nginx”

ports:

– containerPort:  80

name:  http

volumeMounts:

– name: localtime

mountPath: /etc/localtime

– name: html

mountPath: /usr/share/nginx/html

volumes:

– name: localtime

hostPath:

path: /usr/share/zoneinfo/Asia/Shanghai

– name: html

persistentVolumeClaim:

claimName:  nginx-pvc  ### 你的申请书的名字

restartPolicy: Always

官方文档连接为:

https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-persistent-volume-storage/

其次是关于PV和PVC中一些原生的配置项

分别关于了回收的策略和访问模式

在之前,我们可以在get pv的时候看到pv的状态栏中有一个RECLAIM POLICY

默认是Retain

这个设置表示的手动回收

其次的状态还有一个Status,在没有和PVC进行绑定之前,状态是Available

绑定之后就是Bound

在删除PVC之后,如果回收的策略是Retain,则不会删除这个PV,而是将PV的Status标记为Release

并且将PV中的数据保存

其次,如果标记为Recycle,那么就是删除PV内部的数据,再次变为可用

还有一个是Delete,就是在删除PVC的时候,PV一同删除

对于不同的PV实现,支持的也不同

目前,仅 NFS 和 HostPath 支持回收(Recycle)。 AWS EBS、GCE PD、Azure Disk 和 Cinder 卷都支持删除(Delete)。

典型测试的Yaml如下:

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

name: pv-12-recycle

namespace: default

labels:

app: pv-12-recycle

spec:

storageClassName: my-nfs-storage  ### pv分组

accessModes:

– ReadWriteOnce

resources:

requests:

storage: 12m

apiVersion: v1

kind: PersistentVolume

metadata:

name: pv-volume-12m-recycle

labels:

type: local

spec:

persistentVolumeReclaimPolicy: Recycle  ## 回收

storageClassName: my-nfs-storage

capacity:

storage: 12m

accessModes:

– ReadWriteOnce

nfs:  ## 使用nfs存储系统

server: 10.170.11.8  ## 没type

path: /nfs/data/recycle  ### abc文件夹提前创建

我们将回收的策略persistentVolumeReclaimPolicy标记为了Recycle

如果将绑定的PVC删除后,这个PV会从Bound状态变为Available

而如果标记Retain,那么则是显示为Release,表示之前和哪个PVC绑定,方便管理员去手动的进行释放,如果想要复用,可以考虑创建新的PV卷

Status的状态有

Released pv释放,释放了和PVC的关联,但其他的PVC并不能重新绑定上来

Available pv可用,可以和任意的pvc进行绑定

Bound 已经绑定

Failed 卷的自动回收操作失败了

然后是访问模式

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

分为了

ReadWriteOnce 供一个节点进行读写挂载

ReadOnlyMany 供多个节点只读挂载

ReadWriteMany 供多个节点进行读写瓜子啊

ReadWriteOncePod 供一个Pod以读写进行挂载

还有这一些缩写形式

RWO – ReadWriteOnce

ROX – ReadOnlyMany

RWX – ReadWriteMany

RWOP – ReadWriteOncePod

官方文档上还有这不同的type的Volume对于读写模式的支持

最后是关于PV中的动态供应

因为从上面的PV和PVC的书写方式来看

需要运维人员提前创建好不同的PV,由K8S进行负责绑定

这样的处理相当繁杂,不可能有一万个PVC就要手动创建一万个PV

于是K8S提供了动态供应

图片

上面的中我们假设有HDD SDD等存储阵列

而一个PVC被创建出来了,根据填充的storageClass字段

来选择对应的storageClass进行匹配,而选择的StorageClass则是根据内部配置的供应商去动态的创建PV

详细的架构图如下

图片

开发人员创建PVC,选择对应StorageClass,StorageClass由集群管理员创建

内部有不同的供应商,来根据PVC来创建PV,并进行绑定

那么这个StorageClass的提供者是其中的一个字段

StorageClass的provisioner

我们看NFS提供的Provisioner如何书写

https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

这里面表示我们需要部署一个Deployment去管理提供商Pod

然后是对应的RBAC权限分配

apiVersion: apps/v1

kind: Deployment

metadata:

name: nfs-client-provisioner

labels:

app: nfs-client-provisioner

# replace with namespace where provisioner is deployed

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: gcr/nfs-subdir-external-provisioner:v4.0.2

# resources:

#    limits:

#      cpu: 10m

#    requests:

#      cpu: 10m

volumeMounts:

– name: nfs-client-root

mountPath: /persistentvolumes

env:

– name: PROVISIONER_NAME

value: k8s-sigs.io/nfs-subdir-external-provisioner

– name: NFS_SERVER

value: 10.170.11.8 ## 指定自己nfs服务器地址

– name: NFS_PATH

value: /nfs/data  ## nfs服务器共享的目录

volumes:

– name: nfs-client-root

nfs:

server: 10.170.11.8

path: /nfs/data

RBAC就暂时不贴上来了

需要注意的是,上面的image是很可能拉不下来的,需要注意换成私有源或者国内的源

下面的ENV中我们配置了相关的NFS-Server配置

Volumes中也配置了nfs的配置

然后需要配置一个StorageClass

apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

name: managed-nfs-storage

annotations:

storageclass.kubernetes.io/is-default-class: “true”

provisioner: k8s-sigs.io/nfs-subdir-external-provisioner

#provisioner指定一个供应商的名字。

#必须匹配 k8s-deployment 的 env PROVISIONER_NAME的值

parameters:

archiveOnDelete: “true”  ## 删除pv的时候,pv的内容是否要备份

#### 这里可以调整供应商能力。

需要注意,上面的provisioner中的值是要和provisioner中的对应ENV一致的

其次是annotaions中我们加上了注解storageclass.kubernetes.io/is-default-class: “true”

表示这个StorageClass是默认的Class

之后就可以申请PVC进行使用了

提供商会自动创建一个PV给PVC使用

默认的回收策略是delete

如果需要配置其他的回收策略,比如当其中有文件的时候进行备份,则可以进行设置日其他

图片

apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

name: nfs-client

provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment’s env PROVISIONER_NAME’

parameters:

pathPattern: “${.PVC.namespace}/${.PVC.annotations.nfs.io/storage-path}” # waits for nfs.io/storage-path annotation, if not specified will accept as empty string.

onDelete: delete

发表评论

邮箱地址不会被公开。 必填项已用*标注