Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
数時間かかる週一リリースを毎日何度も爆速でできるようにするまで / CI/CD Confere...
Search
Takashi Kokubun
September 03, 2021
Programming
21
14k
数時間かかる週一リリースを毎日何度も爆速でできるようにするまで / CI/CD Conference 2021
CI/CD Conference 2021
Takashi Kokubun
September 03, 2021
Tweet
Share
More Decks by Takashi Kokubun
See All by Takashi Kokubun
YJIT Makes Rails 1.7x faster / RubyKaigi 2024
k0kubun
7
13k
Ruby JIT Hacking Guide / RubyKaigi 2023
k0kubun
2
9.5k
YJIT: Dive into Ruby's JIT compiler written in Rust / Rust.Tokyo 2022
k0kubun
1
2k
Towards Ruby 4 JIT / RubyKaigi 2022
k0kubun
3
11k
Optimizing Production Performance with MRI JIT / RubyConf 2021
k0kubun
1
410
Why Ruby's JIT was slow / RubyKaigi Takeout 2021
k0kubun
3
1.8k
Ruby 3 JIT's roadmap / RubyConf China 2020
k0kubun
0
770
Ruby 3.0 JIT on Rails
k0kubun
9
9.1k
JIT ロードマップ / Ruby 3 さみっと
k0kubun
2
1.4k
Other Decks in Programming
See All in Programming
talk-with-local-llm-with-web-streams-api
kbaba1001
0
170
Symfony Mapper Component
soyuka
2
730
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
180
Stackless и stackful? Корутины и асинхронность в Go
lamodatech
0
600
Keeping it Ruby: Why Your Product Needs a Ruby SDK - RubyWorld 2024
envek
0
180
Go の GC の不得意な部分を克服したい
taiyow
2
760
KMP와 kotlinx.rpc로 서버와 클라이언트 동기화
kwakeuijin
0
130
Recoilを剥がしている話
kirik
5
6.6k
急成長期の品質とスピードを両立するフロントエンド技術基盤
soarteclab
0
920
Criando Commits Incríveis no Git
marcelgsantos
2
170
暇に任せてProxmoxコンソール 作ってみました
karugamo
1
710
42 best practices for Symfony, a decade later
tucksaun
1
180
Featured
See All Featured
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.2k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
How GitHub (no longer) Works
holman
311
140k
Become a Pro
speakerdeck
PRO
26
5k
Optimizing for Happiness
mojombo
376
70k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
32
2.7k
Reflections from 52 weeks, 52 projects
jeffersonlam
347
20k
Mobile First: as difficult as doing things right
swwweet
222
9k
Transcript
数時間かかる週一リリースを 毎日何度も爆速で できるようにするまで @k0kubun / Takashi Kokubun - CI/CD Conference
2021
自己紹介 • GitHub, Twitter: @k0kubun • Treasure Data ◦ API:
プラットフォーム 1年 ◦ SRE: デプロイ 1年 ◦ Backend: ストレージ 2年半
None
今日話すこと • なぜ継続的にリリースすべきなのか • 継続的リリースのために必要なこと ◦ リリースのリスク最小化 ◦ オペレーションの自動化 ◦
デプロイの高速化
なぜ継続的にリリースすべきなのか
背景: 私が入社した時のリリースフロー • リリースマネージャが変更をcherry-pick • リリースノートにオペレーションを手動で記録 ◦ チケットにリリースタグを追加 ◦ stagingデプロイ後、最低2時間、通常1日待つ
◦ 定期実行される結合テスト結果を記録 • 全台sshか30分おき定期実行でのChefによるリリース
何が困るか • 面倒な手動オペレーションが多く、リリース頻度が減る ◦ 結果、毎回のリリースの変更粒度が大きく、問題の切り分けが困難に • リリースマネージャとのコミュニケーションコストが大きい ◦ 時差が分かれてると返事を見るのが1日後とかになる •
様々な依存のあるChef実行はランダムで失敗し、時間もかかる
弊社のデプロイターゲット数 • productionのAutoScalingグループの数: 約600 • 手動作業が多いほど、本質的作業に費やせる時間が減る • サービスが多いほど、それぞれのリリースを安全にする必要性は高 まる
入社時のチームのリリース • 待ち時間: 2〜24時間 • デプロイ時間: 40分 • リリース頻度: 週1回
現在のチームのリリース • 待ち時間: 10分 • デプロイ時間: 5分 • リリース頻度: 週28回とか
(週による)
継続的にリリースできると何が嬉しいのか • 要望に対応するまでの時間が短くなり、顧客満足度が上がる • リリースごとの影響範囲を小さくし、低リスク化しやすい • リリース待ちの変更が少なくなり、調整コストが減る
継続的リリースのために必要なこと • リリースのリスク最小化 • オペレーションの自動化 • デプロイの高速化
リリースのリスク最小化
デザインレビュー • アーキテクチャの改善によりリスクを早いフェーズで減らせる ◦ スケーラブルな設計、障害発生ポイントの最小化 • サービスが満たすべきチェックリストを作り、漏れを防ぐ • システムの本番投入はセキュリティデザインレビュー必須 ◦
顧客情報流出を防ぐため
タイムアウト、リトライ、サーキットブレーカー • タイムアウト: スレッドが1つの処理に占有されるのを避ける • リトライ: 一時的故障のクライアント影響の最小化 ◦ POST的な操作も含め、全てをリトライ可能なように作る •
サーキットブレーカー: 故障時に望ましい挙動を実装する ◦ 旧実装に切り替えたり、低速化している依存先を呼ぶのを避けレイテンシを抑 える、等
結合テスト • 単体テストではサーバーの設定起因のバグをキャッチできない ◦ なので、stagingにデプロイしたサーバーに対してのテストを行なう • この仕組みは元からあったが、結合テストが一切ない機能などで障 害が起きる傾向にある ◦ 最近はQAチームがテスト要件のドキュメントを書き、そのレビューを行なったり
している
SLOとエラーバジェット • コンポーネントごとにService Level Objectiveを設定、監視 ◦ リリース品質に関する顧客満足度のプロキシになる ◦ 具体的な目標があると、その差分のための計画を立てられる ◦
例えばSLOを満たしていない時はリリースを控えてリスクを減らすなど
デプロイとリリースの分離 • デプロイには時間がかかるし、影響範囲の粒度も大きくなる • Feature Flagでコードの変更と機能追加のタイミングを分ける ◦ リスクの高い変更のリリース待ちで他がブロックされなくなる • フラグを増やすとテスト対象が増えることに注意
◦ フラグ同士で依存関係がある状態は避けるか、有効化順序を自動で強制
段階的リリース • 変更の影響範囲が大きい場合、デプロイ対象サーバー数やユー ザー数で範囲を絞り、徐々にリリースする ◦ テスト時に予期していなかった問題や、本番でのみ発生する問題は、リリース 対象を小さくすることでしか制御できない • 壊れるリスクが高い新機能は、それが欲しいユーザーにベータリ リースを検討
リリース告知 • 非互換や、ダウンタイムが必要な変更は事前に通知 ◦ 無告知で非互換をいれると、クライアント側が壊れてそこが障害になることが ある
アラート • SLO違反だけでなく、その要因となるメトリクスの劣化を自動検知 ◦ ユーザーより先に自分たちが問題に気付くことが大事 • サービスのタイプごとにアラートをパターン化し、新サービスでの漏 れをなくす ◦ HTTPサーバーではtoo
many 5xx、too large p99 latencyなど
ダッシュボード • false positiveがあるメトリクスの監視や、障害時のデバッグ用 ◦ 4xxレスポンスが増えても必ずしも障害とは限らないが、リリース時に増えると リリース関連の障害の可能性が高い ◦ モニターが多すぎると監視が大変になるので、リリース時に見るべきものとデ バッグ用のものはセクションを分ける
• 依存しすぎるとモニタリングが属人化していくので、可能な限りア ラート化する
オペレーションの自動化
結合テストの自動実行 • 2時間おきに定期実行される結合テストを、mainブランチのコミット からトリガーするように変更 ◦ 使うリソースにCIのジョブIDをいれるなど、並列実行しても動くように工夫が必 要 • 丸1日結合テストを流し続けてからテスト、をやめた ◦
同じ実装に同じテストを何回も走らせる意義は薄い ◦ 社内検証時間はFeature Flagで社内へ公開する形で、より長く確保する
リリースノート作成と通知の自動化 • コミット履歴からリリース対象チケットのタグ付けを自動化 ◦ パッケージ名にコミットのshaをいれ、diffに含まれるコミットメッセージからチ ケット名を抽出 • コンプライアンス上、各コミットにチケット名が入るのは必須になって いる •
安易に手動のチェックリストを増やさない
サービスクラスタ作成ツール • YAML 1枚書いてSlackにコマンドを書くと、クラスタができる ◦ SlackコマンドはAWS LambdaからPythonでAWS SDK (boto3) を叩く実装
◦ 現在のリソースとYAMLを比較し、必要な差分を作るようになっている ◦ ASG, Launch Config, Lifecycle Hook, ALB, Route53, CodeDeploy • 本番の作業と同じようにオンデマンドクラスタを作れる ◦ 開発中ブランチのテストやベンチマークに便利
Terraform • オンデマンドクラスタに不要なリソースをTerraformで管理 ◦ 主に複数クラスタから共有されるリソース: IAM, Security Group, RDS, DynamoDB,
Kinesis • モニターやアラートの定義も最近ほぼTerraform化された • 入社した時はこのあたりが大体手動管理だった
CodeDeploy • S3にzipを置いて、各インスタンスのagentがpullしてシェルスクリプト がデプロイ ◦ 全台同時sshより安定する ◦ デプロイサーバーにあたる部分がマネージドなので便利 • 元々デプロイに使われていたChefの変わりに、mitamaeやChef
Soloが使われることも
ライフサイクルフック • 以前はインスタンス停止オペレーションは毎回手動だった • ローテーションの手間が増え、オートスケールの妨げになるので自 動化した ◦ ただし、48時間以内に強制停止されるので、それまでに安全に停止できるも のしか使えない
オートスケール • ほぼ全てのサービスがAutoScalingグループを使っているので、 AutoScalingポリシーを設定するだけ ◦ APIベースのはALBのインスタンスあたりリクエスト数が一番安定する ◦ ワーカーベースのものはSQSベース ◦ 両方ハマらない時はCPUベースだが、外部依存の遅さやリトライでブロックし
てる時にスケールアウトされない • キャパシティプランニングの労力やスケーリングの手間が軽減
AMIの自動更新 • SREが全サービス向けのAMIをメンテナンス、結合テストが通ったら リリース • サービスによってはAMIを自動更新し、AutoScalingグループのMax Instance Lifetimeで自動ローテーション • システムライブラリの定期更新のために手動ローテーションすること
がほぼなくなった
デプロイの高速化
なぜデプロイは速くなくてはならないか • モニタリングしなければいけない時間が長くなる • ロールバックにかかる時間が長くなり、障害のインパクトを大きくして しまう
CodeDeploy: Traffic Controlは必要か • ALBのBlock/Allow TrafficがCodeDeployのボトルネックになる • とはいえ、サーバーのgraceful restartは意図しない状態が残りがち なので避ける
• 適当に停止してデプロイ中意図的に502を出すことによって、クライ アントがリトライを適切にしているかのテストになる
CodeDeploy: ALBヘルスチェック/タイムアウト変更 • Block/Allow Trafficにかかる最低時間はヘルスチェックやタイムア ウトの設定で決まる • 必要以上に安全にしようとすると、時間を浪費することになる
CodeDeploy: 同時デプロイ割合の変更 • In-placeデプロイの場合、大きなクラスターでOneAtATimeデプロイ をすると時間がかかる • HalfAtATimeを利用したり、最大25%や10%デプロイするカスタム設 定を用意する
CodeDeploy: Blue-Greenデプロイ • そもそもIn-placeデプロイは途中台数が少なくなったり、サーバーの 状態が使い回しになるのが不便 • Blue-Greenデプロイなら、台数を減らさずデプロイ可能 • AutoScalingグループの名前がデプロイの度に変わることに対応が 必要
今後の課題
結合テストのfalse positive/negative減らし • リリースの待ち時間を最小にするために、以下を両方減らす必要が ある ◦ false positive: 外部依存や外的要因による、actionableでないテスト失敗 ◦
false negative: 書かれていないテストや、関連しているがリリース前確認に含 まれないテスト
インターナルな結合テストの自動実行 • 自動でkickする結合テストは基本CircleCI上で行なっている • ストレージ最適化など、インターネット越しに観測が難しいテストはそ れが使えない ◦ 結合テストシステム自体はあるが、自動でkickしないと手動オペレーション増 加に繋がる
デプロイツールのメンテコスト改善 • 自社デプロイツールのメンテコストが高い ◦ なるべくコミュニティが使うツールに寄せ、自社独自要件のみ実装するようにす る • 議論されたアイデア: ◦ Terraformだけでは達成できない要件も、Terraformを薄くラップして実現
◦ その他OSSのデプロイツール (Spinnakerなど) を利用
AWS Lambda, KDA, EKSへのリリース自動化 • 一番スタンダードなデプロイ方法しか自動化できていない ◦ ほとんどのサービスはEC2 AutoScaling Groupにデプロイしているため
• デプロイ基盤の整備具合から、新サービスのインフラに妥協が入る ことも ◦ CodeDeployにdocker saveしているものは、EKSの方が楽にデプロイでき、リ ソースも柔軟にコントロールできるようになる
まとめ • リリースの安全性確保が第一 • あとは好きに自動化・高速化し、たくさんリリースする ◦ 高速な価値提供だけでなく、リリースの低リスク化にも繋る