fu3ak1's tech days

何事もシンプルに。主にAWS関連の記事を書いています

re:Invent2020セッションレポート :(BLD207) Hands-off: Automating continuous delivery pipelines at Amazon

概要

Amazonにおける継続的デプロイ(CD)自動化の事例紹介です。 この内容はThe Amazon Builders' Libraryの記事にも掲載されており、基本的にはそれと同じ内容です。 ブログのほうが詳細な部分もある気がしますが、セッションでは人の説明を聞くことでよりわかりやすい部分もあったかなという印象です。

aws.amazon.com

内容

スピーカーのClareさんもAmazonに来る前はVery manual(手動)だとおっしゃっていましたw

  • AWSサービスのCDパイプライン例、多くのStageあり

f:id:fu3ak1:20201203223304p:plain

Balance safety and speed deployments

  • 本番リリースは安全に行いたい、でもできるだけ早く顧客へ届けたい。バランスが重要
    • スピードを重視すると顧客影響が大きくなる、ゆっくりデプロイすること(例えば1顧客ごと)でリスクは下げられる
  • Amazonのアプローチは、まずは小さい範囲でデプロイ、その後広げる(多くの範囲にデプロイ)

f:id:fu3ak1:20201203223743p:plain

  • パイプラインはマイクロサービス単位で用意、細かく分けることでサービス全体への影響を下げる

f:id:fu3ak1:20201203224208p:plain

  • ただしプロダクションデプロイメントでは影響が出ることも多い、そこでOne-Boxを追加

f:id:fu3ak1:20201203224424p:plain

  • One-Box
    • One-BoxはいわゆるEC2やコンテナを1個ということ
    • 新アプリケーションのインスタンスを1つ用意して、例えば10%という小さい割合で流す

f:id:fu3ak1:20201203224559p:plain

  • 徐々に新アプリインスタンスを増やしていく、最終的に全部入れ替え

f:id:fu3ak1:20201203224814p:plain

  • 更にリスクを低減するためRegion単位でOne-box、デプロイステージを用意
  • ただしこれでも最初のRegionはリスクがあるかもしれない

f:id:fu3ak1:20201203225046p:plain

  • Regionから更にAZ単位に分解

f:id:fu3ak1:20201203225143p:plain

  • AZ単位で全部やってたら遅いよね(最初のスピードとリスクの話も含め)

f:id:fu3ak1:20201203225243p:plain

  • スピードUPのためWaveという概念を投入
  • Waveで並行デプロイを実現
  • 最初の2つは小さいスコープ(1Region)、うまくいったら対象リージョンを増やして並行に

f:id:fu3ak1:20201203225358p:plain

  • 実際の開発現場ではさまざまな機能追加があるため、色々なデプロイが入り混じる。1つ目のパイプライン実行中に次が来るなど
  • Waveではステージごとに独立したデプロイを実現しているため、各ステージでバージョンが異なっても問題ない
  • これにより多数のデプロイを実現している

f:id:fu3ak1:20201203225923p:plain

  • Waveの詳細、1Waveの中身
  • ステージを並行にしているだけで、各ステージあたりのスコープは小さい
  • 1Waveの中で異なるバージョンの混在も可能

f:id:fu3ak1:20201203230156p:plain

Roll back automatically

  • Amazonに入る前は、リリース後メトリクスグラフ(レスポンスタイム)とにらめっこしていた
    • これは異常なのか?など考えながら見ていた
  • Amazonではそれはやらない、hands-off、自動化
  • 開発者がメトリクスを見るのではなく、パイプラインに監視させる

f:id:fu3ak1:20201203230615p:plain

f:id:fu3ak1:20201203230817p:plain

  • パイプラインは多くのメトリクスを見ている
  • リージョン単位、AZ単位、One-Box単位でもメトリクスを見ている

f:id:fu3ak1:20201203231151p:plain

  • フロント、Backend、DBなど各レイヤーが相互に影響することもあるため、それぞれ監視する

f:id:fu3ak1:20201203231457p:plain

  • リリース後、しばらくしてから異常になることもある
  • Bake Timeという期間を設けており、リリース後、Baketime中も監視を継続する
  • Bake Time中にSpike(異常)が発生したら自動ロールバックする。次のステージにも進まない

f:id:fu3ak1:20201206221307p:plain

  • 1つのリージョンで障害が発生すると、on-callエンジニアがその後どうするのか判断する
  • すべてロールバックすることも、そのまま他のリージョンは進めて対象リージョンだけ修正することも可能

f:id:fu3ak1:20201206221509p:plain

  • Amazonでは互換性を大事にしているため、旧フォーマットでの処理ができるか確認する
  • Prepare(準備フェーズ)で、新フォーマットと旧フォーマットを処理して問題ないことを確認する、エクササイズ段階で書き込みは旧フォーマットベース
  • 問題ないことを確認できたら、Activateを行い、書き込みを新フォーマットベースにする
  • (必要であれば)旧フォーマットの処理ロジックをコードから削除する
  • すべてのデプロイが互換性を持ったデプロイができるわけではない

f:id:fu3ak1:20201206222044p:plain

Automate pre-production testing

  • Build段階ではユニットテスト、静的コード解析を行う。IaCではLintersを使用
  • AlphaステージでFunctional tests、コンポーネント単体テスト
  • BetaステージでEnd-to-end tests、システム全体で処理が問題ないか確認する
    • フロント、バックエンド、DBがあればその3層全てを見る
  • Gammaステージでは Production環境に近いテストを実施
    • one-boxを用意してCanaryモニタリング
    • 自動ロールバックの設定、監視しきい値の設定もあり
    • レイテンシーの上昇もここで確認できる
    • End-to-end testsもここでもう一度行う(よりProductionに近い環境で)
    • 本番リリースと同じような処理を行うイメージ

f:id:fu3ak1:20201206223027p:plain

  • 下位互換性を確認するために、Zetaテストを設定することもある

f:id:fu3ak1:20201206223418p:plain

セッションまとめ

  • Hands-off デプロイの主要な戦略はそこまで多くない、それらをどう組み合わせてパイプラインとして構築するか考えている
  • バランスとスピードを取るためにOne-box、AZ、リージョン、Waveという単位でリリース
  • メトリクスベースのアラームを用意して自動ロールバック、リリース後のBaketimeも用意
  • 本番リリース前にひととおりのテストをパイプライン実行する
  • 最初に見せたパイプラインは一見複雑(テキストも小さい)であるが、説明したコアな戦略を理解すれば、そこまで複雑ではない。処理が組み合わさっているだけ
  • builders-libraryも見てね

f:id:fu3ak1:20201206224117p:plain

感想

リリース処理、監視、ロールバック、テストなど自動化レベルの最高峰かなと感じました。 私としてもこういったリリース処理やテスト等はパイプラインに任せたほうが楽になるし、かつ品質も良くなると考えているため、真似できるところは実装してみたいなと思いました。

特にGammaステージの本番同等のテストはなかなか難しいかもしれませんが・・

一方で、ソースコードは徹底的に人の目でレビューをしているところ、on-callエンジニアがいること(親近感)もあり、サービス品質に直結するところはやはり人による対応が必要なんだなと感じました。

また、小さな単位でリリースを行っているとのことでしたが、例えば大規模リリースやキャンペーンなどで全リージョン(もしくは1リージョン)で同タイミングリリースが必要な場合は、また別の工夫点があるのかなと気になりました。

パイプラインの本質を知れたような気がして、とても良かったです。