[Coherence, Docker] Coherence Clusters on Docker Swarm

原文はこちら。
https://blogs.oracle.com/developers/coherence-clusters-on-docker-swarm

Javaのインメモリ・データグリッドは、通常数多くのJVMでクラスタを構成し、データをクラスタ間に分散させるという共通の機能を有しています。JVMが起動時のクラスタ探索にあたっては、マルチキャストを使いますが、これはDockerコンテナ内では機能しません。そのため、インメモリ・データグリッド製品は別の探索機構にフォールバックする必要があります。通常、これはクラスタメンバー・アドレスのリストを手作業で注入したり、別の探索機構を参照したりします。

Oracle CoherenceはDocker Storeからご利用いただけます。
Oracle Coherence
http://store.docker.com/images/oracle-coherence-12c
Docker SwarmでOracle Coherenceクラスタを実行する場合、以前よりもずっとクラスタの探索が簡単になっています。起動時にアドレスリストを挿入する必要がありますが、これはクラスタの開始前にクラスタメンバーのコンテナのIPアドレスのすべてまたは一部を知っている、という点に頼っています。Dockerでは、実行時にコンテナの固定IPアドレスを指定できるため実現できます。とはいえ、アドレス割り当てを気にする必要がないとより柔軟なのは明らかです。

クラスタメンバーが起動すると、クラスタメンバー内のアドレスを検索する必要がありますが、これはクラスタIPアドレスを保持する外部データソースに頼っています。これを実現するDockerサービスの検出に利用可能なアプリケーションがありますが、インフラストラクチャに追加するもう1つの可動要素です。シンプルなアプリケーション・インフラストラクチャであるほど、変なことにならなくなって、より簡単になります。

以前のOracle Coherence on Dockerのブログエントリでは、Coherenceメンバーが複数のDockerホストでクラスタを構成できるようにするために、ホスト・ネットワーキングまたはオーバーレイ・ネットワークを使用する必要がある、と記載しました。
Oracle Coherence on Docker
http://thegridman.com/coherence/oracle-coherence-on-docker/
マルチキャストが可能なホスト・ネットワーキングは最も簡単な解決策ですが、常に利用できるとは限りません。確かに現代のクラウド環境では使えないことがあります。これにより、オーバーレイネットワークを使うことになるわけですが、それに伴い、サービス発見の問題が発生します。しかし、DockerのSwarm Modeが導入されたことで、Oracle Coherenceを使用するコンテナのクラスタ構成がずっと簡単になりました。
Swarm mode overview
https://docs.docker.com/engine/swarm/

Coherence Cluster Discovery

既に触れたように、CoherenceはJVMが起動時にクラスタメンバを探索するための複数の方法を有しています。最も簡単な方法は、マルチキャストですが、これは常に利用可能というわけではなく、確かにDockerコンテナ内では利用できません。もう一つの方法は、well-know-addressingです。これは1個以上のIPアドレスのリストをJVMに渡すというもので、コンテナ内部ではこの方法を使う必要があります。

Well known addressは2方法で提供できます。Coherenceの操作構成ファイル(通常はオーバーライドファイルと呼ばれます)を使って管理します。
<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
          xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config coherence-operational-config.xsd">
 
    <cluster-config>
        <unicast-listener>
            <well-known-addresses>
              … wka configuration …
            </well-known-addresses>
        </unicast-listener>
    </cluster-config>
</coherence>
well-known-addresses要素の内容は、アドレスの提供方法によって異なり、2種類の方法があります。
一つは、カスタムアドレスプロバイダという、com.tangosol.net.AddressProviderを実装したもので、通常は3rdパーティソースからアドレスリストを取得し、必要に応じてそれらを返すカスタムクラスを使います。例えば、私が関わっていたプロジェクトでは、コンテナ管理にMarathon/Mesosを使用しており、このプロジェクトでは、Coherenceクラスタ内のコンテナのIPアドレスを取得するためにMarathon APIに照会するカスタムアドレスプロバイダを使用しています。このアドレスプロバイダの構成例は以下の通りです。
<cluster-config>
        <unicast-listener>
            <well-known-addresses>
                <address-provider>
                    <!-- Specify AddressProvider class name -->
                    <class-name>com.oracle.coherence.clustering.MarathonAddressProvider</class-name>
                </address-provider>
            </well-known-addresses>
        </unicast-listener>
    </cluster-config>
もう一つの方法は、アドレスを直接overridesファイルに書き込むことです。
<cluster-config>
        <unicast-listener>
            <well-known-addresses>
                <!-- Specify one or more IP addresses or host names where the cluster members are running -->
                <address>foo.oracle.com</address>
                <address>bar.oracle.com</address>
            </well-known-addresses>
        </unicast-listener>
    </cluster-config>
