EKS Auto ModeとEKS on Fargateの違いを調べてみた

こんにちは。
本記事は[Japan AWS Top Engineers Advent Calendar 2024](https://qiita.com/advent-calendar/2024/aws-top-engineers)の六日目の記事です！

今年のre:Inventもわくわくする発表ばかりですね。個人的には特にEKS Auto Modeが気になっているのですが、EKS on Fargateとは実際何が違うのか説明できるようにするために調査・検証してみました。

## 概要
### EKS Auto Modeとは
2024/11に発表されたEKSの機能。ノードのコンピューティングやストレージ、ネットワークをAWSが責任をもって管理してくれるのでより簡単にk8sクラスタを運用することができます。

https://aws.amazon.com/jp/blogs/containers/getting-started-with-amazon-eks-auto-mode/

### EKS on Fargateとは
Fargateがノードを管理してくれるので簡単にk8sクラスタを運用できます。詳しくは当時のブログをどうぞ。

https://aws.amazon.com/jp/blogs/news/amazon-eks-on-aws-fargate-now-generally-available/


## 比較サマリ

早速ですがサマリの表です!

|項目  |EKS Auto Mode  |EKS Fargate  |
|---|---|---|
|コントロールプレーンのバージョンアップ  |マニュアル  |マニュアル|
|ノードのバージョンアップ|不要（コントロールプレーンの後に自動実行）|不要（Podの再起動は必要）|
|ノードへのSSH|×|×|
|イメージのキャッシュ|〇（ノードにあれば）|×|
|GPUノードの利用|〇|×|
|Windowsノードの利用|×|×|
|Security Group for Pods|×|〇|
|Public IPを持つPod|〇|×|
|DaemonSetの作成|〇|×|
|特権コンテナの実行|〇|×|
|HostPort, HostNetwork|〇|×|
|ArmベースのCPU|〇|×|
|課金（クラスタ以外）|インスタンス単位|Pod単位|
|Spotインスタンスの利用|〇|×|
|RI/SavingsPlanの利用|RI/SP|SP|
|GuardDuty runtime monitoring対応|〇|×
## 各項目について
### コントロールプレーンのバージョンアップ
コントロールプレーンのバージョンアップはどちらも利用者が明示的に開始する必要があります
### ノードのバージョンアップ
Auto Modeはコントロールプレーンのバージョンアップ後、ノードのバージョンアップを自動で開始します。CoreDNSやkube-proxyなどのコンポーネントは一緒に更新してくれますが以下のものは自身でアップデートする必要があります。
- クラスタ内のアプリやワークロード
- 自製のアドオンやコントローラ
- Amazon EKS アドオン

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

Managed Nodeと比較してバージョンアップの考慮範囲が減るのは嬉しいですね。Blue/Greenによるクラスタアップグレード戦略をもともと採用していた場合、In-Place戦略に変えるほどのメリットではないと思いますが。

一方、FargateはPodを削除->起動すればバージョンアップされたノードで起動してきます。

> Fargate ノードを更新するには、そのノードが表すポッドを削除します。次にコントロールプレーンを更新し、ポッドを再デプロイします。Fargate で起動する新しいポッドには、クラスターのバージョンと一致する kubelet バージョンがあります。既存の Fargate ポッドは変更されません。

https://repost.aws/knowledge-center/eks-plan-upgrade-cluster

### ノードへのSSH
EKS Auto NodeのノードはEC2のサービスコンソールからも目視できますがSSH（Session Manager含む）はできません。

これはEKS Auto Modeは管理責任がAWS側にある`Managed Instance`というインスタンスを利用しているためです。

>EC2 Instances created by EKS Auto Mode are different from other EC2 Instances, they are managed instances. These managed instances are owned by EKS and are more restricted. You can’t directly access or install software on instances managed by EKS Auto Mode

https://docs.aws.amazon.com/eks/latest/userguide/automode-learn-instances.html

なお、管理責任はAWS側にある一方でノードのログはPUT可能なHTTPのURLを利用者側で用意することで出力が可能です。

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


Fargateも接続できるEC2インスタンスがないためSSHはできません。（なお、Podでのシェル実行についてはどちらも`kubectl exec -it <podname> -- sh`などで可能です。Podにシェルがあれば）

### イメージのキャッシュ
Auto Modeは新しくPodを立ち上げる際に、当該のノードで同じイメージからPodを起動したことがあればイメージのキャッシュが効くことが期待できます。FargateはPodごとにノードが分離されているので全く効きません。

### GPUノードの利用
Auto Modeは起動するノードのインスタンスタイプを指定することはできませんが、NodePoolでインスタンスタイプを制限できます。サポートされているインスタンスタイプにはGPU搭載のものも含まれています。

https://docs.aws.amazon.com/eks/latest/userguide/automode-learn-instances.html#_supported_instance_reference

一方、FargateはGPU未サポートです。
GPUサポートはAI・機械学習系のワークロードでは必須級なのでこれは大きいですね。

### Windowsノードの利用

両方未サポートです。

### Security Group for Pods
Auto ModeではPod単位のセキュリティグループはサポートされていません。ノード単位のセキュリティグループを利用できます。

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


:::note info
EKS on Fargateも最初はPod単位のセキュリティグループをサポートしていなかったので時間の問題かもしれません。
:::

一方、FargateはPod単位のセキュリティグループを利用できます。

ただ、Fargateの比較という点だとこれは大差ないと考えています。
1つのノードで1つのPodのみ実行し、通信の制御をノードのセキュリティグループで行えばほぼ同じことを実現できるからです。1つのノードで1つのPodのみ実行するのはPodAntiAffinityを使って以下のように定義できます。
```yaml
# 同じ app=my-app ラベルを持つPodは同じノードにスケジュールしない
apiVersion: v1
kind: Pod
metadata:
  name: one-pod-per-node
  labels:
    app: my-app
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - my-app
        topologyKey: kubernetes.io/hostname
  containers:
  - name: my-container
    image: my-image
```

なのでどちらかというとSecurity Group for Podsの制限は、EKSのManaged Nodeを利用するかAuto Modeを利用するかの選択の際に効いてくる印象です。


### Public IPを持つPod
Auto ModeではPodにPublic IPを付与できます。Fargateは未サポートです。

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

### DaemonSetの作成
検証の結果、Auto Modeでは作成可能でした。Fargateは未サポートです。
```bash
$ kubectl get ds
NAME      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
fluentd   1         1         1       1            1           <none>          54m
```

DaemonSetが使えるとなると、Fargateでロギングなどの機能を仕方なくサイドカーとしてPodごとに持たせていた場合に特にうれしいですね。Podごとに持たせていた場合、Podの増加に比例してクラスタ全体で必要なリソースを増やさなければならないのでコスト効率の観点で課題がある印象です。

### 特権コンテナの実行
検証の結果、Auto Mode、`priviledged: true`の特権コンテナを作れました。作れるということを認識し、必要に応じてGatekeeperなどで起動を防ぐ必要がありますね。なお、Fargateは未サポートです。


```bash
# privileged:trueのマニフェストを用意
cat << EOF > privileged.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    name: test-app-deployment
  name: test-app-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-app
  template:
    metadata:
      labels:
        app: test-app
    spec:
      containers:
        - image: nginx:latest
          name: test-app-container
          securityContext:
            privileged: true
EOF

# 適用する
$ kubectl apply -f privileged.yaml
deployment.apps/test-app-deployment created

# 以下、ホストのディレクトリ見れるか確認

# Pod一覧の確認
$ kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
fluentd-s2l4x                          1/1     Running   0          30m
nginx-deployment-d556bf558-lnzhj       1/1     Running   0          30m
nginx-deployment-d556bf558-n28r4       1/1     Running   0          30m
nginx-deployment-d556bf558-whrg9       1/1     Running   0          30m
test-app-deployment-58c4dcb56d-sc6c6   1/1     Running   0          28m

# マウント先の作成
$ kubectl exec test-app-deployment-58c4dcb56d-sc6c6  -- mkdir -p /mnt/hoge

# ホストをマウント
$ kubectl exec test-app-deployment-58c4dcb56d-sc6c6  -- mount /dev/nvme1n1p1 /mnt/hoge 

# マウントできてそう
$ kubectl exec test-app-deployment-58c4dcb56d-sc6c6  -- ls /mnt/hoge
mnt
opt
var

# 他のコンテナのログディレクトリが見れる。やはり特権モードで実行できている模様
$ kubectl exec test-app-deployment-58c4dcb56d-sc6c6  -- ls /mnt/hoge/var/log/containers
fluentd-s2l4x_default_fluentd-elasticsearch-b1b8edbcd9b1e0bd2641dfc14c690f220b0de77f5c66bec62fa6793e0ad9bb3d.log
nginx-deployment-d556bf558-lnzhj_default_nginx-3dff4d994e57dc86b04c3468f1c436a37e8ce008f827ec192b873a1ec3cab5c6.log
nginx-deployment-d556bf558-n28r4_default_nginx-62bb0e40317470e34a586a7b41a3cfb1a3aad08f2be46bb4d92f48f4eec43c41.log
nginx-deployment-d556bf558-whrg9_default_nginx-faf13f5b1837a1b57ab466f1f63b17875e314c19d74e87a9fb9dbe3f9d12c0a8.log
test-app-deployment-58c4dcb56d-sc6c6_default_test-app-container-b173c35bb9a383e995ac683f7bf3eba4fe3454b9328928ba69eae09cfed64897.log
```

### HostPort, HostNetwork
Auto Modeでは[サポートされています](https://docs.aws.amazon.com/eks/latest/userguide/auto-networking.html
)。FargateはPodがノードのホストネットワークに直接アタッチされる形態なのでサポートされていません。

### ArmベースのCPU
Auto Modeでは対応しています。Fargateでは未サポートです。

CPUをGravitonなどのArmベースにすると一般にコストが抑えられる効果があります。なお動かすミドルウェアやそのバージョンによってはArmベースのCPUに非対応な場合があります。

### 課金
EKS Auto Mode では、通常の EC2 インスタンスのコストに加えて、起動した EC2 インスタンスタイプに基づいた管理料金が請求されます。

一方、Fargateはタスクまたはポッドのために要求された vCPU、メモリ、オペレーティングシステム、CPU アーキテクチャ、およびストレージリソースに基づいて課金されます。

https://aws.amazon.com/jp/fargate/pricing/

では実際どの程度の価格差になるのか、東京リージョンの2025年3月時点の料金で計算したのがこちらの表になります。


|Instance|vCPU|Mem|Auto Mode|Fargate|Auto Mode/Fargate|
|:--|--:|---:|--:|--:|--:|
|<font color="#1e90ff">c7g.medium</font>|<font color="#1e90ff">1|<font color="#1e90ff">2|<font color="#1e90ff">$0.05096|<font color="#1e90ff">$0.06162|<font color="#1e90ff">82.7%|
|<font color="#1e90ff">r7g.medium</font>|<font color="#1e90ff">1|<font color="#1e90ff">8|<font color="#1e90ff">$0.07215|<font color="#1e90ff">$0.0948|<font color="#1e90ff">76.1%|
|<font color="#1e90ff">m7g.medium</font>|<font color="#1e90ff">1|<font color="#1e90ff">4|<font color="#1e90ff">$0.05902|<font color="#1e90ff">$0.07268|<font color="#1e90ff">81.2%|
|c7i.xlarge|4|8|$0.25166|$0.24648|102.1%|
|<font color="#1e90ff">c7g.xlarge</font>|<font color="#1e90ff">4|<font color="#1e90ff">8|<font color="#1e90ff">$0.20373|<font color="#1e90ff">$0.24648|<font color="#1e90ff">82.7%|
|r7i.large|2|16|$0.17875|$0.1896|94.3%|
|<font color="#1e90ff">r7g.large</font>|<font color="#1e90ff">2|<font color="#1e90ff">16|<font color="#1e90ff">$0.0155|<font color="#1e90ff">$0.1447|<font color="#1e90ff">76.3%|
|m7i.4xlarge|16|64|$1.16659|$1.16288|100.3%|
|<font color="#1e90ff">m7g.4xlarge</font>|<font color="#1e90ff">16|<font color="#1e90ff">64|<font color="#1e90ff">$0.94438|<font color="#1e90ff">$1.16288|<font color="#1e90ff">81.2%|

:::note info
列の説明
Instance：EKS Auto Modeで動かすインスタンスタイプ
Auto Mode：Auto Modeを利用した場合の料金の総計
Fargate：インスタンスと同じvCPU/MEMのタスクを実行した場合の料金

青字の列はArm(Graviton)を使用しているインスタンスです
:::

表をまとめる中で以下のことがわかりました
- EKS Auto Modeで対応しているインスタンスサイズの最小は*.medium
    - FargateはvCPU:0.25, MEM:0.5のタスクから対応している
    - 1つのノードで動かすPodの要求するリソース合計が極端に少ない場合はFargateのほうがコスト的には安くなる可能性がある
- EKS Auto Modeの`起動したEC2に基づく管理料金`はr7g, r7i, m7i, m7g, c7i, c7gのインスタンスタイプに限るとみな一様に12%だった
- Intel系インスタンスの料金と、Fargateの料金はほぼ同じくらい
- Arm系インスタンスの料金と、Fargateの料金は前者が2割引きくらい

### Spotインスタンスの利用
Auto Modeでは[サポートされています](https://docs.aws.amazon.com/eks/latest/userguide/create-node-pool.html#_eks_auto_mode_supported)。Fargateは[未サポートです](https://github.com/aws/containers-roadmap/issues/622)。

### RI/SPの利用
Auto ModeではRI/Savings Plansがサポートされています。Karpenterを利用しているので、ROIを最大化するという観点ではインスタンスタイプに自由度があるSavings Planのほうがよさそうでしょうか。FargateではSavings Planのみサポートされています。

### GuardDuty Runtime Monitoring対応
GuardDuty Runtime Monitoringはコンテナランタイムの脅威検知をおこなう機能で、コンテナの権限昇格や不正なプロセス実行を検知できます。

Auto Modeはサポート、EKS Fargateは未サポートです。

> Runtime Monitoring supports Amazon EKS clusters running on Amazon EC2 instances and Amazon EKS Auto Mode.
>
>Runtime Monitoring doesn't support Amazon EKS clusters with Amazon EKS Hybrid Nodes, and those running on AWS Fargate.

https://docs.aws.amazon.com/guardduty/latest/ug/how-runtime-monitoring-works-eks.html

## EKS on Fargateと今後はどう付き合うか考える
実は公式から今後はEKS Auto Modeを推奨する旨が示されています（re:Inventのセッションでは言及されておらず、探し回ってFAQでようやく公式見解を見つけました）

https://x.com/_takahash/status/1878422630744703061

また、上記の比較結果からもEKS Auto ModeではできないけどEKS on Fargateにはできることは目立って存在しません。「Security Group for Pods」の利用可否は先に述べた通り、Fargateとの比較という観点ではあまり差がありません。

このことから、新規にEKS on Fargateを利用したほうが良いケースは限定的で、EKS Auto Modeを基本使用する形が良いと思います（思いついた限定的な例を以下に示します）。

- ノードのことを極力考えたくない
    - EKS Auto ModeでもEC2の管理は不要ですが、Karpenterの管理は必要なのでノードは透けて見えますしKarpenterの知識が必要です
- 特権コンテナが実行される可能性を少しでも減らしたい
    - EKS Auto ModeでもGateKeeperなどで特権コンテナの実行を制御できますが、Fargateはそもそも実行できないのでよりセキュアです
- 1つのノードで動かすPodが要求するリソースの総計が非常に少ない。*.small以下のインスタンスサイズでも足りそう
    - EKS Auto Modeが対応しているのは*.mediumから
    - この場合は、ECS/Fargateで代替できないかは検討余地があるように思います。クラスタ自体のコストはかからず、Armも使えます。

既存のEKS on Fargateからの移行については、即座に切り替えるほどの明確なメリットがあるかは疑問です。EKS Auto Modeが公式に推奨されるようになったとはいえ、現在Fargateで必要な機能が満たされているなら、より自由度が高くなる分、管理上の検討事項も増加します。移行コストの回収期間など、綿密な検討が必要となるでしょう。

なお移行時の重要な注意点として、EKS on Fargateで使用中の既存ロードバランサーをEKS Auto Modeに直接統合することはできません。

したがって移行する場合は、Fargate環境と並行してEKS Auto Modeの環境を構築し、DNSを活用してエンドユーザーからのトラフィックを両環境のロードバランサー間で切り替えていくアプローチが実用的でしょう。
![switch.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552758/30616e3e-65b0-4690-b326-e9308b184202.png)



## おわりに
EKS Auto ModeとFargateの違いについてまとめてみました！
何かのお役に立てば幸いです。