Skip to content

EKS 存储测验 - 第 1 部分

本测验测试你对 Amazon EKS 中存储概念的理解,包括持久卷、存储类和动态预置。

多项选择题

1. Amazon EKS 默认原生支持哪种存储驱动?

A. Amazon EFS CSI Driver B. Amazon EBS CSI Driver C. Amazon FSx for Lustre CSI Driver D. Amazon S3 CSI Driver

显示答案

答案:B. Amazon EBS CSI Driver

解释: Amazon EKS 默认原生支持的存储驱动是 Amazon EBS CSI (Container Storage Interface) Driver。该驱动允许将 Amazon Elastic Block Store (EBS) 卷用作 Amazon EKS 集群中的持久存储。

主要特性:

  1. 作为 EKS Add-on 提供:Amazon EBS CSI driver 作为 EKS add-on 提供,便于安装和管理。

    bash
    aws eks create-addon \
      --cluster-name my-cluster \
      --addon-name aws-ebs-csi-driver \
      --service-account-role-arn arn:aws:iam::111122223333:role/AmazonEKS_EBS_CSI_DriverRole
  2. 支持动态预置:通过 StorageClass 支持 EBS 卷的动态预置。

    yaml
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: ebs-sc
    provisioner: ebs.csi.aws.com
    volumeBindingMode: WaitForFirstConsumer
    parameters:
      type: gp3
      encrypted: "true"
  3. 支持卷快照:支持卷快照和恢复功能。

    yaml
    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: ebs-volume-snapshot
    spec:
      volumeSnapshotClassName: ebs-snapshot-class
      source:
        persistentVolumeClaimName: ebs-claim
  4. 多种 EBS 卷类型:支持多种 EBS 卷类型,包括 gp2、gp3、io1、io2、sc1、st1。

所需 IAM 权限:

EBS CSI driver 需要以下 IAM 权限才能运行:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateSnapshot",
        "ec2:AttachVolume",
        "ec2:DetachVolume",
        "ec2:ModifyVolume",
        "ec2:DescribeAvailabilityZones",
        "ec2:DescribeInstances",
        "ec2:DescribeSnapshots",
        "ec2:DescribeTags",
        "ec2:DescribeVolumes",
        "ec2:DescribeVolumesModifications"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateTags"
      ],
      "Resource": [
        "arn:aws:ec2:*:*:volume/*",
        "arn:aws:ec2:*:*:snapshot/*"
      ],
      "Condition": {
        "StringEquals": {
          "ec2:CreateAction": [
            "CreateVolume",
            "CreateSnapshot"
          ]
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DeleteTags"
      ],
      "Resource": [
        "arn:aws:ec2:*:*:volume/*",
        "arn:aws:ec2:*:*:snapshot/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateVolume"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "aws:RequestTag/ebs.csi.aws.com/cluster": "true"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateVolume"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "aws:RequestTag/CSIVolumeName": "*"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DeleteVolume"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DeleteVolume"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "ec2:ResourceTag/CSIVolumeName": "*"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DeleteVolume"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "ec2:ResourceTag/kubernetes.io/created-for/pvc/name": "*"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DeleteSnapshot"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "ec2:ResourceTag/CSIVolumeSnapshotName": "*"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DeleteSnapshot"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true"
        }
      }
    }
  ]
}

限制:

  1. 可用区限制:EBS 卷受限于单个可用区,因此 pods 必须在与该卷相同的可用区中运行。
  2. 单节点挂载:EBS 卷一次只能挂载到一个节点(ReadWriteOnce 访问模式)。
  3. Fargate 限制:Amazon EKS Fargate 目前不支持 EBS CSI driver。

其他选项的问题:

  • A. Amazon EFS CSI Driver:EFS CSI driver 在 EKS 中受支持,但默认不会安装。必须单独安装。
  • C. Amazon FSx for Lustre CSI Driver:FSx for Lustre CSI driver 在 EKS 中受支持,但默认不会安装。必须单独安装。
  • D. Amazon S3 CSI Driver:目前没有官方的 Amazon S3 CSI driver。S3 通常通过 S3 API 访问,而不是通过 CSI 直接挂载。

