アジャイル DevOps: 動的な構成

ソフトウェア・デリバリー・ライフサイクルにおける静的構成を削減する

アプリケーション、環境、そして個々のインスタンスの間で、皆さんは構成値の管理にどれくらいの時間をかけているでしょうか?おそらく皆さんは、予想以上の時間、または認めたくないほどの時間を費やしているはずです。しかし、構成管理にそれほど手間をかける必要はありません。この記事では DevOps のエキスパートである Paul Duvall が、デプロイ時のエラーにつながる可能性がある重複や構成の誤りを削減するには構成データをどのように管理すればよいかを説明します。

Paul Duvall, CTO, Stelligent

Paul DuvallPaul Duvall は、Stelligent の CTO です。数々の主要なソフトウェア・カンファレンスでメインの講演者を務めている彼は、ソフトウェア・プロジェクトの開発者、プロジェクト・マネージャー、アーキテクト、およびテスターと、実質上すべての役割を担当した経験を持ちます。彼が中心的な著者となった共著書『継続的インテグレーション入門 開発プロセスを自動化する 47 の作法』(Addison-Wesley、2007年) は、2008年度の Jolt Award を受賞しました。また、『Startup@Cloud』、『DevOps in the Cloud LiveLessons』(Pearson Education、2012年6月) の著者でもあります。その他の本にも貢献し、developerWorks では 20 の記事からなる連載「万人のためのオートメーション」を書いています。彼は、継続的デリバリーとクラウドを利用して、高品質のソフトウェアをより短時間に、より頻繁に提供することに熱意を持っています。Stelligent.com で彼のブログを読んでください。



2013年 5月 09日

この連載について

開発部門は、運用部門から多くのことを学べます。同じく運用部門も開発部門から多くのことを学べます。この連載では、運用部門の考え方と開発部門の考え方を相互に適用し、ソフトウェア製品をこれまでよりも迅速かつ頻繁に提供可能な総体的要素として捉える場合の実用性を探ることに話題を絞ります。

複数の環境の構成を管理する作業は、多くのソフトウェア・デリバリー・システムの悩みの種となりがちです。ほとんどの組織は、静的プロパティー・ファイル (local.properties、dev.properties、test.properties、stage.properties、prod.properties など) を使用して、異なる環境のプロパティーを管理します。私自身、今までそうした方法で多くのソフトウェア・デリバリー・システムを設計してきており、「万人のためのオートメーション: オートメーションによるデプロイメントの円滑化」という記事では、その方法を説明しました。その方法は、私が見てきた中では最も単純な方法の 1 つでしたが、多数のアプリケーションや何百というインスタンスのための、何百、さらには何千というプロパティーを持つソフトウェア・デリバリー・システムを管理しなければならない場合には、この方法はスケーラブルでないため、最終的に管理不能になります。構成が失敗する場合というのは、1 つのソフトウェア・システムに対して何百種類もの異なるプロパティー・ファイルがあり、そのいずれかに誰かが誤った値を入力したことによって発生するケースがほとんどです。

しかし、そうした状況に望みがないわけではありません。異なる環境間でソフトウェアを移行する場合にも、自動化、動的構成、クラウド・インフラストラクチャーを効果的に使用することにより、ソフトウェア・デリバリー・システムに必要な静的プロパティーを大幅に減らすことができます。この記事では、その方法について説明します。

典型的なプロパティー

表 1 に、組織内のチームが管理する典型的なプロパティーの一部を示します。

表 1. ソフトウェア・デリバリー・システムにおける典型的なプロパティー
プロパティー説明
IP アドレス一意に指定できる、ノードのロケーション
エンドポイント任意のノード (ロード・バランサー、インスタンスなど) のドメイン名
ドメイン名ユーザーがアプリケーションにアクセスするために使用し、一意に指定できるドメインの名前。ドメイン登録機関やドメイン・サービスとの間で、ドメイン名に関するやりとりが行われます。
データベース名アプリケーションが使用するデータベースの名前
ポート内部および外部からノードにアクセスする場合に使用される 0 から 65535 の間の一意の数値
ユーザー名とパスワードリソースへのヘッドレス・アクセスで使用されるユーザー名とパスワード
ディレクトリーとファイルオペレーティング・システム内のディレクトリーとファイル
SSH 鍵セキュアなリソースにアクセスするための Secure Shell 鍵ファイル

この表はすべてを網羅したものではありませんが、典型的なソフトウェア・システムで最も一般的に使用されるプロパティーを表しています。


従来のプロパティー管理

