Amazon EKS FargateでEFSをマウントしてみた

はじめに

こんにちは、久しぶりのブログ投稿となってしまった今日この頃です。

今回は、EKS FargateにEFSをマウントしてみたので備忘録として記録します。

構成図

構成図にあります、EKS FargateとEFS部分について触れていきます。

その他のコンポーネントについては触れませんのでご了承ください。

EKS FargateからPersistentVolume(PV)とPersistentVolumeClaim(PVC)を作成し、作成したリソースをpodから使用する流れとなります。

前提条件

次の項目を完了している。

クラスターの IAM OIDC プロバイダーを作成する – Amazon EKS

Amazon EFS で伸縮自在なファイルシステムを保存する – Amazon EKS

ステップ 1: IAM ロールを作成する
ステップ 2: Amazon EFS CSI ドライバーを取得する
ステップ 3:Amazon EFS ファイルシステムを作成する

kubectl および eksctl のセットアップ – Amazon EKS

リンク先に出てくるkubectlやeksctコマンドはこちらからダウンロード可能です。

補足事項

前提条件にあります、「ステップ 2: Amazon EFS CSI ドライバーを取得する」について補足します。

クラスターアドオン画面から「Amazon EFS CSI ドライバー」を追加するところで、アドオンアクセス項目より「サービスアカウントの IAM ロール (IRSA)」を選択します。

IAM ロールの選択で「AmazonEKS_EFS_CSI_DriverRole」を選択するのを忘れないようにして下さい。

※ AmazonEKS_EFS_CSI_DriverRoleは「ステップ 1: IAM ロールを作成する」で作成するIAMロールを使用します。

efs-csi-controllerの修正

クラスターアドオン画面から「Amazon EFS CSI ドライバー」を追加すると、クラスターにサービスアカウントやdeployment、pod等が展開されますが、deploymentの設定に「privileged」という特権に関する設定が入っていることでデプロイが正常になされませんので修正します。

privilegedの削除

kubectl get deployment efs-csi-controller -n kube-system -o yaml > efs-csi-controller.yaml.org
 →まず、こちらのコマンドを使用して、deploymentの設定をバックアップします。

cp -p efs-csi-controller.yaml.org efs-csi-controller.yaml
 →編集用にコピーします。

次のコマンドを使用して、特権記述を削除する行番号を確認します。

cat -n efs-csi-controller.yaml | grep -C 3 "privileged"

    74              cpu: 100m
    75              memory: 128Mi
    76          securityContext:
    77            privileged: true
    78          terminationMessagePath: /dev/termination-log
    79          terminationMessagePolicy: File
    80          volumeMounts:

76行目と77行目部分を削除する必要がありますのでsedコマンドを使用して削除します。

sed -i_privileged '76,77d' efs-csi-controller.yaml

追加の処理としてFargateプロファイルを指定

Fargateでは、AZ分散が保証されないため次のリンク先に記載がある通り、Fargateプロファイルを指定してAZ分散を保証させます。

fargate-profile-2とfargate-profile-3を事前に作成しており、fargate-profile-2がus-east-1c、fargate-profile-3がus-east-1aというように各プロファイルへサブネット(AZ)別を1つのみ指定し設定してあるプロファイルを使用します。

※ Fargateプロファイル作成の仕方は上記リンク先に記載がございます。

sed -i_profile-2 '/template:/,/labels:/!b;/labels:/a\ eks.amazonaws.com/fargate-profile: mysystem-primary-fargate-profile-2' efs-csi-controller.yaml
 →sedコマンドを使用して、template: -> labels: 配下へ追記する内容で追記します。

※ 「mysystem-primary-fargate-profile-2」は各自のFergateプロファイル名に置き替えてください。
※ us-east-1aやus-east-1cなど各自の環境に読み替えてください。
※ 本記事中に度々出てきますが、各自の環境に合わせて読み替えるようお願いします。

deployment名を変更(us-east-1c)

us-east-1a、us-east-1c(AZ)別のdeploymentを作成する必要がありますのでdeployment名が重複しないよう名前を変更します。

sed -i_deployment '/^metadata:/,/^ name:/s/^ name: efs-csi-controller$/ name: efs-csi-controller-us-east-1c-fargate-profile-2/' efs-csi-controller.yaml
 →metadata: -> name: 項目を変更します。

us-east-1c が sedコマンド中に入っていますので、注意してください。

レプリカ数の変更

各AZにdeploymentを設定するため、次のコマンドを使用してレプリカ数を1に変更します。

このようにすることで各AZにpod(Fargate)が1つずつ存在するようになります。

sed -i_replicas 's/^\(\s*replicas:\s*\).*/\11/' efs-csi-controller.yaml
 →レプリカの項目を1に変更する sed コマンドです。

