Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

リリースのリスク最小化

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

オペレーションの自動化

Slide 24

Slide 24 text

結合テストの自動実行 ● 2時間おきに定期実行される結合テストを、mainブランチのコミット からトリガーするように変更 ○ 使うリソースにCIのジョブIDをいれるなど、並列実行しても動くように工夫が必 要 ● 丸1日結合テストを流し続けてからテスト、をやめた ○ 同じ実装に同じテストを何回も走らせる意義は薄い ○ 社内検証時間はFeature Flagで社内へ公開する形で、より長く確保する

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

デプロイの高速化

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

今後の課題

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

デプロイツールのメンテコスト改善 ● 自社デプロイツールのメンテコストが高い ○ なるべくコミュニティが使うツールに寄せ、自社独自要件のみ実装するようにす る ● 議論されたアイデア: ○ Terraformだけでは達成できない要件も、Terraformを薄くラップして実現 ○ その他OSSのデプロイツール (Spinnakerなど) を利用

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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