クラスタリングについて

全体のワークロードを複数のサーバーに分散するため、 Incus はクラスタリングモードで動かせます。 このシナリオでは、クラスタメンバーとそのインスタンスの設定を保持する同じ分散データベースを任意の台数の Incus サーバーで共有します。 Incus クラスタは incus クライアントまたは REST API を使って管理できます。

クラスタメンバー

Incus クラスタは 1 台のブートストラップサーバーと少なくともさらに 2 台のクラスタメンバーから構成されます。 クラスタは状態を 分散データベース に保管します。これは Raft アルゴリズムを使用して複製されるCowsql データベースです。

2 台のメンバーだけでもクラスタを作成することは出来なくはないですが、少なくとも 3 台のクラスタメンバーを強く推奨します。 このセットアップでは、クラスタは少なくとも 1 台のメンバーの消失に耐えることができ、分散状態の過半数を確立できます。

クラスタを作成する際、 Cowsql データベースは 3 番目のメンバーがクラスタにジョインするまではブートストラップサーバー上でのみ稼働します。 そして 2 番目と 3 番目のサーバーはデータベースの複製を受信します。

詳細は クラスタを形成するには を参照してください。

メンバーロール

3 台のメンバーのクラスタでは、すべてのメンバーがクラスタの状態を保管する分散データベースを複製します。 クラスタのメンバーがさらに増えると、一部のメンバーだけがデータベースを複製します。 残りのメンバーはデータベースへアクセスしますが、複製はしません。

任意の時点で、選出されたリーダーが 1 つ存在し、他のメンバーの健康状態をモニターします。

データベースを複製する各メンバーは voterstand-by のロールを持ちます。 クラスタリーダーがオフラインになると voter の 1 つが新しいリーダーに選出されます。 voter のメンバーがオフラインになると stand-by メンバーが自動的に voter に昇格します。 データベース (そしてクラスタ) は voter の過半数がオンラインである限り利用可能です。

以下のロールが Incus クラスタメンバーに割り当て可能です。 自動のロールは Incus 自身によって割り当てられユーザーによる変更は出来ません。

ロール

自動

説明

database

yes

分散データベースの voter メンバー

database-leader

yes

分散データベースの現在のリーダー

database-standby

yes

分散データベースの stand-by(voter ではない)メンバー

event-hub

no

内部 Incus イベントへの交換ポイント(hub)(最低 2 つは必要)

ovn-chassis

no

OVN ネットワークのアップリンクゲートウェイの候補

voter メンバーのデフォルトの数(cluster.max_voters)は 3 です。 stand-by メンバーのデフォルトの数(cluster.max_standby)は 2 です。 この設定では、クラスタを稼働したまま一度に最大で 1 つの voter メンバーの電源を切ることができます。

詳細は クラスタを管理するには を参照してください。

オフラインメンバーと障害耐性

クラスタメンバーがダウンして設定されたオフラインの閾値を超えると、ステータスはオフラインと記録されます。 この場合、このメンバーに対する操作はできなくなり、すべてのメンバーの状態変更を必要とする操作もできなくなります。

オフラインのメンバーがオンラインに戻るとすぐに操作が再びできるようになります。

オフラインになったメンバーがリーダーそのものだった場合、他のメンバーは新しいリーダーを選出します。

サーバーを再びオンラインに復旧できないあるいはしたくない場合、クラスタからメンバーを削除 できます。

応答しないメンバーをオフラインと判断する秒数はcluster.offline_threshold設定で調整できます。 デフォルト値は 20 秒です。 最小値は 10 秒です。

オフラインのメンバーからインスタンスを自動的に退避するには、cluster.offline_threshold設定をゼロでない値に設定してください。

詳細はクラスタを復旧するにはを参照してください。

Failure domains

オフラインになったメンバーにロールを割り当てる際に、どのクラスタメンバーを優先するかを指示するために failure domain を使用できます。 たとえば、現在データベースロールを持つクラスタメンバーがシャットダウンした場合、 Incus はデータベースロールを同じ failure domain 内の別のクラスタメンバーがあればそれに割り当てようとします。