ここまでの変更差分確認(us-east-1c)

次の差分結果のように「name、replicas、fargate-profile、privileged」の差分が確認できれば問題ないです。

diff -u efs-csi-controller.yaml.org efs-csi-controller.yaml

--- efs-csi-controller.yaml.org 2024-12-01 03:09:09.832839200 +0900
+++ efs-csi-controller.yaml     2024-12-01 03:13:11.419364600 +0900
@@ -7,13 +7,13 @@
   generation: 1
   labels:
     app.kubernetes.io/name: aws-efs-csi-driver
-  name: efs-csi-controller
+  name: efs-csi-controller-us-east-1c-fargate-profile-2
   namespace: kube-system
   resourceVersion: "1300114"
   uid: 751b2f8c-c6e9-465c-8da4-f5c9c81b94d0
 spec:
   progressDeadlineSeconds: 600
-  replicas: 2
+  replicas: 1
   revisionHistoryLimit: 10
   selector:
     matchLabels:
@@ -29,6 +29,7 @@
     metadata:
       creationTimestamp: null
       labels:
+        eks.amazonaws.com/fargate-profile: mysystem-primary-fargate-profile-2
         app: efs-csi-controller
         app.kubernetes.io/instance: aws-efs-csi-driver
         app.kubernetes.io/name: aws-efs-csi-driver
@@ -73,8 +74,6 @@
           requests:
             cpu: 100m
             memory: 128Mi
-        securityContext:
-          privileged: true
         terminationMessagePath: /dev/termination-log
         terminationMessagePolicy: File
         volumeMounts:
@@ -167,6 +166,6 @@
     status: "True"
     type: Progressing
   observedGeneration: 1
-  replicas: 2
+  replicas: 1
   unavailableReplicas: 2
   updatedReplicas: 2

適用前に既存のデプロイメントを削除

既存のdeploymentを削除する必要がありますので次のコマンドを使用して削除します。

kubectl delete -f efs-csi-controller.yaml.org

deployment.apps "efs-csi-controller" deleted

削除するとサービスに影響が出ますので注意してください。

us-east-1c用deploymentを適用

us-east-1c用のdeploymentが完成しましたのでapplyコマンドで適用します。

kubectl apply -f efs-csi-controller.yaml

deployment.apps/efs-csi-controller-us-east-1c-fargate-profile-2 created

cp -p efs-csi-controller.yaml efs-csi-controller-us-east-1c-fargate-profile-2.yaml
 →分かりやすい名前でバックアップします。

us-east-1aにデプロイするdeployment作成

次のコマンドを使用して、Fargateプロファイル名を変更します。

sed -i_profile-3 's/mysystem-primary-fargate-profile-2/mysystem-primary-fargate-profile-3/g' efs-csi-controller.yaml

deployment名を変更(us-east-1a)

sed -i_deployment '/^metadata:/,/^ name:/s/^ name: efs-csi-controller-us-east-1c-fargate-profile-2$/ name: efs-csi-controller-us-east-1a-fargate-profile-3/' efs-csi-controller.yaml
 →metadata: -> name: 項目を変更します。

us-east-1a が sed コマンド中に入っていますので注意してください。

cp -p efs-csi-controller.yaml efs-csi-controller-us-east-1a-fargate-profile-3.yaml
 →us-east-1a用のdeploymentを分かりやすい名前でバックアップします。

ここまでの変更差分確認(us-east-1a)

次のコマンドを使用して「name、fargate-profile」の差分が確認できれば問題ないです。

diff -u efs-csi-controller-us-east-1c-fargate-profile-2.yaml efs-csi-controller.yaml

--- efs-csi-controller-us-east-1c-fargate-profile-2.yaml        2024-12-01 03:13:11.419364600 +0900
+++ efs-csi-controller.yaml     2024-12-01 03:29:17.303843800 +0900
@@ -7,7 +7,7 @@
   generation: 1
   labels:
     app.kubernetes.io/name: aws-efs-csi-driver
-  name: efs-csi-controller-us-east-1c-fargate-profile-2
+  name: efs-csi-controller-us-east-1a-fargate-profile-3
   namespace: kube-system
   resourceVersion: "1300114"
   uid: 751b2f8c-c6e9-465c-8da4-f5c9c81b94d0
@@ -29,7 +29,7 @@
     metadata:
       creationTimestamp: null
       labels:
-        eks.amazonaws.com/fargate-profile: mysystem-primary-fargate-profile-2
+        eks.amazonaws.com/fargate-profile: mysystem-primary-fargate-profile-3
         app: efs-csi-controller
         app.kubernetes.io/instance: aws-efs-csi-driver
         app.kubernetes.io/name: aws-efs-csi-driver