実際、Oracle CoherenceのWKA構成では、単一のアドレスがSystemプロパティを介して渡されるように設定されています。 以下はその設定例です。
<cluster-config>
        <unicast-listener>
            <well-known-addresses>
                <address system-property="coherence.wka"></address>
            </well-known-addresses>
        </unicast-listener>
    </cluster-config>
これはつまり単一のWKAの値を実行時に設定でき、この値を使ってクラスタメンバを特定するため、最初のクラスタメンバを当該サーバで起動する必要があります。具体的には以下のような感じです。
$ java -cp ${COHERENCE_HOME}/lib/coherence.jar \
  -Dcoherence.wka=foo.oracle.com \
  com.tangosol.net.DefaultCacheServer
この場合、各Coherenceメンバはfoo.oracle.com上のメンバを探し、このメンバを使って残るクラスタメンバを探します。
これはつまり、Coherenceに設定を追加せずに、すぐにクラスタを起動でき、一つのアドレスを渡すことができ、このアドレスを持つサーバ上のCoherenceメンバは、新しいJVMクラスタメンバが他のメンバを探し始める際に連絡をうけとる、ということです。当該サーバーに問題がある場合を除いて、これでOKです。例えば、クラッシュした場合にはWKAリストが無効なIPアドレスを指しているため、新しいクラスタメンバを開始できません。これを回避するには、通常、構成ファイルに複数のWKAアドレスを指定します。

Coherence Clusters on Docker Swarm

DockerにSwarm Modeとサービスが導入されたことで、結果としてコンテナ内からDNSを使用してサービスのメンバを検索できるようになりました。Oracle CoherenceがWKA名を使用する方法の1つは、これらの名前がDNSを介して複数のアドレスに解決された場合、CoherenceはそれらのすべてのアドレスをWKAリスト用に使用します。したがって、デフォルトのCoherence構成で単一のホスト名しか指定できない上記の場合、DNSを使用してそのホスト名を複数のサーバーに解決できるのであれば、これは制限とはなり得ません。これこそが、Docker Swarm Modeを使ってサービスを構成するコンテナのためにできることです。DockerでサービスとしてCoherenceクラスタを起動すると、特別なホスト名を使用して、そのサービスを構成するコンテナのIPアドレスをすべて検索できます。Dockerのドキュメントには、Swarm Mode Networkingの仕組みの説明があります。
Attach services to an overlay network
https://docs.docker.com/engine/swarm/networking/
上記URLから、Oracle Coherenceにとって重要なことは、全てのサービスはDNS名を有しており、この名前を使ってIPアドレスの検索に利用できる、ということです。Dockerのドキュメントのサンプルをおさらいすると、どれほど簡単かがわかります。

まず、サービスが利用するオーバーレイ・ネットワークを作成します。
$ docker network create \
  --driver overlay \
  --subnet 10.0.9.0/24 \
  my-network
基本的なコンテナを持つシンプルなサービスを起動します。
$ docker service create \
  --name my-busybox \
  --network my-network \
  busybox \
  sleep 3000
サービスをリストアップすると、my-busyboxサービスが実行中であることがわかるはずです。
$ docker service ls
ID            NAME        MODE        REPLICAS  IMAGE
tpsqpgwh423c  my-busybox  replicated  1/1       busy box
サービスを3個のコンテナにスケールアップすることができます。
$ docker service scale my-busybox=3
my-busybox scaled to 3
実行中のコンテナをリストアップすると、my-busyboxサービスを構成するコンテナが確認できるはずです。
$ docker ps --format "{{.ID}}: {{.Names}}"
443d3ea90e62: my-busybox.2.mx5nq93n8w7z80ndfkqd1zmhj
81893dfcdaf8: my-busybox.3.nd4lp1z7iliys8wsplusxkq0a
19d4fdded3dd: my-busybox.1.xewffdq29h7pomx8jhw9xib14
では、nslookupをコンテナ内で使ってtasks.my-busyboxのアドレスを検索します(訳注:nslookupでよいのかどうかはさておき…)
$ docker exec my-busybox.1.xewffdq29h7pomx8jhw9xib14 nslookup tasks.my-busybox
Server:    127.0.0.11
Address 1: 127.0.0.11
 