2. 当 Amazon EKS 中多个 pods 需要同时读/写访问时,最合适的存储解决方案是什么?

A. Amazon EBS B. Amazon EFS C. Amazon S3 D. Amazon FSx for Lustre

显示答案

答案:B. Amazon EFS

解释: 当 Amazon EKS 中多个 pods 需要同时读/写访问时,最合适的存储解决方案是 Amazon EFS (Elastic File System)。EFS 是一项托管的 NFS (Network File System) 服务,支持 ReadWriteMany (RWX) 访问模式,允许多个 pods 同时读取和写入同一个卷。

主要特性:

  1. 多可用区访问:EFS 可以跨多个可用区访问,允许运行在不同节点和可用区中的 pods 访问相同的数据。

  2. 支持 ReadWriteMany:EFS 支持 ReadWriteMany (RWX) 访问模式,使多个 pods 能够同时读取和写入同一个卷。

    yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: efs-claim
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: efs-sc
      resources:
        requests:
          storage: 5Gi
  3. 可扩展性:EFS 会自动扩展,消除了容量规划的需要。

  4. 持久性和可用性:提供 99.999999999%(11 个 9)的持久性和 99.99% 的可用性。

EFS CSI Driver 安装:

bash
# Install using Helm
helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/
helm repo update
helm upgrade -i aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver \
  --namespace kube-system \
  --set controller.serviceAccount.create=true \
  --set controller.serviceAccount.name=efs-csi-controller-sa

EFS 文件系统创建:

bash
# Create EFS file system
aws efs create-file-system \
  --creation-token eks-efs \
  --performance-mode generalPurpose \
  --throughput-mode bursting \
  --tags Key=Name,Value=EKS-EFS

# Create mount target
aws efs create-mount-target \
  --file-system-id fs-0123456789abcdef0 \
  --subnet-id subnet-0123456789abcdef0 \
  --security-groups sg-0123456789abcdef0

StorageClass 和 PVC 配置:

yaml
# Create StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId: fs-0123456789abcdef0
  directoryPerms: "700"

# Create PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Gi

使用场景:

  1. 共享文件系统:当多个 pods 需要访问相同文件时
  2. Web Server 内容:当多个 web server pods 需要提供相同的静态内容时
  3. 日志聚合:当多个 pods 写入同一个日志目录时
  4. CI/CD Pipelines:当构建产物需要共享时

性能注意事项:

  1. 性能模式
    • General Purpose:适用于大多数工作负载
    • Max I/O:适用于需要高吞吐量的工作负载
  2. 吞吐量模式
    • Bursting:默认模式,基于文件系统大小提供突增积分
    • Provisioned:在需要一致吞吐量时预置特定吞吐量
  3. 延迟:EFS 的延迟可能高于块存储,因此可能不适合对延迟敏感的应用程序。

安全注意事项:

  1. 加密:EFS 支持传输中和静态加密。

    bash
    aws efs create-file-system \
      --creation-token eks-efs \
      --encrypted \
      --kms-key-id 1234abcd-12ab-34cd-56ef-1234567890ab
  2. 访问控制:可以通过 IAM policies、network ACLs 和 security groups 控制访问。

  3. Access Points:EFS access points 可用于限制对特定目录的访问。

其他选项的问题:

  • A. Amazon EBS:EBS 仅支持 ReadWriteOnce (RWO) 访问模式,因此一次只能挂载到一个节点。
  • C. Amazon S3:S3 是对象存储,不是文件系统,因此不能通过标准文件系统接口直接挂载。
  • D. Amazon FSx for Lustre:FSx for Lustre 适用于高性能工作负载,但与 EFS 相比,设置更复杂且成本更高。

4. 在 Amazon EKS 中使用 EBS 卷时有什么限制?

A. EBS 卷可以让多个 pods 同时进行读/写访问 B. EBS 卷可以跨多个可用区访问 C. EBS 卷一次只能让一个 pod 进行读/写访问 D. EBS 卷可以与 Fargate pods 一起使用

显示答案

答案:C. EBS 卷一次只能让一个 pod 进行读/写访问

