LoginSignup
6
0

More than 1 year has passed since last update.

Amazon EKSでEC2料金を節約する

Last updated at Posted at 2021-12-11

この記事は NTTコムウェア Advent Calender 2021 12日目の記事です。

はじめに

NTTコムウェアのtonomuraです。
本記事では、AWSのマネージドサービスであるAmazon EKSにおけるリソース使用料の節約を試みた内容を紹介します。

想定読者

・Amazon EKSをステージング環境で利用していて、利用料金に悩んでいる方
・平日日勤帯以外などの未使用時間にサーバを止めておきたい方
・コスト削減したいけどAWS Fargateへの移行に踏み切れない方

Amazon EKSとは

Amazon Elastic Kubernetes Service の略であり、AWS上でkubernetes環境を簡易に構築・運用できるマネージド・サービスです。

似たようなサービスにAmazon ECSやAmazon EKS on Fargateなどがあり、これらはサーバを意識することなくコンテナをデプロイできるサービスになります。

対して、Amazon EKSはワーカーノードと呼ばれる、コンテナがデプロイされるサーバ(EC2インスタンス)は自分たちで管理する必要があり、従量課金で使った分だけ課金されてしまいます。

本記事の内容

そこで、主にステージング環境用途で使用する場合において、少しでも利用料金を節約するために、使っていない間にEC2インスタンスを落としておく方法を紹介します。

また、EC2インスタンスの復旧までにどのくらい時間がかかるのか、kubernetesリソースの状態はどのように遷移するのか、コマンド実行結果と合わせて紹介します。

前提条件

・本記事で扱うアプリケーションは、コンテナ化されたWeb三層構造のサンプルアプリです
・複数のサービスを組み合わせている場合、Podの起動順序等の制約により、正しく動作しない場合があります
・EKSクラスター(eksctlを利用して構築)やAuto Scalingグループは予め設定済みの状態です

・使用するツールとワーカーノードの構成は以下のとおりです

$ aws --version
aws-cli/2.2.12 Python/3.8.8 Linux/4.14.77-70.59.amzn1.x86_64 exe/x86_64.amzn.2018 prompt/off
$ kubectl get nodes
NAME                                       STATUS   ROLES    AGE     VERSION
ip-10-**-**-**.region.compute.internal     Ready    <none>   38h   v1.20.7-eks-*****
ip-10-**-**-**.region.compute.internal     Ready    <none>   38h   v1.20.7-eks-*****
ip-10-**-**-**.region.compute.internal     Ready    <none>   38h   v1.20.7-eks-*****
ip-10-**-**-**.region.compute.internal     Ready    <none>   38h   v1.20.7-eks-*****

ノード名は伏せていますが、2つのノードグループで構成されており、各ノードグループに対してデプロイされるPodを振り分けています。

初期状態

まずはどのようなPodが立ち上がっているかを確認します。
今回の環境では、サンプルアプリ以外にもPodのログを収集するContainer Insights のリソースが動いています。

$ kubectl get pods -A
NAMESPACE           NAME                                      READY   STATUS    RESTARTS   AGE
amazon-cloudwatch   cloudwatch-agent-fjfdz                    1/1     Running   0          20m
amazon-cloudwatch   cloudwatch-agent-jz4wf                    1/1     Running   0          36m
amazon-cloudwatch   cloudwatch-agent-x28qt                    1/1     Running   0          27m
amazon-cloudwatch   cloudwatch-agent-z5c5j                    1/1     Running   0          27m
amazon-cloudwatch   fluentd-cloudwatch-dgt4x                  1/1     Running   0          20m
amazon-cloudwatch   fluentd-cloudwatch-gj9lf                  1/1     Running   0          27m
amazon-cloudwatch   fluentd-cloudwatch-jqtcz                  1/1     Running   0          36m
amazon-cloudwatch   fluentd-cloudwatch-xqdnk                  1/1     Running   0          27m
test-ap             test-ap-5ffc6fc4cc-29cmv                  1/1     Running   0          44d
test-ap             test-ap-5ffc6fc4cc-c4h9f                  1/1     Running   0          44d
test-ap             test-ap-5ffc6fc4cc-msrtp                  1/1     Running   0          44d
test-ap             test-ap-5ffc6fc4cc-v7cdx                  1/1     Running   0          44d
test-ap             nginx-8c489f6cf-968ps                     1/1     Running   0          29m
test-ap             nginx-8c489f6cf-cb26n                     1/1     Running   0          29m
test-ap             nginx-8c489f6cf-fzxc9                     1/1     Running   0          29m
test-ap             nginx-8c489f6cf-nsdph                     1/1     Running   0          29m
kube-system         alb-ingress-controller-68f5cb8b4b-rklj2   1/1     Running   0          29m
kube-system         aws-node-hj5gf                            1/1     Running   0          27m
kube-system         aws-node-jfqps                            1/1     Running   0          37m
kube-system         aws-node-w2sbs                            1/1     Running   0          27m
kube-system         aws-node-zxctr                            1/1     Running   0          21m
kube-system         coredns-5fd8748bdd-5jhct                  1/1     Running   0          29m
kube-system         coredns-5fd8748bdd-kkr2x                  1/1     Running   0          29m
kube-system         efs-csi-node-6kq4b                        3/3     Running   0          37m
kube-system         efs-csi-node-g9lss                        3/3     Running   0          27m
kube-system         efs-csi-node-jzbpf                        3/3     Running   0          27m
kube-system         efs-csi-node-v4p7w                        3/3     Running   0          21m
kube-system         kube-proxy-46xxl                          1/1     Running   0          21m
kube-system         kube-proxy-gbktt                          1/1     Running   0          27m
kube-system         kube-proxy-hbnff                          1/1     Running   0          37m
kube-system         kube-proxy-xq275                          1/1     Running   0          27m

