万人のためのオートメーション: オートメーションによるデプロイメントの円滑化

オートメーションを利用してソフトウェアをさまざまな環境に素早く移行させる

自動ビルドは開発チームのためだけのものではありません。自動ビルドを拡張することで、ソフトウェアを開発から実動へと容易に移行させることもできます。「万人のためのオートメーション」では今回、オートメーションのエキスパート、Paul Duvall が Ant を Java™ Secure Channel と組み合わせて使用して、リモートでソフトウェアを複数のターゲット環境にデプロイする方法を説明します。

Paul Duvall (paul.duvall@stelligent.com), CTO, Stelligent Incorporated

Paul DuvallPaul Duvall はコンサルティング会社、Stelligent Incorporated の CTO および思想的指導者として、開発チームが機動的ソフトウェア作成を最適化できるように支援しています。彼は Addison-Wesley Signature Series から出版されている『Continuous Integration: Improving Software Quality and Reducing Risk』(Addison-Wesley、2007年) の共著者で、『UML 2 Toolkit』(Wiley、2003年) および『 No Fluff Just Stuff Anthology』(Pragmatic Programmers、2007年) の著作にも貢献しました。



2008年 1月 08日

この連載について

私たちは開発者として、ユーザーのプロセスを自動化するために作業しますが、自分自身の開発プロセスを自動化するチャンスは見落としがちです。そこで、連載記事「万人のためのオートメーション」では、実用的なソフトウェア開発プロセスの自動化を検討し、自動化を上手に適用するタイミングと方法を教えます。

多くのチームではソフトウェアを開発環境から実動環境へ移すことについて考えるのは後回しになっていることにお気付きですか。これまで私は、数週間、場合によっては数ヶ月にも及ぶデプロイメント・スケジュールを設定している開発チームに出くわしたことがありますが、個人的には時間の無駄にしか思えません。自動ビルドの場合と同じオートメーションを利用してデプロイメントの構成に関する問題に費やす時間を大幅に節約すれば、結果的にはデプロイメント・インフラストラクチャーの非効率性が改善されることになるからです。

考えてみてください。ソフトウェアをデプロイする際の効率が悪いと、それはすなわち、開発した素晴らしいアプリケーションをユーザーの手元に届けるのが遅れるということです。さらに厄介なことに、デプロイメントは絆創膏をはがすようなもの (痛いのは一瞬のこと) だと考えている人々もいます。実際、ほとんどのプロジェクトではデプロイメントの問題がなかなか解消されず、配布のたびにその問題が何度でも持ち上がります。

実動までの遅れに加え、非効率的なデプロイメント・インフラストラクチャーもチームを変更に適応しにくくする一因です。デプロイメント・インフラストラクチャーの効率が悪いためにチームは 1 回のリリースにあまりにも多くの機能を詰め込もうとすることが (リリースは頻繁に行われないため)、悪循環を生み出します。ビジネスとしてはユーザーがソフトウェアをすぐに使えるようにしたいところですが、リリースにこぎつけるまでは非常に時間がかかりすぎ、その結果、誰もがリリースという絶好の機会を最大限に生かそうと大々的な計画を立てることになるのです。

苦労のないデプロイメントは可能です

デプロイメントの基本プロセスには、コンパイル、データ変更内容の統合 (データベース・テーブルなど)、リモートから他のマシンへのディストリビューション (JAR、WAR など) のデプロイメント、そしてこれらのマシンのリソース管理が含まれます。実際には、インストール媒体の作成、テスト、ユーザー文書の生成など、さらに多くのことを自動化することができますが、この記事では基本部分のみにとどめ、ここに挙げたプロセスすべてを自動ビルド・プロセスに組み込む方法を紹介します。具体的には、以下のプロセスについて説明します。

  • リモート・マシンへのバイナリのデプロイメント
  • 構成プロパティーの外部化
  • リモートからの Mysql RDBMS の更新
  • リモートからの Jakarta Tomcat Servlet コンテナーの構成

上記のプロセスを自動化することによってデプロイメントの悩みの種が減り、最終的にはソフトウェアを短時間で顧客に配布できるようになります。


必要なツール

デプロイメントを自動化する際に中心となるツールはビルド・スクリプトです (この記事の例では Ant がドライバーになります)。私の Ant スクリプトは、プロパティー・ファイル (ステージングや実動など、ターゲットとする環境に固有のファイル) を使用し、Ant の sql タスクによって Mysql データベースとのインターフェースを取り、そして JSch (Java Secure Channel) を使用してリモート・マシンへのファイルのコピー (SCP (Secure-Copy Protocol) を使用)、Tomcat サービスの停止と起動 (SSH を使用) を行います。