解释: Amazon EBS (Elastic Block Store) 卷一次只能让一个 pod 进行读/写访问。这是 EBS 的基本限制,因为 EBS 卷仅支持 ReadWriteOnce (RWO) 访问模式。

主要限制:

  1. 单节点挂载:EBS 卷一次只能挂载到一个 EC2 instance。因此,跨多个节点的 pods 无法访问同一个 EBS 卷。

  2. 可用区限制:EBS 卷受限于其创建所在的可用区。运行在不同可用区节点上的 pods 无法访问该卷。

    yaml
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: ebs-sc
    provisioner: ebs.csi.aws.com
    volumeBindingMode: WaitForFirstConsumer  # Delay volume creation until pod is scheduled
  3. Fargate 不兼容:Amazon EKS Fargate 目前不支持 EBS 卷。Fargate pods 无法挂载 EBS 卷。

  4. 访问模式限制:EBS 仅支持以下访问模式:

    • ReadWriteOnce (RWO):由单个节点进行读写挂载
    yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: ebs-claim
    spec:
      accessModes:
        - ReadWriteOnce  # The only access mode supported by EBS
      storageClassName: ebs-sc
      resources:
        requests:
          storage: 10Gi

解决这些限制的替代方案:

  1. 使用 StatefulSet:通过为每个 pod 提供专用 EBS 卷来运行有状态应用程序

    yaml
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      serviceName: "nginx"
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
      volumeClaimTemplates:
      - metadata:
          name: www
        spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: ebs-sc
          resources:
            requests:
              storage: 10Gi
  2. 使用 Amazon EFS:当多个 pods 需要访问同一个卷时,使用支持 ReadWriteMany (RWX) 访问模式的 EFS

  3. 卷复制:将数据复制到多个 EBS 卷,以允许多个 pods 访问

  4. 拓扑感知调度:使用 volumeBindingMode: WaitForFirstConsumer 在 pod 被调度的可用区中创建卷

可用区注意事项:

  1. 使用 Node Selector:将 pods 调度到特定可用区中的节点

    yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: az-pod
    spec:
      nodeSelector:
        topology.kubernetes.io/zone: us-west-2a
      containers:
      - name: app
        image: nginx
  2. 卷快照和恢复:当数据需要移动到不同可用区时,使用卷快照

    yaml
    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: ebs-snapshot
    spec:
      volumeSnapshotClassName: ebs-snapshot-class
      source:
        persistentVolumeClaimName: ebs-claim

最佳实践:

  1. 适当的存储选择:根据工作负载要求选择适当的存储类型
    • 单 pod 访问:EBS
    • 多 pod 访问:EFS
    • 高性能工作负载:FSx for Lustre
  2. 可用区感知部署:确保 pods 和卷位于同一个可用区
  3. 卷备份:通过定期快照保护数据

其他选项的问题:

  • A. EBS 卷可以让多个 pods 同时进行读/写访问:这是不正确的。EBS 卷仅支持 ReadWriteOnce (RWO) 访问模式。
  • B. EBS 卷可以跨多个可用区访问:这是不正确的。EBS 卷受限于其创建所在的可用区。
  • D. EBS 卷可以与 Fargate pods 一起使用:这是不正确的。Amazon EKS Fargate 目前不支持 EBS 卷。

简答题

6. 在 Amazon EKS 中为 EBS 卷进行动态预置时,PersistentVolumeClaim 中必须指定哪种访问模式?

显示答案

答案: ReadWriteOnce (RWO)

详细解释:

在 Amazon EKS 中为 EBS 卷进行动态预置时,PersistentVolumeClaim (PVC) 中必须指定的访问模式是 ReadWriteOnce (RWO)。这是由 EBS 卷的基本特性决定的:它一次只能让一个节点进行读/写访问。

访问模式说明:

  1. ReadWriteOnce (RWO):该卷可以由单个节点以读写模式挂载。
  2. ReadOnlyMany (ROX):该卷可以由多个节点以只读模式挂载。
  3. ReadWriteMany (RWX):该卷可以由多个节点以读写模式挂载。

为什么 EBS 仅支持 RWO:

