『継続的デリバリー』 第2章 学習メモ

構成管理

1.はじめに

継続的デリバリーにおける、構成管理についての調査記録です。
継続的デリバリーの中での、構成管理が持つ責務について記載します。
『継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化』の第2章に対応します。

2.概要・目的

構成管理とは、あらゆる成果物とその関係を保存、検索、識別、修正するプロセスである。
構成管理では、以下の5項目について、ベースラインを格納し、変更をコントロールするための戦略を準備する必要がある。

  • アプリケーションのソースコードやビルドスクリプト、テストドキュメント、要件、データベーススクリプト、ライブラリ、設定ファイル。
  • デプロイメントやテスト、運用に使うツールチェーン。
  • 開発環境、テスト環境、本番環境。
  • アプリケーションに関連するすべてのアプリケーションスタック。バイナリと設定両方。
  • あらゆる環境で実行されるあらゆるアプリケーションに関連する設定。

この設定は、アプリケーションのライフサイクル全体(ビルド、デプロイメント、テスト、運用)をまたがるもの。

構成管理戦略を適切に策定することで、以下を達成できる。

  • あらゆる環境を正確に再現
    再現すべきものは以下の項目。
    • OSのバージョン
    • パッチレベル
    • ネットワーク構成
    • ソフトウェアスタック
    • デプロイされるアプリケーションとその設定
  • 再現すべき項目それぞれに対して、個別にインクリメンタルな変更を行い、それを自分の環境のどれかや、すべてに対して簡単にデプロイできる
  • 特定の環境で発生した変更を、簡単に見分けられる。
    また、変更の内容(What,Who,When,Why)を追跡して正確に突き止められる
  • 従うべきコンプライアンスの規約をすべて満たすことができる。
  • チームのメンバ全員が必要な情報を取得し、必要な変更を行うことが容易となる。
  • 効率的なデリバリーを妨げず、サイクルタイムを短く保ち、十分なフィードバックを得られる

3.問題

構成管理における問題として、以下の3点がある。

  • アプリケーションのビルド・デプロイ・テスト・リリースプロセスを管理するために必要な前提条件として、以下の2つを問題とする。
    • バージョン管理
    • 依存関係の管理
  • アプリケーションの設定の管理
  • 環境全体に対する構成管理
    ソフトウェア、ハードウェア、アプリケーションが依存する基盤を含む。

4.対応概要

(1)バージョン管理

  • 問題:ソフトウェアの特定のバージョンの構成要素の識別。ソフトウェアのバイナリと設定の特定の状態を再現すること。
    対応:一度格納されたあらゆるファイルに対して、すべてのバージョンを保持し、アクセスできるようにする
  • 問題:変更の内容(What,Who,When,Why)を追跡して、正確に突き止められるようにする。アプリケーションの経緯を分かるようにする。
    対応:バージョン管理システムにより、分散したチームでも協力を可能にする。

(2)アプリケーションの構成管理

アプリケーションの構成管理の原則として、以下が挙げられる。

  • アプリケーションのライフサイクルの中で、設定を注入する意味のある時点を特定する。
  • アプリケーションで使うことのできる設定オプションを、ソースコードと同じリポジトリ内に保持する。
    ただし、設定とコードのライフサイクルの違いや、セキュリティの問題から、値は別の場所に保持する。
  • 常に、自動化されたプロセスで、設定リポジトリから取得した値で設定する。
  • アプリケーション・バージョン・デプロイされる環境に応じて、アプリケーションに個別の値を提供する。
  • 設定オプションには、明確な命名規約を使用する。
  • 設定情報をモジュール化し、カプセル化する。
  • Don't Repeat Yourself.
  • 要件や意味があるときのみ、設定情報を使用する。
  • できるだけ、設定はシンプルにする。
  • デプロイメント時やインストール時に、確実にテストを実施する。

(3)環境の管理

環境構築を完全に自動化されたプロセスで行い、環境を再現できるようにすることで、以下を満たすことができる。

  • 基盤や設定が、特定の人に依存するリスクの回避
  • 正しく動くとわかっている状態に、既知の時間で戻すことができる。
  • テスト環境を本番環境の正確なレプリカとすることで、設定の問題を早期発見できる。

5.対応詳細

