Upgrade to Pro — share decks privately, control downloads, hide ads and more …

数時間かかる週一リリースを毎日何度も爆速でできるようにするまで / CI/CD Conference 2021

数時間かかる週一リリースを毎日何度も爆速でできるようにするまで / CI/CD Conference 2021

CI/CD Conference 2021

Takashi Kokubun

September 03, 2021
Tweet

More Decks by Takashi Kokubun

Other Decks in Programming

Transcript

  1. 数時間かかる週一リリースを
    毎日何度も爆速で
    できるようにするまで
    @k0kubun / Takashi Kokubun - CI/CD Conference 2021

    View Slide

  2. 自己紹介
    ● GitHub, Twitter: @k0kubun
    ● Treasure Data
    ○ API: プラットフォーム 1年
    ○ SRE: デプロイ 1年
    ○ Backend: ストレージ 2年半

    View Slide

  3. View Slide

  4. 今日話すこと
    ● なぜ継続的にリリースすべきなのか
    ● 継続的リリースのために必要なこと
    ○ リリースのリスク最小化
    ○ オペレーションの自動化
    ○ デプロイの高速化

    View Slide

  5. なぜ継続的にリリースすべきなのか

    View Slide

  6. 背景: 私が入社した時のリリースフロー
    ● リリースマネージャが変更をcherry-pick
    ● リリースノートにオペレーションを手動で記録
    ○ チケットにリリースタグを追加
    ○ stagingデプロイ後、最低2時間、通常1日待つ
    ○ 定期実行される結合テスト結果を記録
    ● 全台sshか30分おき定期実行でのChefによるリリース

    View Slide

  7. 何が困るか
    ● 面倒な手動オペレーションが多く、リリース頻度が減る
    ○ 結果、毎回のリリースの変更粒度が大きく、問題の切り分けが困難に
    ● リリースマネージャとのコミュニケーションコストが大きい
    ○ 時差が分かれてると返事を見るのが1日後とかになる
    ● 様々な依存のあるChef実行はランダムで失敗し、時間もかかる

    View Slide

  8. 弊社のデプロイターゲット数
    ● productionのAutoScalingグループの数: 約600
    ● 手動作業が多いほど、本質的作業に費やせる時間が減る
    ● サービスが多いほど、それぞれのリリースを安全にする必要性は高
    まる

    View Slide

  9. 入社時のチームのリリース
    ● 待ち時間: 2〜24時間
    ● デプロイ時間: 40分
    ● リリース頻度: 週1回

    View Slide

  10. 現在のチームのリリース
    ● 待ち時間: 10分
    ● デプロイ時間: 5分
    ● リリース頻度: 週28回とか (週による)

    View Slide

  11. 継続的にリリースできると何が嬉しいのか
    ● 要望に対応するまでの時間が短くなり、顧客満足度が上がる
    ● リリースごとの影響範囲を小さくし、低リスク化しやすい
    ● リリース待ちの変更が少なくなり、調整コストが減る

    View Slide

  12. 継続的リリースのために必要なこと
    ● リリースのリスク最小化
    ● オペレーションの自動化
    ● デプロイの高速化

    View Slide

  13. リリースのリスク最小化

    View Slide

  14. デザインレビュー
    ● アーキテクチャの改善によりリスクを早いフェーズで減らせる
    ○ スケーラブルな設計、障害発生ポイントの最小化
    ● サービスが満たすべきチェックリストを作り、漏れを防ぐ
    ● システムの本番投入はセキュリティデザインレビュー必須
    ○ 顧客情報流出を防ぐため

    View Slide

  15. タイムアウト、リトライ、サーキットブレーカー
    ● タイムアウト: スレッドが1つの処理に占有されるのを避ける
    ● リトライ: 一時的故障のクライアント影響の最小化
    ○ POST的な操作も含め、全てをリトライ可能なように作る
    ● サーキットブレーカー: 故障時に望ましい挙動を実装する
    ○ 旧実装に切り替えたり、低速化している依存先を呼ぶのを避けレイテンシを抑
    える、等

    View Slide

  16. 結合テスト
    ● 単体テストではサーバーの設定起因のバグをキャッチできない
    ○ なので、stagingにデプロイしたサーバーに対してのテストを行なう
    ● この仕組みは元からあったが、結合テストが一切ない機能などで障
    害が起きる傾向にある
    ○ 最近はQAチームがテスト要件のドキュメントを書き、そのレビューを行なったり
    している

    View Slide

  17. SLOとエラーバジェット
    ● コンポーネントごとにService Level Objectiveを設定、監視
    ○ リリース品質に関する顧客満足度のプロキシになる
    ○ 具体的な目標があると、その差分のための計画を立てられる
    ○ 例えばSLOを満たしていない時はリリースを控えてリスクを減らすなど

    View Slide

  18. デプロイとリリースの分離
    ● デプロイには時間がかかるし、影響範囲の粒度も大きくなる
    ● Feature Flagでコードの変更と機能追加のタイミングを分ける
    ○ リスクの高い変更のリリース待ちで他がブロックされなくなる
    ● フラグを増やすとテスト対象が増えることに注意
    ○ フラグ同士で依存関係がある状態は避けるか、有効化順序を自動で強制

    View Slide

  19. 段階的リリース
    ● 変更の影響範囲が大きい場合、デプロイ対象サーバー数やユー
    ザー数で範囲を絞り、徐々にリリースする
    ○ テスト時に予期していなかった問題や、本番でのみ発生する問題は、リリース
    対象を小さくすることでしか制御できない
    ● 壊れるリスクが高い新機能は、それが欲しいユーザーにベータリ
    リースを検討

    View Slide

  20. リリース告知
    ● 非互換や、ダウンタイムが必要な変更は事前に通知
    ○ 無告知で非互換をいれると、クライアント側が壊れてそこが障害になることが
    ある

    View Slide

  21. アラート
    ● SLO違反だけでなく、その要因となるメトリクスの劣化を自動検知
    ○ ユーザーより先に自分たちが問題に気付くことが大事
    ● サービスのタイプごとにアラートをパターン化し、新サービスでの漏
    れをなくす
    ○ HTTPサーバーではtoo many 5xx、too large p99 latencyなど

    View Slide

  22. ダッシュボード
    ● false positiveがあるメトリクスの監視や、障害時のデバッグ用
    ○ 4xxレスポンスが増えても必ずしも障害とは限らないが、リリース時に増えると
    リリース関連の障害の可能性が高い
    ○ モニターが多すぎると監視が大変になるので、リリース時に見るべきものとデ
    バッグ用のものはセクションを分ける
    ● 依存しすぎるとモニタリングが属人化していくので、可能な限りア
    ラート化する

    View Slide

  23. オペレーションの自動化

    View Slide

  24. 結合テストの自動実行
    ● 2時間おきに定期実行される結合テストを、mainブランチのコミット
    からトリガーするように変更
    ○ 使うリソースにCIのジョブIDをいれるなど、並列実行しても動くように工夫が必

    ● 丸1日結合テストを流し続けてからテスト、をやめた
    ○ 同じ実装に同じテストを何回も走らせる意義は薄い
    ○ 社内検証時間はFeature Flagで社内へ公開する形で、より長く確保する

    View Slide

  25. リリースノート作成と通知の自動化
    ● コミット履歴からリリース対象チケットのタグ付けを自動化
    ○ パッケージ名にコミットのshaをいれ、diffに含まれるコミットメッセージからチ
    ケット名を抽出
    ● コンプライアンス上、各コミットにチケット名が入るのは必須になって
    いる
    ● 安易に手動のチェックリストを増やさない

    View Slide

  26. サービスクラスタ作成ツール
    ● YAML 1枚書いてSlackにコマンドを書くと、クラスタができる
    ○ SlackコマンドはAWS LambdaからPythonでAWS SDK (boto3) を叩く実装
    ○ 現在のリソースとYAMLを比較し、必要な差分を作るようになっている
    ○ ASG, Launch Config, Lifecycle Hook, ALB, Route53, CodeDeploy
    ● 本番の作業と同じようにオンデマンドクラスタを作れる
    ○ 開発中ブランチのテストやベンチマークに便利

    View Slide

  27. Terraform
    ● オンデマンドクラスタに不要なリソースをTerraformで管理
    ○ 主に複数クラスタから共有されるリソース: IAM, Security Group, RDS,
    DynamoDB, Kinesis
    ● モニターやアラートの定義も最近ほぼTerraform化された
    ● 入社した時はこのあたりが大体手動管理だった

    View Slide

  28. CodeDeploy
    ● S3にzipを置いて、各インスタンスのagentがpullしてシェルスクリプト
    がデプロイ
    ○ 全台同時sshより安定する
    ○ デプロイサーバーにあたる部分がマネージドなので便利
    ● 元々デプロイに使われていたChefの変わりに、mitamaeやChef
    Soloが使われることも

    View Slide

  29. ライフサイクルフック
    ● 以前はインスタンス停止オペレーションは毎回手動だった
    ● ローテーションの手間が増え、オートスケールの妨げになるので自
    動化した
    ○ ただし、48時間以内に強制停止されるので、それまでに安全に停止できるも
    のしか使えない

    View Slide

  30. オートスケール
    ● ほぼ全てのサービスがAutoScalingグループを使っているので、
    AutoScalingポリシーを設定するだけ
    ○ APIベースのはALBのインスタンスあたりリクエスト数が一番安定する
    ○ ワーカーベースのものはSQSベース
    ○ 両方ハマらない時はCPUベースだが、外部依存の遅さやリトライでブロックし
    てる時にスケールアウトされない
    ● キャパシティプランニングの労力やスケーリングの手間が軽減

    View Slide

  31. AMIの自動更新
    ● SREが全サービス向けのAMIをメンテナンス、結合テストが通ったら
    リリース
    ● サービスによってはAMIを自動更新し、AutoScalingグループのMax
    Instance Lifetimeで自動ローテーション
    ● システムライブラリの定期更新のために手動ローテーションすること
    がほぼなくなった

    View Slide

  32. デプロイの高速化

    View Slide

  33. なぜデプロイは速くなくてはならないか
    ● モニタリングしなければいけない時間が長くなる
    ● ロールバックにかかる時間が長くなり、障害のインパクトを大きくして
    しまう

    View Slide

  34. CodeDeploy: Traffic Controlは必要か
    ● ALBのBlock/Allow TrafficがCodeDeployのボトルネックになる
    ● とはいえ、サーバーのgraceful restartは意図しない状態が残りがち
    なので避ける
    ● 適当に停止してデプロイ中意図的に502を出すことによって、クライ
    アントがリトライを適切にしているかのテストになる

    View Slide

  35. CodeDeploy: ALBヘルスチェック/タイムアウト変更
    ● Block/Allow Trafficにかかる最低時間はヘルスチェックやタイムア
    ウトの設定で決まる
    ● 必要以上に安全にしようとすると、時間を浪費することになる

    View Slide

  36. CodeDeploy: 同時デプロイ割合の変更
    ● In-placeデプロイの場合、大きなクラスターでOneAtATimeデプロイ
    をすると時間がかかる
    ● HalfAtATimeを利用したり、最大25%や10%デプロイするカスタム設
    定を用意する

    View Slide

  37. CodeDeploy: Blue-Greenデプロイ
    ● そもそもIn-placeデプロイは途中台数が少なくなったり、サーバーの
    状態が使い回しになるのが不便
    ● Blue-Greenデプロイなら、台数を減らさずデプロイ可能
    ● AutoScalingグループの名前がデプロイの度に変わることに対応が
    必要

    View Slide

  38. 今後の課題

    View Slide

  39. 結合テストのfalse positive/negative減らし
    ● リリースの待ち時間を最小にするために、以下を両方減らす必要が
    ある
    ○ false positive: 外部依存や外的要因による、actionableでないテスト失敗
    ○ false negative: 書かれていないテストや、関連しているがリリース前確認に含
    まれないテスト

    View Slide

  40. インターナルな結合テストの自動実行
    ● 自動でkickする結合テストは基本CircleCI上で行なっている
    ● ストレージ最適化など、インターネット越しに観測が難しいテストはそ
    れが使えない
    ○ 結合テストシステム自体はあるが、自動でkickしないと手動オペレーション増
    加に繋がる

    View Slide

  41. デプロイツールのメンテコスト改善
    ● 自社デプロイツールのメンテコストが高い
    ○ なるべくコミュニティが使うツールに寄せ、自社独自要件のみ実装するようにす

    ● 議論されたアイデア:
    ○ Terraformだけでは達成できない要件も、Terraformを薄くラップして実現
    ○ その他OSSのデプロイツール (Spinnakerなど) を利用

    View Slide

  42. AWS Lambda, KDA, EKSへのリリース自動化
    ● 一番スタンダードなデプロイ方法しか自動化できていない
    ○ ほとんどのサービスはEC2 AutoScaling Groupにデプロイしているため
    ● デプロイ基盤の整備具合から、新サービスのインフラに妥協が入る
    ことも
    ○ CodeDeployにdocker saveしているものは、EKSの方が楽にデプロイでき、リ
    ソースも柔軟にコントロールできるようになる

    View Slide

  43. まとめ
    ● リリースの安全性確保が第一
    ● あとは好きに自動化・高速化し、たくさんリリースする
    ○ 高速な価値提供だけでなく、リリースの低リスク化にも繋る

    View Slide