図 1 に、このプロセスのアーキテクチャー概要を示します。ここでは、すべてのソフトウェア・アセットがバージョン管理リポジトリーに保存されていることが不可欠です。その理由は、理想的なビルド・プロセスではまずローカル側でソース・コード (および構成ファイル) をチェックアウトしてコンポーネントのコンパイルとパッケージ化を行い、次にリモート側で sql 文を実行してから、ディストリビューションをデプロイして Tomcat を再起動するからです。

図 1. リモート・デプロイメントのためのビルド・アーキテクチャー概要
リモート・デプロイメントのためのビルド・アーキテクチャー概要

上記のプロセスはすべて自動化することができますが、そうすることによって、デプロイメントを単一のコマンドやマウスのクリックでトリガーしたり、さらには人間が介入することなくプロセスの実行をスケジューリングすることが可能になります。画期的だと思いませんか?


プロパティーの外部化

ファイル・ロケーション、ホスト名、データベース名、ポート番号など、ターゲット環境によって異なる構成値を (例えばソース・コードなどに) ハードコーティングすることはできません。これらの属性を管理するのにより適しているのは、.properties ファイルです。プロパティーを外部化することにより、ある環境でコンパイルに使ったビルド・スクリプトを、ソース・コードを変更したり再コンパイルしなくても別の環境でデプロイメントに使用することができます。

プロパティーのルール

環境によって変わる値は、外部の .properties ファイルに配置してください。ビルド・スクリプト内で 1 つの値を複数回参照している場合、その値はビルド・スクリプト (build.xml) 内のプロパティーに含めておくべきです。値が絶対に 1 箇所からしか参照されないことがわかっている場合は、プロパティーに含める必要はありません (ただし、これは相当な前提条件になります)。

リスト 1 は、Ant ビルド・スクリプト内でプロパティーを定義する単純な例です。こうすると、.properties ファイルを特定のターゲット環境に関するすべての値が含まれるシステム・パラメーター (test.properties など) として渡すことができます。property.file.location は C:\Documents and Settings\patrick.henry\test.properties といったパスになるので、コマンド・ラインからは、例えば ant -Dproperty.file.location=C:\Documents and Settings\patrick.henry\test.properties と入力することになります。

リスト 1. プロパティー属性の外部化
<property file="${property.file.location}" />

リスト 2 に、ターゲット環境の .properties ファイルの一例を記載します。このファイルに含まれる属性の値はターゲット環境によって変わりますが (変わる可能性がありますが)、属性の名前は常に同じです。

リスト 2. プロパティー・ファイルの属性および対応する値の例
db.database=brewery
db.username.system=root
db.password.system=sa
db.username=root
db.password=sa
db.hostname=my-hostname.domain.com
db.driver=com.mysql.jdbc.Driver
db.port=3306
db.url.system=jdbc:mysql://${db.hostname}:${db.port}/
db.url=jdbc:mysql://${db.hostname}:${db.port}/${db.database}

このようにプロパティーの属性と値を外部化すると、複数のターゲット環境をサポートできる柔軟性の高いビルドおよびデプロイメント・アーキテクチャーを作成できます。


簡潔な中核部分

ソフトウェアを別の環境にデプロイするのが厄介なプロセスであってはなりません。私に言わせると、「deploy」と入力すればよいくらいに簡単なプロセスであるべきです。幸いなことに、Ant のようなビルド・システムはこれを実現してくれます。一連のステップを順に実行するワークフローを整然と定義することで、これらのステップを呼び出す単一のコマンドを作成することができます。

リスト 3 の depends 属性に列挙された Ant ターゲットは (上位レベルで) 詳細に自動デプロイメントを定義します。このスクリプトはまず、前に生成された成果物をローカル環境から削除し (ターゲットの clean を使用)、ソース・コードをコンパイルしてリモートでデータベースを作成します。それからテスト・データを適用し、データベースを起動し、最後にターゲット環境内の Tomcat コンテナーにリモートから WAR ファイルをデプロイします。

リスト 3. リモート・デプロイメントで実行される主要なターゲット
<target name="build" 
  depends="clean, compile, refresh-database, remote-tomcat-deploy" />

データベースを更新してリモートでアセットをデプロイする作業は簡単ではありませんが、賢いスクリプトさえあれば、すぐに自信を持って実行できるはずです。


DBA の自動化

