DevOps 継続的デリバリへ継続性 を導入 - Oracle ·...

5
DevOps ORACLE.COM/JAVAMAGAZINE ///////////////////////////// JULY/AUGUST 2015 26 続的インテグレーション(CI)とは開 発手法の一種で、コードを定期的に 共有リポジトリへ統合(アップロード) することを開発者に求め、通常は 1 日数回の ペースでこの統合を行います。自動ビルドによ り、チェックインが行われるごとに検証が実行 されるため、チームは早期に問題を検出して修 正できます。自動ビルドの一環として、コード 品質チェック、単体テスト、統合テストも行わ れます。それに合格すると、ビルドされたバイ ナリはセントラル・リポジトリにアップロードさ れ、デプロイメントが可能になります。 継続的デリバリ(CD)とは、CI のさらに一 歩先を行くもので、ユーザー受入テスト(UAT) 環境を含むすべてのビルドとデプロイメントの ステップを自動化するものです。CI プロセスは ほとんどの組織に定着していますが、デプロイ メントを自動化するツールは十分であるとはい えません。 本記事では、Git、Maven、Nexus、 Jenkins、Private Chef など、オープン・ソー ス・ツールを使用して CD を実現する方法につ いて説明します。また、JBoss AS 6 EAP スタン ドアロン・インスタンスへ Web アプリケーショ ンをデプロイする方法も説明します。Web アプ リケーションは、Postgres データベースからデー タを読み込んで表示するものです。このアプリ ケーションは、Maven を使用してビルドを行い、 WAR ファイルにパッケージ化して Nexus リポジ トリにアップロードします。 注:本記事で紹介するコードの完全なリスト は、リスト用サイトからダウンロードできます。 コードによるインフラストラクチャのモデリング 最初のステップは、コードでインフラストラク チャをモデリングすることです。ここでは、オー プン・ソース・ツールである Chef を使用します。 このステップで、他のツールの作業の大部分が 自動化できます。本記事でモデリングするのは、 図1 に示す構成です。ご覧のとおり、前述した 要素の他に Chef サーバーが記載されています。 Chef サーバーについては、後ほど説明します。 Chef クライアントをインストールする追加のマ シンは、ノードと呼びます。 Chef のレシピは、DSL か Ruby のコードで 記述します。レシピには、構成情報が必要です。 一般的に使用されるのは、次の 4 つの主要要 素です。 Chefでデプロイメント環境を自動構築し、真の継続的デリバリを実現する ALAN FRYER 継続的デリバリへ継続性 を導入 図1.Chefの一般的なシステム構成 jenkins.c2b2.co.uk Jenkins Chef Client Knife Git Client Chef Client jboss.c2b2.co.uk JBoss Standalone chef.c2b2.co.uk Chef scm.c2b2.co.uk Git Repo Nexus

Transcript of DevOps 継続的デリバリへ継続性 を導入 - Oracle ·...

Page 1: DevOps 継続的デリバリへ継続性 を導入 - Oracle · 継続的インテグレーション(ci)とは開 発手法の一種で、コードを定期的に 共有リポジトリへ統合(アップロード)

DevOps

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// JULY/AUGUST 2015

26

継続的インテグレーション(CI)とは開発手法の一種で、コードを定期的に共有リポジトリへ統合(アップロード)

することを開発者に求め、通常は 1日数回のペースでこの統合を行います。自動ビルドにより、チェックインが行われるごとに検証が実行されるため、チームは早期に問題を検出して修正できます。自動ビルドの一環として、コード品質チェック、単体テスト、統合テストも行われます。それに合格すると、ビルドされたバイナリはセントラル・リポジトリにアップロードされ、デプロイメントが可能になります。継続的デリバリ(CD)とは、CI のさらに一歩先を行くもので、ユーザー受入テスト(UAT)環境を含むすべてのビルドとデプロイメントのステップを自動化するものです。CIプロセスはほとんどの組織に定着していますが、デプロイメントを自動化するツールは十分であるとはいえません。 本記事では、Git、Maven、Nexus、Jenkins、Private Chef など、オープン・ソース・ツールを使用してCDを実現する方法について説明します。また、JBoss AS 6 EAPスタンドアロン・インスタンスへWebアプリケーショ

