2023/08 に CSI Driver for Amazon EFS を EKS アドオンとして利用可能になりました。
これまでは kubernetes-sigs/aws-efs-csi-driver 記載の手順に従って manifest ファイル等を用意して手動インストールする必要がありましたが、今後はアドオンを活用してより簡単にインストールやアップデート可能になります。
セットアップしてみた
今回は eksctl を使って試してみました。
eksctl version
0.158.0
まず、EKS クラスターを作成します。
eksctl create cluster \
--name test-cluster \
--version 1.24 \
--vpc-cidr 10.0.0.0/16 \
--with-oidc \
--node-type t3.medium \
--nodes 2 \
--nodes-min 1 \
--nodes-max 2
AmazonEFSCSIDriverPolicy
という AWS 管理の IAM ポリシーがあるので、こちらの権限を付与しつつ Service Account に紐づけた IAM ロールを作成します。
eksctl create iamserviceaccount \
--name efs-csi-controller-sa \
--namespace kube-system \
--cluster test-cluster \
--role-name AmazonEKS_EFS_CSI_DriverRole \
--role-only \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
--approve
今回は EKS 1.24 を利用しているので、対応しているアドオンのバージョンを調べてみました。
eksctl utils describe-addon-versions --kubernetes-version 1.24 --name aws-efs-csi-driver | grep AddonVersion
"AddonVersions": [
"AddonVersion": "v1.6.0-eksbuild.1",
"AddonVersion": "v1.5.9-eksbuild.1",
"AddonVersion": "v1.5.8-eksbuild.1",
aws-efs-csi-driver をアドオンとして追加します。バージョンは一番新しい v1.6.0-eksbuild.1
とします。
eksctl create addon \
--cluster test-cluster \
--name aws-efs-csi-driver \
--version v1.6.0-eksbuild.1 \
--service-account-role-arn arn:aws:iam::12345678912:role/AmazonEKS_EFS_CSI_DriverRole \
--force
deployment(efs-csi-controller) と daemonset(efs-csi-node) がそれぞれ作成されます。
kubectl get deployment -n kube-system
NAME READY UP-TO-DATE AVAILABLE AGE
coredns 2/2 2 2 4h19m
efs-csi-controller 2/2 2 2 2m16s
kubectl get daemonset -n kube-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
aws-node 2 2 2 2 2 <none> 4h19m
efs-csi-node 2 2 2 2 2 kubernetes.io/os=linux 2m27s
kube-proxy 2 2 2 2 2 <none> 4h19m
EFS は CloudFormation でさくっと作りました。
AWSTemplateFormatVersion: "2010-09-09"
Description: This template creates an Amazon EFS file system
Parameters:
VolumeName:
Description: The name to be used for the EFS volume
Type: String
MinLength: "1"
Default: myEFSvolume
VPC:
Description: VPC Id to create EFS volume
Type: String
Subnet1a:
Description: Subnet Id in ap-northeast-1a
Type: String
Subnet1c:
Description: Subnet Id in ap-northeast-1c
Type: String
Subnet1d:
Description: Subnet Id in ap-northeast-1d
Type: String
VPCCIDR:
Description: CIDR of VPC
Type: String
Default: 10.0.0.0/16
Resources:
MountTargetSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId:
Ref: VPC
GroupDescription: Security group for mount target
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 2049
ToPort: 2049
CidrIp: !Ref VPCCIDR
FileSystem:
Type: AWS::EFS::FileSystem
Properties:
PerformanceMode: generalPurpose
FileSystemTags:
- Key: Name
Value:
Ref: VolumeName
MountTarget1a:
Type: AWS::EFS::MountTarget
Properties:
FileSystemId:
Ref: FileSystem
SubnetId: !Ref Subnet1a
SecurityGroups:
- Ref: MountTargetSecurityGroup
MountTarget1c:
Type: AWS::EFS::MountTarget
Properties:
FileSystemId:
Ref: FileSystem
SubnetId: !Ref Subnet1c
SecurityGroups:
- Ref: MountTargetSecurityGroup
MountTarget1d:
Type: AWS::EFS::MountTarget
Properties:
FileSystemId:
Ref: FileSystem
SubnetId: !Ref Subnet1d
SecurityGroups:
- Ref: MountTargetSecurityGroup
Outputs:
FileSystemID:
Description: File system ID
Value:
Ref: FileSystem
EFS を CLI で作成する場合は、こちらを参考にすると良いと思います。
動作確認
kubernetes-sigs/aws-efs-csi-driver でサンプルとして紹介されている manifest ファイルを利用して動作確認してみます。
クラスターを作成した状態では EBS を使うための StorageClass のみ存在します。
kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 4h29m
ここで下記マニフェストファイルを適用して、 StorageClass を追加します。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: efs-sc
provisioner: efs.csi.aws.com
examples/kubernetes/static_provisioning/specs/storageclass.yaml に紹介されている manifest ファイルだと、apiVersion: v1
と記載されています。
しかし、 Kubernetes 1.22 でこの API は廃止されているので、apiVersion: storage.k8s.io/v1
に修正して適用します。
kubectl apply -f storageclass.yaml
storageclass.storage.k8s.io/efs-sc created
無事ストレージクラスが追加されました。
kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
efs-sc efs.csi.aws.com Delete Immediate false 3s
gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 4h30m
PersistentVolume (PV) を作成します。
apiVersion: v1
kind: PersistentVolume
metadata:
name: efs-pv
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
storageClassName: efs-sc
persistentVolumeReclaimPolicy: Retain
csi:
driver: efs.csi.aws.com
volumeHandle: [FileSystemId]
この際、spec.csi.volumeHandle
を EFS の ID に書き換えます。
kubectl apply -f pv.yaml
persistentvolume/efs-pv created
Available 状態で PV が作成されます。
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
efs-pv 5Gi RWO Retain Available efs-sc 24s
次に PersistentVolumeClaims(PVC) を作成します。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: efs-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: efs-sc
resources:
requests:
storage: 5Gi
kubectl apply -f claim.yaml
persistentvolumeclaim/efs-claim created
PV の STATUS が Bound に変わります。
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
efs-pv 5Gi RWO Retain Bound default/efs-claim efs-sc 2m22s
PVC の STATUS も同様です。
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
efs-claim Bound efs-pv 5Gi RWO efs-sc 4s
最後に pod を作成します。
この Pod では 5 秒ごとに /data/out.txt
に data -u
の出力を書き込むコンテナが定義されています。
pod を作成する際に、作成済みの PVC を指定することで EFS に書き込めるようになります。
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.txt; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: efs-claim
kubectl apply -f pod.yaml
無事作成され、Volumes.persistent-storage
を確認すると、先程作成した PVC を利用できています。
kubectl describe pod efs-app
Name: efs-app
Namespace: default
Priority: 0
Node: ip-10-0-91-134.ap-northeast-1.compute.internal/10.0.91.134
Start Time: Sun, 24 Sep 2023 20:48:51 +0900
Labels: <none>
Annotations: kubernetes.io/psp: eks.privileged
Status: Running
IP: 10.0.93.179
IPs:
IP: 10.0.93.179
Containers:
app:
Container ID: containerd://d4ff8ed835bf69946092d7b4a58ba48c8a523b137113f7399ff659f8167d1e60
Image: centos
Image ID: docker.io/library/centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Port: <none>
Host Port: <none>
Command:
/bin/sh
Args:
-c
while true; do echo $(date -u) >> /data/out.txt; sleep 5; done
State: Running
Started: Sun, 24 Sep 2023 20:49:12 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/data from persistent-storage (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-gvpwk (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
persistent-storage:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: efs-claim
ReadOnly: false
kube-api-access-gvpwk:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 8m14s default-scheduler Successfully assigned default/efs-app to ip-10-0-91-134.ap-northeast-1.compute.internal
Normal Pulling 8m3s kubelet Pulling image "centos"
Normal Pulled 7m53s kubelet Successfully pulled image "centos" in 9.436549639s
Normal Created 7m53s kubelet Created container app
Normal Started 7m53s kubelet Started container app
下記コマンドを実行すると、/data/out.txt
に書きこめていることが確認できました。
kubectl exec -ti efs-app -- tail -f /data/out.txt
Sun Sep 24 11:58:29 UTC 2023
Sun Sep 24 11:58:34 UTC 2023
Sun Sep 24 11:58:39 UTC 2023
Sun Sep 24 11:58:44 UTC 2023
まとめ
手動でドライバーの管理をするのは面倒なので、アドオンがあるなら積極的に使っていきたいです。
今は手動管理をしている場合もこれからクラスターを作る場合も、是非アドオンの利用を検討してみて下さい。