ターゲット・テスト環境をセットアップする際には大抵、多くの手動プロセスが発生します。例えばデータベースの構成やテスト・データの挿入、それに古いエントリーの削除だけでなく、その他にも何度も繰り返さなければならない (したがって、エラーの原因となることがよくある) プロセスを手作業で行わなければなりません。そこで朗報です。デプロイメント時のデータベースの操作に苦労する必要はありません。

既存のデータベースの削除、データベースの作成、そしてデータベース・ユーザーの作成などといった DDL (Data Definition Language) 文とその後に続く insert 文などの DML (Data Manipulation Language) 文は簡単に Ant ビルド・スクリプトの一部として作成し、実行することができます。その上、これらのステートメントはリモートから実行することも可能です。

例えば、ビルド・スクリプトに (ターゲット環境の .properties ファイルから) db.url.system プロパティーを渡すと (リスト 4 を参照)、ビルド・スクリプトはリモート・データベースに対して sql 文を実行することができます。

リスト 4. データベースを作成してデータを挿入する場合のスクリプト
<target name="refresh-database" depends="create-database,insert-data" />
<target name="create-database">
  <sql driver="${db.driver}"
    url="${db.url.system}" 
    userid="${db.username.system}"
    password="${db.password.system}"
    src="${database.dir}/create-database.sql"> 
    <classpath>
      <pathelement location="${mysql-connector.jar}"/>
    </classpath>
  </sql>
</target>
...
<target name="insert-data">
  <sql driver="${db.driver}"
    url="${db.url}"
    userid="${db.username}"
    password="${db.password}"
    src="${database.dir}/insert-data.sql">
    <classpath>
      <pathelement location="${mysql-connector.jar}"/>
    </classpath>
  </sql>
</target>

リスト 4 の insert-data ターゲットから呼び出されるのは、リスト 5 の insert-data.sql ファイルに含まれる内容です。DDL であるか DML であるかにかかわらず、すべての sql 文はこのように Ant の sql タスクを使って同じ方法で実行することができます。

リスト 5. sql 文によるデータの挿入
insert into beer(id, beer_name, date_received) values 
  (1, 'Samuel Adams Lager','2006-12-09');
insert into beer(id, beer_name, date_received) values 
  (2, 'Guinness Stout','2006-12-29');
insert into beer(id, beer_name, date_received) values 
  (3, 'Olde Saratoga Lager','2007-02-14');
insert into beer(id, beer_name, date_received) values 
  (4, 'Sierra Nevada Pale Ale','2007-05-14');

リモート・データベースはこれで更新できました。次に行うステップはもちろん、Tomcat を実行するリモート環境にアセットをデプロイすることです。


配布とデプロイメント

リモート・デプロイメントを実装するのはローカル・デプロイメントの場合とそれほど変わりません。ただ単に、ビルド・マシンとターゲット環境間でのセキュアなコピーを可能にする別のチャネルが必要になるだけです。セキュリティーは大抵の企業にとって優先事項であるため、単純な FTP でのファイル転送や telnet 通信で常に事足りるとは限りません。その場合、セキュアなコピーを容易に実現するのは SCP および SSH です。Ant ではこの 2 つのチャネルを簡単に利用することができます。実際、私がリモート・マシンにファイルをコピーしてコマンドを実行する場合によく使うのは、JSch の sshexec タスクと scp タスクです。

実動への移行

特定のソフトウェア・アプリケーション (例えば、SaaS (Software as a Service) など) ではデプロイメントの頻度が変わってきますが、実動への移行はありきたりな作業ではありません。そのため、ソフトウェア・システムを前の状態に戻せるように、アプリケーションおよびデータベースのロールバックを追加する必要があります。ロールバックを追加するかどうかによって、何百万ドルもの利益になるか損失になるかが決まります。ソフトウェア・システム自体をテストする場合と同じように、自動デプロイメント・プロセスに対しても徹底的なテストが必要です。

SCP によるセキュアなファイル・コピー

SCP を使用すると、マシン間でセキュアにアセットをコピーすることができます。SCP をサポートするツールはさまざまにありますが、Ant では必然的に JSch が SCP を使用して、人手を介さずに (私好みの表現を使えば、自動的に) アセット (JAR ファイルなど) をコピーします。

リスト 6 の scp タスク (JSchが提供) は、ビルド・マシンからリモート・マシンに WAR ファイル (この例の場合) をコピーします。付け加える点として、scp タスクを利用するには Ant のクラスパスに JSch ライブラリー (jsch-0.1.36.jar) が含まれていなければなりません。

