存储

pod 内的容器可以通过挂载卷的方式挂载一个存储位置,但是当pod重启的时候,容器内的挂载的volume将清空。
这对于一些比如数据库的应用来说是不可接收的。需要通过挂载可以持久化的网络存储。

k8s 支持多种持久卷的类型

比如 awsElasticBlockStore awsEBS
azureDisk Azure Disk
local 节点上的本地存储设备
nfs 网络文件存储

   ..... 

可以根据具体的环境选择使用云厂商的存储服务或节点磁盘或自行搭建存储服务。

挂载nfs 远程存储

NFS 是Network File System的缩写,即网络文件系统。一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向外公布。功能是通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据,是在类Unix系统间实现磁盘文件共享的一种方法。

k8s 支持挂载nfs的网络存储。

  1. 一个新的存储机器上安装nfs服务,这里选用 192.168.1.105 机器
1
yum install -y nfs-utils 

创建一个挂载路径并暴露

1
2
mkdir -p /data/html

编辑文件暴露文件路径

1
vim /etc/exports 

添加暴露路径

1
/data/html  *(rw,no_root_squash)

开启服务

1
systemctl start nfs

关闭防火墙或开放端口

nfs tcp 2049 这个很明显到处都是
sunrpc tcp 111 这个很明显到处都是
sunrpc udp 111 其中这个很难发现,仔细排查才看到
acp-proto udp 4046 其中仔细看udp的会找到

1
2
3
4
5
6
7
8
9
10
firewall-cmd --zone=public --add-port=2049/tcp --permanent
firewall-cmd --zone=public --add-port=111/tcp --permanent
firewall-cmd --zone=public --add-port=111/udp --permanent
firewall-cmd --zone=public --add-port=4096/udp --permanent

firewall-cmd --reload


firewall-cmd --zone=public --list-ports

或直接关闭防火墙

1
2
systemctl stop firewalld.service
firewall-cmd --state
  1. node节点上 同样需要安装服务,并启动
1
2
3
4
5
yum install -y nfs-utils 

systemctl start nfs


  1. 创建一个直接使用远程挂载的nfs的deploy

vim nginx-nfs.yaml

1
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
27
28
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dep1
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
volumes:
- name: wwwroot
nfs:
server: 192.168.1.105
path: /data/html

1
2

kubectl apply -f nginx-nfs.yaml

在nfs的 /data/html 中写入一个文件

1
touch a.html

进入pod中查看挂载路径下是否存在此文件

1
2
kubectl exec -it nginx-dep1-6b475c7749-xv5fv bash

使用pv pvc 定义持久化存储

Kubernetes对于有状态的容器应用或者对数据需要持久化的应用, 不仅需要将容器内的目录挂载到宿主机的目录或者emptyDir临时存储 卷,而且需要更加可靠的存储来保存应用产生的重要数据,以便容器应 用在重建之后仍然可以使用之前的数据。

当使用持久化的存储方案,比如nfs 或awsElasticBlockStore 的时候会有一些问题
每个deploy都需要进行配置,如果需要切换存储方案也需要一一进行修改,同时对于这些存储地址的重要信息也是容易暴露。

为了能够更好的管理持久化存储,k8s 引入了pv 和pvc的这2种概念。

pv

PV是对底层网络共享存储的抽象,将共享存储定义为一种”资源”。
pv 中定义了具体的存储类型和存储的相关的配置信息。
此资源由管理员创建,一般也只能管理员查看和修改,用于其他的部署人员,只需要进行使用就好。

pv 配置的关键参数

  • Capacity 存储能力 描述存储设备具备的能力,目前仅支持对存储空间的设置 (storage=xx),未来可能加入IOPS、吞吐率等指标的设置。

  • Volume Mode 卷模式 Filesystem(文件系统)和Block(块) 针对不同的存储方式,选择不同的模式,比如nfs选文件系统,云服务的块存储服务就得选块。

  • Access Modes 访问模式

    • ReadWriteOnce(RWO):读写权限,并且只能被单个Node挂 载。
    • ReadOnlyMany(ROX):只读权限,允许被多个Node挂载。
    • ReadWriteMany(RWX):读写权限,允许被多个Node挂载。
  • Class 存储类别 通过storageClassName参数指定一个 StorageClass资源对象的名称。同一个类别和同一个类别的pvc进行绑定使用

PV 状态描述
Avaliable创建好的 PV 在没有和 PVC 绑定的时候处于 Available 状态。
Bound当一个 PVC 与 PV 绑定之后,PVC 就会进入 Bound 的状态。
Released一个回收策略为 Retain 的 PV,当其绑定的 PVC 被删除,该 PV 会由 Bound 状态转变为 Released 状态。 注意:Released 状态的 PV 需要手动删除 YAML 配置文件中的 claimRef 字段才能与 PVC 成功绑定。

​ pv 的状态

pvc

pvc 定义用户对pv的请求资源信息。比如申请的空间大小,存储类别等信息。
对于pod的使用的是pvc 而不是直接使用pv


pv 和pvc的生命周期

PVC 状态描述
Pending没有满足条件的 PV 能与 PVC 绑定时,PVC 将处于 Pending 状态。
Bound当一个 PV 与 PVC 绑定之后,PVC 会进入 Bound 的状态。

​ pvc的状态

pv 和pvc示例

  1. 定义pv

vim pv-test.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
nfs:
path: /data/html
server: 192.168.1.105


  1. 定义pvc
1
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dep1
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
volumes:
- name: wwwroot
persistentVolumeClaim:
claimName: my-pvc

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi

  1. 应用这2个文件,然后进入容器内查看文件,能查看到存储文件表示成功

查看pv pvc

注意:当有pvc 使用的时候 看到pv的状态是 Bound ,当无pvc 使用的时候 pv的状态为 Released

pvc 和pv的自动匹配规则

pvc 会自动向pv申请存储资源;但是并不是一定会成功的。

需要满足几个条件

当 PVC 绑定 PV 时,需考虑以下参数来筛选当前集群内是否存在满足条件的 PV。

参数描述
VolumeMode主要定义 volume 是文件系统(FileSystem)类型还是块(Block)类型,PV 与 PVC 的 VolumeMode 标签必须相匹配。
StorageclassPV 与 PVC 的 storageclass 类名必须相同(或同时为空)。
AccessMode主要定义 volume 的访问模式,PV 与 PVC 的 AccessMode 必须相同。
Size主要定义 volume 的存储容量,PVC 中声明的容量必须小于等于 PV,如果存在多个满足条件的 PV,则选择最小的 PV 与 PVC 绑定。

PVC 创建后,系统会根据上述参数筛选满足条件的 PV 进行绑定。如果当前集群内的 PV 资源不足,系统会动态创建一个满足绑定条件的 PV 与 PVC 进行绑定。