ンをデプロイする方法も説明します。Webアプリケーションは、Postgres データベースからデータを読み込んで表示するものです。このアプリケーションは、Mavenを使用してビルドを行い、WARファイルにパッケージ化してNexusリポジトリにアップロードします。 注:本記事で紹介するコードの完全なリストは、リスト用サイトからダウンロードできます。

コードによるインフラストラクチャのモデリング最初のステップは、コードでインフラストラクチャをモデリングすることです。ここでは、オープン・ソース・ツールであるChef を使用します。このステップで、他のツールの作業の大部分が自動化できます。本記事でモデリングするのは、図 1に示す構成です。ご覧のとおり、前述した要素の他にChefサーバーが記載されています。Chef サーバーについては、後ほど説明します。Chefクライアントをインストールする追加のマシンは、ノードと呼びます。Chef のレシピは、DSL か Ruby のコードで記述します。レシピには、構成情報が必要です。一般的に使用されるのは、次の 4つの主要要素です。

Chefでデプロイメント環境を自動構築し、真の継続的デリバリを実現する ALAN FRYER

継続的デリバリへ継続性を導入

図1.Chefの一般的なシステム構成

jenkins.c2b2.co.uk

Jenkins

Chef Client

Knife

Git Client

Chef Client

jboss.c2b2.co.uk

JBoss Standalone

chef.c2b2.co.uk

Chef

scm.c2b2.co.uk

Git Repo

Nexus

Page 2: DevOps 継続的デリバリへ継続性 を導入 - Oracle · 継続的インテグレーション(ci)とは開 発手法の一種で、コードを定期的に 共有リポジトリへ統合(アップロード)

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// JULY/AUGUST 2015

27

■ クックブックには、レシピの Chef DSL や Ruby のコード、ライブラリ、ノードで実行すべきリソースや操作の定義が含まれています。Rubyのコード(ロジック)はクックブック、ロール、データ・バッグ、環境で定義される属性を参照します。

■ データ・バッグは、クックブック内のすべてのコードが使用するグローバル属性を定義しています。

■ 環境は、Chef が管理するノードに関連付けられており、クックブックやそのシステムに固有の属性を定義しています。クックブックはあるバージョンに「ピン留め」できるため、開発環境、テスト環境、本番環境にそれぞれ別のバージョンを適用できます。

■ ロールには、サーバーの目的を記述します。また、ノードに適用するレシピの実行リストや実行順序も定義しています。Chef サーバーは、あらゆる構成管理データをクックブック、環境、ロール、データ・バッグの属性として保存しています。通常、クックブックとロールには、環境によって変わることがない静的な属性を保存します。環境固有のプロパティは、環境で定義します。 環境、ロール、データ・バッグの属性は、Chefコンソールから作成するか、JSON形式のソース・ファイルで作成します。Chef が管理するすべてのサーバー(ノード)には、Chefクライア

ントをインストールしてHTTPSで Chef サーバーに接続できるよう構成する必要があります。図 1のノード jboss.c2b2.co.uk は Chef サーバー chef.c2b2.co.uk に登録されており、リスト1で定義されているC2B2Dev 環境が割り当てられています。

