なるべく環境を止めずにアップデートを行うTips群

2024/02/22に公開

はじめに

こんにちは、DELTAの馬場です。
直近あった天下一武道会には弊社のCTOも登壇していました。
https://no1.connpass.com/event/305664/
弊社ではCTO Boosterというコスト削減の事業をしているので、コスト削減についてのあれこれが聞くことができ、私自身大変勉強になるイベントでした。
https://costcut.cloud/

今回の記事では、我々が実際にCTO Boosterの事業でコスト削減を行う際に、大幅なコスト削減を行うのと同じくらい大切にしている。お客様のサービスになるべく影響を与えずに変更をデリバリーする方法について紹介していきます。

どんなものがあるか?

既存サービスになるべく影響を与えずにAWSのサービスを変更する手段としては大きく以下3つのタイプに分類できるかと思います。

  • 無停止で実施できるもの
  • 工夫すれば無停止にできるもの
  • 停止時間をなるべく短くするもの

無停止で実施できるもの

まず、無停止で変更できるものについて解説していきます。

EBS

EBSのボリュームサイズ追加やパフォーマンスの増減、ボリュームタイプの変更はサービス断無しに実行できます。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/requesting-ebs-volume-modifications.html

ボリュームサイズの変更については追加でファイルシステムの拡張が必要です。
何個かコマンドを実行するだけですが、本記事では割愛させていただきます。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html

OpenSerch

インスタンスおよびストレージボリュームの追加/変更などのドメインのスケーリングも無停止で行うことができます。
https://aws.amazon.com/jp/opensearch-service/faqs/

しかし、BGデプロイ等でオンラインな変更を実施するため変更の適用中には通常より負荷がかかってしまいます。
そのため、CloudWatchのメトリクスから自サービスの負荷特性を確認し、負荷の低いタイミングに実施する必要があります。
https://docs.aws.amazon.com/ja_jp/opensearch-service/latest/developerguide/managedomains-cloudwatchmetrics.html

ElastiCache(for Redis)

Elasticache for Redis も バージョン 3.2.10 以降であればOpenSearchと同じくほぼノーダウンタイムで垂直スケーリングが可能です。
https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/scaling-redis-cluster-mode-enabled.html
https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/redis-cluster-vertical-scaling.html
5.0.6 以降では、クラスターバージョンのアップグレードもほぼノーダウンタイムで可能です。
https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/VersionManagement.html

ElastiCacheでも同じくなるべく負荷のかかっていない時間帯を狙ってスケーリング等を実行する必要はあります。

垂直スケーリングプロセスは、完全にオンラインのままになるように設計されており、古いノードと新しいノードとの間でデータを同期させることに依存します。データトラフィックが最小になると予想される時間帯にスケールアップ/ダウンを開始することをお勧めします。

S3

S3のストレージクラスの変更についてもダウンタイム無しで実施することが可能です。
こちらについては違和感ない話かな?と思うので、例えばGlacierに移しても良いのか?
いつ時点のものを移すべきなのか?をどう調査するのか?について記載します。

S3にはストレージクラス分析とS3 インベントリいう機能(有料)があり、任意のバケットに対して有効化することで、移行にかかるコストやライフサイクルの期間単位でリクエスト等を確認することができます。
その結果を判断材料に○○日経過後にストレージクラスを変更するライフサイクルの作成をすることで、より根拠に基づいた効果のある運用を行うことができます。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/storage-inventory.html
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/analytics-storage-class.html

工夫すれば無停止にできるもの

EC2のインスタンスタイプ変更

ELB配下(ALB配下に置かれることが多いのでALBを題材に記載)のインスタンスについて、新しいインスタンスと古いインスタンスをターゲットグループにアタッチ・デタッチすることで無停止でインスタンスの入れ替えが可能です。

丁寧に説明すると

  1. AMIからインスタンスを任意のインスタンスタイプで作成。
  2. ターゲットグループにそのインスタンスを追加。
  3. インスタンスのヘルスチェックが完了するのを待つ。
  4. Connection Drainingの設定を確認。サービスの要件に合うように遅延を設定する。
      ALBだと属性というタブに設定箇所があります。
  5. 既存のインスタンスをターゲットグループから削除。