リスト 6. マシン間でのセキュアな WAR ファイルのコピー
<target name="copy-tomcat-dist">
  <scp file="${basedir}/target/brewery.war" 
  trust="true" 
  keyfile="${ssh.key.file}"
  username="${ssh.username}"
  passphrase=""
  todir="${ssh.server.username}:${ssh.server.password}@${ssh.server.hostname}
  :${tomcat.home}/webapps" />
</target>

scp タスクを呼び出すときには、コピー元のローカル・ファイルの場所と併せてローカルの SSH 秘密鍵ファイル (リスト 6 では ssh.key.file に該当。このファイルはセキュアな認証に使用されます) の場所を指定する必要があります。さらに、リモート・マシン (リスト 6 では ssh.server.hostname に該当) 上で scp にローカル・ファイル (複数可) を配置させる場所も指定してください。

SSH によるプロセスのリモート呼び出し

SCP での場合と同じく、リモート・マシンでコマンドを実行するにはセキュアなメカニズムが必要になることがよくあります。そんなセキュアなメカニズムとなるのが、SSH です。リスト 7 では、JSch の sshexec Ant タスクを使用してリモート・マシン上にある Tomcat コンテナーを停止してから再び起動しています。このリモート・マシンは、ビルド・プロセスによって一連のアセット (WAR ファイルなど) がまさにセキュアにコピーされた (コピー先の) マシンであるという前提です。

リスト 7. リモート Tomcat インスタンスの停止と起動
<target name="remote-tomcat-stop>
  <sshexec host="${ssh.hostname}"
  port="${ssh.port}"  
  keyfile="${ssh.key.file}"
  username="${ssh.username}"
  passphrase=""
  trust="true"
  command="${tomcat.home}/bin/shutdown" />
  <sleep seconds="${sleep.time}" />
</target>
...
<target name="remote-tomcat-start">
  <sshexec host="${ssh.hostname}"
  port="${ssh.port}"
  username="${ssh.username}" 
  passphrase=""
  trust="true"
  keyfile="${ssh.key.file}" 
  command="${tomcat.home}/bin/startup" />
  <sleep seconds="${sleep.time}" />
</target>

リスト 7 で指定しているのは、Tomcat が常駐するマシン名、Tomcat に対応したポート番号 (通常は 8080)、ビルド・スクリプトがマシンにセキュアにアクセスできるようにするための秘密鍵ファイル (ssh.key.file)、そして実行する特定のコマンドです。ご覧のように、ここでは shutdown コマンドを呼び出してから startup コマンドを呼び出しています。

自動ビルド・プロセスに組み込む作業は、この最後の一連のステップで完了です。これまでの作業でリモート・データベースを構成し、Web アプリケーションをリモート・マシンに移行させ、Tomcat のインスタンスをバウンス (一度停止してから起動) しました。これで、テスト用、さらには普段使用するための新しいバージョンのアプリケーションが実行されていることになります。


万人のための自動デプロイメント

以上の説明で、デプロイメント・プロセスの自動化は簡単に実現できることがわかっていただけたでしょうか。ソフトウェアを開発から顧客の元に渡すプロセスは手動で行う必要はなく、むしろ手動のプロセスであってはなりません。さらに、開発チームのビルド・プロセスと明確に切り離す必要もありません。事実、この記事で紹介した方法を使えば、ボタンを押すだけで簡単にソフトウェアをリリースすることが可能になります。それによってもちろん、開発チームは頻繁に機能を提供できるようになるはずです。

参考文献

学ぶために

製品や技術を入手するために

  • JSch: セキュアな通信を可能にする JSch (Java Secure Channel) をダウンロードしてください。
  • Ant: Ant をダウンロードして、分かりやすく繰り返し可能な形でソフトウェアのビルドを開始してください。
  • Tomcat: Web アプリケーションのビルドを簡単にする Tomcat Web コンテナーをダウンロードしてください。
  • DbUnit: DbUnit をダウンロードして、XML でデータ操作を管理してください。
  • サンプル・コード: この記事で使用したサンプル・スクリプトです。

議論するために

  • Improve Your Java Code Quality ディスカッション・フォーラム: このディスカッション・フォーラムでは、developerWorks の常連寄稿者 Andrew Glover が、コード品質の改善を重点にコンサルタントとして豊富な専門的知識を提供しています。
  • Accelerate development スペース: developerWorks のコントリビューターとしてお馴染みの Andrew Glover がホストを務める、開発者テスト、継続的インテグレーション、コード・メトリック、そしてリファクタリングに関するあらゆるものを網羅したワンストップ・ポータルです。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology
ArticleID=287100
ArticleTitle=万人のためのオートメーション: オートメーションによるデプロイメントの円滑化
publish-date=01082008