ダウンタイムなしでEC2からEKSへ移行しました！

![eyecatch_2103EC2toEKSwithoutDonwtime.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218415/75fc3996-8770-6fd8-8dd9-bdac611c4c98.png)

※ 本稿は <a href="https://tech.drecom.co.jp/?_src=qiita">Tech Inside Drecom</a> に掲載された記事、「<a href="https://tech.drecom.co.jp/ec2toeks-without-downtime/?_src=qiita">ダウンタイムなしでEC2からEKSへ移行しました！</a>」の Qiita 出張版です。

2021/06/27 の Drecom SRE Sunday にて、 この記事にかかれている EKS 移行に関する情報共有を行いました！
<a href="https://drecom.connpass.com/event/213139/" target="_blank">Drecom SRE Sunday (connpass)</a>

---

#はじめに
こんにちは！
enza SREチームのmendと申します！

先日の安藤さんの記事「<a href="https://tech.drecom.co.jp/migrate-rails-app-to-container/?_src=qiita" target="_blank">古き良きRailsアプリケーションをコンテナ化してKubernetes上で動かす</a>」にもある通り、運用しているプロダクトをAmazon EC2からAmazon EKSに移行しました。

プロダクトをダウンタイムなしにEC2からEKSに移行しましたので、今回は<b>ダウンタイムなしを実現したインフラ側の構成</b>について紹介させて頂きたいと思います。


#背景
まず背景としましては、私の関わっているプロダクトはこれまでEC2で動作しておりました。
EC2上でdockerコンテナを起動しているのではなく、capistranoでデプロイされ直接Railsを実行する一般的なスタイルになります。
インフラ構成は図にすると以下のようになります。
![p1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218415/a61d3308-73da-a027-50a7-93ff01e1e4e5.png)
Route53で管理しているドメインの後ろにApplication Load Balancer(以下ALB)を置き、ALBのアクセス先としてターゲットグループを用意してある形になります。

#移行方法の候補
初期段階で考えていた方法では、ALBに紐づくターゲットグループを切り替える案がありました。
しかしこの案だと、ALBがターゲットグループと紐付けされてからターゲットとなるインスタンスのヘルスチェックを行うため、切り替え直後はヘルスチェックが完了していないインスタンスが存在する時間が発生します。
結果として切替時にサーバーの負荷が急激に上昇しアクセスが処理できなくなってしまうため一時的にアクセスを遮断する対応、すなわちダウンタイムが必要でした。
しかしダウンタイムの発生はビジネス的な面で損失が大きいため、ダウンタイムを出さない、かつ段階的な移行を実現する方法として、2つの案が候補として挙がりました。

##Route53の加重ルーティングポリシー
Route53のルーティングポリシーの一つである<b>加重ルーティングポリシー</b>を設定し、任意の割合でRoute53のエイリアスを振り分ける設定になります。

###動作例
example.comのレコードのエイリアスとして、A：ALB1のドメイン名、B:ALB2のドメイン名を設定したとします。
A:Bの重み付けを4:6にした場合、example.comの名前解決時に40%の確率でALB1のドメイン名を返し、60%の確率でALB2のドメイン名を返す動作となります。

###加重ルーティングのメリット
Route53のルーティングポリシーを変更するだけのため、<b>割合変更のために操作するリソースがRoute53だけで済む</b>というメリットがあります。
併せてEKSで一般的に使用される<a href="https://github.com/kubernetes-sigs/aws-load-balancer-controller" target="_blank">ALB Ingress Controller</a>を使用できるため、一般的なEKSクラスターで使用しやすいメリットがあります。

###加重ルーティングのデメリット
加重ルーティングはアクセスを振り分けるためのもう一つのALBを作成する必要があり、ALBとターゲットグループ等のような<b>ALBに関連するリソース</b>を作る必要も発生してしまいます。

併せてRoute53が返却するエイリアスを割合で変更する設定のため、Route53の振り分け割合設定がユーザーに反映されるまで時間がかかり、<b>アクセスを任意の設定で振り分けるまでにラグが発生してしまう欠点</b>があります。

この欠点は一方のアクセス先で問題が発生したときに切り戻しにかかる時間が長くなり、<b>障害が完全に収束するまでの時間を伸ばしてしまう要因</b>になることが考えられます。

##ALBの加重ターゲットグループ
ALBのターゲットグループに複数のターゲットグループを設定し、<b>加重ターゲットグループ</b>とすることで任意の割合でアクセスを受け取るターゲットグループを振り分ける設定になります。

###動作例
ALBのターゲットグループとして、A:ターゲットグループ1、B:ターゲットグループ2の２つのターゲットグループを紐付けるとします。
A:Bの重み付けを4:6にした場合、ALBからターゲットグループに渡されるアクセスの40%がターゲットグループ1, 60%がターゲットグループ2に割り振られるようになります。

