Chefを使ってWebLogic Server 動的クラスタを構成してみた


# 概要
構成済みのWebLogicドメインに対して、Chefを利用して動的クラスタを作成してみました。

以下の投稿の中でWebLogic ドメインの基本的な構成をChefを利用して自動的に作成できるように整えてきました。

-[Chefを使ってWebLogic Serverの基本ドメインを作ってみた](http://qiita.com/shinyay/items/8ea3c25b0160ec91d666)
-[Chefを使ってWebLogic Serverのマシンを構成してみた](http://qiita.com/shinyay/items/33ecd87d48c522dd668d)

この状態では、次の図のように管理サーバのインスタンスのみがある状態です。

![Domain_Machine-Admin.png](https://bytebucket.org/shinyay/images-for-blog/raw/fea1d6c8a70d8b90d9072b4edfaf982ed4ad87a7/qiita/160730_chef-oracle-weblogic-machine/Domain_Machine-Admin.png)

冗長構成など考慮した可用性構成とはなっておらず、いわゆる単体開発用の環境となっています。
そこで、可用性をもたせるようにサーバインスタンスの冗長化が行われている構成をとりたいと思います。

## アプリケーションサーバの冗長構成（クラスタリング）
ところで、アプリケーションサーバの冗長構成とはどういうものか、ご存知でしょうか。簡単に説明をしておきます。

クラスタリングとは、文字通り（Cluster：群れ、集団）アプリケーションサーバのインスタンスを集団化することです。
複数のアプリケーションサーバをひとまとめにし、そのサーバ上で稼働するアプリケーションを使用するユーザーから見ると、１台のアプリケーションサーバに見えるようにする技術になります。

利用する事により次のようなメリットがあります。

- 高い可用性
    - 複数インスタンスで１台のサーバのように振る舞うため、いずれかがダウンしたとしても全体として止まることはありません。
- スケーラブルな構成
    - クラスタ構成をとった場合の性能は、サーバ群全体の総和での性能になります。そのため、サーバを追加する事で容易な性能向上が可能になります。 
- 負荷分散
    - 複数台あるサーバインスタンスに対して、リクエストを分散して振り分ける事が可能です。
- セッション（状態）のレプリケーション
    - アプリケーションの状態をセッション情報というものとしてアプリケーションサーバ上に保持します。このセッション情報をサーバ群でコピーして保有するため、どこかのサーバがダウンしても別のサーバがセッション情報のコピーを保有しているので、サービスをそのまま継続する事が可能です。

## WebLogic Server - 動的クラスタ
クラスタという技術について簡単に説明しました。
WebLogic Serverでは、前述のような通常のクラスタ構成に加えて、自動でサーバインスタンスを生成してスケールアップが可能な**動的クラスタ**という仕組みを提供しています。

- [動的クラスタ](http://docs.oracle.com/cd/E72987_01/wls/CLUST/dynamic_clusters.htm)

この動的クラスタをChefを使って自動で定義するレシピを作成します。

## 今回作成するRecipe
- 動的クラスタを構成する
    - 初期クラスタサイズや最大クラスタサイズ数をパラメータ設定可能とする

# Recipe. 動的クラスタの構成
以下の3種類のファイルを作成します。
- Recipe
- Template
- Attribute

## [recipe] WLSTスクリプトファイルを生成
テンプレート(**create_dynamic-cluster.py.erb**)からWLSTスクリプトファイルを生成し、オーナー/グループ権限を設定します。

```recipes/create-dynamic-cluster.rb
template "#{node['weblogic-domain']['response_file_dir']}/create_#{node['weblogic-domain']['domain_name']}_dynamic-cluster.py" do
  source "create_dynamic-cluster.py.erb"
  owner node['weblogic-domain']['owner']
  group node['weblogic-domain']['group']
  mode '0755'
end
```

## [recipe] WLSTにより動的クラスタを構成
WLSTを起動して先に作成したスクリプトファイルを実行します。

```recipes/create-dynamic-cluster.rb
execute "wlst.sh create_#{node['weblogic-domain']['domain_name']}_dynamic-cluster.py" do
  command <<-EOH
    . #{node['weblogic-domain']['wls_home']}/server/bin/setWLSEnv.sh
    #{node['weblogic-domain']['oracle_common']}/common/bin/wlst.sh #{node['weblogic-domain']['response_file_dir']}/create_#{node['weblogic-domain']['domain_name']}_dynamic-cluster.py
  EOH
  user node['weblogic-domain']['user']
  group node['weblogic-domain']['group']
  action :run
  not_if { File.open("#{node['weblogic-domain']['domain_home']}/#{node['weblogic-domain']['domain_name']}/config/config.xml").read().include?("#{node['weblogic-domain']['cluster_name']}") }
end
```

既に動的クラスタを作成している場合には、再度作成シーケンスをに入らないように実行チェックを以下の箇所で実施しています。

```recipes/create-dynamic-cluster.rb
  not_if { File.open("#{node['weblogic-domain']['domain_home']}/#{node['weblogic-domain']['domain_name']}/config/config.xml").read().include?("#{node['weblogic-domain']['cluster_name']}") }
```

- **not_if**
    - 後続の条件が真の場合には、アクションを実施ししない
- **File.open().read().include?()**
    - Rubyスクリプトで、クラスタ名がWebLogic Serverの構成情報（config.xml）に含まれているか検証を実施している

## [template] WLSTスクリプトファイルのひな型
WLSTスクリプトの中では以下のフローを取ります。

1. WLS管理サーバに接続
2. 編集モードに設定
3. サーバテンプレートを定義
4. 動的クラスタを定義
5. 動的クラスタのサイズを定義
6. 反映
7. 管理サーバから切断

以下、Templateファイルより抜粋

```tempalates/default/create_dynamic-cluster.py.erb
connect('<%= node['weblogic-domain']['admin_user'] %>','<%= node['weblogic-domain']['admin_password'] %>','t3://localhost:<%= node['weblogic-domain']['listen_port'] %>')

edit()

print '########## CREATING Dynamic Cluster in <%= node['weblogic-domain']['domain_name'] %> DOMAIN ##########'
startEdit()
print '#################### CREATING Server Template ####################'
cd('/')
cmo.createServerTemplate('<%= node['weblogic-domain']['cluster_name'] %>-Template')
cd('/ServerTemplates/<%= node['weblogic-domain']['cluster_name'] %>-Template')
cmo.setListenPort(7100)
cd('/ServerTemplates/<%= node['weblogic-domain']['cluster_name'] %>-Template/SSL/<%= node['weblogic-domain']['cluster_name'] %>-Template')
cmo.setListenPort(8100)
cd('/ServerTemplates/<%= node['weblogic-domain']['cluster_name'] %>-Template')
cmo.setMachine(getMBean('/Machines/<%= node['weblogic-domain']['machine_name'] %>'))
print '#################### CREATED Server Template ####################'
cd('/')
cmo.createCluster('<%= node['weblogic-domain']['cluster_name'] %>')
cd('/Clusters/<%= node['weblogic-domain']['cluster_name'] %>')
cmo.setClusterMessagingMode('unicast')
cd('/ServerTemplates/<%= node['weblogic-domain']['cluster_name'] %>-Template')
cmo.setCluster(getMBean('/Clusters/<%= node['weblogic-domain']['cluster_name'] %>'))
cd('/Clusters/<%= node['weblogic-domain']['cluster_name'] %>/DynamicServers/<%= node['weblogic-domain']['cluster_name'] %>')
cmo.setServerTemplate(getMBean('/ServerTemplates/<%= node['weblogic-domain']['cluster_name'] %>-Template'))
cmo.setDynamicClusterSize(<%= node['weblogic-domain']['cluster_size'] %>)
cmo.setMaxDynamicClusterSize(<%= node['weblogic-domain']['cluster_max_size'] %>)
cmo.setCalculatedListenPorts(true)
cmo.setCalculatedMachineNames(false)
cmo.setCalculatedListenPorts(true)
cmo.setServerNamePrefix('<%= node['weblogic-domain']['cluster_name'] %>-')
activate()

print '########## CREATED Dynamic Cluster in <%= node['weblogic-domain']['domain_name'] %> DOMAIN ##########'

disconnect()
```

## [attribute] デフォルト値の設定
動的クラスタの構成実施の直後に初期サイズで設定している数の管理対象サーバが定義されます。
そこで、簡単に任意のサイズに設定が行えるようにWLSTスクリプトでサイズを設定する箇所をパラメータ化しておきます。

```tempalates/default/create_dynamic-cluster.py.erb
cmo.setDynamicClusterSize(<%= node['weblogic-domain']['cluster_size'] %>)
cmo.setMaxDynamicClusterSize(<%= node['weblogic-domain']['cluster_max_size'] %>)
```

```attributes/default.rb
default['weblogic-domain']['cluster_name'] = 'app-cluster'
default['weblogic-domain']['cluster_size'] = '2'
default['weblogic-domain']['cluster_max_size'] = '8'
```

# Chefの実行イメージ
![chef-oracle-weblogic-dynamic-cluster.gif](https://bytebucket.org/shinyay/images-for-blog/raw/42675083ff252e9f84ddd1adf72ca14dc48a228b/qiita/160807_chef-oracle-weblogic-dynamic-cluster/160807_chef-oracle-weblogic-dynamic-cluster.gif)

# まとめ
動的クラスタをWebLogic ドメインに追加し、マシンを設定しました。
![Domain_DynamicCluster.png](https://bytebucket.org/shinyay/images-for-blog/raw/42675083ff252e9f84ddd1adf72ca14dc48a228b/qiita/160807_chef-oracle-weblogic-dynamic-cluster/Domain_DynamicCluster.png)

これにより作成したクラスタや、管理対象サーバはノードマネージャの管理配下に追加されます。
そしてノードマネージャ経由でのライフサイクル管理が可能となるため、管理サーバ経由、つまり管理コンソール経由でクラスタを制御する事が可となります。