『継続的デリバリー』読書会 第一章 ソフトウェアデリバリーの問題 大崎的デリバリー @hidesuke
Jul 07, 2015
『継続的デリバリー』読書会 第一章
ソフトウェアデリバリーの問題 大崎的デリバリー @hidesuke
1.1 導入 この本の目的
• 本書の焦点 – ビルド、デプロイ、テスト、リリースプロセス
– 安全で信頼でき、素早くソフトウェアをリリースできるようにする
• ソフトウェアの開発からリリースまで効率的にすすめるためのパターンを解説する
1.1 導入 デプロイメントパイプライン
• ビルド・デプロイ・テスト・リリースといったプロセスを自動化する実装
• リリースする際の「価値の流れ(バリューストリーム)」は組織によって異なる – 組織毎に独自のデプロイメントパイプラインを実装
– どの組織でも原則は同じ
1.1導入 デプロイメントパイプラインの例
コミットステージ
自動化された受け入れテス
ト
自動化されたキャパシティテスト
手作業でのテスト
リリース
1.1導入 デプロイメントパイプライン
• 継続的インテグレーション(CI)のプロセスが基礎となっている – CIの考え方を論理的に突き詰めたもの
• 3つの目的 – 見える化し共同作業をやりやすくする – 早い段階での問題特定/解決の手助け – 任意のバージョンのソフトウェアを任意の環境に完全に自動化されたプロセスを通して好きなようにデプロイできるようにする
1.2 リリースによくあるアンチパターン
• リリース日 => 緊迫した空気 – プロセスが原因でリリースが恐ろしいものに
• リリースのよくある風景 – 手作業 – 集中力が必要 – 各ホストに手作業でソフトウェアをセットアップ
– 構成要素を1つずつ手動でたちあげ
1.2 リリースによくあるアンチパターン
• 間違える可能性のある要素が多すぎる • 一つでも間違えばアプリケーションは動かない
1.2.1 アンチパターン:ソフトウェアを手作業でデプロイする
• 広範囲にわたる詳細な手順書 – 必要なステップが全て記述してある – でも、リリース中に頻繁に修正
• 手動テストで動作確認 • 開発チームにデプロイがうまくいかない理由ついて頻繁に問い合わせ
• クラスタ内に設定の異なるノードがある • 数分単位でリリースが終わらない • リリースの結果が予測できない
– リリース前状態への切り戻し – 不測の問題に行き当たる
• 帰れない アンチ
パターン
1.2.1 アンチパターン:ソフトウェアを手作業でデプロイする
• デプロイは完全に自動化するべき • 人間がやるべきことは2つ – どのバージョンをどの環境にデプロイするかを選択する
– デプロイボタンを押す
解決策
解決策
1.2.1 アンチパターン:ソフトウェアを手作業でデプロイする
• 自動化しないといけない – 手動だとエラーがおきる – 手動だと反復可能にならない、信頼できない。デプロイで起こったエラーのバグに時間がとられる
– 手順書を作らなくてよくなる – デプロイスクリプトがあれば自動化できる
• デプロイをうまくやるためにデプロイスクリプトは常にメンテナンスされる
• 共同作業が促進される – デプロイメント職人が不要になる
アンチパター
ン
1.2.2 アンチパターン:開発が終わってから擬似本番環境にデプロイする
• ステージングへのデプロイが必要になったときに、初めてデプロイチームが招集される – デプロイに必要なステップはステージング環境でテストされないことが多い
– ドキュメントが重要なステップを抜かしてる可能性
– ドキュメントやスクリプト上の想定が誤っていて、デプロイに失敗
– 開発チームと協力していないので、失敗の原因を当て推量
アンチパター
ン
1.2.2 アンチパターン:開発が終わってから擬似本番環境にデプロイする
• ステージングに最初にデプロイするときが最もトラブルが多い
• リリースサイクルが長くなるほど、デプロイの前に行う想定は不正確になり、修正に時間がかかる
• 大きな組織で、役割毎に組織が縦割りになっている場合、申請書提出地獄になる
• 開発環境と本番環境の違いが大きいほど、想定も現実と乖離する – Windows機上でSolarisクラスタにデプロイするアプリを開発してるとか
解決策
1.2.2 アンチパターン:開発が終わってから擬似本番環境にデプロイする
• テスト・デプロイ・リリースを開発プロセス中に統合する
• リリースを行うチーム、テスター、開発者まで全員がプロジェクトの最初から確実に協力しあう
• ソフトウェアとデプロイプロセスの両方をテストする
1.2.3 アンチパターン:本番環境について手作業で構成管理を行う
• 本番環境の構成管理を運用担当チームで行なっている場合…… – 本番サーバに対して手作業で変更が行われる • データベース接続設定とか
– 変更の記録が変更管理DBに残される
例えばこんな場合
アンチパター
ン
1.2.3 アンチパターン:本番環境について手作業で構成管理を行う
• ステージングへのデプロイは何度も成功してるけど、本番へのデプロイで失敗する
• クラスタ内の別々のメンバで振る舞いが違う – 他のメンバだと耐えられる負荷に耐えられない子がいる
– 処理に時間がかかる子がいる • 運用チームがリリースのために時間がかかる • システムを以前の状態に戻せない • クラスタ内でバージョンが統一されていない • 本番を直接編集で設定を修正
解決策
1.2.3 アンチパターン:本番環境について手作業で構成管理を行う
• 設定などは自動プロセスを通じてバージョン管理から適用されるべき – テスト環境、ステージング環境、本番環境のあらゆる設定 – 特にサードパーティーの要素の設定
• 構成管理にはあらゆる構成要素を繰り返し再現できるということも含まれる – OS、パッチレベル、OSの設置、アプリケーションスタックとその設定、基盤設定など、全てが管理されていなくてはならない
– 仮想化はその第一歩 • バージョン管理されていれば、以前のバージョンへのロールバックも可能
1.3 もっとうまくできないのだろうか?
• 本書の目的→リリースをごく単純な作業にする
• 開発環境、テスト環境、本番環境までどんなデプロイ対象にもボタンひとつでソフトウェアをリリースできるようにする – 小規模な開発チームだけでなく、分散したチームによる大規模なエンタープライズプロジェクトでも実施できる
1.4 どうすれば目標を達成できるか?
• 目標:役に立って動作するソフトウェアをできる限り素早くユーザに届けること
• サイクルタイムを減らす – サイクルタイム:変更すると決めてからユーザが使えるようになるまでの時間
– 機会損失を減らす/投資の回収を素早く開始する • サイクルタイムを最小化し、(顧客からの)効果的なフィードバックループを構築する => 素早いデリバリーが重要
1.4 どうすれば目標を達成できるか?
• 使い勝手おいて重要な部分を占めるのが品質
• 品質を適切なレベルに保つことが重要
• 高品質で価値のあるソフトウェアを効率的で素早く、信頼できるやり方でリリースする方法を見つけ出したい
1.4 どうすれば目標を達成できるか?
• 高品質で価値のあるソフトウェアを効率的で素早く、信頼できるやり方でリリースする方法を見つけ出したい
• 自動化 – ビルド・デプロイ・テスト・リリースを自動化し、こまめに繰り返す
• こまめに – こまめなリリースによって、リリース間の差異を小さくする => リリースリスクを小さく
– フィードバックを素早く得られるようにする
1.4 どうすれば目標を達成できるか?
• フィードバック大事 – あらゆる変更はフィードバックプロセスを引き起こさなくてはならない
– フィードバックは早く伝えなくてはならない – デリバリーチームはフィードバックを受け取り、それに対して行動を起こさなければならない
ここで言っているフィードバックとは 変更に対してテストを実行した結果のことも指している
1.4.1 あらゆる変更はフィードバックプロセスを引き起こさなければならない
• ソフトウェアアプリケーションの4つの要素 – 実行可能なコード – 設定 – ホスト環境 – データ
• どれかが変更されたら、そのせいでアプリケーションの振る舞いが変化する可能性がある
1.4.1 あらゆる変更はフィードバックプロセスを引き起こさなければならない
• 継続的インテグレーション(第3章で説明) • 実行可能コード – あらゆる環境にデプロイされるものと同一でなければならない
• 設定 – 環境ごとに変更される必要があるものは設定情報として扱う必要がある
– 設定変更されれば、どの環境であれテストしなければならない
1.4.1 あらゆる変更はフィードバックプロセスを引き起こさなければならない
• ホスト環境 – 環境に変更があれば、環境を変更した上でシステム全体をテストしなければならない
– 環境とはOS、ソフトウェア(ミドルウェア)、ネットワーク構成、あらゆる基盤や外部システムが含まれる
• データ – データ構造が変更されたらテストしなければならない(データ管理については12章)
1.4.1 あらゆる変更はフィードバックプロセスを引き起こさなければならない
• 変更時のフィードバックプロセス – 前述した各種テスト – 受け入れテスト、非機能要件テスト – 顧客に対するデモンストレーション
• できる限り完全に自動化されたテストの実施 => フィードバックプロセスを引き起こす
1.4.2 フィードバックはできる限り早く受けとらなければならない • 素早いフィードバックの鍵は自動化 – プロセスが完全に自動化されていればハードウェアを投入すればいくらでもスケールする
– 繰り返し作業は機械に任せる => 人的リソースの用途を最適化する
1.4.3 デリバリーチームはフィードバックを受け取り、それに対応しなければならない
• デリバリーチームがフィードバックプロセスに関わっていることが重要 – 頻繁に会うことで、デリバリープロセスの改善につながる
• フィードバックに対応できる => 情報を広くつたえることに繋がる
• フィードバックに対して、チーム全体の責任として対処する
1.4.4 このプロセスはスケールするのか?
• 小さいチームでしかうまくいかない? => NO! 大小様々なプロジェクトで実践してきた方法について本書では解説している
• リーン生産方式の影響をうけている – リーンは巨大な組織のために作られたもの – リーンの理論やプラクティスは小さいチームと同様に大きなチームにも当てはまる
1.5 どんな恩恵を受けられるのか?
• 反復可能で信頼でき、予測可能なリリースプロセスの構築 – サイクルタイムの短縮 – コストの節約
• その他にも恩恵がある
1.5.1 チームに権限を与える • プルシステム – テスターや運用担当者、サポート担当者が自分の望むバージョンのアプリケーションを好きな環境に自分でリリースできるようにすること
– 従来はこういった人達は「適正なビルド」が提供されるのを待っていた => この待ちや手続きが非効率だった
1.5.1 チームに権限を与える • プルシステムによる恩恵の例 – テスターは古いバージョンのアプリを選択して、新しいバージョンにおける振る舞いの変更を検証できる
– サポート担当者はリリースされたバージョンのアプリをテスト環境にデプロイして、欠陥を再現させることができる
– 運用担当者はディザスタリカバリーの演習の一貫として正しく動くとわかっているビルドを本番環境にデプロイできる
– リリースがボタンひとつで実行できる
1.5.1 チームに権限を与える • チームメンバーは自分たちの仕事をコントロールできるようになる
• 仕事の品質が向上 • アプリケーションの品質も向上 • 正しいビルドが渡されるのを待つ必要がなくなる
1.5.2 エラーを削減する • 構成管理がまずいせいでエラーになる場合について述べる
• (詳細は2章) • 構成管理は、典型的なアプリケーションを動かすために適切に設定しなくてはならない
1.5.2 エラーを削減する • 変化する可能性があるものをすべて、積極的にバージョン管理で管理する – 設定ファイル/DBスキーマ生成スクリプト/ビルドスクリプト/テストハーネス/デプロイメント環境/OSの設定
• 設定の適用をコンピュータを使うようにする(人力で適用しない)
1.5.3 ストレスを低減する • リリースのストレスからの開放!
• まずは自動のデプロイメントプロセスを準備しておく
• リリースまでにこまめに実行 • 変更前の状態に戻せるようにもしておく • 最初は痛みを伴うが、じょじょに簡単になっていき、大きな恩恵が得られる
1.5.4 デプロイメントの柔軟性 • 新環境でアプリを動かしはじめるというタスクはシンプルであるべき
• 筐体や仮想イメージを作動させ、環境固有の設定情報をつくるだけにしたい
• そこに自動化されたデプロイメントプロセスを利用して環境構築&アプリのリリースを行う
1.5.5 「できるようになりたければ、練習しろ」
• どこにデプロイする場合でも、デプロイのアプローチを同一にする – 特別な受け入れテストとか本番用のデプロイ戦略とかいうことがあってはいけない
– 何回も本番にデプロイするのと同じ方法でデプロイすることになる
• 唯一例外が許されるのは開発環境のみ – 開発者が自分でバイナリをビルドする必要があったりするので
1.6 リリース候補 • ビルドやデプロイの自動化が包括的な自動テストと併せて行われていれば、集中的で大々的な手動テストは必要ない – 手動テストは機能を満たしていることを確認するだけでよい
• 開発プロセス終了後にテストを実施すると品質は低下する
• 欠陥は素早く修正されるべき – 発見がおくれると修正にかかるコストは増加する
1.6.1 あらゆるチェックインは潜在的にリリースにつながる
• 統合フェーズでまとめて統合を行う => 統合フェーズまできちんと動いているかわからない! 痛みが大きすぎる!
• こまめに統合する – 壊れたらすぐに修正 – ソフトウェアは常に動く状態が保たれる – 常にリリースできる状態 – 継続的インテグレーションの第一のルール
1.7 ソフトウェアデリバリーの原則
• ソフトウェアをリリースするための、反復可能で信頼できるプロセスを作り上げよ
• ほとんどすべてを自動化せよ • すべてバージョン管理に入れよ • 痛みを伴うものはこまめに実施し、痛い思いは早めにしておけ
• 品質を作り込め • 完了したとはリリースしたということだ • 誰もがデリバリープロセスに対して責任を負う • 継続的改善
1.7.1 ソフトウェアをリリースするための、反復可能で信頼できるプロセスを作り上げよ
• リリースが簡単 => 何回も(リリースする)テストができる
• バージョン管理に端を発する完全に自動化されたプロセスを作ることが重要
1.7.2 ほとんどすべてを自動化せよ
• 自動化できないものは多くはない – 人間の指示や意思決定が必要になるプロセス直前までは自動化するべき
– 受け入れテスト、DBのアップグレード/ダウングレード、ファイアウォールの設定も自動化できる
• 手作業のほうが簡単に思えるかもしれないが、それを何回も繰り返すなら自動化したほうが楽
1.7.3 すべてバージョン管理にいれよ
• バージョン管理できるストレージにありとあらゆる物を保管しなくてはならない – 要件定義ドキュメント、テストスクリプト、自動テストのケース、ネットワーク構成スクリプト、デプロイメントスクリプト、初期化スクリプト、ツール群、ライブラリなどなどなど
• 変更セットは単一の識別子を保つ必要がある • 新しいチームメンバーが新規の新しいマシンに座り、リポジトリからチェックアウトして、コマンドを1行実行したらアプリケーションがビルドできる必要がある
1.7.4 痛みを伴うものはこまめに実施し、痛い思いは早めにしておけ
• 最も役に立つ経験則 • 例) 統合はひどい苦痛を伴うプロセス => 誰かがチェックインするたびに統合を行おう! プロジェクトの最初から
• とにかく苦痛と思うもの(リリース、結合、テスト、などなど)はこまめに普段から自動化して実施する
1.7.5 品質をつくりこめ • リーンからパクった原則 • 欠陥を早く見つけるほど、修正も安くあがる
• 継続的インテグレーションで、欠陥を常に検知できるようになった => すぐに修正できるようにする
• チームが品質に対する責任を負う
1.7.6 完了したとはリリースしたということだ
• 「完了した」とは価値をユーザに届けたとき – 外部のユーザに価値が届くまでは時間がかかる……
• 擬似本番環境にリリースし、ユーザコミュニティの代表者(プロダクトオーナーや依頼者)に対してデモを行い、触ってもらったときが完了ということにしている
• 80%完了などない。完了したか、してないかのみ
1.7.7 誰もがデリバリープロセスに対して責任を負う
• 縦割りだと責任のなすりつけ合いになる • プロジェクトの最初から全員をデリバリープロセスに巻き込む
1.7.8 継続的改善 • アプリケーションは進化していく => デリバリープロセスも一緒に進化することは重要
• デリバリープロセスに関する振り返りを行うべき
• 組織内の誰もがPDCAサイクルに関わる – 壁を設けない。縦割りしない。犯人探しにならないようにする
1.8 まとめ • ビルド・テスト・デプロイメントを自動化する – 変更を確認できるようになる – 複数の環境にまたがってプロセスを再現できるようになる
– 本番にエラーが交じる可能性を大幅に低減できる
– ビジネス上の利益を素早く提供できるようになる
– ワークライフバランスが改善される
感想 • 同じ事繰り返し何度もいってるので辛い • もっとまとめられそう • この本を元に違う本が書けそう • 継続的デリバリー重要 • 宗教的 • 哲学的