※補足
マネージドサービスのため、etcdapiserverなどのリソースは参照できないため登場しません。

ノードを落としてみる

早速、この状態からワーカーノードを落としてみます。
落とす方法としては、Auto Scalingグループの設定の内、「希望する容量」を変更し、ノードが強制的に0台になるようにします。

コマンドは以下のとおりです。

#ノードグループ1 の希望する容量を「0」にする
$ aws autoscaling set-desired-capacity --auto-scaling-group-name eksctl-test-ap-nodegroup-z1-nodeg-NodeGroup-1PXBUVII5GDBS \
  --desired-capacity 0
#ノードグループ2 の希望する容量を「0」にする
$ aws autoscaling set-desired-capacity --auto-scaling-group-name eksctl-test-ap-nodegroup-z2-nodeg-NodeGroup-1IHPM2OH5CEW9 \
  --desired-capacity 0

ノードの状態を確認してみます。

$ kubectl get nodes
No resources found in default namespace.

リソースが見つからない状態になりました。

この時点で、EC2インスタンスは停止状態のため、EC2料金は課金されなくなりました。

続いて、PodのSTATUS(状態)を確認してみます。

$ kubectl get pods -A
NAMESPACE     NAME                                      READY   STATUS    RESTARTS   AGE
test-ap       test-ap-5ffc6fc4cc-4lc8c                  0/1     Pending   0          2s
test-ap       test-ap-5ffc6fc4cc-d756p                  0/1     Pending   0          2s
test-ap       test-ap-5ffc6fc4cc-gjkt9                  0/1     Pending   0          2s
test-ap       test-ap-5ffc6fc4cc-ljmp7                  0/1     Pending   0          2s
test-ap       nginx-8c489f6cf-dthxl                     0/1     Pending   0          22s
test-ap       nginx-8c489f6cf-lsb8q                     0/1     Pending   0          23s
test-ap       nginx-8c489f6cf-p878k                     0/1     Pending   0          2s
test-ap       nginx-8c489f6cf-vdcg9                     0/1     Pending   0          2s
kube-system   alb-ingress-controller-68f5cb8b4b-mshkq   0/1     Pending   0          2s
kube-system   coredns-5fd8748bdd-cf584                  0/1     Pending   0          2s
kube-system   coredns-5fd8748bdd-zdzkm                  0/1     Pending   0          2s

一部のPodが見えなくなり、STATUS(状態)がPending(保留)に変わりました。

この状態で試しにアプリにアクセスしてみます。

$  curl -k https://xxxx/test-ap/login/ -o /dev/null -w '%{http_code}\n' -s
503

503エラーとなりアクセスできなくなりました。

ノードを復旧させる

復旧させる方法は、Auto Scalingグループの設定を同じコマンドでもとに戻すだけです。

#ノードグループ1 の希望する容量を「2」にする
$ aws autoscaling set-desired-capacity --auto-scaling-group-name eksctl-test-ap-nodegroup-z1-nodeg-NodeGroup-1PXBUVII5GDBS \
  --desired-capacity 2
#ノードグループ2 の希望する容量を「2」にする
$ aws autoscaling set-desired-capacity --auto-scaling-group-name eksctl-test-ap-nodegroup-z2-nodeg-NodeGroup-1IHPM2OH5CEW9 \
  --desired-capacity 2

ノードのSTATUS(状態)を確認します。

$ kubectl get nodes
No resources found in default namespace.

実行直後はまだノードの情報は出力されません。
しばらく-wオプションで待機すると、およそ2分ほどでノードの状態が確認できるようになりました。

$ kubectl get nodes -w
NAME                                     STATUS     ROLES    AGE   VERSION
ip-xx-xx-xx-xx.region.compute.internal   NotReady   <none>   0s    v1.20.7-eks-xxxxxx
ip-xx-xx-xx-xx.region.compute.internal   NotReady   <none>   0s    v1.20.7-eks-xxxxxx
ip-xx-xx-xx-xx.region.compute.internal   NotReady   <none>   0s    v1.20.7-eks-xxxxxx
ip-xx-xx-xx-xx.region.compute.internal   NotReady   <none>   0s    v1.20.7-eks-xxxxxx

