【AWS】ブルーグリーンデプロイ形式によるダウンタイムを避けた移行切り替えの検討

AWSの環境を移行する際に、ダウンタイムを出来る限り避け、切り替えを行う方法について検討する。
ここではAWS -to AWSの環境移行の場合を対象とする。

システム構成は以下である。

旧基盤:
API Gateway→NLB→ALB→EKS on EC2→RDS

新基盤:
API Gateway→NLB→ALB→EKS on Fargate→aurora

①ELBのターゲットに比重ルーティングする

まず最初に考えたのはNLBの設定で、ターゲットへの比重ルーティングを行う方法だ。
リスナールールに旧基盤向けのターゲットグループ(以下TG)と新基盤向けのTGを紐づけて、Weightにトラフィックを送る割合を指定する。
例えば旧基盤TGのWeightが8で、新基盤TGのWeightが2ならトラフィックは8:2の割合で旧基盤と新基盤へそれぞれ分散される。

この設定を現状稼働している旧基盤のNLBに対して行えば、新基盤向けのWeightの値を徐々に大きくしていくことで、段階的かつ、ダウンタイムがなく切り替えることができるだろうと考えた。
またこの方式は比較的にシンプルかつ、現行にあまり変更を加えない作業で実現することができる。

前提として、2つの新旧基盤はTransit gatewayやVPC ピアリングなどでネットワークが接続され互いに疎通できることが必要である。
また旧基盤に新規で新基盤へトラフィックを送る用のTGを作成したうえで、ターゲットとなる新基盤側のリソースのセキュリティグループ(以下SG)に旧基盤からのインバウンドを穴あけしておく必要がある。
VPC ピアリングであれば、旧基盤のNLBのSGのIDをインバウンドに許可する方法もあるだろうし、NLBのプライベートIPアドレスや、VPC、サブネット単位でCIDRを許可するというやり方でも構わない。
今回の構成では、旧基盤のNLBがあるサブネットCIDRのインバウンド許可を新基盤のEKSのSGに許可することとした。また両基盤はVPC ピアリングで接続した。

しかしここで大きな問題が発覚した。

リスナールールを使用して複数のTGにルーティングするという機能がNLBには実装されていなかったのだ。
ALBのみ複数のTGに負荷分散することが可能だった。

それではALBから新基盤へトラフィックを分散することも考えたがここでまた別の制約に引っかかった。
それはCIDR制限である。

新基盤EKSは今回Fargateで稼働するため、固定のインスタンスを持たず、TGのターゲットにはPodのIPアドレスを指定する必要があった。
しかし新基盤のVPCのCIDRがTGのVPC外のIPアドレスへのルーティングの際の許可されているCIDRの範囲外だったのだ。

IP アドレスによるターゲットの登録または登録解除

IPv4 ターゲット

登録する IP アドレスは、次のいずれかのCIDRブロックからのものである必要があります。ターゲットグループの VPC のサブネット
10.0.0.0/8 (RFC1918)
100.64.0.0/10 (RFC 6598)
172.16.0.0/12 (RFC1918)
192.168.0.0/16 (RFC 1918)

Application Load Balancer ターゲットグループにターゲットを登録する - Elastic Load Balancing

またALBはkubernetes Ingressにより自動生成されるリソースのため、そもそもEKSのPodへのルーティング以外の用途に使うことはできないものだった。

そこでELBによる移行切り替えを断念し、API GatewayのCanaryリリース機能を使用して、移行切り替えを行う方法を検討した。
なお、この時点でCIDR設計は上記の範囲内に修正することとした。

②API GatewayのCanaryリリース

API Gatewayには開発中のAPIの試験的なリリースや、ブルーグリーンデプロイによる切り替えのためにCanaryという機能がある。

Canary リリースは、新しいバージョンの API (および他のソフトウェア) をテスト目的でデプロイするソフトウェア開発戦略であり、ベースバージョンは同じステージで通常のオペレーション用の本稼働リリースとしてデプロイされたままになります。説明のため、このドキュメントではベースバージョンを本稼働リリースとします。これは合理的ですが、テストのために Canary リリースを非本稼働バージョンにも自由に適用できます。

Canary リリースのデプロイでは、すべての API トラフィックはランダムに区切られて事前に設定された比率で本稼働リリースと Canary リリースに送られます。通常、Canary リリースは低い割合の API トラフィックを受け取り、残りは本稼働リリースが受け取ります。更新された API 機能は、Canary を介した API トラフィックのみに認識されます。Canary トラフィックの割合を調整してテストカバレッジやパフォーマンスを最適化できます。

Canary トラフィックを低く保ち、選択をランダムにすることにより、どのような時でもほとんどのユーザーは新しいバージョンの潜在的なバグに悪影響を受けず、また、常に悪影響を受け続けるユーザーもいません。

テストメトリクスが要件を満たしたら、Canary リリースを本稼働リリースに昇格させ、Canary をデプロイから無効にします。これにより、本稼働ステージで新機能が使用可能になります。

API Gateway の Canary リリースデプロイの設定 - Amazon API Gateway

つまり、既存のAPIのステージにCanaryを設定することで、Canaryリリースと本稼働のリリースに対して任意の割合でトラフィックを分散することができるのである。

公式サポートに問い合わせた結果、切り替え時のダウンタイムは発生しないという回答があった。
APIステージに対するデプロイの実行から設定変更が反映されるまでの時間は約1分間であり、変更が反映されるまでは、変更前の設定でAPIリクエストを受信するためである。

この機能を使用して、Canaryリリースが新基盤へトラフィックを送るように設定すれば、ダウンタイムなく切り替えを行うことができると考えた。

新基盤へトラフィックを送るために旧基盤に新たにNLBを作成した。
API Gatewayは新旧基盤ともにNLBとVPC Linkを通じて紐づいている構成であったため、新たに新基盤のNLBのプライベートIPアドレスをターゲットにしたNLBとそのNLBをAPI Gatewayと紐づけるためのVPC Linkを構築した。

CanaryリリースにはOverRide変数という環境変数を設定することができる。
これはCanaryリリースが受信したトラフィックのみに適用され、本稼働リソースへの本稼働リソースへのトラフィックはステージ変数というもともと設定されている環境変数を適用するというものだった。
今回のAPI Gatewayの設定では、環境変数からNLBのDNS名とVPC LinkのIDをAPI Gatewayに渡して、リクエストを送信する向き先を定義していた。そこでその環境変数の値を新基盤向けに作ったNLBに変えると、新基盤へトラフィックを送ることができる。
OverRide変数に、新基盤向けのNLBのDNS名とVPC Link IDを指定して、これを実現した。
APIトラフィックの割合は0.0から100.0の間で設定でき、それによって完全に新基盤に切り替えたり、旧基盤に切り戻したりといったことが可能になる。

例:
Canaryトラフィックの割合:20.0
→旧基盤へのトラフィック:80% 新基盤へのトラフィック:20%

まとめ

今回はブルーグリーンデプロイによるAWS環境の切り替えの検討内容をまとめた。その中で様々な課題や制約があり、それにどう対処したのかという具体策を提示することによって、少しでも何かの課題解決に役立ててれば幸いだ。

また後日、追記する形で具体的な設定の方法であったり、変更用のスクリプト、CloudformationのYAMLなどもお伝えしていく。
なかなかイメージがわかないと思うが、やってみると案外設定自体は難しくなく、ダウンタイムも発生しないため、AWS環境間の移行切り替えにとどまらず、ブルーグリーンデプロイ方式の一案として検討してみてはいかがだろうか。

いいなと思ったら応援しよう!