ソフトウェアを扱う組織のほとんどは、開発チームと運用チームのサイロで構成されており、開発チーム (つまり、開発者、テスター、アナリストなど) は多くの場合、以下の作業を行います。

  • ワークステーション関連のプロパティーを管理するためのファイル (local.properties など) を作成する。
  • dev.properties ファイル内にある「開発」環境用のプロパティーを変更し、そのファイルをバージョン管理リポジトリーにコミットする。動的プロパティー (IP アドレスなど) は変更される可能性があるため、そのような変更が発生した場合、開発チームは必ずこのファイルを変更する必要があります。
  • テスターが使用する IP アドレス、ファイル、ディレクトリーは異なる可能性があるため、test.properties ファイルをテスター向けに、属性は同じで値が異なるプロパティーに変更する。

開発チームが行う構成は通常、これでは終わりません。組織の開発サイドは、「開発」環境と「テスト」環境に加え、他の環境も管理するのが一般的です。

従来の組織では、ソフトウェア・デリバリー・サイクルの一部として、開発チームから運用チーム (DBA、システム/運用担当、リリース・エンジニアリング担当など) にソフトウェア・パッケージが引き渡され、下流工程の環境にそのソフトウェアがデプロイされます。運用チームは以下の作業を行います。

  • stage.properties ファイル内にある「ステージング」環境用プロパティーを変更し、そのファイルをバージョン管理リポジトリーにコミットする。
  • prod.properties ファイル内にある「本番」環境用の同様のプロパティーを変更し、そのファイルをバージョン管理リポジトリーにコミットする。動的プロパティー (IP アドレスなど) は変更される可能性があるため、そのような変更が発生した場合、運用チームは必ずこのファイルを更新する必要があります。

私はかつて、プロパティーを階層構造にしているチームを見たことがあります。このチームでは、ローカル、環境 (通常少なくとも 4 つの環境プロパティー・ファイルがありますが、大抵はもっと多くあります)、アプリケーション、サブシステム、インスタンスのプロパティーを階層構造にしていました。インスタンスが何百もある場合には、何百もの異なるプロパティー・ファイルがあり、IP アドレス、ディレクトリー、その他のプロパティーが頻繁に変更されると、その変更を管理するのは事実上不可能でした。その結果、環境の問題やデプロイ時のエラーが頻繁に発生することとなり、多くの場合、そのトラブルシューティングは非常に困難でした。それは、変更管理の難題 (つまり誰が何をいつ変更したかの管理) がエラーの根本原因の特定を難しくしていたからです。

外部化されたプロパティー

従来の手法を使用する、適切に設計されたソフトウェア・システムでは、環境によって異なる可能性のあるプロパティーは、すべてプロパティー・ファイルに外部化されます。つまり、変更される可能性のある設定がアプリケーション・コード内にハードコーディングされることはありません。しかしプロパティーが増えれば増えるほど、デプロイ時にエラーが発生しやすくなります。こうしたエラーは、トラブルシューティングが難しく、それに伴う代償も大きいため、ユーザーにソフトウェアを提供するための「ビルド推進」プロセスの遅れにつながりがちです。

リスト 1 は簡単なプロパティー・ファイルの例です。

リスト 1. プロパティー・ファイル内で定義される構成
jboss.home=/usr/local/jboss
jboss.server.hostname=jenkins.example.com
jboss.server.port=8080
jboss.server.name=default

複雑なシステムでは、この例のようなプロパティー・ファイルに何百というプロパティーが含まれることは、ごく一般的です。またそうしたプロパティーは通常、開発環境、テスト環境、ステージング環境、本番環境で重複しており、本番用にソフトウェアを提供する際には何百、あるいは何千というプロパティーを管理することになります。

リスト 2 に、プロパティー・ファイルから値を取得する Java コード・スニペットを示します。

リスト 2. プロパティーを取得する Java コード・サンプル
public PropertyReader(final String name, final ClassLoader loader) {
  try {
    InputStream is = loader.getResourceAsStream(convertName(name));
    if (is != null) {
      properties.load(is);
      is.close();
    } else {
      throw new IOException("Couldn't find property file: "
        + convertName(name));
      }
    } catch (IOException problem) {
        System.out.println("Property Reader: problem initializing");
  }
}

