Azure Arc 启用的 AKS 中的应用程序的存储选项

适用于:Azure Local 上的 AKS

使用 Azure Arc 启用Azure Kubernetes 服务在 AKS 部署中运行的应用程序可能需要存储和检索数据。 对于某些应用程序工作负载,在删除 Pod 时,数据可在不需要的节点上使用本地快速存储(Kubernetes 使用 Pod 来运行应用程序的实例)

其他工作负载可能需要存储在更为持久的常规数据卷上的存储。 多个 Pod 可能需要共享相同的数据卷,或者,如果在其他节点上重新计划 Pod,则需要重新附加数据卷。 此外,如果 Pod 包含敏感数据或应用程序配置信息,则可能需要存储选项。

显示主节点和节点的集群存储架构图像。

本文介绍在 AKS Arc 中向应用程序提供存储的核心概念,包括:

  • 容量
  • 永久性卷
  • 存储类
  • 永久性卷声明 (PVC)

容量

应用程序通常需要能够存储和检索数据。 由于 Kubernetes 通常将单个 Pod 视为可释放的临时资源,因此应用程序可通过不同方法来使用和保存数据。 卷表示一种跨 Pod 和应用程序生命周期存储、检索及保存数据的方法。

在 Kubernetes 中,卷可能不仅仅表示用于存储和检索信息的传统卷。 Kubernetes 卷还可以用于将数据插入 Pod 以供容器使用。 某些常见 Kubernetes 卷类型包括:

  • emptyDir:此卷通常用作 Pod 的临时存储空间。 Pod 中的所有容器都可以访问卷上的数据。 写入此卷类型的数据仅在 Pod 的生命周期内持续保存,当 Pod 被删除时,卷也会删除。 此卷通常使用基础本地节点磁盘存储,但它也可以单独存在于节点的内存中。

  • secret - 此卷用于将敏感数据(如密码)包含在 Pod 中。 首先,使用 Kubernetes API 创建机密。 在定义 Pod 或部署时,您可以请求特定的密钥。 机密仅提供给所计划的 pod 需要该机密的节点,且机密存储在 tmpfs 中,不写入磁盘。 当需要机密的节点上的最后一个 Pod 被删除时,该节点的 tmpfs 中的机密也将被删除。 机密存储在给定的命名空间中,只有同一命名空间中的 pod 能访问该机密。

  • configMap:此卷类型用于向 Pod 注入键值对属性,例如应用程序配置信息。 无需在容器映像中定义应用程序配置信息,而是可以将其定义为 Kubernetes 资源,以便在部署新 Pod 实例时可轻松为其更新并应用。 与使用机密类似,首先使用 Kubernetes API 创建 ConfigMap 。 然后,定义 Pod 或部署时,可能会请求此 ConfigMapConfigMap 存储在给定的命名空间中,只能由同一命名空间中的 Pod 访问。

永久性卷

卷作为 Pod 生命周期的一部分定义和创建,且仅在删除 Pod 之前存在。 如果在维护事件期间(尤其是在 StatefulSets 中)于另一台主机上重新计划 Pod,则 Pod 通常会预期其存储会被保留。 永久性卷是由 Kubernetes API 创建和管理的存储资源,可以在单个 Pod 的生命周期之外存在。

你可以使用由 VHDX 支持的 AKS 磁盘卷,这些卷被装载为 ReadWriteOnce,并且一次可供单个节点访问。 或者,你可以使用由 SMB 或 NFS 文件共享支持的 AKS 文件卷。 这些卷作为 ReadWriteMany 装载,可同时供多个节点使用。

群集管理员可以静态创建永久性卷,也可以由 Kubernetes API 服务器动态创建卷。 如果已计划 Pod 并请求当前不可用的存储,则 Kubernetes 可以创建基础 VHDX 文件并将其附加到 Pod。 动态预配使用 StorageClass 来标识需要创建的存储类型

存储类

若要定义存储的不同层(和位置),可以创建 StorageClassStorageClass 还定义了 reclaimPolicy。 删除 Pod 后且可能不再需要永久性卷时,此 reclaimPolicy 可控制基础存储资源在此情况下的行为。 可以删除或保留基础存储资源,以便与将来的 Pod 一起使用。

在 AKS Arc 中,默认的存储类会自动创建,并使用 CSV 创建基于 VHDX 的卷。 回收策略确保在删除使用基础 VHDX 的持久卷时会删除该磁盘。 存储类还会将永久性卷配置为可扩展,因此只需编辑具有新大小的永久性卷声明。

如果未为永久性卷指定 StorageClass,则使用默认 StorageClass。 请求持久卷时,请确保它们使用适当的存储。 可以创建 StorageClass 以满足其他需求。

永久性卷声明

PersistentVolumeClaim 会请求特定 StorageClass 和大小的 ReadWriteOnceReadWriteMany 存储。 如果不存在基于定义的 StorageClass 满足声明的现有资源,Kubernetes API 服务器可以在 AKS Arc 中动态预配基础存储资源。 卷连接到 Pod 后,Pod 定义即会包含装载。

可用存储资源分配给请求它的 Pod 后,PersistentVolume 就会绑定到 PersistentVolumeClaim。 永久性卷与声明之间存在 1:1 的映射。

以下示例 YAML 清单显示使用默认 StorageClass 并请求 5Gi 磁盘的永久性卷声明:

apiVersion: v1 
kind: PersistentVolumeClaim 
metadata: 
  name: aks-hci-vhdx 
spec: 
  accessModes: 
  - ReadWriteOnce 
  storageClassName: default 
  resources: 
    requests: 
      storage: 5Gi 

创建 Pod 定义时,你将指定持久性卷声明来请求需要的存储。 然后,您还要指定 volumeMount 以便应用程序读取和写入数据。 以下示例 YAML 清单说明如何使用先前的永久性卷声明来将卷装载到 /mnt/aks-hci

kind: Pod 
apiVersion: v1 
metadata: 
  name: nginx 
spec: 
  containers: 
    - name: myfrontend 
      image: k8s.gcr.io/nginx 
      volumeMounts: 
      - mountPath: "/mnt/aks-hci" 
        name: volume
  nodeSelector:
      kubernetes.io/os: linux
  volumes: 
    - name: volume 
      persistentVolumeClaim: 
        claimName: aks-hci-vhdx 

以下示例演示如何在 Windows 容器中挂载存储卷并指定盘符和路径:

volumeMounts: 
        - mountPath: "d:" 
          name: volume 
        - mountPath: "c:\k" 
          name: k-dir 

保护 Pod 对已挂载卷的访问

若要使应用程序正常运行,pod 应作为定义的用户或组运行,而不应作为 root 运行。 通过 Pod 或容器的 securityContext,可定义 fsGroup 等设置,以承担已安装的卷上的相应权限 。

fsGroup 是 Kubernetes Pod 规范中的 securityContext 字段。 它定义了一个补充组 ID,Kubernetes 将该 ID 分配给 Pod 中的所有进程,并以递归方式分配给已挂载卷中的文件。 这可确保 Pod 对共享存储卷具有正确的组级访问权限。

装载卷后,Kubernetes 会更改卷内容的所有权,以匹配 fsGroup 值。 当容器作为非根用户运行并且需要对共享卷进行写入访问权限时,这尤其有用。

以下示例 YAML 显示了 fsgroup 值:

securityContext:
  fsGroup: 2000

在此示例中,装载卷中的所有文件都可以由 GID 2000 访问。

后续步骤