お問い合わせフォーム
(ウルシステムズ株式会社のBlueRabbitサイトへ )

1. 概要

このシリーズではマイクロサービスに必要となるAPIゲートウェイ機能のためのKong Community Editionの使い方を、ブラウザベースの管理ツールである「 Konga 」を利用しながら調べていきます。

マイクロサービスを登録する基本となる前回の「 Service & Route編 」に続き、今回はマイクロサービスをスケールアウトや冗長化するための仕組みである「Upstream」と「Target」の設定項目と手順についてです。

2. 環境

今回使用するKong、Konga、登録マイクロサービスついての詳細は以下の通りです。

なお、KongとKongaのインストール方法については省略しますが、「ServiceManager Online」(無料、近日提供)による自動構築も可能です。これは弊社BlueRabbitソリューションのマイクロサービス/サービスメッシュ化プラットフォームである NanaHoshi にも組み込まれています。

2.1. Kong

前回の「 Service & Route編 」と同じ。

マイクロサービスでは可用性とスケーラビリティが大切なのでデータベースにはApache Cassandraを選択しています。

2.2. Konga

こちらも前回の「 Service & Route編 」と同じです。

2.3. マイクロサービス

【メモ】

今回用にPythonで作成したサンプルプログラムです。ソースコードはGitHub上の こちら の「article02」に置いてあります。

標準モジュールのみで作成しており、Python 2.7で動作確認をしています。


とてもシンプルな仕様となっており、

http://[host_or_ip]:8000/macaddress

をGETメソッドで呼び出すと、そのサーバのMACアドレスを戻してくれるサンプルマイクロサービスになっています。

python macaddress.py

とすると起動して8000番ポートでリクエストを待ち受けます。

今回は2台のサーバでこのプログラムを実行してください。これによりKongがリクエストをこの2台に振り分けたことをMACアドレスで判定します。

3. スケールアウトや冗長化のための設定

基本的な概念は以下の通りです。

下図のように前回の「 Service & Route編 」のようなシンプルな構成では、1つの「Service」から見てマイクロサービスが直接1つ対応していましたが、これに代わって「Upstream」という仮想的なロードバランサを1つ対応付けます。

そしてこのUpstreamに「Target」として実際のマイクロサービスのサーバ群を登録しておくことで、リクエストの度にUpstreamが適切なTargetを選択し、スケールアウトや冗長化を実現できるようになります。


Upstreamのロードバランサーは「リングバランサ」という概念に基づいて、リクエストを登録されたTargetへ振り分けています。

リングバランサは多数の「slot」の集まりで、Upstream登録時に指定する「slots」がその総数となります。この中からランダムに選ばれた1つのslotに対して、Target登録時に指定する「weight」のその合計に対する割合に応じて1つのTargetに割り当てられます。これをまだ割り当てられていないslotが無くなるまで繰り返すことで、リング内の全てのslotがweightに応じた割合で各Targetに割り当てられます。

下の概念図では24個のslotと3種類のTargetでリングが構成されています。Targetは3種類ともweightが等しいため、24個のslotは8個ずつ均等にTarget-A、Target-B、Target-Cに割り当てられています。もしそれぞれのweightが20、30、10の場合、その合計(つまり20+30+10=60)に対する割合に応じてそれぞれ8個、12個、4個のslotが割り当てられます。(この計算時に端数が生じる場合は個数を若干増減させることで総数が合うように調整されます)

この時あるリクエストが来ると、リクエストに含まれる情報を入力としてハッシュ値が計算され、そのハッシュ値をslot合計数(つまり「slots」)で割った余りを使用してどのslotを選択するかが決まり、そのslotに紐づけられているTargetが示すマイクロサービスサーバにリクエストが転送されるようになります。例えばリクエストから計算したハッシュ値が38の場合、38を24で割った余りである14に対応するslotが選択され、これに紐付けられているTarget-Aにリクエストが転送されます。

3.1. Upstream の登録

Konga画面左側にある「UPSTREAMS」メニューをクリックするとUpstream一覧画面が表示されます。


ここで「+ CREATE UPSTREAM」ボタンをクリックすると下図のようなUpstream登録モーダルが表示されます。


各入力フィールドついては以下の表にまとめました。参考までに、直接KongのAPIを使用してUpstreamを登録する際のパラメータに対応する項目である場合は「APIパラメータ名」列に記載しています。

(Active health checks及びPassive health checksのフィールド群はUpstreamで管理するマイクロサービスの健全性をプローブを使用してActiveに又はプローブを使用せずにPassiveに確認するための設定フィールドですが、これらについては別途記事にすることにして今回は使用しません)

フィールド 必須 Kong パラメータ 内容
Name name Upstreamのhost名。
半角英数と「.-」のいずれかのみ入力可。ここで登録した値をServiceのhostに登録することになります。
Slots × slots リングバランサのslotの数。
デフォルトは1000。10~65535の範囲で設定可能。このUpstreamに登録するTargetの数×100が推奨値となっています。
Hash on × hash_on リングバランサでのslot選択時のハッシュ値計算方法を選択します。
デフォルトはnone。選択肢はnone、consumer、ip、header。それぞれの内容は以下の通り。
 none:
  ハッシュ値を計算せずにラウンドロビン方式でslotを選択します。
 consumer:
  リクエストに付随するConsumerの内部キーを元にハッシュ値が計算されます。
 ip:
  リクエストの送信元IPアドレスを元にハッシュ値が計算されます。
 header:
  リクエストのヘッダーに格納されている値を元にハッシュ値が計算されます。

