LambdaでEKS Worker Nodeの夜間・休日停止を行う


はじめに

検証環境やステージング環境でEKSを使用するときには夜間・休日には停止させて料金を抑えたいことがあると思います。
しかしながらEKSのWorker Nodeの数は宣言的であるがために停止させても新たに立ち上がります。
Masterを消すにしても元の状態に戻すためのアプリケーションのバックアップ・リストア作業を全て自動化しておかないと面倒です。

今回はLambdaでAutoscaling Groupのパラメータを変更することでWorker Nodeを夜間・休日にシャットダウンさせます。

実施手順

1. Lambda関数の作成

ランタイムはPython 3.7とします。

関数は次のようになります。
停止と起動の両方に対応できるようにします。

lambda_function.py
import boto3

autoscaling = boto3.client("autoscaling")

def lambda_handler(event, context):
  args = dict(AutoScalingGroupName=event["AutoSaclingGroupName"], 
              MinSize=event["MinSize"], 
              MaxSize=event["MaxSize"], 
              DesiredCapacity=event["DesiredCapacity"])
  autoscaling.update_auto_scaling_group(**args)

2. CloudWatch Eventsルールの作成

起動停止の2種類のルールをCloudWatch Eventsで作成していきます。
Nodeは平日7:00-23:00(JST)で起動しているものとします。

停止ルール

スケジュールではcron式(0 14 ? * MON-FRI *)(日本時間で平日23:00)を入れますがUTCであることに注意しましょう。
関数は手順1で作成したものです。

関数への入力は次のJsonを指定します。
Node数が0になるようにします。

{
  "AutoSaclingGroupName": "pulumi-eks-cluster-5b04401d-NodeGroup-1OC0O09KCF829",
  "MinSize": 0,
  "MaxSize": 0,
  "DesiredCapacity": 0
}

ルール名を指定して作成を完了させます。

起動ルール

起動ルールではcron式(0 22 ? * SUN-THU *)(日本時間で平日7:00)とします。
こちらもUTCであることに注意しましょう。

入力のJsonは次のようになります。
デフォルトNode数を2としています。

{
  "AutoSaclingGroupName": "pulumi-eks-cluster-5b04401d-NodeGroup-1OC0O09KCF829",
  "MinSize": 1,
  "MaxSize": 2,
  "DesiredCapacity": 2
}

ルール名を指定して作成を完了させます。

3. IAM Policyのアタッチ

手順1で自動で作成されたIAM RoleにAutoScalingGroupを操作するためのIAM Policyをアタッチします。

updateするだけなのでオーバーキルではありますが、事前に用意されているAutoScalingFullAccessを選択することとします。

問題なくアタッチされたことを確認します。

テスト

Lambdaの画面でテストをします。

テストイベント設定でNode停止ルールを設定します。

実際にテストしてみましょう。
成功となることが確認できます。

AutoScalingGroupの画面でNode数が0になることが確認できます。

おわりに

LambdaでEKS Worker Nodeに紐付くAutoscaling GroupのNode数を変更し夜間・休日に停止させる手順を説明しました。

本当に料金を抑えるなら下記3つの設定を全てコード化しておき毎日削除・作成を行うことが理想だと思います。

  • AWSリソース
  • Kubernetesリソース
  • アプリケーション

ただ、コード化する時間が取れない場合はとりあえず今回の手順に沿ってWorker Nodeだけ落とすだけでも料金は抑えられます。