リスト1:{ "name":"C2B2Dev", "description":"", "cookbook_versions":{ }, "json_class":"Chef::Environment", "chef_type":"environment", "default_attributes":{ "jboss":{ "jboss_home":"/opt/jboss/jboss-eap-6.3", "jboss_install":"/opt/jboss", ...

jboss.c2b2.co.uk には、リスト2の JbossStandaloneロールも割り当てられています。

リスト2:{ "name":"JbossStandalone", "description":"", "json_class":"Chef::Role", "default_attributes":{ }, "override_attributes":{ }, "chef_type":"role", "run_list":[ "recipe[jboss6::installjboss]", "recipe[jboss6::adduser]", "recipe[jboss6::installpostgresmodule]", "recipe[jboss6::startstandalone]", "recipe[jboss6::configurestandalone]" ], "env_run_lists":{ }}

Chef には、knifeと呼ばれるコマンドライン・ユーティリティが付属しています。このユーティリティで Chef のオブジェクトと環境を管理します。サブコマンド knife ssh を使用すると、ノードのサブセットでSSHコマンドを(パラレルに)実行できます。実行するノードは Chefサーバー上の検索処理で決まるので、対象とする環境内の特定のロールを持つノードで Chefクライアントを実行できます。たとえば、次のknifeコマンド 1つで、JBoss のインストール、構成、Webアプリケーションのデプロイメントまで行うことができます。

knife ssh -x afryer "chef_environment:C2B2Dev AND role:JbossStandalone" "sudo -u root chef-client -l info"

knife sshコマンドは、Chef サーバーに問合せを行い、C2B2Dev 環

Chef サーバーは、あらゆる構成管理データをクックブック、環境、ロール、データ・バッグの属性として保存しています。

Page 3: DevOps 継続的デリバリへ継続性 を導入 - Oracle · 継続的インテグレーション(ci)とは開 発手法の一種で、コードを定期的に 共有リポジトリへ統合(アップロード)

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// JULY/AUGUST 2015

28

境で JbossStandaloneロールに関連付けられているノードのリストを返します。検索で見つかった各ノードで、ユーザー afryer によるSSHセッションが開始され、sudoでアクセス、実行されるChefクライアントを通して各処理が実行されます。Chefクライアントは Chef サーバーに接続し、ノードのデータセットの属性をノードに割り当てられた環境とクックブックの値で更新します。次に、C2B2Devロールの実行リストで定義されているレシピを実行します。レシピは、ノードの属性を参照し、アプリケーションのインストールと構成に使用する構成管理データを読み込みます。たとえば、次に示すのは、JBoss のホーム・ディレクトリを変数に読み込む処理です。

jboss_home = node['jboss']['jboss_home']

ここで使用する属性の値は、環境 C2B2Devで定義されています。前述のリスト1の最後に近い部分です。

CHEFコードの分析本記事の後半では、鍵となる操作をどのように指定しているかについて説明します。本文中に示しているのは、関連するコードの抜粋です。完全なリストは、本記事向けのリスト用サイトからダウンロードできます。JBoss のインストール:リスト3のレシピは、ユーザー jboss を作成し、Nexus からzipファイルとして保存されている JBoss EAP 6.3.0 バイナリをダウンロードし、インストール・ディレクトリに解凍するものです。このレシピでは、JBoss の実行ユーザーおよびインストール・ディレクトリの作成に必要なリソースをChef DSLで定義しています。JBoss の zipファイルは、remote_fileリソースにNexus Rest API の URLを指定してNexus からダウンロードしています。引数として、リポジトリ、グループ ID、アーチファクトID、バージョン、パッケージ形式を指定しています。executeリソースでは、zipファイルを解凍するLinuxコマンドを実行し、JBoss のディレクトリ構造の所有者をユーザー jboss に変更しています。ユーザーの追加:リスト4の adduserレシピは、executeリソースを使用してシェル・スクリプト$JBOSS_HOME/bin/add-user.sh を呼び出し、JBoss 管理コンソールを保護する目的で、管理ユーザーとパスワードを作成しています。Chef では、属性の暗号化はデータ・バッグの中でのみ行うことができます。そのため、パスワードのような機密性の高いデータは、暗号化したデータ・バッグに格納するようにします。データ・バッグを暗号化するため、最初に暗号化と復合化に使用する秘密鍵を作成します。Chefワークステーションで秘密鍵を作成するには、次

のコマンドを実行します。

openssl rand -base64 512 > /home/afryer/certs/c2b2_secret_key

このファイルを、Chefクライアントを実行しているすべてのノードにコピーします。暗号化データ・バッグを使用するレシピは、このファイルを参照する必要があります。暗号化データ・バッグは、次のコマンドで作成できます。

knife data bag create- -secret-file /home/afryer/certs/c2b2_secret_key bancs_dev_credentials c2b2

knife ツールに関連付けられているテキスト・エディタで、一時 JSONファイルをプレーン・テキストとして編集用に開きます。id 属性には、入力されたデータ・バッグ項目の名前が設定されています。暗号化する属性は、"attribute-name": "attribute-value"という形式でファイルに追加します。属性を新しく追加する場合は、カンマで区切ります。

{ "id":"c2b2", "mgmt_pwd":"password"}ファイルを保存してエディタを閉じると、暗号化されたデータ・バッグがサーバー上に作成されます。各環境について、認証情報を格納する暗号化データ・バッグを作成する必要があります。管理ユーザーmgm_pwdのパスワードは、リスト4Aのレシピでデータ・バッグから読み取ります。Postgresモジュールのインストール:リスト5の installpostgresmoduleレシピでは、JBoss の modulesフォルダに Postgres JDBCドライバをインストールしています。directoryリソースで$JBOSS_HOME/modules/postgres/mainフォルダを作成し、templateリソースでクックブック・ファイルmodule.xml(リスト6)をそのフォルダにコピーします。 JBoss Standaloneインスタンスの起動:リスト7の startstandaloneレシピは、executeリソースでシェル・スクリプト$JBOSS_HOME/bin/standaloe.sh(リスト7A)を実行し、JBoss Standaloneインスタンスをnohupモードで起動しています。

Page 4: DevOps 継続的デリバリへ継続性 を導入 - Oracle · 継続的インテグレーション(ci)とは開 発手法の一種で、コードを定期的に 共有リポジトリへ統合(アップロード)

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// JULY/AUGUST 2015

29

-bオプションと-Djboss.bind.address.management オプションにそれぞれノード属性 node['fqdn'] の値を設定することによって、管理アドレスとJBossサーバーが対象のサーバーのDNS名にバインドされます。 JBoss Standaloneインスタンスの設定:リスト8のconfigurestandaloneレシピでは、Postgres データソースの構成を行い、Nexus からアプリケーションWARファイルをダウンロードしてJBoss サーバーにデプロイしています。設定とデプロイメントは、稼働中のサーバーに対して JBoss CLI スクリプトを実行することによって行います。CLIスクリプト(リスト9)は、クックブック・テンプレートとして定義されています。このファイルは組込み Rubyテンプレートで、変数とテンプレート内部に記述されたロジックに基づいてCLIスクリプトを生成する仕組みになっています。テンプレートは次のリソース定義を使用して生成されます。この定義によって、ノードから読み込んだ変数をテンプレートに渡しています。

template cli_script do source "configure-standalone.cli.erb" variables( ds_jndi_name:"postgresDS", ds_pool_name:"postgresDS", db_host: node['jboss']['database_hostname'], db_port: node['jboss']['database_port'], db_name: node['jboss']['database_name'], db_user: node['jboss']['database_user'], db_password: creds["postgres"], jboss_install: jboss_install, artifact:"#{artifact_id}.war", version: version ) owner process_user group process_groupend

次に、executeリソースでシェル・スクリプト$JBOSS_HOME/bin/jboss-cli.sh を実行します。オプション --file=configure-standalone.cliが指定されているため、テンプレートから生成された CLIスクリプトが実行されます。

CHEFとJENKINS の統合Jenkins を実行しているサーバーには、Chefクライアントとknifeツールを構成する必要があります。このステップを行うためには、管理コンソールを使用してChef サーバーにユーザー jenkins を作成し、それを組織(今回の例では C2B2)と関連付ける必要があります。ユーザー用の秘密鍵を生成し、knife ツールの設定フォルダである/home/jenkins/.chef に保存します。また、Chef サーバーへの接続を構成するファイル knife.rbで、接続の認証に使用する秘密鍵の場所やローカル Chefリポジトリのクックブックのフォルダの場所を指定します(リスト10)。Chef の実行には、Jenkins Freestyle Project を使用します。ビル

ドが始まると、Chef のコードがGitリポジトリの特定のブランチからCHEF_ENVIRONMENTとCHEF_ROLE によって決まるビルド用ワークスペースにチェックアウトされます。チェックアウトされたコードには、リスト11のシェル・スクリプトが含まれています。これは、ビルドの一環として実行されます。 シェル・スクリプトは、ビルドに対して構成されているGitリポジトリ・

ブランチからチェックアウトしたクックブックをアップロードします。さらに、knife sshコマンドを実行して、スクリプトに渡される環境とロールに一致するノードで Chefクライアントを実行します。 Nexusリポジトリに格納されている JBoss インストーラとWebアプ

リケーションは、グループ ID、アーチファクトID、バージョンの 3つを指定してダウンロードします。Webアプリケーションのビルドは別のJenkinsプロジェクトによって行います。そのプロジェクトでは、Mavenを使用してビルドとパッケージ化を行い、パッケージ化したWARをNexus にリリースしています。

まとめ以上の作業によって、複数のノード環境へのアプリケーションのデプロイメントを自動化する仕組みができました。最終的には、コマンドラインを1度呼び出すだけでデプロイメントが完了するようになっています。Jenkins サーバーに knife ツールを設定すると、knife sshコマンドを起動するシェル・スクリプトを1つ実行するだけで、環境への自動デプロイメントを開始できます。テスト完了後に自動的に実行できるだけでなく、定期的に実行することや、随時手動で実行することも可能です。その結果、開発環境、テスト環境、UAT 環境で継続的デリバリを実現できます。一度構成してしまえば、Chef はアプリケーションのデプロイメントを

これで、複数のノー

ド環境へのアプリ

ケーションのデプロ

イメントを自動化す

る仕組みができま

した。コマンドライ

ンを1度呼び出す

だけでデプロイメン

トが完了します。

Page 5: DevOps 継続的デリバリへ継続性 を導入 - Oracle · 継続的インテグレーション(ci)とは開 発手法の一種で、コードを定期的に 共有リポジトリへ統合(アップロード)

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// JULY/AUGUST 2015

30

反復可能な作業として実行できるため、デプロイメント時間の大幅な短縮が可能です。開発チームやサポート・チームも付加価値のある作業に集中できるようになります。このアプローチは、複数の環境間で一貫性のある構成を提供する場合に適しています。手動でのデプロイメント時に起こりやすい構成エラーのデバッグに費やす時間も減らすことができます。レシピを注意深くデザインすれば、Chef をはじめとするソリューションを用い、新規プロジェクト向けの標準環境として、実証済みミドルウェア・スタック構成を使用する環境を迅速に構築することも可能です。こういった仕組みによって、優れた手法がすべてのプロジェクトに浸透すれば、構築するシステムの質は向上し、開発やサポートにかかるコストの削減にもつながります。</article>

Alan Fryer:12 年にわたって Java EEシステムを設計しており、Java EE のコンサルティング、トラブルシューティング、問題解析、パフォーマンス・チューニング、本番環境インフラストラクチャ・デザイン、システム管理の分野において豊富な経験を持つ。現在は、C2B2 の主席コンサルタントとして政府の大規模な部門の長期プロジェクトに携わっており、Java EEアプリケーションの開発とサポートを行うDevOps チームに対してミドルウェア関連のコンサルティングを行っている。