EKS Auto Mode使ってみた


## はじめに

2024年12月1日 に EKS Auto Mode が GA されたので使ってみました！

使ってみた感想としては、実務で使えるかはまだまだ検証が必要ですが、今まで EKS クラスターを作成してから、導入に一手間が必要だった ALB Controller の管理やワーカーノードの管理をマネージドで行うことで、かなり運用するためのハードルが下がったと感じました。

## EKS Auto Mode とは
>EKS 自動モードを使用すると、新規または既存の EKS クラスターで Kubernetes 準拠のマネージドコンピューティング、ネットワーク、ストレージを利用できます。
>...
>EKS 自動モードは、AWS が制御するアクセスとライフサイクル管理を使用して、アカウント内の EC2 インスタンスをプロビジョニング、操作、保護、アップグレードします。OS のパッチと更新を処理し、エフェメラルコンピューティングでセキュリティリスクを制限し、デフォルトでセキュリティ体制を強化します。


https://aws.amazon.com/jp/about-aws/whats-new/2024/12/amazon-eks-auto-mode/

このように書かれているように、今まで Kubernetes のバージョンアップ時に対応を行っていた、ワーカーノードや各種アドオンの更新作業をマネージドで行ってくれます。

また、EKS Auto Mode では以下のコンポーネントをマネージドで管理が行われるようです。
- CoreDNS
- KubeProxy
- AWS Load Balancer Controller
- Karpenter
- AWS EBS CSI Driver

https://docs.aws.amazon.com/eks/latest/userguide/auto-upgrade.html

## クラスター構築
既存クラスターを Auto Mode に移行することも可能のようですが、今回は eksctl を用いて新規にクラスターを構築します。
```shell
$ eksctl create cluster --name=s-tanaka-dev-auto-cluster-01 --enable-auto-mode
```

※ eksctl で Auto Mode を有効化を行うには 0.195.0 以上のバージョンが必要です。
https://github.com/eksctl-io/eksctl/releases/tag/v0.195.0

上記コマンドを実行することで、EKS Auto Mode が有効となった EKS クラスターを新規で構築することができました。
![CleanShot 2024-12-03 at 18.02.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456939/8ecaec0a-e38a-cfc1-3e02-053efa37c00d.png)

構築した直後に Node を取得してもワーカーノードは存在せず、EC2 も作成されていませんでした。
```console
~ ⎈ s-tanaka-dev-auto-cluster-01 ❯ kubectl get node                                                      ▼ 04:56:53 PM
No resources found

~ ⎈ s-tanaka-dev-auto-cluster-01 ❯
```

ただ、適当に Nginx の Deployment を apply すると以下のようにワーカーノードと c5a.large の EC2 が作成され Pod が Running となりました。
```console
~ ⎈ s-tanaka-dev-auto-cluster-01 ❯ k apply -f nginx.yml
deployment.apps/nginx-deployment created

~ ⎈ s-tanaka-dev-auto-cluster-01 ❯ k get node -o wide
NAME                  STATUS   ROLES    AGE     VERSION               INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                                            KERNEL-VERSION   CONTAINER-RUNTIME
i-02603338ec9143f48   Ready    <none>   2m43s   v1.30.5-eks-baa6d11   192.168.105.2   <none>        Bottlerocket (EKS Auto) 2024.11.25 (aws-k8s-1.30)   6.1.115          containerd://1.7.22+bottlerocket

~ ❯
~ ⎈ s-tanaka-dev-auto-cluster-01 ❯ k get po -A
NAMESPACE   NAME                                READY   STATUS    RESTARTS   AGE
default     nginx-deployment-77d8468669-76wfj   1/1     Running   0          2m59s
default     nginx-deployment-77d8468669-cchqk   1/1     Running   0          2m59s
default     nginx-deployment-77d8468669-s4jcg   1/1     Running   0          2m59s

~ ⎈ s-tanaka-dev-auto-cluster-01 ❯
```

## ロードバランサーを使用するワークロード
上述した通り、EKS Auto Mode では AWS Load Balancer Controller もマネージドで管理が行われます。
そのため、Ingress リソースを作成すると AWS Load Balancer Controller のセットアップをせずとも ELB がプロビジョニングされます。

今回は公式チュートリアルで用意されている以下のマニフェストを apply しました。
```yaml
apiVersion: v1
kind: Namespace
metadata:
  name: game-2048
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: game-2048
  name: deployment-2048
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: app-2048
  replicas: 5
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app-2048
    spec:
      containers:
        - image: public.ecr.aws/l6m2t8p7/docker-2048:latest
          imagePullPolicy: Always
          name: app-2048
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: "0.5"
---
apiVersion: v1
kind: Service
metadata:
  namespace: game-2048
  name: service-2048
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: NodePort
  selector:
    app.kubernetes.io/name: app-2048
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  namespace: game-2048
  labels:
    app.kubernetes.io/name: LoadBalancerController
  name: alb
spec:
  controller: eks.amazonaws.com/alb
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: game-2048
  name: ingress-2048
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: service-2048
                port:
                  number: 80
```

apply を行うと、以下のように ALB がプロビジョニングされていることが確認できました。
```console
~ ⎈ s-tanaka-dev-auto-cluster-01 ❯ k apply -f game.yaml
namespace/game-2048 created
deployment.apps/deployment-2048 created
service/service-2048 created
ingressclass.networking.k8s.io/alb created
ingress.networking.k8s.io/ingress-2048 created

~ ❯
~ ⎈ s-tanaka-dev-auto-cluster-01 ❯ k get ingress -A
NAMESPACE   NAME           CLASS   HOSTS   ADDRESS                                                                      PORTS   AGE
game-2048   ingress-2048   alb     *       k8s-game2048-ingress2-xxxxxxxx-xxxxxxx.ap-northeast-1.elb.amazonaws.com   80      89s

~ ❯
```
加えて、このようにアクセスできることも確認できました。
![CleanShot 2024-12-03 at 18.19.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456939/c70116bc-5d82-c467-14f2-714cef8a73ed.png)

## 永続ボリュームを使用するワークロード
AWS Load Balancer Controller 以外にも EBS CSI アドオンも対応をしているため、公式チュートリアルの内容を元に検証を行いました。
同様に公式チュートリアルで用意されている以下のマニフェストを apply しました。

```yaml
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"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: auto-ebs-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: auto-ebs-sc
  resources:
    requests:
      storage: 8Gi
---
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
```
上記のマニフェストを apply すると、Pod の中身までは確認しませんでしたが EBS が作成され問題なく Bound されていることを確認できました。

```console
~ ⎈ s-tanaka-dev-auto-cluster-01 ❯ k apply -f storage.yaml
storageclass.storage.k8s.io/auto-ebs-sc created
persistentvolumeclaim/auto-ebs-claim created
deployment.apps/inflate-stateful created
~ ❯
~ ⎈ s-tanaka-dev-auto-cluster-01 ❯ k get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
auto-ebs-claim   Bound    pvc-86c5f600-88bd-4992-b831-311e06864f4a   8Gi        RWO            auto-ebs-sc    <unset>                 91s

~ ❯
```

## まとめ
作成されるインスタンスタイプなど制御が必要な部分は多いと思いますが、「はじめに」で記述した通り、導入に一手間必要だった ALB Controller を導入せずとも使うことができるのに加えて、学習コストが高い EKS を使うためのハードルが下がり使いやすくなったのではと感じています。
これを機に EKS を扱ってみてはいかがでしょうか。

## 参考
https://docs.aws.amazon.com/eks/latest/userguide/auto-elb-example.html
https://docs.aws.amazon.com/eks/latest/userguide/sample-storage-workload.html