クラスタメンバーの failure domain を更新するには、incus cluster edit <member> コマンドを使って failure_domain プロパティを default から他の文字列に変更します。

メンバー設定

Incus クラスタメンバーは一般的に同一のシステムと想定されています。 それはクラスタにジョインするすべての Incus サーバーはブートストラップサーバーとストレージプールとネットワークについて同一の設定を持つ必要があるということです。

少し異なるディスクの順序やネットワークインターフェースの名前付けのようなことに対応するため、ストレージとネットワークに関連してメンバー固有のいくつかの設定が例外的に用意されています。

クラスタ内にそのような設定が存在する場合、追加するサーバーにはそれらの設定に対する値を提供する必要があります。 たいていの場合、これはインタラクティブな incus admin init コマンドで実行され、ユーザーにストレージやネットワークに関連する設定の値の入力を求めます。

通常これらの設定には以下のものが含まれます:

  • ストレージプールのソースデバイスとサイズ

  • ZFS プール、 LVM thin pool、または LVM ボリュームグループの名前

  • ブリッジネットワークの外部インターフェースと BGP の next-hop

  • 管理された physical または macvlan ネットワークの親のネットワークデバイス名

詳細は クラスタのストレージを設定するにはクラスタのネットワークを設定するには を参照してください。

事前に質問を調べたい(スクリプトでの自動化に有用)場合、 /1.0/cluster API エンドポイントをクエリしてください。 これは incus query /1.0/cluster あるいは他の API クライアントを使って実行できます。

イメージ

デフォルトでは、 Incus はデータベースメンバーと同じ数のクラスタメンバーにイメージを複製します。 通常これはクラスタ内で最大 3 つのコピーを持つことを意味します。

障害耐性とイメージがローカルで利用できる確率を改善するためこの数を増やすことができます。 そのためには、cluster.images_minimal_replica 設定を変更してください。 すべてのクラスタメンバーにイメージをコピーするには-1という特別な値を使用できます。

クラスタグループ

Incus のクラスタではクラスタグループにメンバーを追加できます。 これらのクラスタグループは、すべての利用可能なメンバーのサブセットに属するクラスタメンバー上で、インスタンスを起動するのに使用できます。 たとえば、GPU を持つすべてのメンバーからなるクラスタメンバーを作って、GPU が必要なすべてのインスタンスをこのクラスタグループ上で起動できます。

デフォルトでは、すべてのクラスタメンバーは default グループに属します。

詳細は クラスタグループをセットアップするには特定のクラスタメンバー上でインスタンスを起動する を参照してください。

インスタンスの自動配置

クラスタのセットアップでは各インスタンスはクラスタメンバーの 1 つの上で稼働します。 インスタンスを起動する際、特定のクラスタメンバー、クラスタグループをターゲットにするか、あるいは Incus に自動的にどれかのクラスタメンバーに割り当てさせることもできます。

デフォルトでは、自動的な割り当てはインスタンス数が一番少ないクラスタメンバーを選択します。 複数のメンバーが同じインスタンス数の場合は、それらの 1 つがランダムで選ばれます。

しかし、この挙動を scheduler.instance 設定で制御することもできます:

  • クラスタメンバーの scheduler.instanceall に設定されると、以下の条件でこのクラスタメンバーが選ばれます:

    • インスタンスが --target を指定せずに作成され、かつクラスタメンバーのインスタンス数が最小である。

    • インスタンスがこのクラスタメンバー上で稼働するようにターゲットされた。

    • インスタンスがこのクラスタメンバーが所属するクラスタグループのメンバー上で稼働するようにターゲットされ、かつクラスタメンバーがそのクラスタグループの他のメンバーと比べてインスタンス数が最小である。

  • クラスタメンバーの scheduler.instancemanual に設定されると、以下の条件でこのクラスタメンバーが選ばれる:

    • インスタンスがこのクラスタメンバー上で稼働するようにターゲットされた。

  • クラスタメンバーの scheduler.instancegroup に設定されると、以下の条件でこのクラスタメンバーが選ばれる:

    • インスタンスがこのクラスタメンバー上で稼働するようにターゲットされた。

    • インスタンスがこのクラスタメンバーが所属するクラスタグループのメンバー上で稼働するようにターゲットされ、かつクラスタメンバーがそのクラスタグループの他のメンバーと比べてインスタンス数が最小である。