(1)バージョン管理 

a.バージョン管理に入れるべきもの

ソースコードと設定情報の他に、アプリケーションサーバコンパイラ仮想マシン・ツールチェーンの一部について、バイナリイメージをバージョン管理する。
これらをバージョン管理することで、開発・テスト・本番環境のための、安定したプラットフォームを作ることができる。

b.バージョン管理に入れるべきでないもの

アプリケーションをコンパイルした結果のバイナリはバージョン管理に格納しない
これは、リポジトリ内の1バージョンを特定できるという理念が崩れてしまうため。
この理念は、デプロイメントパイプラインを作るうえで重要となる。

c.フィーチャブランチの問題点

フィーチャブランチには、統合・マージ。リファクタリングが困難になるという問題がある。
この問題は、以下の条件を満たすことで回避できる。

  • オープンソースソフトウェアで、十分な制約があるとき。
  • 定期的にメインラインに統合されるとき。

d.ソフトウェアを常に動く状態に保つ

新しい機能をインクリメンタルに開発し、バージョン管理のメインラインに定期的にコミットする必要がある。
これにより、CIサーバが自動テストをメインラインに対して実行することで、ソフトウェアが常にテストされた状態になる。
統合にかかわる問題が即座に、容易に修正できるうちに検出できる。

e.チェックインでアプリケーションを壊さない

チェックインの際にアプリケーションを壊さないことを保証するため、以下のプラクティスを実践する。

  • チェックイン前のコミットテスト、プレコミットテストを実施する。
  • 変更をインクリメンタルに行う

f.コミットメッセージ

コミットメッセージは、以下の理由で必要となる。

  • ビルドが壊れた時に、誰がどんな理由で壊したかわかる。
  • 複雑な問題のデバッグのコストが下がる。

適切なコミットメッセージの書き方として、以下の2点がある。

  • 1行目に要約を書き、2行目以降に詳細な説明を記載する。
  • 取り組んでいるフィーチャやバグを、プロジェクト管理ツールに紐づける。

(2)依存関係の管理

a.外部ライブラリの保持

外部ライブラリは、以下のいずれかの方法で保持する。

  • ローカルでコピーを保持する。
  • 組織用のリポジトリで、利用するライブラリの適切なバージョンを保持する。

b.ビルドシステム

ビルドシステムでは、利用している外部ライブラリの正確なバージョンを指定する必要がある。

c.コンポーネントの分割

コンポーネント複数のパイプラインに分割するときは、ソースではなく、バイナリに依存関係を持たせる。
理由は、依存関係のリコンパイルが非効率的なうえに、テストしたものとは潜在的に異なる成果物となるためである。

(3)設定の管理

アプリケーションを構成する主な3つの要素は、設定・バイナリ・データである。

a.設定の問題

設定の問題として、検証レベルが低いことがある。
この問題は、開発スモークテストを実施することで和らげられる。

b.設定の注入

設定は以下の4つのタイミングで注入できる

  • ビルド。
  • パッケージング。
  • デプロイメント。
  • 起動時や実行時。

アプリケーションと組織内にあるすべての環境のための設定情報は、同じ仕組みを使って提供する必要がある。
同じ仕組みで提供することで、設定の変更や管理・バージョン管理・(必要な時は)上書きを行うときの、起点を統一できる。

c.バージョン管理から分離

設定情報のうち、パスワードやデジタル認証などのセキュリティに関連する設定要素は、バージョン管理から分離しなければならない。

d.設定情報の格納場所

設定情報の格納場所の候補は以下の3つである。

e.設定情報の取得

あらゆるアプリケーションが必要な設定を取得できるように設定を管理する上で、最も効果的な方法は、中央集権的なサービスを置くことである。
設定情報へのアクセスのための技術的詳細からアプリケーションを隔離するために、シンプルなファサードクラスを作成する。

f.設定の構成

アプリケーションの設定は、タプルの集合で構成される。
設定は以下の3つに依存する。

  • アプリケーション。
  • アプリケーションのバージョン。
  • アプリケーションの実行環境(開発環境、UAT環境、性能環境など)。

g.設定のモデリング