このコードには、チームがプロパティーの管理で使用する最も一般的な手法が示されていますが、最近のソフトウェア・デリバリー・システムは、今までにないスケールで動作することができます。ハードウェアのコモディティー化が進み、仮想化やクラウド・コンピューティングが利用されるようになったことにより、ソフトウェア・システムを提供、管理する際には何百もの環境を起動 (または終了) する可能性があります。そうした状況に合わせて、構成管理手法もスケーラブルでなければなりません。そして (同じくハードウェアのコモディティー化、仮想化、クラウド・コンピューティングのおかげで)、それは可能なのです。


動的構成の仕組み

この記事で紹介する手法では、プロパティーを動的に設定、取得します。インフラストラクチャー自動化ツールを使用して環境を定義する場合 (「アジャイル DevOps: インフラストラクチャーの自動化」を参照) には、データベース名、ファイル名、ディレクトリー名などの構成項目を構成データベースに設定します。その設定はスクリプトによって行うことができます。なぜなら、インフラストラクチャー全体がゼロからスクリプトで作成され、そのスクリプトがバージョン管理リポジトリーにコミットされるからです。また、クラウド・インフラストラクチャーや仮想インフラストラクチャーでは、従来のインフラストラクチャーでは静的に設定されることが多い IP アドレスやドメイン名などの構成項目を動的に設定、取得することができます。

リスト 3 のコードは、SimpleDB (NoSQL) データベースに構成項目をロードする Ruby スクリプトです。

リスト 3. 構成項目を NoSQL データベースに動的に書き込むコード
AWS::SimpleDB.consistent_reads do
  domain = sdb.domains["stacks"]
  item = domain.items["#{opts[:itemname]}"]
  
  file.each_line do|line|
    key,value = line.split '='
    item.attributes.set(
      "#{key}" => "#{value}")
  end
end

ユーザー名とパスワード

Capistrano は、スクリプトによってデプロイメントを定義するための Ruby ベースのドメイン特化言語 (DSL) です。リスト 4 のコードは、ユーザーが一度定義したパラメーターに基づき、データベースのユーザー名とパスワードを定義する Capistrano スクリプトです。

リスト 4. ユーザー名とパスワードを設定する Capistrano のコード
set :dataSourceUsername do
  item = sdb.domains["stacks"].items["wildtracks-config"]
  item.attributes['dataSourceUsername'].values[0].to_s.chomp
end
set :dataSourcePassword do
  item = sdb.domains["stacks"].items["wildtracks-config"]
  item.attributes['dataSourcePassword'].values[0].to_s.chomp
end

CloudFormation

AWS (Amazon Web Services) の CloudFormation は、AWS リソースのプロビジョニングを記述するためのテンプレート言語です。CloudFormation は Chef や Puppet などのインフラストラクチャー自動化ツールと同様、JSON と宣言型手法を使用する DSL です。CloudFormation は、AWS リソースのプロビジョニングを定義するのに最も適した言語であり、他のインフラストラクチャー・リソースのプロビジョニングは Chef スクリプトや Puppet スクリプトで処理することができます。現状では、AWS 以外の主要なクラウド・プロバイダーは、リソースを定義するための CloudFormation のような DSL を提供していませんが、多くの場合はプロバイダーの API を使用することでプロバイダーのリソースを操作することができます。

スクリプトによってインフラストラクチャーを完全に制御できるため、データベースのユーザー名とパスワードを自動生成し、セキュアな構成データベースに格納することができます。

この構成は、ソフトウェア・デリバリー・システムの他の部分すべてに使用することができます。このデータベースにデータをプッシュすると、そのデータを上流環境で動的に取得したり、下流環境で使用したりすることができます。

IP アドレス

リスト 5 のコードは、外部 IP アドレスを動的に設定して関連付ける AWS CloudFormation の JSON スクリプトの一部です。

リスト 5. IP アドレスを動的に設定する CloudFormation のコード
"IPAddress" : {
  "Type" : "AWS::EC2::EIP"
},

"IPAssociation" : {
  "Type" : "AWS::EC2::EIPAssociation",
  "Properties" : {
    "InstanceId" : { "Ref" : "WebServer" },
    "EIP" : { "Ref" : "IPAddress" }
  }
},

このようなスクリプトは、関連する自動テストと共にバージョン管理リポジトリーにコミットすることができます。

ドメイン名

CloudFormation で記述したリスト 6 の JSON コードは、AWS の Route 53 サービスを使用してアプリケーションの A ドメイン・レコードを動的に設定します。