※ consumer、ip、headerでは対象の値を特定できない場合はHash fallbackの指定内容に処理が引き継がれます。
※ konga-0.11.2ではheaderを選択して登録しようとすると「Hashing on 'header', but no header name provided」と表示されて登録できません。headerを選択する場合、Kong Admin APIの仕様上は「hash_on_header」というハッシュ値計算の元となる値を格納しているヘッダ名を入力するパラメータを指定する必要がありますが、Kongaのモーダルではこれを指定するするためのフィールドが用意されていないため、現状ではheaderが設定できません。
Hash fallback × hash_fallback 「Hash on」で指定した(none以外の)方法でハッシュ値を計算できなかった場合に、ここで指定した方法でハッシュ値を計算します。
仕様はHash onと同じ。headerについても同様の理由で現実的に選択不可になっています。もしこのHash fallbackでもハッシュ値を計算できなかった場合はnodeを選択した時と同様(つまりラウンドロビン)となります。

今回は下図のように指定しました。Targetを2つ登録する予定のため、推奨値に従ってSlotsは200にしています。

Name: MacAddrServiceUpstream

Slots: 200

Hash on: ip

Hash fallback: none


最後に「SUBMIT UPSTREAM」ボタンをクリックしてUpstreamの登録完了となり、Upstream一覧画面には登録されたUpstreamが表示されるようになります。

登録したUpstreamの詳細を見たい又は編集したい場合は、対象行の「DETAILS」をクリックすることで詳細・編集画面が表示されます。

3.2. Target の登録

Upstreamを登録したので、次はこのUpstreamに紐付けるTargetの登録です。

先ほどのUpstream詳細画面にある「Targets」をクリックしてTarget一覧画面を表示させます。


次に「ADD TARGET」ボタンをクリックして以下のような登録モーダルを表示させます。


各入力フィールドついては以下の表にまとめました。参考までに、直接KongのAPIを使用してTargetを登録する際のパラメータに対応する項目である場合は「APIパラメータ名」列に記載しています。

フィールド 必須 Kong パラメータ 内容
Target target このTargetに紐付けるマイクロサービスのアドレス(ホスト名又はIPアドレス)及びポート番号。
デフォルトのポート番号は8000。host名がDNSのSRVレコードで解決された場合、portはそのDNSレコードに定義されている値が継承されます。
 入力値の例) 
  IPアドレス版 => 127.0.0.1:8080
  ホスト名版  => example.com:8888
ホスト名がDNSのSRVレコードで解決される場合、ポート番号はそのSRVレコードで定義されている値で上書きされます。
Weight × weight Targetのウェイト。
デフォルトは100。このTargetが属するするUpstreamに登録されている全てのTargetのWeight値の合計を分母とした時の割合に応じて、UpstreamのSlot数が割り当てられます。ホスト名がDNSのSRVレコードで解決される場合、そのSRVレコードで定義されている値で上書きされます。

今回は下図のように指定しました。Weightはデフォルトのままにしています。

Target: (下図ではマスクしていますが、ご利用環境に合わせてmacaddress.pyを動作させているホスト名/IPアドレスを指定してください)

Weight: 100


最後に「SUBMIT TARGET」ボタンをクリックしてTargetの登録の完了となり、Target一覧画面には登録されたTargetが表示されるようになります。

今回はマイクロサービスのサーバを2台用意したため、同様にして2つ目も登録してください。


TargetのWeightの修正方法は特殊で、登録時と同じ「ADD TARGET」ボタンから行います。表示されるモーダルのTargetフィールドに変更したいTargetと同じフィールド値を指定した上で、Weightを変更したものを登録する手順になります。

これは、UpstreamがTargetの変化を履歴をとして管理しており、最新のもののみがリングバランサの構成に使われるようになっているためです。


削除も同様の理由でWeightを0にしたTargetを登録する手順になるのですが、KongaではTarget一覧画面の「DELETE」ボタンをクリックすることで削除できます。

なお、Kong Admin APIではkong-0.10.1から削除用APIが用意されており、内部では上記のWeightを0にする処理が行われるようになっています。

3.3. Service、Routeの登録

最後にService及びRouteについては前回の Service & Route編 の3.2と3.3の手順とほぼ同じですが、ServiceのHostフィールドには使用したいUpstreamのNameフィールドの値を指定する必要があります。

今回の内容に合わせて下図のように指定しました。

■Service

Name: MacAddrService

Description: MACアドレスを取得するAPI

Tags: mac address, port 8000

Protocol: 8000

Path: /macaddress

Retries: 5

Connect timeoiut: 60000

Write timeout: 60000

Read timeout: 60000


■Route

Paths: /macaddress

Methods: GET

Strip Path: YES

Preserve Host: NO

Protocols: http


4. 動作確認

以上で準備が整ったので、実際にUpstreamのロードバランサによる振り分け動作の確認を行います。

Kongサーバにリクエストを1000回送ることで取得したMACアドレスを判別して、2つのTargetにそれぞれどのように振り分けられたかを調べます。

この時、Hash onが

none

ip

の2パターン用意し、さらにそれぞれにおいて2つのTargetのWeightが

100と100

100と50

100:0

の3パターンで計測します。


■Hash on = none

ラウンドロビンでリクエストが振り分けられるため、各Targetのリクエスト数はweightの比率通りになっていることが分かります。

Target 100:100 100:50 100:0
サーバ1 500 670 1000
サーバ2 500 330 0

■Hash_on = ip

リクエスト送信元IPアドレスが変わらないため、ハッシュ値はリクエスト毎に変わらず、Weightの値に依らず常に同じTargetへ振り分けられ、Weightが0になった(つまりそのTargetを無効にした)段階で残りのサーバへ切り替わっていることが分かります。

Target 100:100 100:50 100:0
サーバ1 0 0 1000
サーバ2 1000 1000 0