OpenShift持久化存储实现与实践
一 持久化存储概述
1.1 存储类型说明
在OpenShift容器平台中,Pod使用的默认存储为临时存储。每个Pod由一个或多个容器组成,这些容器共享存储和网络资源,可随时被创建、启动、停止或销毁。临时存储的特点是当容器终止时,写入容器文件系统中的所有数据都会丢失。
针对需要长期保存数据的应用场景,OpenShift基于Kubernetes的PersistentVolume(持久卷)机制为Pod提供持久化存储解决方案。
1.2 典型应用场景
数据库类应用是持久化存储的典型代表。当启动数据库Pod时如果使用默认临时存储,Pod销毁重建后将导致数据丢失。使用持久化存储后,数据库数据被保存到Pod外部的持久卷中,即使Pod被销毁重建,数据库服务仍可访问原有数据。
1.3 核心概念定义
持久卷(PersistentVolume,简称PV)是集群级别的资源,由管理员负责创建和删除,用于表示集群中所有节点均可访问的网络存储资源。
持久化存储体系包含两个核心组件:
- PersistentVolume:由PersistentVolume API对象定义,代表集群管理员预先配置的网络存储资源。PV独立于单个Pod而存在,其生命周期与使用它的Pod无关。
- PersistentVolumeClaim(PVC):由PersistentVolumeClaim API对象定义,表示开发人员对存储空间的需求声明。类似于Pod消耗节点资源,PVC消耗PV资源。
1.4 支持的存储后端
OpenShift通过插件机制支持多种存储后端:
- 网络文件系统:NFS
- 分布式存储:GlusterFS、Ceph RBD
- 云存储服务:AWS EBS、GCE Persistent Disk、Azure Disk、Azure File、OpenStack Cinder
- 存储协议:iSCSI、Fibre Channel
- 虚拟化平台:VMWare vSphere
- 其他:FlexVolume(用于扩展不支持原生插件的存储后端)
- 高级功能:动态供给、存储类、卷选择器绑定、卷安全策略
1.5 卷访问模式
不同存储Provider支持不同的访问能力,每个持久卷都可以设置特定的访问模式。NFS存储支持多节点读写,而某些存储只能以只读方式导出。
| 访问模式 | CLI缩写 | 功能描述 |
|---|---|---|
| ReadWriteOnce | RWO | 仅允许单个节点以读写方式挂载 |
| ReadOnlyMany | ROX | 允许多个节点以只读方式挂载 |
| ReadWriteMany | RWX | 允许多个节点以读写方式挂载 |
PVC与PV的匹配基于两个条件:访问模式和存储容量。系统会优先匹配访问模式,然后按容量从大到小排序选择。例如,PVC请求RWO模式时,即使可用的NFS卷同时支持RWO、ROX、RWX三种模式,仍会匹配成功,因为NFS支持RWO访问。
1.6 存储类机制
通过storageClassName属性,PVC可以指定所需的存储类。只有存储类名称相同的PV才能与PVC绑定。集群管理员可以配置默认存储类,或设置动态供给程序来管理多个存储类。
1.7 PV与PVC的生命周期
供给阶段:管理员创建PV资源,定义实际存储信息供集群用户使用。
绑定阶段:用户创建PVC声明,指定存储容量、访问模式和存储类。集群Master监控PVC事件,寻找匹配的PV或等待存储类供给程序创建PV,然后完成绑定。
使用阶段:Pod使用PVC作为存储卷。集群查找已绑定的PV并挂载到Pod中。对于支持多种访问模式的卷,用户需要在Pod卷配置中指定具体使用的模式。
1.8 NFS存储配置要点
OpenShift容器以随机UID运行,将Linux用户从节点映射到NFS服务器的方式无法正常工作。作为OpenShift PV使用的NFS共享必须满足以下条件:
- 所属用户和组为nfsnobody
- 权限设置为rwx------(0700)
- 配置all_squash选项
配置示例:
/var/export/vol *(rw,async,all_squash)
关于NFS的sync和async选项:async模式可提升写入性能,NFS服务器立即响应客户端而无需等待数据写入磁盘;sync模式则需等待数据持久化后再响应。在高延迟环境中,async选项能显著加快镜像推送等场景的操作速度。
注意事项:NFS共享的文件系统大小和用户配额对OpenShift无影响。PV容量在资源定义中指定,若实际文件系统容量小于PV定义,PV仍会被创建绑定;若实际容量更大,OpenShift不会限制容器使用物理存储空间,项目级别的存储配额和存储限制由OpenShift自身提供。
默认SELinux策略阻止容器访问NFS共享。需要在每个OpenShift节点上启用相关策略:
setsebool -P virt_use_nfs=true
setsebool -P virt_sandbox_use_nfs=true
1.9 回收策略配置
NFS卷支持OpenShift的Recycle插件,可根据持久卷上配置的策略自动执行回收任务。
默认策略为Retain(保留),允许手动回收资源。删除PVC后,PV仍然存在且被视为已释放,但无法被新的PVC绑定,因为前一个PVC的数据仍保留在卷上。此时需要管理员手动清理卷数据。
当回收策略设置为Recycle时,删除PVC后会执行数据清除操作(类似rm -rf命令),之后该卷可立即绑定新的PVC。
1.10 补充组配置
补充组(Supplemental Group)是标准的Linux组机制。进程在Linux中运行时具有UID、主GID和补充组。容器主进程可以配置这些属性。
补充组ID通常用于控制NFS、GlusterFS等共享存储的访问权限,而fsGroup用于控制Ceph RBD、iSCSI等块存储的访问。
OpenShift共享存储插件挂载卷时,会使挂载点权限与目标存储权限匹配。例如目标存储的owner ID为1234、group ID为5678,则宿主机和容器内的挂载点具有相同ID,容器进程必须匹配其中一个ID才能访问卷。
1.11 块存储与fsGroup
fsGroup定义Pod的文件系统组ID,会被添加到容器的补充组中。补充组ID适用于共享存储,而fsGroup ID适用于块存储。
Ceph RBD、iSCSI及各类云块存储通常专用于单个Pod。与共享存储不同,块存储由Pod独占,Pod或镜像定义中指定的用户和组ID会应用到实际的物理块设备上。
1.12 SELinux与卷安全
除SCC(安全上下文约束)外,所有预定义的SCC都将seLinuxContext设置为MustRunAs。最匹配Pod需求的SCC会强制Pod使用对应的SELinux策略。Pod使用的SELinux策略可以在Pod本身、镜像、SCC或项目中定义。
SELinux标签可在Pod的securityContext中定义,支持user、role、type和level标签。
1.13 SELinuxContext选项
- MustRunAs:若未使用预分配值,需配置seLinuxOptions。系统会使用seLinuxOptions作为默认值进行验证。
- RunAsAny:不提供默认值,允许指定任意seLinuxOptions。
二 持久卷实践演练
2.1 环境准备
准备完整的OpenShift集群环境。
2.2 练习初始化
lab deploy-volume setup
2.3 配置NFS服务
本实验使用预置脚本完成NFS配置,由services节点提供存储服务。
less -FiX /root/DO280/labs/deploy-volume/config-nfs.sh
/root/DO280/labs/deploy-volume/config-nfs.sh
showmount -e
输出显示NFS导出目录已创建:
2.4 节点挂载测试
mount -t nfs services.lab.example.com:/var/export/dbvol /mnt
mount | grep /mnt
ll -a /mnt/
umount /mnt/
建议在其他计算节点也进行挂载测试,测试完成后建议卸载,OpenShift会在需要时自动挂载。
2.5 创建持久卷
oc login -u admin -p redhat https://master.lab.example.com
less -FiX /home/student/DO280/labs/deploy-volume/mysqldb-volume.yml
PV资源定义示例:
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysqldb-volume
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
nfs:
path: /var/export/dbvol
server: services.lab.example.com
persistentVolumeReclaimPolicy: Recycle
oc create -f /home/student/DO280/labs/deploy-volume/mysqldb-volume.yml
oc get pv
查看结果:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM
mysqldb-volume 3Gi RWX Recycle Available
2.6 创建项目
oc login -u developer -p redhat https://master.lab.example.com
oc new-project persistent-storage
2.7 部署应用
oc new-app --name=mysqldb \
--docker-image=registry.lab.example.com/rhscl/mysql-57-rhel7 \
-e MYSQL_USER=ose \
-e MYSQL_PASSWORD=openshift \
-e MYSQL_DATABASE=quotes
oc status
输出确认:
In project persistent-storage on server https://master.lab.example.com:443
svc/mysqldb - 172.30.39.72:3306
dc/mysqldb deploys istag/mysqldb:latest
deployment #1 deployed 58 seconds ago - 1 pod
2.8 配置持久卷声明
oc describe pod mysqldb | grep -A2 'Volumes'
当前Pod使用临时存储EmptyDir:
Volumes:
mysqldb-volume-1:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
修改部署配置并创建PVC:
oc set volumes dc mysqldb \
--add --overwrite --name=mysqldb-volume-1 -t pvc \
--claim-name=mysqldb-pvclaim \
--claim-size=3Gi \
--claim-mode='ReadWriteMany'
验证配置结果:
oc get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES
mysqldb-pvclaim Bound mysqldb-volume 3Gi RWX
2.9 端口转发测试
oc get pod
NAME READY STATUS RESTARTS AGE
mysqldb-2-r7wz8 1/1 Running 0 4m
oc port-forward mysqldb-2-r7wz8 3306:3306
2.10 数据库功能验证
mysql -h127.0.0.1 -uose -popenshift \
quotes < /home/student/DO280/labs/deploy-volume/quote.sql
mysql -h127.0.0.1 -uose -popenshift \
quotes -e "select count(*) from quote;"
验证NFS服务端数据存储:
ssh root@services ls -la /var/export/dbvol
drwxr-x---. 2 nfsnobody nfsnobody 54 Jul 21 23:43 quotes
ssh root@services ls -la /var/export/dbvol/quotes
total 116
drwxr-x---. 2 nfsnobody nfsnobody 54 Jul 21 23:43 .
drwx------. 6 nfsnobody nfsnobody 4096 Jul 21 23:39 ..
-rw-r-----. 1 nfsnobody nfsnobody 65 Jul 21 23:39 db.opt
-rw-r-----. 1 nfsnobody nfsnobody 8584 Jul 21 23:43 quote.frm
-rw-r-----. 1 nfsnobody nfsnobody 98304 Jul 21 23:44 quote.ibd
2.11 清理持久卷
oc delete project persistent-storage
oc delete pv mysqldb-volume
2.12 数据持久性验证
删除PV后验证数据是否保留:
ssh root@services ls -la /var/export/dbvol
drwxr-x---. 2 nfsnobody nfsnobody 54 Jul 21 23:43 quotes
ssh root@services rm -rf /var/export/dbvol/*
数据成功持久化在NFS存储中。
三 内部镜像仓库持久化存储
3.1 仓库存储配置
OpenShift内部镜像是S2I流程的关键组件,S2I流程的输出镜像会被推送到内部仓库供部署使用。生产环境中建议为内部仓库配置持久化存储,否则Master节点重启后S2I创建的Pod可能无法启动。
OpenShift安装程序默认配置NFS持久仓库,通过Inventory文件中的openshift_hosted_registry_storage_*变量定义。生产环境建议使用外部专用存储实现高可用。
高级安装程序使用外部NFS服务器作为持久存储后端:
[OSEv3:vars]
openshift_hosted_registry_storage_kind=nfs
openshift_hosted_registry_storage_access_modes=['ReadWriteMany']
openshift_hosted_registry_storage_nfs_directory=/exports
openshift_hosted_registry_storage_nfs_options='*(rw,root_squash)'
openshift_hosted_registry_storage_volume_name=registry
openshift_hosted_registry_storage_volume_size=40Gi
[nfs]
services.lab.example.com
配置参数说明:
- storage_kind:定义存储后端类型
- storage_access_modes:定义访问模式,ReadWriteMany允许多节点读写挂载
- storage_nfs_directory:NFS服务器上的存储目录
- storage_nfs_options:NFS挂载选项,rw支持读写访问,root_squash阻止远程root特权
- storage_volume_name:持久卷名称
- storage_volume_size:持久卷容量
持久化仓库配置完成后,OpenShift在default项目中创建名为registry-volume的持久卷,容量40Gi,默认Retain策略。
oc describe pv registry-volume
Name: registry-volume
Labels: <none>
Annotations: pv.kubernetes.io/bound-by-controller=yes
StorageClass:
Status: Bound
Claim: default/registry-claim
Reclaim Policy: Retain
Access Modes: RWX
Capacity: 40Gi
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: services.lab.example.com
Path: /exports/registry
ReadOnly: false
Events: <none>
验证内部仓库配置:
oc describe dc/docker-registry | grep -A4 Volumes
Volumes:
registry-storage:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: registry-claim
ReadOnly: false
验证镜像存储:
ssh root@master ls -l \
/var/export/registryvol/docker/registry/v2/repositories/default/
四 综合实验
4.1 环境准备
准备完整的OpenShift集群环境。
4.2 初始化实验环境
lab storage-review setup
4.3 配置NFS存储
less -FiX /root/DO280/labs/storage-review/config-review-nfs.sh
/root/DO280/labs/storage-review/config-review-nfs.sh
showmount -e
4.4 创建持久卷
oc login -u admin -p redhat https://master.lab.example.com
less -FiX /home/student/DO280/labs/storage-review/review-volume-pv.yaml
PV定义:
apiVersion: v1
kind: PersistentVolume
metadata:
name: review-pv
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
nfs:
path: /var/export/review-dbvol
server: services.lab.example.com
persistentVolumeReclaimPolicy: Recycle
oc create -f /home/student/DO280/labs/storage-review/review-volume-pv.yaml
oc get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS
review-pv 3Gi RWX Recycle Available
4.5 部署模板
less -FiX /home/student/DO280/labs/storage-review/instructor-template.yaml
oc create -n openshift -f /home/student/DO280/labs/storage-review/instructor-template.yaml
4.6 创建项目
oc login -u developer -p redhat https://master.lab.example.com
oc new-project instructor
4.7 Web界面部署
通过浏览器访问控制台:https://master.lab.example.com
依次选择Catalog → PHP → 使用instructor-template模板,设置应用主机名后继续。模板将自动创建数据库服务器。
监控构建过程,构建完成时显示绿色勾选标记。
4.8 端口转发配置
oc login -u developer -p redhat https://master.lab.example.com
oc get pod
NAME READY STATUS RESTARTS AGE
instructor-1-9fmct 1/1 Running 0 43s
instructor-1-build 0/1 Completed 0 2m
mysql-1-f7rrq 1/1 Running 0 2m
oc port-forward mysql-1-f7rrq 3306:3306
4.9 初始化数据库
mysql -h127.0.0.1 -u instructor -ppassword \
instructor < /home/student/DO280/labs/storage-review/instructor.sql
mysql -h127.0.0.1 -u instructor -ppassword instructor -e "select * from instructors;"
4.10 应用访问测试
浏览器访问:http://instructor.apps.lab.example.com
4.11 数据操作测试
4.12 实验验证
lab storage-review grade
4.13 环境清理
oc login -uadmin -predhat
oc delete project instructor
oc delete pv review-pv
ssh root@services
rm -rf /var/export/review-dbvol
rm -f /etc/exports.d/review-dbvol.exports