Auto ModeのEKSでEBSを扱ってみた #AWSreInvent
昨日 EKS に Auto Mode が追加されました。
EBS CSI ドライバーの設定不要で、EBS を扱えるようになったので試してみました。
Auto Mode で何が解決されたか
EKS 上のコンテナから EBS を利用するためには、EBS CSI ドライバーをセットアップする必要がありました。
EKS アドオンとして利用しやすいようになってはいるものの、IAM ロールの設定やアドオンの追加が必要でした。
追加したアドオンは継続してアップグレードする必要もあり、EKS 利用時の面倒なポイントの一つでした。
Auto Mode を利用することで、この辺りの設定を AWS 側にオフロード可能です。
やってみる
eksctl で Auto Mode のクラスターを作成します。
作成方法の詳細は下記を参考にして下さい。
公式ドキュメントにシナリオが用意されているので、こちらに沿って試してみます。
最初はほぼリソースが無い状態からスタートです。
EBS CSI driver 関連のリソースは何も見えないですね。
$ kubectl get all -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 60m
kube-system service/eks-extension-metrics-api ClusterIP 10.100.125.4 <none> 443/TCP 60m
最初からある Storage Class として、gp2 を利用するものが見つかります。
$ kubectl describe sc gp2 -A
Name: gp2
IsDefaultClass: No
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{},"name":"gp2"},"parameters":{"fsType":"ext4","type":"gp2"},"provisioner":"kubernetes.io/aws-ebs","volumeBindingMode":"WaitForFirstConsumer"}
Provisioner: kubernetes.io/aws-ebs
Parameters: fsType=ext4,type=gp2
AllowVolumeExpansion: <unset>
MountOptions: <none>
ReclaimPolicy: Delete
VolumeBindingMode: WaitForFirstConsumer
Events: <none>
EKS Auto Mode で EBS を扱う場合は、ebs.csi.eks.amazonaws.com
を参照するストレージクラスを作成する必要があります。
EKS Auto Mode does not create a StorageClass for you. You must create a StorageClass referencing ebs.csi.eks.amazonaws.com to use the storage capability of EKS Auto Mode.
https://docs.aws.amazon.com/eks/latest/userguide/create-storage-class.html
なので、シナリオ通りに gp3 を利用する Storage Class を作成していきます。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: auto-ebs-sc
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.eks.amazonaws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
type: gp3
encrypted: "true"
無事作成できました。
$ kubectl apply -f sc.yaml
storageclass.storage.k8s.io/auto-ebs-sc created
内容を確認します。
$ kubectl describe sc auto-ebs-sc
Name: auto-ebs-sc
IsDefaultClass: Yes
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"},"name":"auto-ebs-sc"},"parameters":{"encrypted":"true","type":"gp3"},"provisioner":"ebs.csi.eks.amazonaws.com","volumeBindingMode":"WaitForFirstConsumer"}
,storageclass.kubernetes.io/is-default-class=true
Provisioner: ebs.csi.eks.amazonaws.com
Parameters: encrypted=true,type=gp3
AllowVolumeExpansion: <unset>
MountOptions: <none>
ReclaimPolicy: Delete
VolumeBindingMode: WaitForFirstConsumer
Events: <none>
EBS CSI driver をアドオンとして入れている時は Provisioner として ebs.csi.aws.com を指定していたので、この点は注意が必要です。
provisioner: ebs.csi.eks.amazonaws.com - Uses EKS Auto Mode
https://docs.aws.amazon.com/eks/latest/userguide/sample-storage-workload.html
他は今まで通りですね(EKS というより Kubernetes の世界の設定なので、そりゃそうだって感じですが)。
PVC を作成していきます。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: auto-ebs-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: auto-ebs-sc
resources:
requests:
storage: 8Gi
kubectl apply を実行します。
$ kubectl apply -f pvc.yaml
persistentvolumeclaim/auto-ebs-claim created
無事 PVC が作成されました。
$ kubectl describe pvc auto-ebs-claim
Name: auto-ebs-claim
Namespace: default
StorageClass: auto-ebs-sc
Status: Pending
Volume:
Labels: <none>
Annotations: <none>
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal WaitForFirstConsumer 6s (x3 over 34s) persistentvolume-controller waiting for first consumer to be created before binding
PVC を利用するアプリケーションを作成します。
volumes セクションに記載されている通り、作成した PVC を利用して EBS ボリュームを /data にマウントします。
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate-stateful
spec:
replicas: 1
selector:
matchLabels:
app: inflate-stateful
template:
metadata:
labels:
app: inflate-stateful
spec:
terminationGracePeriodSeconds: 0
nodeSelector:
eks.amazonaws.com/compute-type: auto
containers:
- name: bash
image: public.ecr.aws/docker/library/bash:4.4
command: ["/usr/local/bin/bash"]
args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 60; done"]
resources:
requests:
cpu: "1"
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: auto-ebs-claim
kubectl apply を実行します。
$ kubectl apply -f deployment.yaml
deployment.apps/inflate-stateful created
Pod が無事 Running になりました。
$ kubectl describe pod inflate-stateful-59db4c8c9-r6hql
Name: inflate-stateful-59db4c8c9-r6hql
Namespace: default
Priority: 0
Service Account: default
Node: i-0636543e5d522d31b/192.168.187.65
Start Time: Tue, 03 Dec 2024 06:42:59 +0900
Labels: app=inflate-stateful
pod-template-hash=59db4c8c9
Annotations: <none>
Status: Running
IP: 192.168.172.128
IPs:
IP: 192.168.172.128
Controlled By: ReplicaSet/inflate-stateful-59db4c8c9
Containers:
bash:
Container ID: containerd://bec6b87f27347132cfdb6f75502c38e2af237747e95746537bf67218b2f8e771
Image: public.ecr.aws/docker/library/bash:4.4
Image ID: public.ecr.aws/docker/library/bash@sha256:347a41a463e19a852e1cc942eb0ef16d62e777038d311314b33da8c587472e40
Port: <none>
Host Port: <none>
Command:
/usr/local/bin/bash
Args:
-c
while true; do echo $(date -u) >> /data/out.txt; sleep 60; done
State: Running
Started: Tue, 03 Dec 2024 06:43:19 +0900
Ready: True
Restart Count: 0
Requests:
cpu: 1
Environment: <none>
Mounts:
/data from persistent-storage (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-htvxj (ro)
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
persistent-storage:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: auto-ebs-claim
ReadOnly: false
kube-api-access-htvxj:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Burstable
Node-Selectors: eks.amazonaws.com/compute-type=auto
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 Nominated 2m31s karpenter Pod should schedule on: nodeclaim/general-purpose-dzvt2
Warning FailedScheduling 2m16s (x5 over 2m32s) default-scheduler no nodes available to schedule pods
Normal Scheduled 2m3s default-scheduler Successfully assigned default/inflate-stateful-59db4c8c9-r6hql to i-0636543e5d522d31b
Normal SuccessfulAttachVolume 2m1s attachdetach-controller AttachVolume.Attach succeeded for volume "pvc-f1edb981-51a9-448e-9fc0-4454bcfa7676"
Warning FailedCreatePodSandBox 2m kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "fe28f5e6743534f765ac2a831e9ccd1938212a5e617efd5e413fb32b615aaea3": plugin type="aws-cni" name="aws-cni" failed (add): add cmd: Error received from AddNetwork gRPC call: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp 127.0.0.1:50051: connect: connection refused"
Normal Pulling 108s kubelet Pulling image "public.ecr.aws/docker/library/bash:4.4"
Normal Pulled 104s kubelet Successfully pulled image "public.ecr.aws/docker/library/bash:4.4" in 4.075s (4.075s including waiting). Image size: 5985546 bytes.
Normal Created 104s kubelet Created container bash
Normal Started 104s kubelet Started container bash
PV も無事作成されています。
$ kubectl describe pv
Name: pvc-f1edb981-51a9-448e-9fc0-4454bcfa7676
Labels: <none>
Annotations: pv.kubernetes.io/provisioned-by: ebs.csi.eks.amazonaws.com
volume.kubernetes.io/provisioner-deletion-secret-name:
volume.kubernetes.io/provisioner-deletion-secret-namespace:
Finalizers: [external-provisioner.volume.kubernetes.io/finalizer kubernetes.io/pv-protection external-attacher/ebs-csi-eks-amazonaws-com]
StorageClass: auto-ebs-sc
Status: Bound
Claim: default/auto-ebs-claim
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 8Gi
Node Affinity:
Required Terms:
Term 0: topology.kubernetes.io/zone in [ap-northeast-1a]
Message:
Source:
Type: CSI (a Container Storage Interface (CSI) volume source)
Driver: ebs.csi.eks.amazonaws.com
FSType: ext4
VolumeHandle: vol-05cf1cccb9405b33c
ReadOnly: false
VolumeAttributes: storage.kubernetes.io/csiProvisionerIdentity=1733171414036-3349-ebs.csi.eks.amazonaws.com
Events: <none>
PVC も Bound 状態になりました。良さそうですね.
$ kubectl describe pvc auto-ebs-claim
Name: auto-ebs-claim
Namespace: default
StorageClass: auto-ebs-sc
Status: Bound
Volume: pvc-f1edb981-51a9-448e-9fc0-4454bcfa7676
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
volume.beta.kubernetes.io/storage-provisioner: ebs.csi.eks.amazonaws.com
volume.kubernetes.io/selected-node: i-0636543e5d522d31b
volume.kubernetes.io/storage-provisioner: ebs.csi.eks.amazonaws.com
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 8Gi
Access Modes: RWO
VolumeMode: Filesystem
Used By: inflate-stateful-59db4c8c9-r6hql
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal WaitForFirstConsumer 68s (x8 over 2m51s) persistentvolume-controller waiting for first consumer to be created before binding
Normal WaitForPodScheduled 38s (x2 over 53s) persistentvolume-controller waiting for pod inflate-stateful-59db4c8c9-r6hql to be scheduled
Normal Provisioning 32s ebs.csi.eks.amazonaws.com_ebscsicontroller-85fd5cbdb9-ddlmj_e441b666-76fd-43ab-b307-8be43dbebfcc External provisioner is provisioning volume for claim "default/auto-ebs-claim"
Normal ExternalProvisioning 32s (x2 over 32s) persistentvolume-controller Waiting for a volume to be created either by the external provisioner 'ebs.csi.eks.amazonaws.com' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
Normal ProvisioningSucceeded 30s ebs.csi.eks.amazonaws.com_ebscsicontroller-85fd5cbdb9-ddlmj_e441b666-76fd-43ab-b307-8be43dbebfcc Successfully provisioned volume pvc-f1edb981-51a9-448e-9fc0-4454bcfa7676
EBS を確認すると、指定した通り 8GiB で作成されています。
$ PV_NAME=$(kubectl get pvc auto-ebs-claim -o jsonpath='{.spec.volumeName}')
$ aws ec2 describe-volumes \
--filters Name=tag:CSIVolumeName,Values=${PV_NAME}
{
"Volumes": [
{
"Attachments": [
{
"AttachTime": "2024-12-02T21:43:01+00:00",
"Device": "/dev/xvdaa",
"InstanceId": "i-0636543e5d522d31b",
"State": "attached",
"VolumeId": "vol-05cf1cccb9405b33c",
"DeleteOnTermination": false
}
],
"AvailabilityZone": "ap-northeast-1a",
"CreateTime": "2024-12-02T21:42:57.416000+00:00",
"Encrypted": true,
"KmsKeyId": "arn:aws:kms:ap-northeast-1:xxxxxxxxxxxx:key/xxxxxxxxxxxxxxxx",
"Size": 8,
"SnapshotId": "",
"State": "in-use",
"VolumeId": "vol-05cf1cccb9405b33c",
"Iops": 3000,
"Tags": [
{
"Key": "CSIVolumeName",
"Value": "pvc-f1edb981-51a9-448e-9fc0-4454bcfa7676"
},
{
"Key": "Name",
"Value": "test-cluster-dynamic-pvc-f1edb981-51a9-448e-9fc0-4454bcfa7676"
},
{
"Key": "eks:eks-cluster-name",
"Value": "test-cluster"
},
{
"Key": "kubernetes.io/created-for/pvc/namespace",
"Value": "default"
},
{
"Key": "kubernetes.io/created-for/pvc/name",
"Value": "auto-ebs-claim"
},
{
"Key": "KubernetesCluster",
"Value": "test-cluster"
},
{
"Key": "ebs.csi.eks.amazonaws.com/cluster",
"Value": "true"
},
{
"Key": "kubernetes.io/created-for/pv/name",
"Value": "pvc-f1edb981-51a9-448e-9fc0-4454bcfa7676"
},
{
"Key": "kubernetes.io/cluster/test-cluster",
"Value": "owned"
}
],
"VolumeType": "gp3",
"MultiAttachEnabled": false,
"Throughput": 125
}
]
}
data としてボリュームをマウントしているので、そちらにファイルが出力されているかを確認します。
$ kubectl exec "$(kubectl get pods -l app=inflate-stateful \
-o=jsonpath='{.items[0].metadata.name}')" -- \
cat /data/out.txt
Mon Dec 2 21:43:19 UTC 2024
Mon Dec 2 21:44:19 UTC 2024
Mon Dec 2 21:45:19 UTC 2024
Mon Dec 2 21:46:19 UTC 2024
Mon Dec 2 21:47:19 UTC 2024
Mon Dec 2 21:48:19 UTC 2024
無事出力されていることを確認できました!
まとめ
めちゃめちゃ楽になりました!
とりあえず Auto Mode で始めるのが吉なように感じました。
個人的には EFS 辺りも最初から使えて良いのでは?と思ってますが、こちらはアドオンの追加が必要です。
いまアドオンの追加が必要なリソースも、選択式だけど AWS 管理みたいな扱いになると嬉しいなと思うのですが、贅沢ですかね。
その辺りのアップデートは今後に期待します!