この時点ではSTATUS(状態)はNotReadyですが、しばらくすると、

$ kubectl get nodes
NAME                                       STATUS   ROLES    AGE     VERSION
ip-xx-xx-xx-xx.region.compute.internal     Ready    <none>   45s   v1.20.7-eks-xxxxxx
ip-xx-xx-xx-xx.region.compute.internal     Ready    <none>   45s   v1.20.7-eks-xxxxxx
ip-xx-xx-xx-xx.region.compute.internal     Ready    <none>   45s   v1.20.7-eks-xxxxxx
ip-xx-xx-xx-xx.region.compute.internal     Ready    <none>   45s   v1.20.7-eks-xxxxxx

STATUS(状態)がReadyになりました。

その後、Podの状態を確認します。

$ kubectl get pods -A
NAMESPACE           NAME                                      READY   STATUS    RESTARTS   AGE
amazon-cloudwatch   cloudwatch-agent-79tfh                    1/1     Running   0          3m41s
amazon-cloudwatch   cloudwatch-agent-fqgzd                    1/1     Running   0          3m51s
amazon-cloudwatch   cloudwatch-agent-gbvbk                    1/1     Running   0          4m1s
amazon-cloudwatch   cloudwatch-agent-nprzt                    1/1     Running   0          4m11s
amazon-cloudwatch   fluentd-cloudwatch-4gfqf                  1/1     Running   0          3m51s
amazon-cloudwatch   fluentd-cloudwatch-5rxrk                  1/1     Running   0          4m11s
amazon-cloudwatch   fluentd-cloudwatch-cd52v                  1/1     Running   0          3m41s
amazon-cloudwatch   fluentd-cloudwatch-p7tx4                  1/1     Running   0          4m1s
test-ap             test-ap-5ffc6fc4cc-4lc8c                  1/1     Running   0          7m31s
test-ap             test-ap-5ffc6fc4cc-d756p                  1/1     Running   0          7m31s
test-ap             test-ap-5ffc6fc4cc-gjkt9                  1/1     Running   0          7m31s
test-ap             test-ap-5ffc6fc4cc-ljmp7                  1/1     Running   0          7m31s
test-ap             nginx-8c489f6cf-dthxl                     1/1     Running   0          7m51s
test-ap             nginx-8c489f6cf-lsb8q                     1/1     Running   0          7m52s
test-ap             nginx-8c489f6cf-p878k                     1/1     Running   0          7m31s
test-ap             nginx-8c489f6cf-vdcg9                     1/1     Running   0          7m31s
kube-system         alb-ingress-controller-68f5cb8b4b-mshkq   1/1     Running   0          7m31s
kube-system         aws-node-54975                            1/1     Running   0          4m31s
kube-system         aws-node-54gjt                            1/1     Running   0          4m31s
kube-system         aws-node-m4lwc                            1/1     Running   0          4m32s
kube-system         aws-node-xw6zn                            1/1     Running   0          4m31s
kube-system         coredns-5fd8748bdd-cf584                  1/1     Running   0          7m31s
kube-system         coredns-5fd8748bdd-zdzkm                  1/1     Running   0          7m31s
kube-system         efs-csi-node-4gvj4                        3/3     Running   0          4m32s
kube-system         efs-csi-node-5v556                        3/3     Running   0          4m31s
kube-system         efs-csi-node-8fln9                        3/3     Running   0          4m31s
kube-system         efs-csi-node-dzfqt                        3/3     Running   0          4m31s
kube-system         kube-proxy-4wdrm                          1/1     Running   0          4m31s
kube-system         kube-proxy-4xtr8                          1/1     Running   0          4m31s
kube-system         kube-proxy-zndfc                          1/1     Running   0          4m31s
kube-system         kube-proxy-zvvxs                          1/1     Running   0          4m31s

すべてのPodが元のRunningに戻りました。

再びアプリにアクセスしてみます。

$  curl -k https://xxxx/test-ap/login/ -o /dev/null -w '%{http_code}\n' -s
200

無事に元どおりアクセス可能な状態に戻りました。

復旧までにかかる時間はトータルで10分程度ではありますが、すべてのノードをコマンド一つで停止し、復旧することができました。

まとめ

Auto Scalingグループの設定を変更するだけで、Amazon EKS 上のEC2インスタンスを停止し、リソース使用料を節約できました。
一時的にPodはPendingになるものの、ノード復旧後も正常にアプリにアクセスすることができました。

その他の使い方

コマンドも簡易であるため、AWS Lambdaなどと組み合わせ、任意のイベントをトリガーとして活用できます。
例えば、チャットに「業務終了」と発言したタイミングでステージング環境を落としたり、定期的に自動実行させることも可能かと思います。

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0