us-east-1a用deployment適用&動作確認

us-east-1a用に作成したdeploymentを適用し動作確認をおこないます。

kubectl apply -f efs-csi-controller.yaml

deployment.apps/efs-csi-controller-us-east-1a-fargate-profile-3 created

 →us-east-1a用のdeploymentを適用します。

kubectl get deployments.apps --all-namespaces

kube-system   efs-csi-controller-us-east-1a-fargate-profile-3   1/1     1            1           5m12s
kube-system   efs-csi-controller-us-east-1c-fargate-profile-2   1/1     1            1           18m

 →ここまでの適用でus-east-1aとus-east-1cのdeploymentがデプロイされていることが確認できます。

kubectl get po –all-namespaces -o wide

NAMESPACE     NAME                                                              READY   STATUS    RESTARTS   AGE     IP           NODE
                   NOMINATED NODE   READINESS GATES
kube-system   efs-csi-controller-us-east-1a-fargate-profile-3-7b9f98fc9c6hvhd   3/3     Running   0          5m52s   10.0.3.12    fargate-ip-10-0-3-12.ec2.internal    <none>           <none>
kube-system   efs-csi-controller-us-east-1c-fargate-profile-2-59b7cdf9f84jdsz   3/3     Running   0          19m     10.0.4.162   fargate-ip-10-0-4-162.ec2.internal   <none>           <none>

 →暫くするとefs-csi-controllerのpodがAZ別にデプロイされることが確認できます。
  「10.0.3.12」、「10.0.4.162」になり、第三オクテットが異なることが確認できます。
  AZ us-east-1aが「10.0.3.0/24」の範囲、AZ us-east-1cが「10.0.4.0/24」の範囲です。

ここまでの処理でようやく、efs-csi-controllerのデプロイがAZ別に完了しました。

次に、作成したEFSストレージクラスを使用したdeploymentサンプル例を提示しながら説明します。

Amazon EFS CSI ドライバーの動作フロー

筆者の理解としては次の動作フローになります。

間違っている可能性がありますので過信しないでください。

アドオンのインストールとここまでの設定で図中の左側および真ん中部分の準備ができました。

※ ストレージクラスはこの後解説する手順で作成する必要があります。

今度はこれらを利用する図中の右側部分の作成をしていく流れとなります。

永続領域の作成

PersistentVolume(PV)とPersistentVolumeClaim(PVC)は永続領域を要求するリソースとなります。

ストレージクラス作成

Amazon EFS CSI ドライバーを利用するCSIドライバーを作成します。

CSIとは、コンテナーオーケストラレーション向けのストレージインターフェースとなり、ストレージベンダーが開発したストレージ関連のプラグイン化された機能を利用できるシステムになります。

次のようにAmazon EFS CSI ドライバーを利用するストレージクラスを定義します。

vi storage_class.yaml

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com

作成した定義を適用させるため次のコマンドを実行します。

kubectl apply -f storage_class.yaml

storageclass.storage.k8s.io/efs-sc created

これでストレージクラスの作成が完了しましたので、PVリソースの作成を実施します。

PersistentVolume(PV)作成

PersistentVolumeは、長期間に渡ってデータを保存するためのボリュームリソースになります。

PVリソースは次のように定義します。

vi pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: efs-pv
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: efs-sc
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-0b550f9eb7473ec50

 →「volumeHandle: fs-0b550f9eb7473ec50」は、EFSのファイルシステムIDを指定します。

5GBの容量を要求し、PVリソース削除時は、データが保持されるようにしています。

PVリソースを削除した際にデータを削除し再利用可能としたい場合、persistentVolumeReclaimPolicyで「Recycle」を指定します。

作成した定義を適用させるため次のコマンドを実行します。

kubectl apply -f pv.yaml

persistentvolume/efs-pv created

STATUSがAvailableになれば問題ありません。

ディレクトリが存在しないなど何かしら問題がある場合にはAvailableにならないので注意。

kubectl get pv コマンドで確認可能です。

これでPVの作成が完了しましたので、PVCリソースの作成を実施します。

PersistentVolumeClaim(PVC)作成

作成したPVリソースを利用するPVCリソースを次のように定義します。

vim pvc.yaml

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

作成した定義を適用させるため次のコマンドを実行します。

kubectl apply -f pvc.yaml

persistentvolumeclaim/efs-claim created

pvc(PersistentVolumeClaim) が pv(PersistentVolume) の確保に失敗すると、ステータスは Pending のままになります。

STATUSがBound状態であれば問題ありません。

kubectl get pvc コマンドで確認可能です。

これでPVCの作成が完了しましたので、これらをPodから利用する設定をします。

