目次


アジャイル DevOps

テスト駆動型インフラストラクチャー

スクリプト化された環境を継続的にテストする

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: アジャイル DevOps

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:アジャイル DevOps

このシリーズの続きに乞うご期待。

環境をプロビジョニングするときに、ほとんどの組織では環境を作成する上での信頼性と再現性を損なうアンチパターンを適用しています。

  • 一部のチームでは、環境を作成するために必要なリソースを、手作業でインストールして構成しています。この場合の問題は、環境を目的の状態にするまでに、通常は数日、数週間、あるいは数ヶ月もかかることです。この作業期間中に、チームのメンバーが入れ替わったり、正確なステップを忘れてしまったりすると、誰一人として意図したとおりの環境を再現できなくなってしまいます。
  • 環境のプロビジョニング・ステップの 1 つひとつをドキュメント化しようとするチームもあります。これは素晴らしい試みであり、プロセスをドキュメント化しないよりはずっとましですが、ドキュメントを作成しても、すぐに古くなって使い物にならなくなるか、あるいは正確性に欠けていたり、指定されたとおりに動作しなかったりします (つまり、人的ミスを起こしやすいということです)。このような理由も含め、私は環境を作成するための記録をドキュメントとして残すことはお勧めしません (ただし、次のセクションで説明するように、環境をプロビジョニングしてテストするシステマチックな手法では、ドキュメントの作成が最初の一歩となる場合があります)。
  • 手作業でインストールしたチームや、何から何までドキュメント化したチームの誤りから学ぼうと決めて、それらの影響を受け過ぎてしまうチームもあります。これらのチームは、一連のスクリプトを使用してインフラストラクチャーのプロビジョニングを自動化します。けれども数ヶ月後には、チームは数え切れないほどのカスタム・シェル・スクリプトやその他のスクリプトで身動きが取れなくなり、自動化するには難しすぎる環境であることが証明されたと判断することになります。

その一方、DevOps を採用している企業の記事を読んで、手作業によるプロビジョニング、ドキュメントに従ったプロビジョニング、そしてまとまりのない一連のスクリプトでの誤りから学んでいるチームもあります。このようなチームは本番環境へ至る過程のなかで、テスト駆動型の手法と成熟したインフラストラクチャー自動化ツールを使用することによって、アンチパターンを免れています。この連載の以前の記事、「インフラストラクチャーの自動化」で述べたように、これらのチームはインフラストラクチャーをコードとして扱います。今回の記事では、テスト駆動型の手法を適用してインフラストラクチャーを定義する方法を説明します。

原則とプラクティス

私はこれまで何度となく、プロセスを継続的なものにするための経験則を 5 つの重要なステップとして書いてきました (「参考文献」を参照)。5 つのステップとは、ドキュメント化、テスト作成、スクリプト化、バージョン管理、そして (プロセスの) 継続化です。以下に、これらのステップのそれぞれについてインフラストラクチャーのコンテキストでさらに詳しく説明します。このコンテキストでは、すべてのステップが互いに作用します。

  • ドキュメント化: プロセスの実行ステップをドキュメント化します。インフラストラクチャーの場合には、コンポーネント (オペレーティング・システム、アプリケーション・サーバーと Web サーバー、そしてデータベースなど) のタイプとバージョンをドキュメント化します。また、これらのインフラストラクチャー・コンポーネントをインストール、構成、実行する方法についても詳しく記述します。テスト駆動型の手法を使用する場合、最終的にドキュメントは処分することになるため、「自動化に向けたドキュメント化」が重要となります。
  • テスト作成: 目的とする結果を記述する自動テストを作成します。インフラストラクチャーの場合、機能や期待される結果 (例えば、特定の場所で稼働状態になっているサーバーなど)、さらには特定のファイルやディレクトリーの存在を定義することができます。
  • スクリプト化: プロセスのすべてのアクションをスクリプトにします。インフラストラクチャーの場合には、上記のステップで指定したテストに従って、Chef や Puppet などのツールを使用して環境を定義します。
  • バージョン管理: ソース・ファイルをバージョン管理します。インフラストラクチャーの場合、これらのソース・ファイルは、Puppet または Chef などで作成されたインフラストラクチャー自動化スクリプトに定義されます。
  • 継続化: プロセスは、ヘッドレス・モードで実行できるようにスクリプト化する必要があります。つまり、人間がコマンドを実行しなくても済むようにするということです。インフラストラクチャーの場合、チームは継続的インテグレーション (Continuous Integration: CI) ジョブの一環としてインフラストラクチャー自動化スクリプトとスクリプト化された環境テストを実行するための CI サーバーを構成します。つまり、あらゆるソース・ファイルの変更を適用してインフラストクチャーが再構築されるようにします。