###加重ターゲットグループのメリット
加重ターゲットグループはALBにターゲットグループを追加するだけのため、Route53の加重ルーティングと異なり<b>同一のALBを使用することができる</b>メリットがあります。

またRoute53のようなDNSでの切り替えではないため、<b>アクセス割合設定の変更が即時反映される</b>特徴があります。

このメリットは非常に大きく、障害が発生したときには一方のアクセス先のみに設定しますが、設定が即時反映されるため、<b>障害発生から収束までスピーディに解決することが可能</b>です。

###加重ターゲットグループのデメリット
加重ターゲットグループの設定はALBに設定する内容のため、EKSで一般的とされるALB Ingress Controllerを使用できないデメリットがあります。

#加重ターゲットグループで移行する
上記2つの方法のメリット・デメリットを考慮したうえで、ALB Ingress ControllerではなくNodePortを使用していること、振り分けの割合設定が即時反映されることから加重ターゲットグループを使用して移行を進めることにしました。

ここからはダウンタイムなしを実現するために構築したインフラについて紹介していきたいと思います。

##移行時のインフラ
移行を行うにあたり、既存のALBのリスナーにEC2のターゲットグループに加え、加重ターゲットグループとしてEKSのターゲットグループを置きます。
図にすると以下のようになります。
![p2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218415/e12c050b-70c8-434d-b3f2-fdeed82a6a13.png)
こちらの図にあるように、ALBからアクセスする先のターゲットグループが複数存在するようになりました。

これらのターゲットグループにはアクセス振り分け割合を設定可能で、
例えば既存EC2側には90%, EKS内にあるターゲットグループには10%と任意の割合でアクセス先の変更をコントロールすることができます。

この割合変更はAWS マネジメントコンソールから手動で行うことができ、かつ設定した内容は即時反映されます。

そのため最初はEKS側に少ない割合のリクエストを振り分け、正しくリクエストが処理されることをPodのログ等から確認し、<b>EKSへのアクセスの割合を徐々に増やしていくことでスムーズな移行が可能になります</b>。

さらに徐々にアクセスの割合を増やすことによってクラスター全体のPodやワーカーノードの負荷を監視しながら移行できるため、万が一リソースが足りないといった問題は移行中に気づくことができるなどの恩恵もあります。

##移行後のインフラ
EKSへ移行後はEC2のターゲットグループへのアクセス割合が0%になっている状態になります。
こちらはEKSに完全に移行した後の図になります。
![p3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218415/5b1ec29c-bd12-6448-9003-6d84319a7c74.png)
こちらにあるように、EC2のターゲットグループにはアクセスが割り振られないため、完全なEKS移行が実現しております。
移行後はEC2側へのアクセスが割り振られていないため、<b>ユーザーに影響を出さずに安全にEC2を終了させることが可能</b>になります。

#移行時に注意すべきこと
上記の流れで行うことでダウンタイムを生むことなく移行ができますが、1つ注意すべき点がありますので記載します。

##EC2を停止するタイミング
ターゲットグループの仕様として、<b>ターゲットグループ内のインスタンスが全てヘルスチェックに失敗している場合はヘルスチェックに失敗しているインスタンスにもアクセスが割り振られます</b>。

<a href="https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/target-group-health-checks.html" target="_blank">ターゲットグループのヘルスチェック</a>には以下のように記載されております。

```
ターゲットグループに異常な登録済みターゲットのみが含まれている場合、ロードバランサーノードは異常なターゲット間でリクエストをルーティングします。
```

このことから、もしEC2側のターゲットグループにアクセス割合を割り振っている状態でEC2インスタンスを全て停止してしまうと、<b>停止しているインスタンスに対してもアクセスが流れてしまう</b>ので注意しましょう。

#まとめ
今回は実際にプロダクトをダウンタイム無しでEC2からEKSに移行した際の方法を紹介させて頂きました。

ダウンタイムを出さずに移行する方法としては<b>Route53の加重ルーティングポリシー</b>と<b>ALBの加重ターゲットグループ</b>のパターンがあり、それぞれのメリット・デメリットを加味したうえでALBの加重ターゲットグループを使用してEKSへの移行を行いました。

これまでEC2で運用しているプロダクトもきちんと手順を正しく踏むことで、安全に夢のEKSに移行できるので、EKSに移行する際に参考なれば幸いです。

今後もk8s関連の情報を発信できればと思います。

---

Tech Inside Drecom の最新の情報は Facebook や Twitter からお届けしています、フォローよろしくおねがいします！

* Twitter: <a href="https://twitter.com/DRECOM_TECH" target="_blank">@DRECOM_TECH</a>
* Facebook: <a href="https://www.facebook.com/tech.inside.drecom" target="_blank">tech.inside.drecom</a>

---

※ その他の Tech Inside Drecom の記事は、<a href="https://tech.drecom.co.jp/?_src=qiita">コチラ</a>からお探しいただけます！