Amazon EBS 是一种块存储服务,设计为一次仅附加到一个 EC2 instance。这不是硬件限制,而是 EBS 服务的设计特性。因此,EBS 卷仅支持 ReadWriteOnce 访问模式。

PVC 示例:

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-claim
spec:
  accessModes:
    - ReadWriteOnce  # The only access mode supported by EBS
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 10Gi

需要其他访问模式时的替代方案:

  1. 需要 ReadOnlyMany (ROX) 时:

    • 创建 EBS snapshot,并创建多个只读 EBS 卷
    • 为每个节点提供单独的只读卷
  2. 需要 ReadWriteMany (RWX) 时:

    • 使用 Amazon EFS(基于 NFS 的文件系统)
    yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: efs-claim
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: efs-sc
      resources:
        requests:
          storage: 5Gi

使用 EBS 卷时的注意事项:

  1. Pod 调度:使用 EBS 卷的 Pods 只能运行在该卷所附加到的节点上。

  2. 可用区限制:EBS 卷受限于其创建所在的可用区。因此,pods 只能运行在该可用区中的节点上。

  3. 卷绑定模式:建议使用 WaitForFirstConsumer 在 pod 调度后创建卷。

    yaml
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: ebs-sc
    provisioner: ebs.csi.aws.com
    volumeBindingMode: WaitForFirstConsumer
  4. 与 StatefulSet 一起使用:StatefulSet 为每个 pod 提供唯一的 PVC,因此适合与 EBS 卷一起使用。

访问模式选择指南:

存储类型ReadWriteOnceReadOnlyManyReadWriteMany
Amazon EBS
Amazon EFS
FSx for Lustre

使用 EBS 卷时,请始终指定 ReadWriteOnce 访问模式。如果需要多个节点同时访问,请考虑 EFS 或 FSx for Lustre 等替代方案。

7. 在 Amazon EKS 中,使用 EBS 卷的 pod 移动到不同节点时,数据会发生什么?

显示答案

答案: EBS 卷会从之前的节点分离,并附加到新节点。数据会被保留,但在卷重新附加过程中可能会有延迟。

详细解释:

当 Amazon EKS 中使用 EBS 卷的 pod 移动到不同节点时(例如由于节点故障、扩缩容、更新等),EBS 卷会从之前的节点分离,并附加到新节点。在此过程中,数据会被保留,但卷重新附加过程中可能会有延迟。

卷重新附加过程:

  1. Pod 终止:pod 在原始节点上终止。
  2. 卷分离:EBS 卷从原始节点分离。
  3. 卷附加:EBS 卷附加到新节点。
  4. Pod 启动:pod 在新节点上启动并挂载该卷。

该过程的影响:

  1. 延迟时间:卷分离和附加操作通常需要 10-30 秒,但在某些情况下可能需要更长时间。
  2. 可用区限制:EBS 卷受限于其创建所在的可用区,因此 pods 只能移动到同一可用区内的其他节点。
  3. 数据持久性:数据会被保留,在卷重新附加过程中不会丢失。

处理此行为的策略:

  1. 使用 PodDisruptionBudget:通过限制可同时中断的 pods 数量来确保可用性

    yaml
    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: app-pdb
    spec:
      minAvailable: 2  # or maxUnavailable: 1
      selector:
        matchLabels:
          app: my-app
  2. 配置适当的 readinessProbe 和 livenessProbe:在卷正确挂载且应用程序就绪之前延迟接收流量

    yaml
    readinessProbe:
      exec:
        command:
        - cat
        - /data/ready
      initialDelaySeconds: 5
      periodSeconds: 5
  3. 使用 StatefulSet:StatefulSet 提供顺序部署和扩缩容,以尽量减少卷重新附加的影响。

  4. 优化卷绑定模式:使用 WaitForFirstConsumer 在 pod 被调度的可用区中创建卷

    yaml
    volumeBindingMode: WaitForFirstConsumer