インスタンス配置スクリプトレット

Incus では埋め込まれたスクリプト(スクリプトレット)を使って自動的なインスタンス配置を制御するカスタムロジックを使用できます。 この方法は、組み込みのインスタンス配置機能よりも柔軟性が高いです。

インスタンス配置スクリプトレットはStarlark言語 (Python のサブセット)で記述する必要があります。 スクリプトレットは、Incus がインスタンスをどこに配置するかを知る必要があるたびに呼び出されます。 スクリプトレットは、配置されるインスタンスに関する情報と、インスタンスをホストできる候補のクラスタメンバーに関する情報を受け取ります。 スクリプトレットからクラスタメンバー候補の状態と利用可能なハードウェアリソースについての情報を要求することもできます。

インスタンス配置スクリプトレットはinstance_placement関数を以下のシグネチャで実装する必要があります:

instance_placement(request, candidate_members):

  • requestは、scriptlet.InstancePlacement の展開された表現を含むオブジェクトである。このリクエストには、projectおよびreasonフィールドが含まれています。reasonは、newevacuation、またはrelocationのいずれかである。

  • candidate_membersは、api.ClusterMember エントリを表すクラスタメンバーオブジェクトのlistである。

たとえば:

def instance_placement(request, candidate_members):
    # 情報ログ出力の例。これは Incus のログに出力されます。
    log_info("instance placement started: ", request)

    # インスタンスのリクエストに基づいてロジックを適用する例。
    if request.name == "foo":
        # エラーログ出力の例。これは Incus のログに出力されます。
        log_error("Invalid name supplied: ", request.name)

        fail("Invalid name") # エラーで終了してインスタンス配置を拒否します。

    # 提供された第1候補のサーバーにインスタンスを配置する。
    set_target(candidate_members[0].server_name)

    return # インスタンス配置を進めるために空を返す。

スクリプトレットは Incus に適用するためにはinstances.placement.scriptletグローバル設定に設定する必要があります。

たとえばスクリプトレットがinstance_placement.starというファイルに保存されている場合、Incus には以下のように適用できます:

cat instance_placement.star | incus config set instances.placement.scriptlet=-

Incus に現在適用されているスクリプトレットを見るにはincus config get instances.placement.scriptletコマンドを使用してください。

スクリプトレットでは(Starlark で提供される関数に加えて)以下の関数が利用できます:

  • log_info(*messages): infoレベルで Incus のログにログエントリを追加する。messagesは 1 つ以上のメッセージの引数。

  • log_warn(*messages): warnレベルで Incus のログにログエントリを追加する。messagesは 1 つ以上のメッセージの引数。

  • log_error(*messages): errorレベルで Incus のログにログエントリを追加する。messagesは 1 つ以上のメッセージの引数。

  • set_target(member_name): インスタンスが作成されるべきクラスタメンバーを設定する。member_nameはインスタンスが作成されるべきクラスタメンバーの名前。この関数が呼ばれなければ、Incus は組み込みのインスタンス配置ロジックを使用する。

  • get_cluster_member_resources(member_name): クラスタメンバーのリソースについての情報を取得する。api.Resourcesの形式でリソースについての情報を含むオブジェクトを返す。member_nameはリソース情報を取得する対象のクラスタメンバーの名前。

  • get_cluster_member_state(member_name): クラスタメンバーの状態を取得する。api.ClusterMemberStateの形式でクラスタメンバーの状態を含むオブジェクトを返す。member_nameは状態を取得する対象のクラスタメンバーの名前。

  • get_instance_resources(): インスタンスが必要とするリソースについての情報を取得する。scriptlet.InstanceResourcesの形式でリソース情報を含むオブジェクトを返す。

注釈

オブジェクト内のフィールド名は対応する Go の型の JSON フィールド名と同じです。