遅いデプロイが原因で起きる会議(2015)
(tidyfirst.substack.com)- エンジニアが「会議のせいでコードを出せない」と感じる状況では、実際の原因は遅いデプロイ能力が生み出す組織的オーバーヘッドかもしれない
- FacebookのChuck Rossiは、1回のデプロイで扱える変更数はほぼ固定されているように見え、変更量を増やすにはデプロイ回数を増やす必要があると考えた
- FacebookはPHPコードのデプロイを週次から日次、さらに1日3回へ増やし、モバイルアプリのデプロイ周期も6週間から4週間、2週間へ短縮した。これを主に牽引したのはリリースエンジニアリングチームだった
- 変更の生産量がデプロイの限界を超えると、デプロイあたりの変更数は簡単には増えず、会議・レビュー・ハンドオフのようなオーバーヘッドが増え、組織は全体の変更量を下げる方向に適応する
- より多くの変更を通すには、会議を減らすだけでなく、デプロイ周期、テスト、モニタリング、分離、チーム内の社会的関係を改善してデプロイ容量を大きくする必要がある
会議は原因ではなく結果かもしれない
- 「会議が多くてコードをデプロイできない」というよくある不満は、因果関係が逆かもしれない
- 組織的オーバーヘッドを追加したり取り除いたりすることは比較的簡単だが、組織のコードデプロイ能力を高めることはより難しい
- 会議やレビューは、デプロイシステムが過負荷にならないよう組織が適応した結果かもしれない
- Chuck RossiはFacebookで、1回のデプロイが処理できる変更数は決まっているかのように見えると観察した
- より多くの変更を望むなら、より多くのデプロイが必要になる
- PHPコードのデプロイは週次から日次、さらに1日3回へ増えた
- モバイルアプリのデプロイ周期は6週間から4週間、2週間へ短縮された
- この改善は主にリリースエンジニアリングチームが推進した
デプロイ容量を増やさなければオーバーヘッドが大きくなる
- 「デプロイあたりの変更数」は簡単には増えない非弾力的な指標のように見え、大きな努力があって初めて改善できる
- 作られる変更数が現在の限界を超えると、デプロイあたりの変更数が増えるよりも、全体の変更量を減らす圧力が生じる
- 会議、レビュー、ハンドオフ、その他のオーバーヘッドが増える
- 時間が経つと、情熱や主体性も低下する可能性がある
- オーバーヘッドの増加は正のフィードバックループを生むことがある
- 処理される仕事が減る
- 圧力が高まる
- ミスが増える
- デプロイあたりの変更数がさらに減る
- オーバーヘッドが再び増える
- オーバーヘッドだけを減らそうとする孤立した試みは、圧力を高め、再びオーバーヘッドを増やす可能性がある
- より多くの変更を通すには、「ホースの遠い端」であるデプロイ容量を広げる必要がある
- 難しい方法: デプロイ周期を短くし、それに伴う混乱を処理する
- さらに難しい方法: より良いテスト、モニタリング、要素間の分離、チーム内の社会的関係によって、デプロイあたりの変更数を増やす
- 会議を減らそうとするだけでは、「会議を減らす方法を議論する会議」につながりかねない
- 最初は間違っているように見えるアイデアを配置する逆因果Thinkieの例と見ることができる
2件のコメント
この意見はいいですね
Hacker Newsのコメント
残念ながら、この記事の結論は少し逆になっているように思う。テストや組織的な特性を改善してデプロイのリスクを下げることは重要だが、それだけが機能する唯一のアプローチではない。
筆者は1回のデプロイあたりの変更量は固定されていて増やしにくいと述べているが、ここでいう「Reversie Thinkie」はむしろ 1回のデプロイあたりの変更量を減らすこと だと考える。デプロイ会議が存在する理由はリスクであり、1回のデプロイに含まれる変更が多いほど、バグや運用上の問題が入り込む可能性は高くなる。小さな変更を頻繁にデプロイすれば、価値をより早く届けられ、失敗もより小さくできる。
ここに カナリアデプロイ と段階的リリースを組み合わせれば、デプロイはもはやスイッチを入れて壊れるか壊れないかの問題ではなく、障害を性能低下や限定的な影響へと変える世界になる。このアプローチは DORA の研究[0]、Accelerate[1]、The Phoenix Project[2]、そしてその精神的先祖である The Goal[3] でもよく扱われている。
[0] https://dora.dev/
[1] https://www.amazon.co.uk/Accelerate-Software-Performing-Tech...
[2] https://www.amazon.co.uk/Phoenix-Project-Helping-Business-An...
[3] https://www.amazon.co.uk/Goal-Process-Ongoing-Improvement/dp...
核心は、組織が 自動テスト にどれだけ時間とリソースを投資するかだ。デプロイ前後を検証するインフラや、失敗した変更をロールバックするインフラがないからこそリリース会議が生まれ、自動検証の不足を一時的な手動チェックで埋めることになる。QA 組織に技術力が不足していれば、自己保身のために手動手順を推し進めるようになる。
さらに悪いことに、こうした会議を経ること自体が、卓越性やベストプラクティスのシグナルであるかのように装われることもある。問題緩和のために雇われた人には、その問題を根本的になくすインセンティブがないからだ。本番にバグが漏れれば「開発者が作った問題を QA があれこれの理由で見つけられなかった」という話になるが、自動テストがあれば PR 段階で見逃すことすら難しい。
会議はリスクがあるからではなく、リスクがあってこそ存在理由が生まれ、それを減らす技術が不足した役割が組織内にあるから生まれる。デプロイ後に変更が実行されて正常に動作するかの最低限のチェックを自動化し、失敗時に自動ロールバックできるなら、会議は不要になる。
こうしたプロセスのかなりの部分は、根本的な解決策がないときに悪い状況を何とか耐え抜くための、合理的ではあるが非技術的な対応だと思う。ただし、まったく無害というわけでもない。ある組織では、新規プロジェクトでも既存の非効率を取り除くプロジェクトでも、意思決定者が 人間中心のプロセス を解決策として繰り返し持ち込んでいた。
技術的想像力が足りないか、既存の問題フレームに閉じ込められているからであり、そうした想像力のある人たちが前に出て、可能なところでは技術的な変化によって人間のプロセスを最小化すべきだと主張しなければならない。すべての人間のプロセスを技術でなくせるわけではないが、不必要なものに広く薄く関わりたいとは思わない。
ある期間に全プロセスの 2%超 を変更するのは「多すぎる」と見なせるかもしれず、この値は調整可能だろう。領域ごとにも違うはずなので、決済処理コードのチームと HR コードのチームでは別の基準を持つべきで、リリースやチームをローテーションするのも理にかなっているかもしれない。
今期はこのチームが難しい仕事をし、本番投入後はまた簡単な仕事に戻す、という具合だ。塹壕攻撃、大隊前進、諸兵科連合作戦にも同じ原理が当てはまる。
もちろんこれは管理の問題だが、かなりの部分は自動化できるし、どのチームが最近センシティブなモジュールにコミットしたかといった感覚入力も有用だ。最後に、この観点からすると Agile/Scrum の スプリント は奇妙に映る。マラソン全体を全力疾走できないことは分かっているのに、スプリントをどう循環的に準備するのか。
機能フラグは使えるが、そうすると「有効化されていない機能のバックログ」が生まれる。結局のところ、機能はたいてい人間が使うものであり、人間には変更に対する 教育 が必要だ。
彼は誰かが The Phoenix Project を書くよりはるか前からフローを扱い、Toyota Production System の原則を翻訳し、物理学をビジネスプロセスに応用してきた。The Phoenix Project も好きだが、The Goal と比べると、IT 業界の人たちが生産ラインの話を読んで「自分は PrOgrAmmEr だから、創造的な仕事は工場のように最適化できない」と逃げ出さないようにした安価な翻案版に近い。
したがって The Phoenix Project は The Goal の 精神的続編 であって、その逆ではない。
「ソフトウェア・リテラシー」という概念を説明しようとしている。今日では企業がポリシー文書やメールのような英語の文章で運営できるように、ビジネスもコードで運営できる、という意味だ。
ここから、「GPUが仕事をするならコーダーが新しい管理者だ」だとか、変更の影響が明確になるような全社テスト装置が必要だ、といった結論が導かれる。このすばらしい文章とも直接関係しているように見える。意思決定者全員が、Jiraやプロジェクト計画ではなくコードを変更プロセスの第一級の対象として見ていないなら、その意思決定者たちはソフトウェア的に非識字だということだ。
「非技術系の経営陣とどう議論するか」という問題はよく出てくるが、答えは「できない」だ。その経営陣が変わらなければならない。30年前にも問題だと思っていたが、コーダーたちが成長すれば消えるだろうとナイーブに見ていた巨大な世代間ギャップだ。しかし会社を「運営」するのにコーディングは必要ないので、新聞編集者が文章を書けないのと同じように、コーディングできないことが恥ずかしいことになるまでは乗り越えにくい。
核心は、SOP、テスト、会議ではなく、コミュニケーションとしてのシステムのように相互に強化し合う新しい概念の集合で運営可能な会社が必要だ、ということだ。
ただ、なぜそれを「リテラシー」と呼ぶのかは分からない。Maturana & Varelaのautopoiesisという用語のほうが核心に近く、Stafford BeerのAutopoietic Systemsもよい知的基盤を与えてくれそうだ。
ただ、ある時点まで行くと、純粋なソフトウェア「ビジネス」は結局ただのSaaSに見えないだろうか、という気もする。
組織はデプロイ改善の試みを積極的に妨げるだろう。「Jenkinsを本番環境の近くに置いてはいけない」「QAなしでは本番に上げられない」「ソフトウェア品質を十分に保証するにはこの時間が必要だ」といったことを真顔で言う。
その一方で、運用バグは何百万件もあり、製品はユーザー要件をほとんど満たしていない。結局のところ、大半の組織では官僚主義と戦うのは事実上不可能だ。とりわけ、こういう会議を生み出す200層の管理レイヤーの一員でないならなおさらだ。
プログラマーとデザイナーを2人くらいだけ残して、あとは全員外に出し、アジャイルコーチ、プロダクト責任者、スクラムマスター、プロダクトエキスパート抜きで勝手にやらせたい。遅いデプロイは問題だが、その問題自体ではない。
どうしても変えられなさそうな場所にばかり行くなら、面接のときにこの点をもっと聞くべきだ。小さな会社では、自分の好みに合う、狂ったような官僚主義のない場所も多かったし、今は大企業にいるが、一貫して説得力を持って動けば、多くのことがゆっくり正しい方向へ向かうこともある。
時間がかかることを理解し、人々がなぜそう作ったのかを理解したうえで、よりよくするための説得力ある論拠を見つける必要がある。本当にひどい場所もあるので、そういう所に残らないのは正しいが、絶望はあまり役に立たない。
解くべきことは多いだろうが、私のバイアスはこの主張寄りだ。
Jenkinsはソフトウェア開発界のWordpressだ。権限分離なしにプラグインを実行する巨大な状態ループだ。Jenkinsインスタンスに本番管理者の認証情報を渡すのは、監査したこともないプラグインを書いたルーマニアの誰か一人にrootキーを渡すようなものかもしれない。みんながそれを望まないのは十分理解できる。
「QAなしでは本番に上げられない」も同じだ。QAを通っていないものを本番にデプロイするなら、QAは何のためにあるのか。後で直すためか。権限を与えなければ、QAにはうまく仕事をする機会も、自分の仕事に誇りを持つ機会もない。
どのイニシアチブでも初日からJenkinsが本番につながっており、しばしばトランクベース開発に直行し、品質はすべての開発者の責任だった。個人貢献者レベルで「官僚主義との戦い」はなかったが、外部パートナーやステークホルダーが深く絡む場合には、リーダーシップ同士で時に激しく議論していたはずだ。
プログラマーとデザイナーだけを残すやり方は私には魅力的だが、スケールしない。ステークホルダーの優先順位をキューに入れるプロダクトの「オーナー」「専門家」「管理者」は最低でも1人は必要だ。この役割を開発者やデザイナーが交代でかぶる「帽子」にしてもいいが、この手の技術に飛び抜けて長けた人もいる。
多くの組織がこのように運営されていないことも理解している。会社をこの方向に変えるときは、こうした実践に専念する志願者ベースの単一の実験チームを作り、上から与えられた権限で保護しつつ、指示はしない形が役に立った。もちろん、ここはCaliforniaだ。
やや関連する話だが、CIパイプラインに約25分かかり、そのうち3000件を超える単体/統合テストが18分を食っている職場で働いたことがある。
本番で問題が起きるたびにテストを追加していて、当然ながら何かが壊れると復旧には最低50分かかった。かなり考えた末に、復旧に集中することにし、一部のテストを緩和・簡略化して全体を5分未満にし、ローリングアップデートの代わりにカナリアデプロイを使った。
私たちにとっては本当に新鮮な経験だったが、ある意味では間違っているようにも感じられた。
もちろん、そのデプロイ速度の中にはありとあらゆる要素が絡み込んでいるが、そのほとんどは良い要素だ。
少し脇道ですが、CloudFormation はなぜこんなに遅いのでしょうか?
VPC 内の Lambda を削除して EFS に接続したケースがありましたが、デプロイ自体はかなり速かった一方で、CloudFormation が後始末して完了するまでに約20分かかりました
状態変更をトランザクションとしてデプロイするたびに、各段階で事前条件と事後条件を確認しなければなりません。少しでも依存関係のある変更のまとまりをリリースするには、各変更を逐次的な段階としてデプロイするしかありません。各段階では、変更の適用、認証、状態ポーリングのために複数のネットワーク呼び出しが行われ、それぞれ 50〜200ms ほどかかるので、すぐに積み上がります
Terraform や Ansible で別のクラウドプロバイダに同じアプリをデプロイしても、似たような結果になります。同じ変更を手作業でデプロイすると、数分で済むものが丸一日の苦行になります
IaC の最大の問題は、高水準すぎて内部でやっていることが多すぎるため、実際にどの変更が適用されているのか、何をしているのか分からない人が出てくることです。そして時間がかかると文句を言います
会社勤めで個人的に経験したことがあります。クリスマス休暇の前に大きな変更があり、不安が大きかったのです。組織はテストを増やす、つまり回帰テストを増やしてオーバーヘッドを大きくするやり方で対応しました
その結果、dev の変更が私のブランチの変更を壊すリスクが高まりました。コードのマージ競合ではなく、複雑適応系の観点でのリスクでした。私はこのリスクに対応するために会議を作り、プロジェクト日程を発表しつつ、PR にコードスタイルのコメントを残しても後続の PR に回されて結局無視されるだろうと、同僚に期待値を説明しました
必要だったのは、コンポーネント間の分離がより良い 細粒度のテスト でした。問題は、経営陣が高すぎるレベルからしか見ておらず、会議を手段ではなく、それ自体が達成する価値のある目標だと見なしていることです。会議が多ければコラボレーションが多く、だから良い、という発想です。非技術系の経営陣と一緒に技術変化を主導する助言が欲しいです
関連記事: Slow Deployment Causes Meetings - https://news.ycombinator.com/item?id=10622834 - 2015年11月、コメント26件
マイクロサービスを使えば、デプロイ頻度も水平スケールできる
独立したモジュールで構成されたモノリシックなアプリでも、マイクロサービスなしで同じだけデプロイできますし、インフラ/CI・CD の複雑さや、アプリの関数呼び出しを不安定な分散システム通信の問題に置き換えてしまうという大きな欠点も避けられます。不要な 付随的複雑性 には抵抗すべきです
[1] https://www.fearofoblivion.com/build-a-modular-monolith-firs...
[2] https://ardalis.com/introducing-modular-monoliths-goldilocks...
そして、デプロイ計画と機能デプロイの同期という楽しい新問題も生まれます
そうでなければ、分散データの問題とさらに多くの複雑性の層、つまりモノリスより多くの会議を同時に抱えることになります
モノリスでは、SOLID、DRY、そのほか「クリーンコード」的なたわごとの巨大な混乱の中で、誰かが何かを変えると壊れるのではないかと恐れて誰も変えられない状態になる危険があります。オブジェクト指向の原則そのものが表面的に間違っているという意味ではありませんが、極端に曖昧すぎて、誰もまともに適用できないことが多いのです
Uncle Bob が批判されるたびに「彼らが原則を誤解したのだ」と片づけるのを見ると、いつも笑ってしまいます。そんなに多くの人が間違うなら、原則のほうが悪いのではないでしょうか? マイクロサービスも悪いガバナンスから守ってくれるわけではなく、別の形の問題として現れるだけです。複数のマイクロサービスを作ったものの、ある変更が他のサービスにどう影響するのか誰にも分からない、という状況はとても簡単に起こりますし、よくあることだと思います
結局はチーム運営の問題であり、私の経験では業界が最も苦手としている領域です。「Team Topologies」のような新世代が入ってくれば改善するでしょうが、本当に終わるとしても数十年はかかるはずです。組織が「IT」を単なるコストセンターとしてしか見ず、ソフトウェア工学のベストプラクティスのプロセスに組み込める形で要求しないなら、デジタル化部門の手を離れてしまうことも多いです
汎用言語として Go が好きな理由の一つは、設計上シンプルで、変更しやすいコードベースにつながることが多いからです。オンライン銀行や賃貸/資産管理プラットフォームのいくつかが Go に移行することで、ビジネスが本当に必要としているものを実際に届けられるようになり、成長していくのを見てきました。一方、競合は扱いにくい Java や C# のコードベースに閉じ込められ、運が良ければ半年に一度、バグの多い機能を出せる程度でした
これは Go、Java、C# 自体の問題ではなく、古いオブジェクト指向アーキテクチャや設計が壊れやすすぎるからです。以前働いていた会社には C# のインターフェースが 1,000 個以上ありましたが、2 つ以上のクラスで使われているインターフェースはありませんでした。何万ものインターフェースがすべて同じフォルダと名前空間にあり、必要なものを見つけるには運を祈るしかありませんでした。Go でも他のどの言語でもそういうことはできますが、古いオブジェクト指向クリーンコード言語の文化にいなければ、そうなる可能性は低いです。特に C# では、デフォルトの抽象化が文化にあまりに深く埋め込まれていて、やらないほうが難しいほどです
個人的には Python 組織にひそかな愛着があります。いつも素早く届けるし、コードはひどい。でも愛おしいのです
おおむね正しいが、そのぶん無関係でもある
要するにソフトウェアの性能、したがって人間の性能だけが重要である。リスク管理とリスク受容は数値で測定できる。ソフトウェアでは他の職業よりはるかに簡単で、ソフトウェアエンジニアは既知の運用上の制約の中でのみリスクを受容でき、残りはすべて先送りされるからだ
もっと速くなりたければ、何よりもまず人間の反復頻度を最大化しなければならない。権限待ちで反復できないなら詰まっているし、ビルドや画面のリフレッシュ待ちなら遅くなっている。これも数値で測定できる
AがBより100倍速く反復できるなら、正確性は二次的になる。Bは遅いため正確性を最大化しなければならない。Aは、より速く、より正確になるために学び、失敗し、改善する極めて大きな柔軟性を持つ
より速く反復しながらリスクを下げる手段の一つが高速なテスト自動化だ。Aが人間の反復4回分の時間内に90%以上のテストカバレッジを実行できるなら、そのテスト自動化はそれでもBの1回の反復より25倍速く、回帰リスクは90%以上低い
速いデプロイは障害対応ウォールームを生む
その減少よりはるかに重要だったのは、問題が起きたときに原因を見つける速度がずっと速くなったことだ。ロールバックされる変更がごく少ないので、差し戻しもずっと安全で簡単だった。誰も3週間分の作業を巻き戻したくはない。それは混沌だ