可用区注意事项:

  1. 多可用区部署:跨多个可用区部署应用程序,以提高对单个 AZ 故障的韧性

  2. 拓扑分布:使用 topologySpreadConstraints 将 pods 分布到多个可用区

    yaml
    topologySpreadConstraints:
    - maxSkew: 1
      topologyKey: topology.kubernetes.io/zone
      whenUnsatisfiable: DoNotSchedule
      labelSelector:
        matchLabels:
          app: my-app
  3. 可用区感知 PDB:为每个可用区配置单独的 PodDisruptionBudget

最佳实践:

  1. 优化应用程序以快速重启:设计应用程序,使其能够快速启动和初始化

  2. 设置适当的终止宽限期:为应用程序优雅终止提供足够时间

    yaml
    terminationGracePeriodSeconds: 60
  3. 关键数据备份策略:通过定期快照或备份保护数据

  4. 考虑无状态设计:在可能的情况下,将应用程序设计为无状态,以尽量减少节点迁移的影响

当使用 EBS 卷的 pod 在节点之间移动时,数据会被保留,但卷重新附加过程中可能会出现延迟,因此在应用程序设计和配置中考虑这一点非常重要。

9. 在 Amazon EKS 中,用于创建 EBS 卷快照的 Kubernetes API 资源是什么?

显示答案

答案: VolumeSnapshot

详细解释:

在 Amazon EKS 中,用于创建 EBS 卷快照的 Kubernetes API 资源是 VolumeSnapshot。该资源是 Kubernetes Volume Snapshot API 的一部分,并与 CSI (Container Storage Interface) drivers 配合使用,以创建持久卷的时间点副本。

使用 VolumeSnapshot 的前提条件:

  1. 安装 EBS CSI Driver:集群中必须安装 AWS EBS CSI driver。

  2. 安装 Snapshot Controller:集群中必须安装 Kubernetes snapshot controller。

    bash
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml
  3. 创建 VolumeSnapshotClass:创建定义快照创建方式的 VolumeSnapshotClass。

VolumeSnapshotClass 示例:

yaml
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: ebs-snapshot-class
driver: ebs.csi.aws.com
deletionPolicy: Delete

VolumeSnapshot 创建示例:

yaml
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: ebs-volume-snapshot
spec:
  volumeSnapshotClassName: ebs-snapshot-class
  source:
    persistentVolumeClaimName: ebs-claim

检查 Snapshot 状态:

bash
kubectl get volumesnapshot ebs-volume-snapshot

从 Snapshot 创建新 PVC:

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-claim-from-snapshot
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 10Gi
  dataSource:
    name: ebs-volume-snapshot
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io

VolumeSnapshot 的主要优势:

  1. 数据保护:创建关键数据的时间点备份
  2. 灾难恢复:在数据丢失或损坏时支持恢复
  3. 环境复制:为开发或测试环境复制生产数据
  4. 数据迁移:将数据从一个集群移动到另一个集群

Snapshot 生命周期管理:

  1. 自动创建 Snapshot:使用 CronJob 自动定期创建 snapshot

    yaml
    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: volume-snapshot-job
    spec:
      schedule: "0 0 * * *"  # Daily at midnight
      jobTemplate:
        spec:
          template:
            spec:
              serviceAccountName: snapshot-creator
              containers:
              - name: snapshot-creator
                image: bitnami/kubectl:latest
                command:
                - /bin/sh
                - -c
                - |
                  cat <<EOF | kubectl apply -f -
                  apiVersion: snapshot.storage.k8s.io/v1
                  kind: VolumeSnapshot
                  metadata:
                    name: ebs-snapshot-$(date +%Y%m%d)
                  spec:
                    volumeSnapshotClassName: ebs-snapshot-class
                    source:
                      persistentVolumeClaimName: ebs-claim
                  EOF
              restartPolicy: OnFailure
  2. Snapshot 保留策略:自动删除旧 snapshots

    yaml
    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: snapshot-cleanup-job
    spec:
      schedule: "0 1 * * *"  # Daily at 1 AM
      jobTemplate:
        spec:
          template:
            spec:
              serviceAccountName: snapshot-manager
              containers:
              - name: snapshot-cleaner
                image: bitnami/kubectl:latest
                command:
                - /bin/sh
                - -c
                - |
                  # Delete snapshots older than 30 days
                  kubectl get volumesnapshot -o json | jq -r '.items[] | select(.metadata.creationTimestamp | fromnow | contains("days") and (split(" ")[0] | tonumber) > 30) | .metadata.name' | xargs -r kubectl delete volumesnapshot
              restartPolicy: OnFailure

