EKSのノード料金を節約するためにやったこと
Kubernetes Advent Calendar 2021その2の20日目の記事です
今年業務で取り組んだことの一つとして管理しているEKSのコストの最適化を行いました。社内のことなので具体的にどれくらい削減したか等は省略しますが、特に気にせずノードを使っていた時に比べて、ノードにかかるコストをかなり節約できたのでどういった観点からコスト最適化をおこなったかを紹介したいと思います。
※紹介するインスタンスタイプ等は2021/12月現在の情報をもとに記載しています。
1. Spotインスタンスの活用とSaving Planの検討
Spotインスタンス
Spotインスタンスの利用はコストカットの点では真っ先に上がってくる話題だと思います。今更書くことも多くないので、以下の記事やWorkshopを参考にしてください。
- https://zenn.dev/nameless_gyoza/articles/how-to-use-spot-instance-on-eks
- https://ec2spotworkshops.com/using_ec2_spot_instances_with_eks.html
Spotインスタンスを利用していると頻繁にノードが入れ替わるので、稼働しているアプリケーションがちゃんと対応しているかどうかは気にしておいてください。特に処理が長時間続くJob等はSpotで動かなさい方がいいケースがあります
Saving Plan
簡単に言うと一定の利用量をあらかじて宣言+前払いすることを条件にして割引を受けられるプランです。似たようなものにリザーブドインスタンスがありますが、Saving Planの方がインスタンスタイプを柔軟に設定できるため、Saving Planを利用する方が適切な場合が多いでしょう。これだけでインスタンスの料金をかなり抑えることができます。
ただ、コミット量をあらかじめ見定めておく必要があるので、後述するリソースの最適化やスポットインスタンスの利用をする前の段階でコミット量を計算すると、コスト最適化を行ったあとに思ってたよりコミット量が少なかったと言う事態が起きてしまうため、Saving palnの導入は諸々の最適化をしたあとに行う方が良いでしょう。
2. インスタンスタイプの使い分け&リソースの最適化
アプリケーションの特性による使い分け
EKS上で稼働させる全てのPodが同じアプリケーションで、同じリソース量を要求するのであれば話は簡単なのですが、実際には様々な種類のアプリケーションが稼働しており、必要なリソース量も異なります。動かしているアプリケーションごとにノードのインスタンスタイプを分けることでコストを最適化させることができる場合があります。
2.1 通常のアプリケーション
バックエンドサーバーなどの通常のアプリケションです。特に考慮すべき点はなく、GracefullShutdown等に対応しており、SpotinstanceのTerminationが頻繁に起きてもサービスとして正常に動く状態になっていれば、インスタンスタイプ等で考慮すべき点はないと思います。
しかし、過剰にリソースを割り当てていたり、逆にリソースが足りていないケースもあります。マイクロサービス運用をしているシステムの場合、Deploymentのリソース割り当てをコピペやテンプレートから持ってきていることも多く、特に問題が起きていないアプリケーションでも割り当てリソースを確認すると適切なリソース割り当てがされていないこともあるので一度確認してみるといいかも知れません。
また、CPU、Memoryの割合にも一度気をつかってみるといいでしょう。M5系のインスタンスの場合、1vCPU当たり4GBが利用できます。CPUを500m割り当てているPodでMemoryを1GBしか割り当てていないといったアプリケーションが多いとMemoryの無駄が多いのでC6系のインスタンスをつかうことも考慮してもいいかも知れません。
2.2 大量のデータをさばくアプリケーション
システムの特性による部分が多いですが、例えば動画データを変換するといったアプリケーションや、ユーザのパーソナライズドなデータをリアルタイムに扱うといったアプリケーションだと、ユーザのアクセスに比例して大きな負荷がかかることがあります。こういったアプリケーションの場合、スケールの幅が大きいため、専用のノードを用意することでリソース効率を上げることができます。
大量にスケールするアプリケーションをそのほかのアプリケーションと同じように稼働させた場合、ノードにある程度リソースの空きが発生することがあります。その代わりにTaintsとTolerationsを利用して専用ノードを用意し、適切なリソースを割り当てることでノードのリソースを余すことなく使うことができます。
例: 2vCPU+8GBのノードの場合kubeletやDeamonsetで500m, 1000Mi使われていれば残りの1.5vCPUと7GB(単位とか色々おかしいですが)を1ノードで動かしたいPod数で割ったリソースを各Podに割り当てることでリソースを余すことなく使うことができます。
2.3 Job系
embulkを使ったDBの同期Jobなどが該当します。どういった使い方をしているのかにもよりますが、データ量が多いケースが多いのでMemoryを多く要求する場合が多いでしょう。C6系よりM5系といったCPUに対するMemoryの量が多いインスタンスタイプを選択すると良いかもしれません(逆も然り)
Job系のPodは専用のノードで動かしておく方がコスト最適化の面でもnoisy neighborを避けるといった点でも良いと思います。
また特性上利用するリソースが多くなりがちな上に、Jobの実行が終わってからノードが削除されるまではまったく利用されない時間が発生するので、Cluster AutoScalerを利用している場合Periodの設定を見直してみたり、Karpenterを利用することでJobが終了してからスケールインするまでにかかる時間を早くすることができます。
3. その他インスタンスタイプについて
同じM5系のインスタンスでもM5よりM5aの方がコストメリットが高かったりするように、CPUやインスタンスの世代によるコストの違いも大きいです。基本的に世代が後になればなるほど性能比のコストが安い場合が多いのでAWS re:Invent 2021でM6aインスタンスが発表されましたが、M5aのインスタンスを利用している場合、Regionで利用できるようになったら積極的に切り替えて行っていいと思います。
インスタンスタイプに関しては以下のスライドが簡潔にまとまっていてわかりやすいです
その他
- KarpenterやManeged SpotノードグループのようにAWS, EKS周りのアップデートは盛んに行われているので色々キャッチアップしていくと新しくコストカットできる部分が見つかることがあります。
- コストカットは数字として成果がわかりやすいので楽しいです。
Discussion