リスト 6. ドメインを設定する CloudFormation のコード
"JenkinsDNS" : {
  "Type" : "AWS::Route53::RecordSetGroup",
  "Properties" : {
    "HostedZoneName" : { "Fn::Join" : [ "", [ {"Ref" : "HostedZone"}, "." ]]},
    "RecordSets" : [
    {
      "Name" : { "Fn::Join" : ["", [ { "Ref" : "ApplicationName" }, ".", \
      { "Ref" : "HostedZone" }, "." ]]},
      "Type" : "A",
      "TTL"  : "900",
      "ResourceRecords" : [ { "Ref" : "IPAddress" } ]
    }]
  }
},

このスクリプトを使用すると、DNS (Domain Name Service) プロバイダーを使用してドメイン名を手動で構成するという、従来の方法を行う必要がなくなります。

データベース名

リスト 7 のコードは、DatabaseName というパラメーターを定義する CloudFormation スクリプトです。

リスト 7. データベース名を設定する CloudFormation のコード
"Parameters": {
  "DatabaseName": {
    "Description" : "The name of the database",
    "Type": "String"
  }
}

このスクリプトによって、アプリケーション用の新しいデータベースが作成されると、DatabaseName パラメーターはインフラストラクチャー・スクリプト (Puppet マニフェストなど) に渡されます。このスクリプト全体をバージョン管理リポジトリーにコミットし、自動テストを作成すれば、データベースにアクセス可能かどうかを検証することができます。

ポート

リスト 8 のコードは、環境 (およびアプリケーション) に対する外部ポートを設定します。

リスト 8. セキュリティー・グループ内のポートへのアクセスを設定する CloudFormation のコード
"FrontendGroup" : {
  "Type" : "AWS::EC2::SecurityGroup",
  "Properties" : {
    "GroupDescription" : "Enable SSH and access to Apache and Tomcat",
    "SecurityGroupIngress" : [
      {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : "0.0.0.0/0"},
      {"IpProtocol" : "tcp", "FromPort" : "8080", "ToPort" : "8080",\
       "CidrIp" : "0.0.0.0/0"},
	  {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", \
	    "CidrIp" : "0.0.0.0/0"}
    ]
  }      
},

参加してください

developerWorks の Agile transformation ゾーンでは、皆さん個人、あるいは皆さんの組織がアジャイル開発の原則に基づく基礎を固めるために役立つニュース、ディスカッション、トレーニングを提供しています。

この例で外部からアクセスできるポートは、ポート 22 (SSH アクセス用)、ポート 8080 (Apache Tomcat 用)、ポート 80 (Apache HTTP サーバー用) のみです。CIDR (Classless Inter-Domain Routing) 表記を使用することで、ネットワークへのアクセス、さらには個々のノードへのアクセスをさらに制限することもできます (「参考文献」を参照)。


動的構成にする

この記事では、ほとんどのソフトウェア・デリバリー・システムで静的に定義される構成は、動的に定義することが可能であること、またそうすべきであること、そしてそれにより、ターゲット環境ごとに構成を変更する必要がなくなり、環境を作成するために必要となる構成可能なプロパティーの数を大幅に減らせることを説明しました。

次回の記事では、クラウド内で継続的ソフトウェア・デリバリーを行うためのオープンソース・プラットフォームを紹介し、そのプラットフォームを実行するための基本的なステップ、デリバリー・パイプラインの使い方、そして環境をプロビジョニングするためのジョブの実行方法とデプロイメントの実行方法について説明します。

参考文献

学ぶために

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

  • IBM Tivoli Provisioning Manager: Tivoli Provisioning Manager により、物理サーバー、仮想サーバー、ソフトウェア、ストレージ、ネットワークの管理を自動化し、動的なインフラストラクチャーを実現することができます。
  • IBM Tivoli System Automation for Multiplatforms: Tivoli System Automation for Multiplatforms により、エンタープライズ規模のアプリケーションや IT サービスの高可用性と自動化を実現することができます。
  • IBM 製品の評価をご自分に最適な方法で行ってください。評価の方法としては、製品の評価版をダウンロードすることも、オンラインで製品を試してみることも、クラウド環境で製品を使用することもできます。また、SOA Sandbox では、数時間でサービス指向アーキテクチャーの実装方法を効率的に学ぶことができます。

議論するために

  • developerWorks コミュニティーに参加してください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者によるブログ、フォーラム、グループ、Wiki を調べることができます。
  • developerWorks の Agile Transformation community では、コミュニティーに参加している個人あるいは組織がアジャイル開発の原則に基づく基礎を固めるために役立つニュース、ディスカッション、トレーニングを提供しています。

コメント

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=DevOps, Open source
ArticleID=928950
ArticleTitle=アジャイル DevOps: 動的な構成
publish-date=05092013