Kubernetes
(简称K8s)是一种强大的容器编排工具,能够自动化应用程序的部署、扩展和管理。在Kubernetes
中,存储是一个关键组件,因为它允许状态化应用程序在容器中运行。本文将介绍Kubernetes
存储的基础知识、不同的存储类型,以及如何配置和使用Kubernetes
存储。
Kubernetes
支持多种类型的存储卷,可以将存储空间挂载到 Pod 中的容器中。以下是一些常见的 Kubernetes
存储卷类型:
EmptyDir
:这是一个临时目录,会在 Pod 创建时在节点上创建,并在 Pod 删除时自动删除。它是临时的,并且不能跨多个节点共享。
HostPath
:此存储卷允许您将宿主机上的某个路径映射到容器中。它主要用于测试和开发目的,不建议在生产环境中使用。
PV&PVC
:PV
是一种可在整个集群中共享的持久性存储资源,而 PVC
则是用户请求的一种持久性存储。PV 可以由管理员预先创建并定义其大小和访问模式,然后由用户通过 PVC
请求使用
ConfigMap&Secret
:这两种特殊类型的存储卷允许您将配置文件和加密数据插入到容器中。它们可以通过存储卷来挂载,也可以通过环境变量或命令行参数来传递给容器。
StorageClass
:这是一个Kubernetes
对象,用于定义一组持久性存储参数和行为,以便用户可以根据需要创建和管理持久性存储卷。
❝在了解了
k8s
存储类型的基础, 我们可以通过具体案例进一步探讨k8s
的不同存储类型及其应用场景。以下示例将详细阐述如何在实际应用中使用这些存储类型,帮助您更好地掌握k8s
存储的配置和管理。
EmptyDir
是Kubernetes
中的一种Volume
类型,用于在同一个Pod
中的不同容器之间共享临时数据。以下是一个使用EmptyDir
的完整示例:
在这个示例中,我们创建了一个包含两个容器的Pod
,并使用EmptyDir
在这两个容器之间共享数据。具体配置如下:
使用 busybox
镜像。
执行命令:在 /mnt/data/message
文件中写入Hello from Container 1
。
挂载共享卷到 /mnt/data
。
使用 busybox
镜像。
执行命令:读取并显示 /mnt/data/message
文件的内容。
挂载共享卷到 /mnt/data
。
定义一个名为 shared-data
的EmptyDir
卷。
两个容器都挂载该卷,以共享数据。
❝
EmptyDir
卷在Pod
生命周期内是持久的,但在Pod
被删除后,数据将会丢失。这种卷类型非常适用于需要在同一个Pod
内的多个容器之间共享临时数据的场景。
HostPath
是Kubernetes
中的一种 Volume
类型,允许将主机(节点)上的文件或目录挂载到Pod
中。这使得容器可以直接访问主机的文件系统资源。以下是一个使用HostPath
的完整示例:
在这个示例中,我们创建了一个包含一个容器的 Pod,并使用 HostPath 将主机上的目录挂载到容器中。具体配置如下:
使用 busybox
镜像。
执行命令:每隔10秒读取并显示 /mnt/host/data.txt
文件的内容。
挂载 HostPath 卷到 /mnt/host
。
定义一个名为 host-data
的 HostPath 卷。
将主机上的 /data
目录挂载到容器内的 /mnt/host
路径。
如果 /data
目录不存在,会自动创建。
❝使用
HostPath
可以方便地在容器中访问和操作主机上的文件系统资源,适用于需要直接使用主机文件系统的场景。然而,由于HostPath
存在安全和隔离性问题,通常只建议在开发、测试环境中使用,不推荐在生产环境中使用。
PV(Persistent Volume)
是集群中的持久化存储卷,代表实际的存储资源。它是全局资源,不受命名空间的限制。PV
的生命周期独立于Pod
,即使没有被Pod
使用,PV
仍然存在于集群中。这使得PV
可以在不同的Pod
之间共享和重用,从而提供稳定的存储解决方案。
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv # PV 的名称
spec:
capacity:
storage: 2Gi # PV 的容量为 2GB
volumeMode: Filesystem # 指定 PV 的文件系统类型
accessModes:
- ReadWriteMany # 设置 PV 的访问模式为 ReadWriteMany,即多个节点可以同时读写
persistentVolumeReclaimPolicy: Retain # 设置 PV 的回收策略为 Retain,保留 PV 的数据
storageClassName: nfs-storage # 引用的 StorageClass 的名称
mountOptions:
- vers=4.1 # 挂载选项,指定 NFS 版本为 4.1
nfs:
path: /your/nfs/path # 指定 NFS 服务器上的共享路径
server: your.nfs.server.ip # 指定 NFS 服务器的 IP 地址
PVC(PersistentVolumeClaim)
是Pod
对PV(PersistentVolume)
的请求,用于声明存储需求,包括容量、访问模式等。通过PVC
,Pod
可以请求连接到PV
提供的存储资源。Kubernetes
会自动匹配符合条件的PV
,并将PVC
与PV
绑定。如何创建PVC
呢?示例如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc # PVC 的名称
namespace: middleware # PVC 所在的命名空间
spec:
accessModes:
- ReadWriteMany # 设置 PVC 的访问模式为 ReadWriteMany,与 PV 一致
storageClassName: nfs-storage # 引用的 StorageClass 的名称,与 PV 一致
resources:
requests:
storage: 2Gi # 申请的存储容量为 2GB
❝注意
storageClassName
部分,这个字段,PVC要与其想申请的PV保持一致。
PVC与PV的成功绑定,有两个条件:(1)PV
的spec
信息满足PVC
的要求(如存储容量、访问模式等)。(2)PV
和PVC
的storageClassName
字段的值需一致。
有了PVC
和PV
的组合,我们可以在需要持久化存储时向Kubernetes
申请 PV
。然而,PV
仍然需要运维人员提前创建。那么,有没有一种方法可以实现动态创建PV
呢?答案就是使用StorageClass
和存储插件。
StorageClass
和存储插件是实现动态创建PV
的一种方式。StorageClass
定义了动态分配存储的属性,如存储类型、访问模式等,并指定使用的存储插件,这些插件通常与外部存储系统(如 Ceph
、NFS
等)相关。当 PVC
请求动态分配存储时,由 StorageClass
指定的存储插件会负责创建 PV
,Kubernetes
的 kube-controller-manager
组件则会将 PV
和 PVC
绑定在一起。
如何创建StorageClass
呢?示例如下:
apiVersion: storage.k8s.io/v1 # Kubernetes API 版本
kind: StorageClass # 定义资源类型为 StorageClass
metadata:
name: local-path # StorageClass 的名称
provisioner: rancher.io/local-path # 使用的存储插件
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
❝需要注意的是,存储插件需要我们提前安装到K8S集群中。这里使用的
rancher.io/local-path
是存储插件的一种。OpenEBS(Open Elastic Block Storage)
是一个开源的容器化存储平台,旨在为Kubernetes
提供动态和分布式的块存储。它允许用户通过 PVC在 Kubernetes 集群中动态创建和管理存储卷。
这样我们就可以通过以下方式创建PVC
,存储插件会创建PV
,之后K8S
会将此PV与我们的PVC
绑定。
apiVersion: v1 # Kubernetes API 版本
kind: PersistentVolumeClaim # 定义资源类型为 PersistentVolumeClaim
metadata:
name: mypvc # PVC 的名称
spec:
storageClassName: local-path # 指定使用的 StorageClass 为 openebs
accessModes:
- ReadWriteOnce # 访问模式为 ReadWriteOnce
resources:
requests:
storage: 1Gi # 请求存储容量为 1Gi
我们如何在应用中使用以上PVC
呢?还是以创建nginx
为例:
apiVersion: apps/v1 # 使用的 Kubernetes API 版本
kind: Deployment # 定义部署对象
metadata:
name: nginx # 部署的名称
spec:
replicas: 1 # 副本数为 1,即只运行一个 Pod
selector:
matchLabels:
app: nginx # 根据标签选择 Pod
template:
metadata:
labels:
app: nginx # Pod 的标签
spec:
containers:
- name: nginx # 容器名称
image: nginx:latest # 使用的 Docker 镜像
ports:
- containerPort: 80 # 容器监听的端口
volumeMounts:
- name: nginx-storage # 挂载名为 data 的 Volume
mountPath: /usr/share/nginx/html # 挂载到容器的路径
volumes:
- name: nginx-storage # 定义名为 data 的 Volume
persistentVolumeClaim:
claimName: mypvc # 指定使用的 PVC 名称
Kubernetes
中的 ConfigMap
和 Secret
是两种特殊类型的存储卷,用于在容器中注入配置信息和敏感数据。
ConfigMap
允许您将配置文件、环境变量或命令行参数传递给容器。它通过将非敏感的配置信息以键值对的形式存储,使得应用程序配置与容器镜像分离,从而更容易管理和更新。以下是一个使用 ConfigMap
的示例:
apiVersion: v1
kind: ConfigMap
metadata:
name: example-config
data:
app.properties: |
database_url=jdbc:mysql://localhost:3306/mydb
database_user=root
database_password=password
然后在Pod
中使用 ConfigMap
:
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: app-container
image: myapp:latest
volumeMounts:
- mountPath: /etc/config
name: config-volume
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: example-config # 该字段是对应ConfigMap中的metadata.name
key: database_url
volumes:
- name: config-volume
configMap:
name: example-config ## 该字段是对应ConfigMap中的metadata.name
Secret
用于存储和管理敏感信息,例如密码、OAuth
令牌和 SSH
密钥。Secret
通过 Base64
编码存储数据,提供了更高的安全性。以下是一个使用 Secret 的示例:
apiVersion: v1
kind: Secret
metadata:
name: example-secret
type: Opaque
data:
password: cGFzc3dvcmQ=
然后在Pod
中使用 Secret
:
apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
containers:
- name: app-container
image: myapp:latest
volumeMounts:
- mountPath: /etc/secret
name: secret-volume # 这个字段与volumes.name是一致
env:
- name: PASSWORD
valueFrom:
secretKeyRef:
name: example-secret # 这个字段与secretName是一致
key: password
volumes:
- name: secret-volume
secret:
secretName: example-secret
Kubernetes
提供了多种存储解决方案,以满足不同的应用需求。持久化存储方面,通过 PV
和 PVC
,我们可以实现存储资源的动态分配和管理,而 StorageClass
结合存储插件则进一步简化了 PV 的动态创建。对于临时和本地存储,Kubernetes
提供了 emptyDir
和 HostPath
,分别用于 Pod
内部容器间的临时数据共享和直接访问主机文件系统。此外,特殊类型的存储卷如 ConfigMap
和 Secret
,帮助我们更安全、便捷地管理应用配置和敏感数据。通过这些灵活多样的存储机制,Kubernetes
有效支持了应用的持久化和高可用性需求。