Route53のルーティング先変更

荷重ルーティング機能を活用します!
https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/routing-policy-weighted.html

ぶっちゃけDNSキャッシュがあるので、一瞬で切り替えてセッション等が問題ないものはえいやでやってしまっても問題ない気がしてますが、丁寧なやり方を紹介します。

例えばアーキテクチャ変更でRoute53 -> ALB -> EC2 なものをRoute53 -> ALB -> ECS なものにする際に切り替えたり
ALBの前にCloudFrontを置いてキャッシュさせたい等あったときに使ったりします。

同一レコード名でルーティング先を登録し重みをつけることができます。
とりあえず最初に、同名で新ルーティング先を登録したものを重量 0で登録し
既存のもののルーティングポリシーを100に設定ます。
旧ルーティング先:新ルーティング先 = 100:0 な状態になります。
重量0 はそこにルーティングされないので、ここから段階を踏んで
旧ルーティング先:新ルーティング先 = 0:100 な状態になるようにします。
この状態で設定しておくことで、何かあった際に動くことが担保されている旧ルーティング先に速やかに戻すことが可能になります。

CloudFrontの入れ替え

まれにCloudFront distribution(以降distributionと記載)を移行させたりする際に代替CNAMEの重複が許されないので、切り替えのために短時間のサービス断が必要な状況が発生するケースで使えるtipsです。

内容は以下の記事の通りなのですが、ワイルドカードをうまく使って移行を行います。
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html#alternate-domain-names-move-use-wildcard
手順を簡単に示すと
ワイルドカードを含むACMの作成が事前に必要

  1. 切り替え先のdistributionの代替CNAMEを*.${ドメイン}で登録
  2. Route53側のレコードの値を切り替え先distributionのDNSに更新(切り替え先のXXX.cloudfront.net)
     ここではまだ元のdistributionにトラフィックが流れている。
  3. 元のdistributionの代替CNAMEを削除。
      このタイミングでトラフィックが切り替え先に流れ始める。
  4. 切り替え先のdistributionの代替CNAMEからワイルドカードのものを削除し、意図していたCNAMEを登録。
  5. 切り替え先のdistributionの代替CNAMEに意図したCNAMEのみが登録されている状態なことを確認。

これでダウンタイム無く移行できます。

停止時間をなるべく短くするもの

RDS フェイルオーバー

AuroraのDBであれば、インスタンスタイプの変更を簡単に比較的短いダウンタイムで実施する方法があります。

手動フェイルオーバーを活用します。

手動フェイルオーバー を参照
https://aws.amazon.com/jp/blogs/news/failover-with-amazon-aurora-postgresql/

流れとしては以下の通りです。

  1. クラスターに新しいインスタンスタイプでリーダーインスタンスを追加
  2. 追加したものをフェイルオーバーしてライターインスタンスになったことを確認
  3. 古いインスタンスを削除

*登録漏れするときがあるので、カスタムエンドポイントが利用されているかもチェックした方が良いです。

RDS BGデプロイ

これは過去記事を書いたので詳しくはこちらに
https://zenn.dev/shogo_b/articles/2ad95b69caad74

簡単に説明すると、BGデプロイを利用することでデータ同期をしながらエンジンバージョンの更新やインスタンスタイプの変更を行ってあらかじめ準備をしておくことが可能です。
準備が完了したら、環境間の切り替えを行います。 ここにのみダウンタイムがかかってきます。

まとめ

一通り概念的にTipsを解説しましたが、実際には自分のアーキテクチャに適応できるかどうか?
前提条件を受け入れられるかどうか?ということを考慮・検討・検証して実運用に乗せる必要があります。
是非一度試してみてください!

We're hiring!

https://note.com/delta_sevenrich/n/n15f551a4d7a5

最後までお読みいただきありがとうございます。
現在DELTA では一緒に働いてくださる仲間を大募集中です!
ご興味をお持ちいただけましたら、お気軽にフォームからご連絡ください。

https://docs.google.com/forms/u/1/d/e/1FAIpQLSfQuWNU1il5lq2rVdICM0tSK_jTsjqwc52LYEwUxBq7_ImtrQ/viewform

DELTAテックブログ

Discussion