インフラストラクチャー・テストの顕著な特徴は、これを実行する順番にあります。テスト・ファースト手法を採用することもできますが、インフラストラクチャー・テストは、インフラストラクチャー・スクリプトがインフラストラクチャー全体を適用した後に、インフラストラクチャー自動化の有効性を検証するために実行されます。アプリケーション・コードのユニット・テストは、これとは逆の順序で行われます。つまり、テストが実行されてから、特定のメソッドやメソッド一式が実行されます。本質的に、テスト駆動型インフラストラクチャーにはアトミック性が伴いません。環境全体が作成されてから、新しくプロビジョニングされた環境に対してテスト一式が実行されます。

テスト駆動型インフラストラクチャーを適用する最も一般的な手法では、インフラストラクチャーをプロビジョニングするステップをドキュメント化するところから開始します。エンジニアはこのドキュメントに基づいて、インフラストラクチャーに期待される結果を記述する自動テストを作成します。これらの自動テストには、環境を完全にプロビジョニングする際にチームがインストールしなければならないコンポーネントを含めることができます。自動テストを作成した後、エンジニアはスクリプトを作成して、バージョン管理システムにそれらのスクリプトをコミットします。そして最後に、CI システムの一環としてスクリプトと自動テストを実行します。これらのステップを組み合わせることで (それらが、私が提示した「教科書的な」逐次プロセスでない場合はよくあるものの)、すべてのチーム・メンバーに素早くフィードバックを提供する、堅牢なテスト駆動型インフラストラクチャーになるのは確実です。

テスト駆動型インフラストラクチャーが機能する仕組み

テスト駆動型インフラストラクチャーを実装する方法は数多くありますが、その 1 つは、ビヘイビア駆動開発 (Behavior-Driven Development: BDD) 手法を適用することです。BDD 手法では、要件とテストを同じファイルに定義します。このファイルは、「フィーチャー・ファイル」と呼ばれます。このセクションでは、Cucumber および Gherkin というドメイン特化言語 (Domain-Specific Languages: DSL) で作成されたフィーチャー・ファイルの例を説明します。

リスト 1 に、Cucumber フィーチャー・ファイルを記載します。production.feature という名前のこのファイルは、フィーチャーおよびその背景とシナリオを記述します。

リスト 1. Cucumber および Gherkinで定義されている実行可能な仕様
Feature: Scripted Provisioning of Target Environment
As a Developer
I would like my target environment provisioned correctly
so I can deploy applications to it

Background:
Given I am sshed into the environment

Scenario: Is the proper version of Postgresql installed?
When I run "/usr/bin/postgres --version"
Then I should see "8.4"

Scenario: Is the proper version of Apache installed?
When I run "/usr/sbin/httpd -v"
Then I should see "2.2"

Scenario: Is the proper version of Java installed?
When I run "java -version"
Then I should see "1.6"

Scenario: Is the proper version of perl installed?
When I run "perl -version"
Then I should see "perl, v5.10.1"

Scenario: Is the proper version of make installed?
When I run "make -version"
Then I should see "GNU Make 3.81"

Scenario: Is the proper version of Ruby installed?
When I run "ruby -v"
Then I should see "ruby 1.9.3"

Scenario: Is the proper version of GCC installed?
When I run "gcc -v"
Then I should see "4.4.6"

FeatureBackgroundGivenScenarioWhen、および Then は、いずれも Cucumber 固有の用語であり、フィーチャー・ファイルを定義するための DSL に含まれています。リスト 1 に定義されている「Scripted Provisioning of Target Environment」フィーチャーは、期待される結果を、チームのすべてのメンバー (ビジネス・アナリスト、開発者、テスター、運用部門など) が組織内で使用している普遍的な言葉で記述しています。/usr/bin/postgres --version などの具体的なアクションには、Gherkin (Cucumber をインストールすると、一緒にインストールされる従属ツール) が使用されます。この BDD 手法は、自動化ツールによって実行できる、実行可能な仕様を定義する方法となります。

リスト 2 に記載する Cucumber フィーチャー・ファイルは、ツールの特定のメジャー・バージョンがインストールされていることを指定する方法を記述しています。この手法では、インフラストラクチャー・スクリプトはここに記述された特定のツールのメジャー・バージョンのいずれかを検出すれば失敗しないことになります。

リスト 2. ツールのメジャー・バージョンをチェックする Cucumber フィーチャー
Feature: Scripted Provisioning of Target Environment
As a Developer
I would like my target environment provisioned correctly
so I can deploy applications to it

Background:
Given I am sshed into the environment

Scenario: Is Tomcat installed?
When I check the version of Tomcat installed
Then the major version should be 6

リスト 3 では Examples キーワードの後に続く行に、シナリオに記述された振る舞いではテストに成功すると複数の内容が結果として出力されることが示されています。

リスト 3. Cucumber および Gherkin で記述された例
Feature: Scripted Provisioning of Target Environment

As a Developer
I would like my target environment provisioned correctly
so I can deploy applications to it

Background:
Given I am sshed into the environment

Scenario Outline: Is the proper version of libxml2-devel installed?
When I run "sudo yum info libxml2-devel"
Then I should see "<output>"

Examples: output I should see
| output |
| Installed Packages |
| 2.7.6 |

疎結合