Name:      tasks.my-busybox
Address 1: 10.0.9.4 my-busybox.2.mx5nq93n8w7z80ndfkqd1zmhj.my-network
Address 2: 10.0.9.5 my-busybox.3.nd4lp1z7iliys8wsplusxkq0a.my-network
Address 3: 10.0.9.3 19d4fdded3dd
各コンテナに1つずつ、3個のアドレスが返っていることがわかります。Docker Storeから利用可能なCoherence Dockerイメージをそのまま使用し、まったく同じコンセプトでOracle Coherenceクラスタを作成できます。ところで、このイメージはOracle LinuxとオフィシャルなOracle Server JREイメージの上に構築されています。
Put Your Containers on a Diet with Oracle Linux
https://blogs.oracle.com/developers/put-your-containers-on-a-diet-with-oracle-linux
Oracle Java 8 SE (Server JRE)
https://store.docker.com/images/oracle-serverjre-8
コンテナエントリポイントとして実行されるイメージ内のシェルスクリプトは、デフォルトでストレージが有効化されたcom.tangosol.net.DefaultCacheServerインスタンスを開始します。シェルスクリプトを使うと、環境変数を設定することで種々のパラメータを渡すこともできます。その1つが、well-known-addressの値を設定するCOH_WKAです。
$ docker pull store/oracle/coherence:12.2.1.2
$ docker service create  --name coh-cluster \
  --network my-network \  
  -e COH_WKA=tasks.coh-cluster \
  store/oracle/coherence:12.2.1.2
サービス起動時にサイズを指定していなかったので、coh-clusterサービスは1個のメンバだけで動作しています。docker psコマンドを実行すると、コンテナを1個のみ表示します。
$ docker ps --format "{{.ID}}: {{.Names}}"
c4917b7c9b9b: coh-cluster.1.tpz4kby4nwpxi0n89herpfsyp
コンテナのログを見ると、1個のメンバを持つ新たなクラスタがあることがわかります。
$ docker logs coh-cluster.1.tpz4kby4nwpxi0n89herpfsyp
ログは以下のような感じで出力されます。
WellKnownAddressList(
  10.0.9.3
  )
MasterMemberSet(
  ThisMember=Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
    Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
  OldestMember=Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
    Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
  ActualMemberSet=MemberSet(Size=1
    Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
      Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
    )
  MemberId|ServiceJoined|MemberState|Version
    1|2017-04-14 11:12:04.36|JOINED|12.2.1.1.0
  RecycleMillis=1200000
  RecycleSet=MemberSet(Size=0
    )
  )
ホスト名 task.coh-service という1個のメンバを持つWKAリストによって単一のコンテナを名前解決したことがわかります。

では、サービスをスケールし、複数のクラスタメンバを持つようにしましょう。
$ docker service scale coh-cluster=3
coh-cluster scaled to 3
この場合、3個のコンテナがあるはずです。
$ docker ps --format "{{.ID}}: {{.Names}}"
50db2c5b76ed: coh-cluster.2.r79i1q03q0umup2b8geovc6m0
8f4159035dd1: coh-cluster.3.i8wdao099zbwa5tdeslx9y2bz
c4917b7c9b9b: coh-cluster.1.tpz4kby4nwpxi0n89herpfsyp
3個目のコンテナのログを見てみると…
$ docker logs coh-cluster.3.i8wdao099zbwa5tdeslx9y2bz
3個のメンバがクラスタに存在しています。
WellKnownAddressList(
  10.0.9.3
  10.0.9.4
  10.0.9.5
  )
MasterMemberSet(
  ThisMember=Member(Id=2, Timestamp=2017-04-14 11:18:01.087, Address=10.0.9.5:42521, MachineId=686, 
    Location=machine:8f4159035dd1,process:1, Role=CoherenceServer)
  OldestMember=Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
    Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
  ActualMemberSet=MemberSet(Size=2
    Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
      Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
    Member(Id=2, Timestamp=2017-04-14 11:18:00.072, Address=10.0.9.4:39874, MachineId=231, 
      Location=machine:df36591c7ab6,process:1, Role=CoherenceServer)
    Member(Id=3, Timestamp=2017-04-14 11:18:01.087, Address=10.0.9.5:42521, MachineId=686, 
      Location=machine:8f4159035dd1,process:1, Role=CoherenceServer)
  )
  MemberId|ServiceJoined|MemberState|Version
    1|2017-04-14 11:12:04.36|JOINED|12.2.1.1.0,
    2|2017-04-14 11:18:00.072|JOINED|12.2.1.1.0,
    3|2017-04-14 11:18:01.087|JOINED|12.2.1.1.0
  RecycleMillis=1200000
  RecycleSet=MemberSet(Size=0
    )
  )
WKAリストに3つのアドレスがすべて含まれていることがわかります。そんなわけで、Swamを使ってCoherenceクラスタを拡張・縮小することができ、Swamの組み込みDNSのおかげで、CoherenceのWKAはうまく機能します。Docker Storeにあるセットアップ手順には、種々の設定やオプションを使い、Oracle CoherenceのDockerイメージを実行することに関する詳細記述があります。

Container Cloud Serviceを使って、Oracle Cloud PlatformでDockerやCoherenceを試すことができます。
Oracle Container Cloud Service
https://cloud.oracle.com/ja_JP/container
以下のURLにアクセスしてアカウントを取得し、300ドルの無料クレジットを取得してください(訳注:日本はこのエントリ執筆時点では無料クレジットの対象外です)。
トライアルページ
https://cloud.oracle.com/ja_JP/tryit

0 件のコメント:

コメントを投稿