Volume资源配置
# 存储卷资源介绍
# 存储卷介绍
由于Pod或Node是可能故障的,而故障会导致Pod的重构,也就会导致Pod内的数据被清除。所以对于需要持久存储的服务,就不应当将保存数据到Pod内,而是应该保存到Pod之外。
我们可以将数据存储到Node之内,但对于一个多Node的集群来说,我们应该将数据存储到网络共享存储之上,比如NFS服务。
# 存储卷分类
emptyDir (临时存储)
- Pod删除时,其中的临时数据也会被删除。临时数据可以存储到内存,也可以存储到硬盘。
hostPath (主机存储)
- 将数据存储到本地,Pod删除时,数据卷中保存的数据仍然保留在本地中。
网络存储
- 使用网络存储首先需要保证节点级可以正常使用目标网络存储服务。
- 传统网络存储如nfs、cifs、ISCSI等,分布式存储如glusterfs、rbd、cephfs等,云存储如EBS、AzureDisk等。
# pause容器
每个Pod都对应了一个pause容器,pause是每个Pod的底层基础容器。Pod中的容器都共享着其所属pause的网络名称空间和存储卷。
这也是Pod中的容器可以使用同一个网络名称空间、同样的存储卷的原因。
# 容器化应用配置方式
- 自定义命令行参数,containers.command、containers.args。
- 将配置文件直接写死进镜像,极不推荐,违背了容器的弹性特性。
- 环境变量传入配置(推荐),containers.env。需要通过entrypoint脚本来预处理环境变量,将环境变量的配置信息,写入配置文件中。
- 存储卷,将配置文件直接放在存储卷中,然后挂载到容器中应用程序的配置文件所在的路径。
# Volume存储卷使用
# 存储卷声明
# pod.spec.volumes <[]object>
- 用于定义容器中会用到的Pod的存储卷。
# volumes.name <string>
- 存储卷名(必选),用于使用时调用。
# volumes.emptyDir <object>
- 用于定义临时存储卷,定义Pod临时存储方式。
medium <string>
- 媒介类型,为空表示使用磁盘作为存储媒介(默认),Memory表示使用内存作为存储媒介。sizeLimit <string>
- 大小限制,限制磁盘或内存的使用大小。
# volumes.gitRepo <object>
- 用于定义Git仓库存储卷。
- 需要Pod的宿主机安装了git能够正常使用Git命令。
- 它是基于emptyDir工作的,它会将Git仓库中的数据下载到本地数据卷中。当Pod销毁时,其数据卷中的数据也会被销毁。
- 它是单向的,本地的修改不会同步到Git仓库中,且并非实时的,仓库数据以Pod启动时的仓库数据为准,不会更新,当然如果需要,可以使用辅助容器去同步。
directory <string>
- 目标目录,指定作为存储卷的仓库的目录,"." 表示仓库根目录。repository <string>
- 仓库URL(必选),指定作为存储卷的仓库URL。revision <string>
- 版本,指定作为存储卷的仓库的版本。
# volumes.hostPath <object>
定义主机路径存储卷。将Pod所在宿主机的文件系统目录作为存储卷,映射为Pod中容器的目录。Pod被删除时,存储卷也不会被删除,数据依然存在。
<string>
- 主机路径(必选),指定作为存储卷的宿主机的文件/目录路径,如果目标是软链接,则会跟随到真实路径。type <string>
- 存储卷类型DirectoryOrCreate
- 存储卷是一个目录,如果已存在则直接使用,如果不存在则创建它再使用。Directory
- 存储卷是一个目录,且必须已存在。FileOrCreate
- 存储卷是一个文件,如果已存在则直接使用,如果不存在则创建它再使用。File
- 存储卷是一个文件,且必须已存在。Socket
- 存储卷是一个Socket文件,且必须已存在。CharDevice
- 存储卷是一个字符设备文件,且必须已存在。BlockDevice
- 存储卷是一个块设备文件,且必须已存在。
# volumes.nfs <object>
用于NFS存储卷。
需要有一个NFS服务器。
yum install -y nfs-utils mkdir -p /nfs && echo "/nfs *(rw,sync)" > /etc/exports systemctl start nfs && systemctl enable nfs netstat -lntup | grep 2049
1
2
3
4需要Pod的宿主机能够正常挂载NFS类型文件系统,也就是需要可以正常使用mount -t nfs命令,安装nfs-utils即可。
server <string>
- NFS服务器(必选),指定NFS服务器的主机名或IP。path <string>
- NFS目录路径(必选),指定用于存储卷的NFS路径,例如"/data"目录就是挂载NFS存储卷中的"/data"目录。readOnly <boolean>
- 是否只读,指定NFS目录是否只读 (默认为读写,也就是False)。
# volumes.configMap <object>
- 定义configMap配置文件存储卷,这种存储卷如果引用的configMap配置发生变动,会同步映射到存储卷中来。
name <string>
- configMap资源名,指定将被引用为配置文件存储卷的configMap资源的名称。会将数据转化为文件,每个键值对为一个文件,键为文件名,值为文件内容。items <[]object>
- 指定要挂载的数据,用于只引用部分数据到数据卷,不指定则默认是configMap资源下的数据全都挂载。key <string>
- 键名(必选),指定要挂载的数据的键名。mode <integer>
- 文件权限,指定挂载的文件的权限。path <string>
- 文件路径,指定挂载的文件的路径,能够以数据卷的根为起始点,向下指定路径。但无法使用”..“指定到数据卷之外。
optional <boolean>
- 可选,指定Pod创建时configMap是否必须存在。
# volumes.secret <object>
- 定义secret存储卷。
# 存储卷挂载
# pod.spec.containers.volumeMounts <[]object>
- 用于指定挂载Pod中的存储卷到容器中,该配置无法在容器运行后动态更新。
# volumeMounts.name <string>
- 挂载的存储卷(必选),指定挂载用的存储卷名称。
# volumeMounts.mountPath <string>
- 目标挂载路径(必选),指定用于挂载的目标路径。
# 使用例子
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-html-volume
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-html-volume
nfs:
server: 192.168.10.100
path: /nfs/html
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 存储管理资源介绍
# 介绍
K8S的存储系统从基础到高级大致分为三个层次:Volume,PV(Persistent Volume)和动态存储供应。
直接在Pod配置中定义的存储卷就叫做Volume,Volume是Pod的附属品,它们之间属于一种静态绑定关系,我们无法单独创建一个Volume,因为它不是一个独立的K8S资源对象。
而**PV(Persistent Volume)是集群之中的一块网络存储,PV跟Volume类似,但独立于Pod之外是一个K8S资源对象,所以我们可以单独创建一个PV。它不和Pod直接发生关系,而是通过PVC(Persistent Volume Claim)**来实现动态绑定。Pod定义里指定的是PVC,然后PVC会根据Pod的要求自动绑定合适的PV给Pod使用。
PVC只有绑定了PV之后才能被Pod使用。K8S会不断地查看当前每一个PVC,是不是处于Bound状态。如果不是则会遍历所有PV,只要有合适的PV,就会将其进行绑定。
但随着集群规模变大,运维需要创建的PV将变得非常多,基本无法靠人工完成,此时就可能出现Pod因为PVC绑定不到PV而启动失败。为了解决这个问题,K8S提供了**动态存储供应(dynamic provisioning)**机制,来动态创建PV,这个机制的核心概念就是StorageClass。
PV、PVC让存储资源的使用变得可控,能够合理规划磁盘资源的使用,从而保障系统的稳定性、可靠性,不会出现磁盘使用超支的情况。StorageClass则用于自动化创建PV,减少人工的工作量。
# PV
PV是对K8S存储资源的抽象,一个PV对应一个存储卷,定义一个PV内容包括了存储类型、存储大小和访问模式等。PV一般由运维人员创建和配置,供容器申请使用。
# PVC
PVC用于描述对PV存储资源的一个申请,请求信息包含存储大小、访问模式等。创建PV后,Pod就可以通过PVC向PV申请磁盘空间了。类似于某个应用程序向操作系统申请1G的磁盘使用空间。
PVC 创建成功之后,Pod 就可以以挂载存储卷(Volume)的方式使用PVC的存储资源了。Pod在使用PVC时必须与PVC在同一个Namespace下。
# StorageClass
K8S有两种存储资源的供应模式:静态模式和动态模式,资源供应的最终目的就是将适合的PV与PVC绑定:
- 静态模式:管理员预先创建许多各种各样的PV,等待PVC申请使用。
- 动态模式:管理员无须预先创建PV,而是通过StorageClass自动完成PV的创建以及与PVC的绑定。
StorageClass就是动态模式,根据PVC的需求动态创建合适的PV资源,从而实现存储卷的按需创建。通过storageClass自动创建的PV会在对应的存储目录上创建一个PV用的目录,用来提供数据读写。
一般某个商业性的应用程序,会用到大量的Pod,如果每个Pod都需要使用存储资源,那么就需要人工时不时的去创建PV,这也是个麻烦事儿。解决方法就是使用动态模式:当Pod通过PVC申请存储资源时,直接通过StorageClass去动态的创建对应大小的PV,然后与PVC绑定,此时PV和PVC基本就是一对一的关系。
StorageClass资源对象的定义主要包括:名称、Provisioner、存储的相关参数配置、回收策略。StorageClass一旦被创建,则无法修改,只能删除重新创建。
# Provisioner
Provisioner是存储插件或者说存储驱动,比如NFS插件、CephFS插件等。在创建PVC时需要指定StorageClass,PVC选择到对应的StorageClass后,与其关联的Provisioner组件就会动态的创建PV资源。
PV和PVC的生命周期包括4个阶段:资源供应(Provisioning)、资源绑定(Binding)、资源使用(Using)、资源回收(Reclaiming)。而Provisioner就是用于进行资源供应的。
# 存储管理实践
# PV/PVC使用
# PV配置编写
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-html-pv
# 需要定义标签用于被PVC选择
labels:
pv: nfs-html-pv
spec:
# 声明PV卷大小
capacity:
storage: 1Gi
# 指定访问模式
accessModes:
- ReadWriteMany
# 指定PV回收策略
persistentVolumeReclaimPolicy: Retain
# nfs配置
nfs:
server: 192.168.10.100
# 指定NFS上的存储路径,必须是已存在的路径
path: /nfs/html
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- accessModes (访问模式)
ReadWriteOnce
- 可被一个节点读写挂载。ReadOnlyMany
- 可被多个节点只读挂载。ReadWriteMany
- 可被多个节点读写挂载。
- persistentVolumeReclaimPolicy (PV回收策略)
- Recycle - 删除PVC时删除PV以及其中的数据。
- Retain - 删除PVC时保留PV以及其中的数据,需要管理员手工清理数据 (默认)。
# PVC配置编写
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-html-pvc
spec:
# 声明请求的资源
resources:
requests:
storage: 100Mi
accessModes:
- ReadWriteMany
# 通过selector查找PV
selector:
matchLabels:
pv: nfs-html-pv
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Pod配置编写
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: nfs-html-pvc
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# StorageClass使用
# 安装Provisioner
使用StorageClass之前我们需要先安装对应的存储插件,nfs的存储插件为nfs-subdir-external-provisioner
。
# 下载nfs-subdir-external-provisioner,下载Source code
https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/releases/
# 解压下载的包
tar -xvf nfs-subdir-external-provisioner-nfs-subdir-external-provisioner-*.tar.gz
# 创建命名空间存储该驱动
kubectl create namespace nfs-provisioner
# 修改相关配置
cd nfs-subdir-external-provisioner-nfs-subdir-external-provisioner-*/deploy/
# 修改镜像源/NFS服务器地址/共享目录配置
sed -ri.bak -e "s#registry\.k8s\.io/sig-storage#registry.cn-shenzhen.aliyuncs.com/xiaohh-docker#" -e "s#10\.3\.243\.101#192.168.10.100#" -e "s#/ifs/kubernetes#/nfs#" deployment.yaml
# 修改命名空间
sed -i 's/namespace: default/namespace: nfs-provisioner/g' $(grep -rl 'namespace: default' ./)
# 安装动态供给
kubectl get all -o wide -n nfs-provisioner
# 查看安装结果
kubectl get all -n nfs-provisioner
# 查看动态供应存储类名称
kubectl get storageclass
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# StorageClass配置编写
# 安装nfs-subdir-external-provisioner的时候会创建一个storageClass,需要另外的可以自己写
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-html-storage
annotations:
# 是否设置为默认storageClass
storageclass.kubernetes.io/is-default-class: "false"
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
# 删除时数据处理方式
archiveOnDelete: "false"
# 指定NFS存储卷目录路径,目录不能已存在,需要删除再添加StorageClass
# 也可以使用变量,如:"${.PVC.namespace}/${.PVC.name}/${.PVC.annotations.nfs.io/storage-path}"
pathPattern: html
mountOptions:
# 访问文件时不更新文件inode中的时间戳,高并发环境可提高性能
- noatime
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- archiveOnDelete
- false - 删除PVC时,删除PV以及其中的数据。
- true - 删除PVC时,保留PV以及其中的数据。
# PVC配置编写
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-html-pvc
spec:
# 指定使用的storageClass名称
storageClassName: nfs-html-storage
# 声明请求的资源
resources:
requests:
storage: 10Mi
accessModes:
- ReadWriteMany
2
3
4
5
6
7
8
9
10
11
12
13
# Pod配置编写
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs
mountPath: /usr/share/nginx/html
volumes:
- name: nfs
persistentVolumeClaim:
claimName: nfs-html-pvc
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16