テストとインフラストラクチャーとの結合は、(JUnit などで作成された) ユニット・テストとアプリケーション・コードとの結合ほど強くはありません。一例として (環境をスクリプト化する方法を思い出してもらうことも目的として)、リスト 4 に Puppet インフラストラクチャー自動化ツールを使用したサンプル・スクリプト (「マニフェスト」) を記載します。

リスト 4. httpd という名前の httpd サーバーについて記述する Puppet マニフェスト
class httpd {
  package { 'httpd-devel':
    ensure => installed,
  }
  service { 'httpd':
    ensure => running,
    enable => true,
    subscribe => Package['httpd-devel'],
  }
}

アプリケーション・コードのユニット・テストとは異なり、リスト 1 のテストでは、この Puppet マニフェストを「実行」するわけではないことに注目してください。代わりに、このマニフェストに定義された構成が (その他多くの構成とともに) 最初にインフラストラクチャーに適用されて、環境が作成されます。その後、リスト 123 で定義したようなテスト・スイートが実行されて、環境がテストによって定義された、期待される状態になっていることが検証されます。

静的分析

この記事を執筆している時点では、インフラストラクチャー自動化の分野における静的分析ツールのエコシステムはそれほど充実していません。アプリケーション・コードの静的分析に使用するツールのうち、インフラストラクチャー自動化にも適したツールはいくつかありますが、大半は、インフラストラクチャー・スクリプトの特異性に対応することができません。それは主に、インフラストラクチャー・スクリプトは本来、手続き型でもオブジェクト指向型でもないからです。ほとんどのインフラストラクチャー・スクリプトは宣言型であり、スクリプトに環境を定義する方法は開発者が決定します。インフラストラクチャーを使用して実際にどのように構成を適用するかは、そのスクリプトに任されます。

Simian のようなツールは、同様のコードが含まれるセクションを特定するのに役立ちます。foodcritic は、オープンソースのインフラストラクチャー自動化ツールである Chef を対象とした lint のようなツールです。(Chef や Puppet などのツールは手続き型またはオブジェクト指向型の言語を使用しないため) テスト・カバレッジに有効な手法は、アプリケーション・コードに適用する従来のコード・カバレッジ・ツールを使用するのではなく、Cucumber などの BDD ツールを使用して「要件カバレッジ」を定義することです。

あらゆるものにテスト駆動型を適用する

この記事では、インフラストラクチャーも、アプリケーション・コード (あるいは、ソフトウェア・システムの他のあらゆる部分) とほとんど同じようにテストできることを明らかにしました。記事では Cucumber と、Cucumber を支える Gherkin BDD 言語を使用してテスト駆動型インフラストラクチャーを実装する例を説明し、最後に、(インフラストラクチャーの静的分析はアプリケーションの静的分析とは異なるものの) 静的分析ツールを使ってインフラストラクチャー自動化コードを改善できることを説明しました。

次回の記事では、ソフトウェア・システムのすべてのコンポーネント (インフラストラクチャー、アプリケーション・コード、構成、そしてデータ) をバージョン管理する方法を説明します。


ダウンロード可能なリソース


関連トピック

  • Automating Infrastructures: Testing, Scripting, Versioning, Continuous」: Stelligentのブログで、Paul Duvall が環境を自動化するための 5 つのステップからなる経験則について説明しています。
  • Test Driven Infrastructure with Vagrant, Puppet and Guard」: SysAdvent のこのブログ投稿では、Patrick Debois 氏が Vagrant、Puppet、および Guard を使用したテスト駆動型インフラストラクチャーについて説明しています。
  • Test-Driven Infrastructure with Chef』(Stephen Nelson-Smith 著、O'Reilly Media、2011年): Chef および Cucumber によるテスト駆動型インフラストラクチャーに関する Nelson-Smith 氏の著書です。
  • Cucumber: Cucumber による BDD について詳しく学んでください。
  • Twitter で developerWorks をフォローしてください。
  • IBM Tivoli Provisioning Manager: Tivoli Provisioning Manager は物理サーバー、仮想サーバー、ソフトウェア、ストレージ、およびネットワークを自動化して、動的なインフラストラクチャーを実現します。
  • cucumber-nagios: cucumber-nagios では、自然言語を使ってシステムの動作仕様を記述できます。
  • Foodcritic: Opscode Chef のクックブックに使用できる lint のようなツールです。
  • IBM Tivoli System Automation for Multiplatforms: Tivoli System Automation for Multiplatforms は、エンタープライズ規模のアプリケーションおよび IT サービスの高可用性および自動化を実現します。
  • ご自分に最適な方法で IBM 製品を評価してください。評価の方法としては、製品の試用版をダウンロードすることも、オンラインで製品を試してみることも、クラウド環境で製品を使用することもできます。また、SOA Sandbox では、数時間でサービス指向アーキテクチャーの実装方法を効率的に学ぶことができます。

コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=DevOps, Open source, Java technology
ArticleID=848023
ArticleTitle=アジャイル DevOps: テスト駆動型インフラストラクチャー
publish-date=12062012