接着k8s实战开始讲,之前讲到k8s集群Deployment的pod高可用的时候有说到我设置对应的副本数以后,当 Pod 因节点故障或手动删除而终止时,Deployment 会自动创建新的 Pod 替换。那这个替换后的这个pod里面的数据还是之前的数据么?怎么做到数据不丢失?
Kubernetes集群中存储数据通常涉及以下几个关键步骤和概念
1. Volume
Volume指的是存储卷,包含可被Pod中容器访问的数据目录,容器中的文件在磁盘上是临时存放的,当容器崩溃时文件会丢失,同时无法在多个Pod中共享文件,通过使用存储卷可以解决这两个问题。
Kubernetes支持很多类型的卷。Pod 可以同时使用任意数目的卷类型。临时卷类型的生命周期与Pod相同,但持久卷可以比Pod 的存活期长。当Pod不再存在时,Kubemetes 也会销毁临时卷;不过Kubemetes不会销毁持久卷。对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失。
卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。所采用的不同卷的类型将决定该目录如何形的、使用何种介质保存数据以及目录中存放的内容。常用的卷类型有configMap、emptyDir、local、nfs、secret等。
2. PV和PVC
- PV:集群级别的存储资源,由管理员创建,定义了存储的容量、访问模式(如ReadWriteOnce、ReadOnlyMany、ReadWriteMany)和存储类等。
- PVC:用户通过PVC向集群请求存储资源,类似于资源配额。PVC会绑定到一个PV,提供存储空间供Pod使用。
3. 存储类型
Kubernetes支持多种存储类型,包括:
NFS:网络文件系统,适合共享存储需求。
iSCSI:基于IP的SAN存储,提供块存储。
Ceph:分布式存储系统,提供高可用性和可扩展性。
GlusterFS:分布式文件系统,适合大规模存储需求。
云存储:如AWS EFS、EBS,Azure File Storage,GCP Filestore等,利用云服务提供商的存储解决方案。
4. 配置存储
- 根据选择的存储类型,配置相应的存储后端。例如,使用NFS时,需要配置NFS服务器并确保K8s节点能够访问该服务器。
- 对于云存储,可能需要配置云提供商的特定驱动或插件,以支持动态存储供应。
5. 创建PV和PVC
- PV配置:编写YAML文件定义PV,指定存储类型、容量、访问模式等。
- PVC配置:编写YAML文件定义PVC,请求特定的存储容量和访问模式。
6. 挂载存储到Pod
在Pod的YAML文件中,指定要使用的PVC,并挂载到Pod的指定路径。
7. 数据持久化
- 使用网络存储(如NFS、云存储)可以实现数据的持久化,即使Pod被重新调度到其他节点,数据仍然存在。
- 本地存储适合临时数据,但不保证数据持久性。
8. StorageClasses
StorageClass用于动态供应存储卷,根据存储需求自动创建PV。
示例:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: my-storage-class
provisioner: example.com/nfs
parameters:
nfsServer: nfs.example.com
nfsPath: /exports/data
9. 云存储集成
对于云平台,如AWS,需要配置云存储驱动(如aws-ebs-csi-driver)以支持EBS卷的动态供应。
示例配置:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: aws-ebs
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
zone: us-west-2a
10. 性能和可靠性
- 选择合适的存储类型和配置,以满足应用的性能需求。例如,高性能应用可能需要使用块存储或高端云存储解决方案。
监控存储性能,确保存储I/O不会成为瓶颈
11. 实际操作示例
创建PV:
apiVersion: v1 kind: PersistentVolume metadata: name: my-pv spec: storageClassName: nfs capacity: storage: 10Gi accessModes: - ReadWriteOnce nfs: server: 10.10.2.242 path: /home/nfs
#配置文件详解 apiVersion: v1 # 使用 Kubernetes 核心 API 版本 kind: PersistentVolume # 定义资源类型为 PersistentVolume (PV) metadata: name: my-pv # PV 名称,集群内唯一标识 spec: storageClassName: nfs # 指定 StorageClass 名称(需与 PVC 匹配) capacity: storage: 10Gi # PV 的存储容量(PVC 请求不可超过此值) accessModes: - ReadWriteOnce # 访问模式:单节点读写,ReadOnlyMany表示多节点只读,ReadWriteMany表示多节点读写 nfs: # 存储后端类型为 NFS server: 10.10.2.242 # NFS 服务器 IP 地址 path: /home/nfs # NFS 共享路径
创建PVC
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: nfs
apiVersion: v1 # 使用 Kubernetes 核心 API 版本 kind: PersistentVolumeClaim # 定义资源类型为 PersistentVolumeClaim (PVC) metadata: name: my-pvc # PVC 名称,集群内唯一标识 spec: accessModes: - ReadWriteOnce # 访问模式:单节点读写,ReadOnlyMany表示多节点只读,ReadWriteMany表示多节点读写 resources: requests: storage: 5Gi # 请求的存储容量为 5Gi storageClassName: nfs # 指定关联的 StorageClass 名称
创建Pod
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: my-image volumeMounts: - mountPath: "/usr/share/nginx/" name: my-storage volumes: - name: my-storage persistentVolumeClaim: claimName: my-pvc
#配置文件详解 apiVersion: v1 # 指定 Kubernetes API 版本 kind: Pod # 定义资源类型为 Pod metadata: # 元数据部分 name: mynginx # Pod 的名称为 `mynginx` spec: # Pod 的详细配置 containers: # 定义容器列表 - name: nginx # 第一个容器的名称是 `nginx` image: nginx:1.20 # 容器使用的镜像为 `nginx:1.20` volumeMounts: # 容器挂载的卷配置 - mountPath: "/usr/share/nginx/" # 将卷挂载到容器内的 `/usr/share/nginx/` 目录 name: my-storage # 挂载的卷名称是 `my-storage` volumes: # 定义 Pod 级别的卷列表 - name: my-storage # 卷名称是 `my-storage` persistentVolumeClaim: # 卷类型为持久化存储(PVC) claimName: my-pvc # 使用的 PVC 名称是 `my-pvc`
挂载到Pod:
如上文所示,Pod配置中挂载PVC到指定路径。12. 注意事项
- 确保存储后端的网络配置正确,允许K8s节点访问存储资源。
- 监控存储资源的使用情况,避免超出容量限制。
- 备份和恢复策略,确保数据安全。
通过以上步骤,你可以在Kubernetes集群中有效地管理和存储数据,满足不同应用的需求
思考:k8s创建存储好麻烦啊,直接挂载NFS对应目录就行了,为啥还要创建pv和pvc呢?
理论上可以直接在Pod中挂载NFS目录(如下示例),但这种方式有以下缺点:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx:1.20
volumeMounts:
- name: nfs-vol
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-vol
nfs:
server: 10.10.2.242
path: /home/nfs
缺点分析:
1. 硬编码存储配置:
- 存储服务器的IP、路径等信息直接写在Pod定义中,导致:
- 跨环境迁移困难(如测试环境到生产环境)。
- 存储配置无法复用,每个Pod都要重复配置。
2. 权限和安全性问题:
- 直接暴露NFS服务器信息,可能存在安全风险(如权限泄露)。
- 无法统一控制存储资源的访问权限(比如限制某些命名空间只能使用特定存储)。
3. 无法动态分配存储:
如果存储资源需要动态创建(如云存储卷),直接挂载无法实现自动化。
4. 缺乏生命周期管理:
删除Pod时,直接挂载的存储卷不会自动清理(如云存储卷需要手动释放)。
为什么需要PV和PVC?
PV和PVC的设计目标是解耦存储配置和应用部署,解决以下问题:
1. 存储资源抽象化
- PV(PersistentVolume) :定义存储资源的物理属性(容量、类型、访问模式等)。
- PVC(PersistentVolumeClaim) :声明应用所需的存储资源(容量、访问模式等)。
- 优势:应用开发者无需关心底层存储细节(如NFS服务器IP),只需声明需求(如“需要10Gi的可读写存储”)。
2. 动态存储分配
StorageClass:通过定义存储类(如nfs-storage、aws-ebs),可以动态创建PV。
示例:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
provisioner: example.com/nfs # 需要NFS Provisioner自动创建PV
parameters:
server: 10.10.2.242
path: /home/nfs
当用户创建PVC时,Kubernetes会自动创建对应的PV,无需手动配置。
3. 跨环境兼容性
- 开发、测试、生产环境可能使用不同的存储后端(如本地NFS、云存储)。
- 通过PV/PVC,应用无需修改YAML文件即可适配不同环境。
4. 权限和配额管理
集群管理员可以统一控制PV的访问权限(如RBAC)。
通过PVC限制资源使用(如某个命名空间只能申请特定大小的存储)。
5. 生命周期管理
PV可以绑定到PVC的生命周期(如删除PVC时自动释放PV)。
思考:如何简化PV/PVC的使用?
如果觉得手动创建PV/PVC太麻烦,可以通过以下方式简化:
1. 使用StorageClass动态创建PV
- 前提:部署NFS Provisioner(如nfs-subdir-external-provisioner),它会根据PVC自动创建PV。
操作步骤:
(1)安装NFS Provisioner。
(2)创建StorageClass:apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-storage provisioner: k8s-sigs.io/nfs-subdir-external-provisioner parameters: server: nfs-server.example.com path: /exports/data mountOptions: ["nfsvers=4.1"]
(3)创建PVC(无需手动创建PV):
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: storageClassName: nfs-storage accessModes: [ReadWriteOnce] resources: requests: storage: 10Gi
(4)Pod挂载PVC:
volumes: - name: my-storage persistentVolumeClaim: claimName: my-pvc
2. 直接挂载NFS目录的替代方案
如果仍希望直接挂载NFS目录,可以使用以下方法(不推荐长期使用):
volumes:
- name: nfs-vol
nfs:
server: nfs-server.example.com
path: /exports/data
但需注意前文提到的缺点。
总结
直接挂载NFS:适合临时测试或简单场景,但缺乏灵活性。
PV/PVC:适合生产环境,提供标准化、动态分配和安全性。
终极简化方案:通过StorageClass + NFS Provisioner实现自动化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。