Amazon EKS で Amazon EFS CSI ドライバー を使ってみる
今回は、Amazon EKS で Amazon EFS CSI ドライバー を使って、Podから EFSボリュームにアクセスしてみます。
手順としては前回の「Amazon EKS で Amazon EBS CSI ドライバー を使ってみる 」の記事の内容と似ているところが多いので、今回の記事も内容や構成が似ていることはご容赦下さいww
ここに記述している内容は、2022 年 9 月11 日時点で動作を確認しています。
また、対象にしている Kubernetes のバージョンは 1.23 です。
今後の Update により、手順等が変更される可能性があることをご留意ください。
なお、下記のドキュメントを参考にしていますので、こちらも併せてご参照ください。
前提と環境
今回は、東京リージョンの「 test123-cluster 」という名前の EKS クラスター (バージョンは 1.23 ) を使う前提とします。
kubectl や eksctl 、AWS CLI 、git が使用でき、対象のクラスターに接続できる Amazon Linux2 の環境で実施していきます。
記事の中で出てくる AWS アカウント ID は、12 桁すべてゼロで表記しています。
Amazon EFS CSI ドライバー用の Service Account の作成
Amazon EFS CSI ドライバーには、Amazon EFS のファイルシステムを操作する権限を付与する必要があります。
その権限を付与するため、AWS の IAM ロールと関連づいた Kubernetes の Service Account を作成します。
まず、クラスター用に IAM OpenID Connect (OIDC) プロバイダーを用意します。 (もし前に IAM ロールと関連付けた Service Account を作成したことがあるなら、すでに実施済のはずなので、その場合は不要です。)
eksctl utils associate-iam-oidc-provider --cluster test123-cluster --approve
次に、IAM ロール に付与する許可ポリシーを作成します。
ここでは、ポリシー名を AmazonEKS_EFS_CSI_Driver_Policy にしています。
curl -o iam-policy-example.json https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/docs/iam-policy-example.json aws iam create-policy \ --policy-name AmazonEKS_EFS_CSI_Driver_Policy \ --policy-document file://iam-policy-example.json
ダウンロードした iam-policy-example.json にも目を通しておくと、どのようなポリシーが必要か確認できます。
そして、Service Account を作成します。
ここでは、Service Account 名を ebs-csi-controller-sa に、IAM ロール名を AmazonEKS_EBS_CSI_DriverRole にしています。
eksctl create iamserviceaccount \ --cluster test123-cluster \ --namespace kube-system \ --name efs-csi-controller-sa \ --attach-policy-arn arn:aws:iam::000000000000:policy/AmazonEKS_EFS_CSI_Driver_Policy \ --approve \ --region ap-northeast-1
Amazon EFS CSI ドライバー を Amazon EKS アドオンとしてインストールする
インストールではHelm も使用できますが、今回は kubectl でマニフェストを使って行います。
また、マニフェストで参照するイメージは、パブリック Amazon ECR レジストリに保存されているイメージを使う前提とします。
最初にマニフェストを取得します。
kubectl kustomize \ "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/?ref=release-1.4" > public-ecr-driver.yaml
public-ecr-driver.yaml
ファイルを編集して、次の行を削除します。
これは、Service Account は前の手順ですでに作成しているためです。
この作業は注意して下さい。ファイル内に Service Account のマニフェストが複数存在している場合、削除する対象を間違えないようにしましょう。
apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/name: aws-efs-csi-driver name: efs-csi-controller-sa namespace: kube-system ---
これでマニフェストの準備が完了したので、適用します。
kubectl apply -f public-ecr-driver.yaml
インストールを確認します。
kubectl get deploy efs-csi-controller -n kube-system
次の出力例のように、efs-csi-controller の Deployment が起動できていることを確認します。
NAME READY UP-TO-DATE AVAILABLE AGE efs-csi-controller 2/2 2 2 3m1s
EFS ファイルシステムを作成する
EFS ファイルシステムを作成するために、まずは VPC の情報を環境変数に入れておきます。
vpc_id=$(aws eks describe-cluster \ --name test123-cluster \ --query "cluster.resourcesVpcConfig.vpcId" \ --output text)
cidr_range=$(aws ec2 describe-vpcs \ --vpc-ids $vpc_id \ --query "Vpcs[].CidrBlock" \ --output text)
次に EFS ファイルシステムのマウントポイントに適用するセキュリティグループを作成します。 今回は、セキュリティグループ名を MyEfsSecurityGroup にしています。
security_group_id=$(aws ec2 create-security-group \ --group-name MyEfsSecurityGroup \ --description "My EFS security group" \ --vpc-id $vpc_id \ --output text)
作成したセキュリティグループに イングレスルールを設定します。
今回は、アクセス元がクラスターの VPC の CIDR であれば NFS トラフィックを許可するルールにします。
aws ec2 authorize-security-group-ingress \ --group-id $security_group_id \ --protocol tcp \ --port 2049 \ --cidr $cidr_range
これで EFS ファイルシステムを作成する準備ができました。
リージョンを指定して EFS ファイルシステムを作成します。
file_system_id=$(aws efs create-file-system \ --region ap-northeast-1 \ --performance-mode generalPurpose \ --query 'FileSystemId' \ --output text)
EFS ファイルシステムのマウントターゲットを作成します。
そのために、まず EKS クラスターのVPCのサブネットの ID を取得します。
aws ec2 describe-subnets \ --filters "Name=vpc-id,Values=$vpc_id" \ --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' \ --output table
出力された表形式の内容から、EKS で EFS ファイルシステムをマウントするノードのサブネットの ID をメモしておきます。
そのサブネット ID を指定して、EFS のマウントターゲットを作成します。 次の例では、サブネット ID を subnet-0b10aaaaaaaaaaaaa と指定しています。
aws efs create-mount-target \ --file-system-id $file_system_id \ --subnet-id subnet-0b10aaaaaaaaaaaaa \ --security-groups $security_group_id
サンプルアプリケーションで確認する
では、Pod から EFS ファイルシステムにアクセスできるかをサンプルアプリケーションを使って試していきます。
まず、作成した EFS ファイルシステムの ID をメモしておきます。 これまでの手順で、$file_system_id という環境変数で参照できます。
echo $file_system_id
aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text
次に、EFS の StorageClass を作成するためのマニフェストを入手します。
curl -o storageclass.yaml https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml
ダウンロードした storageclass.yaml
を編集し、fileSystemId: 部分をメモしておいた ファイルシステム ID に変更します。
次の例では、ファイルシステム ID として fs-54321abc を指定してます。
fileSystemId: fs-54321abc
これで準備ができたので、StorageClassを作成します。
kubectl apply -f storageclass.yaml
Storage Class の情報を表示してみます。NAME に efs-sc 、PROVISONER に efs.csi.aws.com の Storage Class が表示されることを確認します。
kubectl get sc
次にサンプルアプリケーションを取得します。
curl -o pod.yaml https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/pod.yaml
今回は、動的に EFS のボリュームをプロビジョニングするサンプルを動かしていきます。
ダウンロードしたマニフェスト pod.yaml
を適用することで、Persistent Volume、Persistent Volume Claim、それを指定するサンプルの Pod が作成されます。
kubectl apply -f pod.yaml
Persistent Volume と Persistent Volume Claim の STATUS が Bound になっていることを確認します。
kubectl get pv kubectl get pvc
efs-app というPod の STATUS が Running になっていることを確認します。
kubectl get pod efs-app
次のコマンドを実行し、このサンプルアプリケーションの Pod のマニフェストをみてみます。
cat pod.yaml
次のように、Persistent Volume Claim を指定し、/data というパスにボリュームをマウントしています。
そして、echo コマンドを使用し、/data/out に日時を繰り返し書き込んでいます。
apiVersion: v1 kind: Pod metadata: name: efs-app spec: containers: - name: app image: centos command: ["/bin/sh"] args: ["-c", "while true; do echo $(date -u) >> /data/out; sleep 5; done"] volumeMounts: - name: persistent-storage mountPath: /data volumes: - name: persistent-storage persistentVolumeClaim:
では、この Pod が EFS ボリュームに書き込み出来ているかを確認してみましょう。
kubectl exec efs-app -- bash -c "cat data/out"
次のような表示が確認できれば OK です。
出力例
Sun Sep 11 03:15:25 UTC 2022 Sun Sep 11 03:15:30 UTC 2022 Sun Sep 11 03:15:35 UTC 2022 Sun Sep 11 03:15:40 UTC 2022 Sun Sep 11 03:15:45 UTC 2022 Sun Sep 11 03:15:50 UTC 2022 Sun Sep 11 03:15:55 UTC 2022
ここで、もう1つ、同じ EFS のマウントターゲットを使用するPod を作成してみます。
次のマニフェストを作成して、nginx.yaml
として保存します。
apiVersion: v1 kind: Pod metadata: name: efs-app-nginx spec: containers: - name: nginx image: nginx volumeMounts: - name: persistent-storage mountPath: /data volumes: - name: persistent-storage persistentVolumeClaim: claimName: efs-claim
この Pod を作成します。
kubectl create -f nginx.yaml
作成した Pod のシェルに接続してみます。
kubectl exec efs-app-nginx -it -- /bin/bash
次のコマンドを実行し、efs-app の Pod が書き込んだファイルを参照できることを確認します。
cat /data/out
出力例
Sun Sep 11 03:15:25 UTC 2022 Sun Sep 11 03:15:30 UTC 2022 Sun Sep 11 03:15:35 UTC 2022 Sun Sep 11 03:15:40 UTC 2022 Sun Sep 11 03:15:45 UTC 2022 Sun Sep 11 03:15:50 UTC 2022 Sun Sep 11 03:15:55 UTC 2022
これで EFS なので、2つのコンピューティング環境から同時にマウントしてアクセスできることが確認できました!
確認出来たら、シェルを終了します。
exit
サンプルアプリケーションを停止する場合は、次を実行します。
これで、EFS ボリュームも削除されます。( EFS ファイルシステムは削除されません)
kubectl delete po efs-app-nginx
kubectl delete -f pod.yaml
最後に
前回と今回の記事で、Amazon EKS の CSI ドライバーを使用して Amazon EBS や Amazon EFS のボリュームをプロビジョニングして Pod から使用する手順を確認しました。 AWS の公式のドキュメント の内容をベースにしていますが、少し補足しつつ、よりシンプルに確認できる手順にしたつもりです。 これがどなたかのお役に立てば嬉しいです。