最佳实践:

  1. 定期 Snapshots:为关键数据设置定期 snapshot 计划
  2. 测试 Snapshots:定期测试从 snapshots 恢复,以验证备份有效性
  3. 标记:为 snapshots 应用适当标签,便于管理和成本跟踪
  4. 成本监控:监控并优化成本,因为 EBS snapshots 会产生额外费用
  5. 加密:对敏感数据使用加密 snapshots

使用 VolumeSnapshot API 可以用 Kubernetes-native 的方式创建和管理 EBS 卷快照,从而有效实施数据保护和恢复策略。

动手实践题

10. 为 Amazon EKS 集群中具有多样化存储需求的应用程序设计一个存储解决方案。创建满足以下需求的 storage classes 和 persistent volume claims:

  • 用于数据库的高性能块存储
  • 需要在多个 pods 之间共享的配置文件
  • 用于 AI/ML 工作负载的高性能并行文件系统
显示答案

答案:

以下是一个满足 Amazon EKS 集群中多样化存储需求的存储解决方案:

1. 用于数据库的高性能块存储 (Amazon EBS gp3)

StorageClass 定义:

yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-gp3-db
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
  type: gp3
  iops: "16000"  # Maximum IOPS
  throughput: "1000"  # Maximum throughput (MB/s)
  encrypted: "true"
allowVolumeExpansion: true

PersistentVolumeClaim 定义:

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: database-data
  namespace: database
spec:
  accessModes:
    - ReadWriteOnce  # EBS can only be mounted to a single node
  storageClassName: ebs-gp3-db
  resources:
    requests:
      storage: 100Gi

Database Pod 示例:

yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
  namespace: database
spec:
  serviceName: "postgres"
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:14
        env:
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: postgres-secret
              key: password
        ports:
        - containerPort: 5432
        volumeMounts:
        - name: data
          mountPath: /var/lib/postgresql/data
        resources:
          requests:
            cpu: "2"
            memory: "4Gi"
          limits:
            cpu: "4"
            memory: "8Gi"
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: ebs-gp3-db
      resources:
        requests:
          storage: 100Gi

解释:

  • gp3 Volume Type:提供最高 16,000 IOPS 和 1,000MB/s 吞吐量,适合数据库工作负载。
  • WaitForFirstConsumer:将卷创建延迟到 pod 调度时,以防止可用区问题。
  • 加密:为 EBS 卷启用静态数据加密。
  • 卷扩展:允许将来随着数据库规模增长进行卷扩展。
  • StatefulSet:为数据库提供稳定的网络 ID 和持久存储。

2. 跨多个 Pods 共享的配置文件 (Amazon EFS)

EFS CSI Driver 安装:

bash
helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/
helm repo update
helm upgrade -i aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver \
  --namespace kube-system \
  --set controller.serviceAccount.create=true \
  --set controller.serviceAccount.name=efs-csi-controller-sa

StorageClass 定义:

yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId: fs-0123456789abcdef0  # Existing EFS file system ID
  directoryPerms: "700"

PersistentVolumeClaim 定义:

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: config-storage
  namespace: application
spec:
  accessModes:
    - ReadWriteMany  # Multiple pods can read/write simultaneously
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Gi  # This value is symbolic as EFS auto-scales

使用配置文件的 Deployment 示例:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: application
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: web-app
        image: nginx:latest
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
          limits:
            cpu: "1"
            memory: "1Gi"
      volumes:
      - name: config-volume
        persistentVolumeClaim:
          claimName: config-storage

解释:

  • ReadWriteMany Access Mode:EFS 支持多个 pods 同时读取和写入同一个卷。
  • 多可用区支持:EFS 可以跨多个可用区访问,提供对节点故障的韧性。
  • 自动扩展:EFS 根据使用量自动扩展,消除容量规划需求。
  • Access Points:EFS access points 可用于限制对特定目录的访问。

