コンテンツにスキップ

AWS EBS CSI ドライバー@Amazon EKS アドオン

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. AWS EBS CSI ドライバー

アーキテクチャ

PersistentVolume に AWS EBS を紐付け、Pod が AWS EBS を PersistentVolume として使用できるようにする。

ステートレスなアプリケーションでは、AWS EBS にデータを永続化する必要はないため、AWS EBS CSI ドライバーは不要である。

storage_class


02. セットアップ

EKS アドオンとして

▼ Terraform の場合

Terraform を使用する。

Terraform の aws_eks_addon で EKS アドオンをインストールし、AWS EBS CSI ドライバーに関する Kubernetes リソースを作成する。

# Amazon EKSアドオンをインストールする。
resource "aws_eks_addon" "aws_ebs_csi_driver" {

  cluster_name                = data.aws_eks_cluster.cluster.name
  addon_name                  = "aws-ebs-csi-driver"
  addon_version               = "<バージョン>"
  service_account_role_arn    = module.iam_assumable_role_ebs_csi_driver[0].iam_role_arn
  # Terraformで設定を上書きできるようにする
  resolve_conflicts_on_update = "OVERWRITE"
}
module "iam_assumable_role_with_oidc_ebs_csi_driver" {

  source                        = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"

  version                       = "<バージョン>"

  # AWS EBS CSI ControllerのPodに紐付けるIAMロール
  create_role                   = true
  role_name                     = "foo-ebs-csi-driver"

  # Amazon EKS ClusterのOIDCプロバイダーURLからhttpsプロトコルを除いたもの
  # ArgoCDは、デプロイ専用のAmazon EKS Cluster上で稼働している
  provider_url                  = replace(module.eks.cluster_oidc_issuer_url, "https://", "")

  # AWS IAMロールに紐付けるIAMポリシー
  role_policy_arns              = [
    "arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy"
  ]

  # AWS EBS CSI ControllerのPodのServiceAccount名
  # ServiceAccountは、Terraformではなく、マニフェストで定義したほうが良い
  oidc_fully_qualified_subjects = [
    "system:serviceaccount:kube-system:foo-ebs-csi-controller"
  ]
}

また、StorageClass を定義する必要があるが、Terraform かマニフェストでよい。

# KubernetesのStorageClassをTerraformで作成する。
# マニフェストとして定義しても良い。
resource "kubernetes_storage_class" "gp3_encrypted" {

  metadata {
    name = "gp3-encrypted"
    annotations = {
      "storageclass.kubernetes.io/is-default-class" = "true"
    }
  }

  # AWS EBS CSIドライバーをプロビジョナーに設定する
  storage_provisioner = "ebs.csi.aws.com"

  parameters = {
    encrypted = "true"
    fsType    = "ext4"
    type      = "gp3"
  }

  reclaim_policy      = "Delete"
  volume_binding_mode = "WaitForFirstConsumer"
}

別途、AWS EBS CSI ドライバーの Pod に紐付ける ServiceAccount を作成し、IAM ロールの ARN を設定する。

ServiceAccount は、Terraform ではなくマニフェストで定義したほうがよい。

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: <IAMロールのARN>
  name: foo-ebs-csi-controller
  namespace: kube-system

IRSA により、ServiceAccount を介して Pod と AWS IAM ロールが紐づく。

▼ Helm の場合

Helm を使用する。

Kubernetes よりも AWS に依存している要素が多いため、Terraform によるセットアップのほうが個人的にはおすすめである。

$ helm repo add <チャートリポジトリ名> https://kubernetes-sigs.github.io/aws-ebs-csi-driver

$ helm repo update

$ helm install <Helmリリース名> <リポジトリ名>/aws-ebs-csi-driver -n kube-system --version=<バージョンタグ>


02-02. マニフェスト

マニフェストの種類

AWS EBS CSI ドライバーは、Deployment (ebs-csi-controller) 、ServiceAccount などのマニフェストから構成される。


Deployment 配下の Pod

記入中...


ServiceAccount

IRSA の仕組みで、Pod と IAM ロールを紐付ける。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: foo-foo-ebs-csi-controller
  namespace: kube-system
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<アカウントID>:role/foo-ebs-csi-controller-role
secrets:
  - name: foo-ebs-csi-controller-token


03. プロビジョニング

静的プロビジョニング

▼ AWS EBS

AWS EBS を手動で作成する必要がある。

▼ PersistentVolume

*実装例*

apiVersion: v1
kind: PersistentVolume
metadata:
  name: foo-persistent-volume
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  csi:
    # AWS EBS CSI ドライバーをプロビジョナーに設定する
    driver: ebs.csi.aws.com
    # 手動で作成した AWS EBS の ID を設定する。
    volumeHandle: vol-*****

▼ PersistentVolumeClaim

PersistentVolumeClaim で Volume を要求する。

PersistentVolumeClaim で Volume を要求すると、AWS EBS CSI ドライバーは、PersistentVolume とそれに紐づく AWS EBS を自動的に作成する。

Pod の .spec.nodeSelector キーも不要である。

*実装例*

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: foo-persistent-volume-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  # デフォルトの動的プロビジョニングを確実に無効化する
  storageClassName: ""
apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: foo
  template:
    metadata:
      labels:
        app: foo
    spec:
      containers:
        - name: foo
          image: busybox
          command:
            - /bin/bash
            - -c
            - sleep 10000
          volumeMounts:
            - mountPath: /app/data
              name: data
      nodeSelector:
        topology.ebs.csi.aws.com/zone: ap-northeast-1a
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: foo-persistent-volume-claim


動的プロビジョニング

▼ AWS EBS

AWS EBS は、AWS EBS CSI ドライバーが自動で作成するため、作成は不要である。

▼ StorageClass

自動的に PersistentVolume を作成する動的プロビジョニングの場合、StorageClass が必要である。

要求する AWS EBS のタイプを StorageClass で指定する。

reclaimPolicy が Delete になっている PersistentVolumeClaim を削除すれば、StorageClass が EBS もよしなに削除してくれる。

*実装例*

マニフェストまたは Terraform で定義する。

# マニフェストで定義した場合
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: foo-storage-class
parameters:
  type: gp3
provisioner: ebs.csi.aws.com
# PersistentVolumeClaim が削除された時に、AWS EBS も自動的に削除できるようにする
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
# Terraformで定義した場合
resource "kubernetes_storage_class" "gp3_encrypted" {

  metadata {
    name = "foo-storage-class"
  }

  # AWS EBS CSIドライバーをプロビジョナーに設定する
  storage_provisioner = "ebs.csi.aws.com"

  parameters = {
    encrypted = "true"
    fsType    = "ext4"
    type      = "gp3"
  }

  volume_binding_mode = "WaitForFirstConsumer"
}

▼ PersistentVolumeClaim

PersistentVolumeClaim で StorageClass を指定し、外部サービスが提供する Volume を要求する。

StorageClass が指定された PersistentVolumeClaim で Volume を要求すると、AWS EBS CSI ドライバーは、PersistentVolume とそれに紐づく AWS EBS を自動的に作成する。

Pod の .spec.nodeSelector キーも不要である。

*実装例*

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: foo-persistent-volume-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  # AWS EBS CSI ドライバーがプロビジョナーに指定された StorageClass を要求する
  storageClassName: foo-storage-class
apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: foo
  template:
    metadata:
      labels:
        app: foo
    spec:
      containers:
        - name: foo
          image: busybox
          command:
            - /bin/bash
            - -c
            - sleep 10000
          volumeMounts:
            - mountPath: /app/data
              name: data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: foo-persistent-volume-claim