PVCリソースの使用

ここでは、wordpressコンテナーにPVCリソースを利用し、「 /var/www/html 」領域にEFSをマウントする設定例を示します。

containers: 配下に定義するようにします。

vi wordpress.yaml

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-us-east-1a
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      nodeSelector:
        topology.kubernetes.io/zone: us-east-1a
      containers:
      - name: wordpress
        image: wordpress:latest
・・・{中略}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ここから↓
        volumeMounts:
        - name: persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: persistent-storage
        persistentVolumeClaim:
          claimName: efs-claim
ここまで追記↑
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

作成した定義を適用させるため次のコマンドを実行します。

kubectl apply -f wordpress.yaml

deployment.apps/wordpress-us-east-1a created

動作確認

マウントしたPODに入り実際にマウントされているか確認してみます。

kubectl get po コマンドでデプロイされたPODを確認したこちらに対して df コマンドを実施します。

kubectl exec -it wordpress-us-east-1a-75df9fdb69-kbx5q --tty -- df -PTh

Filesystem     Type     Size  Used Avail Use% Mounted on
overlay        overlay   30G   13G   16G  45% /
tmpfs          tmpfs     64M     0   64M   0% /dev
tmpfs          tmpfs    1.9G     0  1.9G   0% /sys/fs/cgroup
overlay        overlay   30G   13G   16G  45% /etc/hosts
/dev/nvme1n1   ext4      30G   13G   16G  45% /etc/hostname
shm            tmpfs     64M     0   64M   0% /dev/shm
127.0.0.1:/    nfs4     8.0E     0  8.0E   0% /var/www/html
tmpfs          tmpfs    3.7G   12K  3.7G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs          tmpfs    1.9G     0  1.9G   0% /proc/acpi
tmpfs          tmpfs    1.9G     0  1.9G   0% /sys/firmware

127.0.0.1:/ nfs4 8.0E 0 8.0E 0% /var/www/html となっており正常にEFSがマウントされていることが確認できます。

EFSでマウントされている領域を ls コマンドで確認すると次のように wordpress のファイル群が存在することが確認できます。

kubectl exec -it wordpress-us-east-1a-75df9fdb69-kbx5q --tty -- ls -la

total 260
drwxr-xr-x  5 www-data www-data  6144 Nov 30 20:14 .
drwxr-xr-x  1 root     root      4096 Nov 21 17:55 ..
-rw-r--r--  1 www-data www-data   261 Nov 21 21:27 .htaccess
-rw-r--r--  1 www-data www-data   405 Feb  6  2020 index.php
-rw-r--r--  1 www-data www-data 19915 Jan  1  2024 license.txt
-rw-r--r--  1 www-data www-data  7409 Jun 18 11:59 readme.html
-rw-r--r--  1 www-data www-data  7387 Feb 13  2024 wp-activate.php
drwxr-xr-x  9 www-data www-data  6144 Nov 21 14:07 wp-admin
-rw-r--r--  1 www-data www-data   351 Feb  6  2020 wp-blog-header.php
-rw-r--r--  1 www-data www-data  2323 Jun 14  2023 wp-comments-post.php
-rw-r--r--  1 www-data www-data  5815 Nov 21 21:25 wp-config-docker.php
-rw-r--r--  1 www-data www-data  3336 Oct 15 15:24 wp-config-sample.php
-rw-r--r--  1 www-data www-data  5919 Nov 30 20:14 wp-config.php
drwxr-xr-x  4 www-data www-data  6144 Nov 21 14:07 wp-content
-rw-r--r--  1 www-data www-data  5617 Aug  2 19:40 wp-cron.php
drwxr-xr-x 30 www-data www-data 14336 Nov 21 14:07 wp-includes
-rw-r--r--  1 www-data www-data  2502 Nov 26  2022 wp-links-opml.php
-rw-r--r--  1 www-data www-data  3937 Mar 11  2024 wp-load.php
-rw-r--r--  1 www-data www-data 51367 Sep 30 19:12 wp-login.php
-rw-r--r--  1 www-data www-data  8543 Sep 18 22:37 wp-mail.php
-rw-r--r--  1 www-data www-data 29032 Sep 30 17:08 wp-settings.php
-rw-r--r--  1 www-data www-data 34385 Jun 19  2023 wp-signup.php
-rw-r--r--  1 www-data www-data  5102 Oct 18 15:56 wp-trackback.php
-rw-r--r--  1 www-data www-data  3246 Mar  2  2024 xmlrpc.php

まとめ

いかがでしたでしょうか、これで永続領域にデータを保存できるため、コンテナーが再作成されても、EFSに保存されたデータを利用することが可能となりました。