3. 用于 AI/ML 工作负载的高性能并行文件系统 (Amazon FSx for Lustre)

FSx CSI Driver 安装:

bash
helm repo add aws-fsx-csi-driver https://kubernetes-sigs.github.io/aws-fsx-csi-driver/
helm repo update
helm upgrade -i aws-fsx-csi-driver aws-fsx-csi-driver/aws-fsx-csi-driver \
  --namespace kube-system \
  --set controller.serviceAccount.create=true \
  --set controller.serviceAccount.name=fsx-csi-controller-sa

StorageClass 定义:

yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fsx-lustre
provisioner: fsx.csi.aws.com
parameters:
  subnetId: subnet-0123456789abcdef0  # Subnet for FSx file system
  securityGroupIds: sg-0123456789abcdef0  # Security group for FSx file system
  deploymentType: SCRATCH_2  # High-performance temporary storage
  perUnitStorageThroughput: "200"  # MB/s/TiB
  dataCompressionType: "LZ4"  # Enable data compression
  s3ImportPath: s3://ml-training-data-bucket/  # Optional: Import data from S3
mountOptions:
  - flock

PersistentVolumeClaim 定义:

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ml-training-data
  namespace: ml-workloads
spec:
  accessModes:
    - ReadWriteMany  # Multiple pods can read/write simultaneously
  storageClassName: fsx-lustre
  resources:
    requests:
      storage: 1200Gi  # FSx for Lustre starts at minimum 1.2TiB

ML Training Job 示例:

yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: ml-training
  namespace: ml-workloads
spec:
  parallelism: 4  # Number of parallel jobs
  template:
    spec:
      containers:
      - name: training
        image: tensorflow/tensorflow:latest-gpu
        command:
          - "python"
          - "/training/train.py"
        volumeMounts:
        - name: training-data
          mountPath: "/training"
        resources:
          limits:
            nvidia.com/gpu: 4  # GPU resource request
          requests:
            cpu: "8"
            memory: "32Gi"
      volumes:
      - name: training-data
        persistentVolumeClaim:
          claimName: ml-training-data
      restartPolicy: Never
  backoffLimit: 2

解释:

  • 高性能:FSx for Lustre 提供数百 GB/s 的吞吐量和数百万 IOPS,适合 AI/ML 工作负载。
  • 并行访问:多个计算节点可以同时访问相同数据,非常适合分布式训练。
  • S3 集成:训练数据可以存储在 S3 中,并导入 FSx for Lustre 进行处理。
  • 数据压缩:使用 LZ4 压缩以提高存储效率。
  • SCRATCH_2 Deployment Type:用于临时处理的高性能、经济高效选项。

其他注意事项和最佳实践

1. 备份和灾难恢复:

yaml
# EBS volume snapshot creation
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: ebs-snapshot-class
driver: ebs.csi.aws.com
deletionPolicy: Retain

---
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: database-snapshot
  namespace: database
spec:
  volumeSnapshotClassName: ebs-snapshot-class
  source:
    persistentVolumeClaimName: database-data

2. 监控和告警:

  • 设置 CloudWatch alarms 来监控存储使用量、延迟和吞吐量。
  • 使用 Prometheus 和 Grafana 可视化存储指标。

3. 成本优化:

  • 删除未使用的卷之前,先删除或创建其 snapshots。
  • 选择适当的存储类型和大小以优化成本。
  • 对于 FSx for Lustre,如果不需要长期存储,请使用 SCRATCH deployment type。

4. 安全:

  • 为所有卷启用加密。
  • 配置适当的 IAM permissions 和 security groups。
  • 使用 PodSecurityPolicy 或 SecurityContext 限制卷访问。

此设计提供了一个全面的存储解决方案,满足多样化的工作负载需求:

  • 用于数据库的高性能 EBS gp3 卷
  • 支持多读/写访问、用于配置文件共享的 EFS
  • 用于 AI/ML 工作负载的高性能并行文件系统 FSx for Lustre

每个存储解决方案都针对特定工作负载需求进行了优化,并在设计中考虑了可扩展性、性能和成本效率。