設定をモデリングするときに考えるべきユースケースは以下の5つである。

  • 新しい環境を追加するとき、新しい環境にデプロイされるアプリケーション用に、新しい値の集合を定義する。
  • アプリケーションの新しいバージョンを生成するとき、新しい設定を導入し、古い設定を削除する。
  • アプリケーションの新しいバージョンをある環境から別の環境に移しかえるとき、新しい環境から新しい設定にアクセスする。
  • データベースサーバをリファクタリングするとき、単純なやり方で、データベースを参照している設定を更新して、新しいデータベースに向ける。
  • 仮想化によって環境を管理するとき、仮想化管理ツールを使って、特定の環境の新しいインスタンスを作る

h.環境をまたがった設定管理

環境をまたがった設定管理のためには、本番の設定として期待されるものをデフォルトとし、それ以外の環境では、適切に上書きする。
このアプローチにより、環境に特化した調整が、どれも設定プロパティだけにまとめられる設定を変更することで、ソフトウェアがその特定の環境で動くことを保証する。

i.設定のテスト

設定のテストのためには2つのステージがある。
最初のステージでは、設定にある外部サービスへの参照が、適切であることを保証する。
デプロイメントスクリプトやインストールスクリプト内で、(少なくともpingを打つなど)スモークテストの実施することで、設定を検証する。
第2のステージでは、アプリケーションがインストールされた後で、期待どおりに作動することを確認する。
設定が正しいかどうかに依存する機能を動作させるテストを含めた、スモークテストを実施することで検証する。
テストに失敗したときは、アプリケーションを止めて、インストールやデプロイメントプロセスを失敗させる

j.アプリケーションをまたがった設定管理

環境の設定を確定するために、アプリケーションをまたいで設定を管理するときは、各アプリケーションにある設定オプションをすべて一覧化しておく。
このために、設定管理の方法は統一する必要がある。

(4)環境の管理

a.環境設定の対象

環境設定の対象として、以下の5つが挙げられる。

  • 環境にある様々なOS。バージョン・パッチレベル・設定を含む。
  • 各環境で、追加でインストールする必要のあるソフトウェアパッケージ。パッケージのバージョンや設定を含む。
  • ネットワークトポロジー
  • アプリケーションが依存する外部サービス。サービスのバージョンや設定を含む。
  • アプリケーション内の、あらゆるデータや状態

b.効果的な構成管理のための原則の適用

効果的な構成管理のための原則として、以下の2つがある。

  • バイナリファイルを構成情報から独立させること。
  • 設定を1か所にまとめておくこと。

この原則により、新しい環境の構築やシステムの一部のアップグレード、システムを止めずに新しい設定をロールアウトさせるといったプロセスを自動化されたシンプルなものにできる
この原則が適用できるソフトウェアの条件として、以下の2つがある。

c.ソフトウェアを評価するための構成管理上の観点

ソフトウェアを評価するための構成管理上の観点として、以下の3つがある。

  • デプロイ可能か。
  • 設定のバージョンを効率的に変えられるか。
  • 自動デプロイメント戦略と整合するか。

d.自動化された環境プロビジョニングシステム

自動化された環境プロビジョニングシステムによって、あらゆるベースラインの構築、再構築が可能となる。

e.OS管理

OS管理を自動化するツールとして、Puppet・CfEngineがある。
これらのツールにより、筐体へのアクセス権をどのユーザに付与するかについてや、どのソフトウェアをインストールするかについて、宣言的に定義できる。
さらに、この定義は、バージョン管理できる

f.環境に対する変更プロセスの検証

環境に対して変更を行うプロセスをテストするため、テスト環境へのデプロイメントプロセスを、本番へのデプロイメントプロセスと揃える

6.影響・作用

構成管理によって、以下の3点が可能となる。(同時に、以下の3点が構成管理の検証観点となる。)

  • バージョン管理された資産により、本番システムを、スクラッチから完全に再構築できる。ただし本番データは除く
  • 正しく動くとわかっている以前の状態に、アプリケーションを戻すことができる
  • 本番・ステージング・テストといったデプロイ対象の環境が、正確に同じやり方でセットアップされていると保証できる。

7.おわりに

以上が、継続的デリバリーの中での、構成管理が持つ責務です。

8.参考文献

『継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化』 第2章 ソフトウェアデリバリーの問題