LINSTOR - linstor

LINSTORはオープンソースのソフトウェアデファインドストレージのソリューションで、DRBDでレプリケートされたストレージボリュームを管理するのによく使われます。シンプルな運用にフォーカスしながらも高可用性でかつ高性能なボリュームを提供します。

LINSTORはそれ自身では配下のストレージは管理せず、代わりにZFSやLVMなどの他のコンポーネントを使ってブロックデバイスをプロビジョニングします。これらのブロックデバイスは次にDRBDでレプリケーションされて、フォールトトレランスとノードのストレージの能力にかかわらず任意のクラスターノードでボリュームをマウントできるようにします。ボリュームはDRBDカーネルモジュールを使ってレプリケートされるので、レプリケーションのデータパスは完全にカーネル空間内にとどまり、ユーザー空間で実装されるソリューションと比べてオーバーヘッドを低減できます。

用語

LINSTORクラスターは2つのメインコンポーネントから構成されます:コントローラーサテライトです。LINSTORコントローラーはデータベースを管理しクラスターの状態と設定を追跡し続けます。一方、サテライトはストレージを提供しクラスター間でボリュームをマウントできるようにします。クライアントはコントローラーとのみ対話し、コントローラーはユーザーのリクエストを満たすために複数のサテライトにまたがる操作を調整する責任を持ちます。

LINSTORは内部の概念にいくぶんオブジェクト指向なアプローチをとっています。これは概念が階層的な性質を持ち、下位レベルのオブジェクトが上位レベルのオブジェクトからプロパティを継承することにも見て取れます。

LINSTORはストレージプールという概念を持ちます。これはLINSTORで使用できる物理ストレージを使ってボリュームを作成します。ストレージプールは(LVMやZFSなどの)バックエンドドライバー、ストレージプールをもつクラスターノードとストレージプール自身あるいはバックエンドストレージに適用できるプロパティを定義します。

LINSTORではリソースはインスタンスで使用できるストレージユニットの表現です。リソースはほとんどの場合DRBDでレプリケートされたブロックデバイスです。その場合そのデバイスの1つのレプリカを表しています。リソースはリソース定義にグルーピングでき、これはこれのすべての子のリソースで継承される共通のプロパティを定義します。同様にリソースグループはそれらの子の定義に適用される共通のプロパティを定義します。またリソースグループは指定のリソース定義にいくつのレプリカを作成し、度のストレージプールを使い、レプリカを異なるアベイラビリティゾーンに分散させるか、などの配置ルールも定義します。LINSTORとやりとりする通常の方法は希望のプロパティを持つリソースグループを定義し、次にそこからリソースをスポーニングさせます。

Incusのlinstorドライバー

注釈

LINSTORはサテライトノード間でボリュームを移動することとマウントすることしかできません。このため、Incusのすべてのクラスタメンバーがボリュームに確実にアクセスできるようにするため、すべてのIncusノードはLINSTORサテライトノードでもあるようにしなければなりません。言い換えると、incusサービスが稼働する各ノードではlinstor-satelliteサービスも動かすべきです。

しかし、これはIncusノードが必ずストレージも提供しなければならないというわけではないことに注意してください。Incusノードに「ディスクレス」なサテライトをデプロイすることでストレージ用のノードと計算用のノードを分離してLINSTORを使うこともできます。ディスクレスなノードはストレージは提供しませんが、DRBDデバイスをマウントしネットワーク越しにIOを実行できます。

他のストレージドライバーとは異なり、このドライバーはストレージシステムをセットアップせず、あなたがLINSTORクラスターを既にインストール済みであることを前提としています。ドライバーはstorage.linstor.controller_connectionオプションがIncusで使われるLINSTORコントローラーのエンドポイントに設定されることを要求します。

このトライバーはリモートとローカル両方のストレージを提供できるという点でも他のドライバーと挙動が異なります。ボリュームのディスクありのレプリカがノード上で利用可能な場合、遅延を減らすため読み書きはローカルで実行されます(ですが書き込みはレプリカに同期的にレプリケーションされる必要があるため、ネットワーク遅延の影響はあります)。同時に、ディスクレスレプリカはすべてのIOをネットワーク越しに行い、物理ストレージのあるなしにかかわらず任意のノード上でボリュームをマウントし使えるようにします。これらのハイブリッドな能力によりLINSTORは必要な際はボリュームをクラスターノード間で移動する柔軟性を持ちながらも低遅延なストレージを提供できます。

Incusのlinstorドライバーはリソースグループを使ってリソースを管理とスポーンします。次の表はIncusとLINSTORの概念のマッピングを表しています:

Incusの概念

LINSTORの概念

ストレージプール

リソースグループ

ボリューム

リソース定義

スナップショット

スナップショット

IncusはLINSTORリソースグループの完全な制御を持っていることを前提とします。 このため、IncusのLINSTORリソースグループ内にIncusで所有されてないエンティティは決して作ってはいけません。作るとIncusが削除してしまうかもしれないからです。

リソースを管理する際、IncusはLINSTORサテライトノードがどのIncusノードに対応するかを決定できる必要があります。デフォルトではIncusはノード名がLINSTORのノード名に一致する(例えばincus cluster listlinstor node listが同じノード名を表示する)ことを想定しています。Incusがスタンドアロンのサーバーとして動いている(クラスターではない)場合、ホスト名がノード名として使われます。IncusとLINSTORでノード名が一致しない場合、各Incusノードでstorage.linstor.satellite.nameを適切なLINSTORサテライトノード名に設定できます。

制限

linstorドライバーは以下の制限があります:

インスタンス間でのカスタムボリュームの共有

content type filesystemがあるカスタムストレージボリュームは通常異なるクラスタメンバー上の複数のインスタンスで共有できます。 しかし、LINSTORドライバーはcontent type filesystemを持つボリュームをDRBDでレプリケートされたデバイス上にファイルシステムを持つことで「シミュレート」しているため、カスタムボリュームは一度に1つのインスタンスにしか割り当てられません。

Incusインストール環境間でのリソースグループの共有

複数のIncusインストール環境間で同じLINSTORリソースグループを共有するのはサポートされていません。

より古いスナップショットの復元

LINSTORは最新のスナップショット以外の復元はサポートしていません。 しかし、古いスナップショットから新しいインスタンスを作ることはできます。 この方法により特定のスナップショットがあなたの必要とするものを含んでいるかを確認することができます。 正しいスナップショットを特定したら、新しいスナップショットを削除してあなたが欲しいスナップショットが最新のスナップショットにしてから復元できます。

別の方法として、復元の際にIncusがより新しいスナップショットを自動で破棄するように設定することもできます。 そうするには、linstor.remove_snapshots設定オプションをボリューム(あるいは対応するvolume.linstor.remove_snapshots設定をプール内のすべてのボリュームのストレージプールに)設定します。

設定オプション

以下の設定オプションがlinstorドライバーを使うストレージプールとそれらのプール内のストレージボリュームで利用できます。

ストレージプール設定

drbd.auto_add_quorum_tiebreaker

LINSTORが必要に応じて自動的にディスクレスリソースを作ってクオラムのタイブレーカーとして振る舞わせることを許可するかどうか(リソースグループに適用される)

Key: drbd.auto_add_quorum_tiebreaker
Type:

bool

Default:

true

Scope:

global

drbd.auto_diskful

ノード上のストレージが利用可能な場合にプライマリのディスクレスリソースがディスクフルに変換されるまでの期間を表す文字列(リソースグループに適用される)

Key: drbd.auto_diskful
Type:

string

Default:
Scope:

global

drbd.on_no_quorum

クオラムが失われた際に使用されるDRBDポリシー(リソースグループに適用される)

Key: drbd.on_no_quorum
Type:

string

Default:
Scope:

global

linstor.raw.*

設定する追加のLINSTORプロパティー。例えば、BCache/PoolNamelinstor.raw.BCache/PoolNameとエンコードされます。

Key: linstor.raw.*
Type:

string

Scope:

global

linstor.resource_group.name

ストレージプールで使用されるLINSTORリソースグループ

Key: linstor.resource_group.name
Type:

string

Default:

incus

Scope:

global

linstor.resource_group.place_count

リソースグループ内のリソースのために作成されるべきディスクフルレプリカの数。すでにボリュームがあるプールでこのオプションの値を増やすと、LINSTORはすべての既存のリソースが新しい値に合致するように新しくディスクフルレプリカを作成することになります

Key: linstor.resource_group.place_count
Type:

int

Default:

2

Scope:

global

linstor.resource_group.storage_pool

サテライトノード上にリソースが配置されるストレージプール

Key: linstor.resource_group.storage_pool
Type:

string

Default:
Scope:

global

linstor.volume.prefix

LINSTORが管理するボリュームの内部名に使われる接頭辞。ストレージプール作成後は変更不可

Key: linstor.volume.prefix
Type:

string

Default:

incus-volume-

Scope:

global

source

LINSTORストレージプール名。linstor.resource_group.nameのエイリアス。これとエイリアスのどちらか一方を使うか同じ値を設定してください。

Key: source
Type:

string

Default:

incus

Scope:

global

volatile.pool.pristine

作成時にプールが空だったかどうか

Key: volatile.pool.pristine
Type:

string

Default:

true

Scope:

global

Tip

これらの設定に加えて、ストレージボリューム設定のデフォルト値を設定できます。 ストレージボリュームのデフォルト値を変更する を参照してください。

ストレージボリューム設定

block.create_options

ボリュームをフォーマットする際にファイルシステム作成ツールに渡す追加のオプション

Key: block.create_options
Type:

string

Default:

volume.block.create_optionsと同じ

Condition:

コンテントタイプfilesystemのブロックベースのボリューム

block.filesystem

ストレージボリュームのファイルシステム: btrfs, ext4 または xfs (未指定の場合 ext4)

Key: block.filesystem
Type:

string

Default:

volume.block.filesystemと同じ

Condition:

コンテントタイプfilesystemのブロックベースのボリューム

block.mount_options

ブロックベースのファイルシステムボリュームのマウントオプション

Key: block.mount_options
Type:

string

Default:

volume.block.mount_optionsと同じ

Condition:

コンテントタイプfilesystemのブロックベースのボリューム

drbd.auto_add_quorum_tiebreaker

LINSTORが必要に応じて自動的にディスクレスリソースを作ってクオラムのタイブレーカーとして振る舞わせることを許可するかどうか(リソースグループに適用される)

Key: drbd.auto_add_quorum_tiebreaker
Type:

bool

Default:

true

Condition:
drbd.auto_diskful

ノード上のストレージが利用可能な場合にプライマリのディスクレスリソースがディスクフルに変換されるまでの期間を表す文字列(リソースグループに適用される)

Key: drbd.auto_diskful
Type:

string

Default:
Condition:
drbd.on_no_quorum

クオラムが失われた際に使用されるDRBDポリシー(リソースグループに適用される)

Key: drbd.on_no_quorum
Type:

string

Default:
Condition:
initial.gid

インスタンス内のボリュームの所有者のGID

Key: initial.gid
Type:

int

Default:

volume.initial.gidと同じか0

Condition:

コンテントタイプfilesystemのカスタムボリューム

initial.mode

インスタンス内のボリュームのモード

Key: initial.mode
Type:

int

Default:

volume.initial.modeと同じか711

Condition:

コンテントタイプfilesystemのカスタムボリューム

initial.uid

インスタンス内のボリュームの所有者のUID

Key: initial.uid
Type:

int

Default:

volume.initial.uidと同じか0

Condition:

コンテントタイプfilesystemのカスタムボリューム

linstor.raw.*

設定する追加のLINSTORプロパティー。例えば、BCache/PoolNamelinstor.raw.BCache/PoolNameとエンコードされます。

Key: linstor.raw.*
Type:

string

Scope:

global

linstor.remove_snapshots

必要に応じてスナップショットを削除するか

Key: linstor.remove_snapshots
Type:

bool

Default:

volume.linstor.remove_snapshotsと同じかfalse

Condition:
security.shared

複数のインスタンスでのボリュームの共有を有効にする

Key: security.shared
Type:

bool

Default:

volume.security.sharedと同じかfalse

Condition:

カスタムブロックボリューム

security.shifted

ID シフトオーバーレイを有効にする (複数の分離されたインスタンスによるアタッチを許可する)

Key: security.shifted
Type:

bool

Default:

volume.security.shiftedと同じかfalse

Condition:

カスタムボリューム

security.unmapped

ボリュームへのIDマッピングを無効にする

Key: security.unmapped
Type:

bool

Default:

volume.security.unmappedと同じかfalse

Condition:

カスタムボリューム

size

ストレージボリュームのサイズ/クォータ

Key: size
Type:

string

Default:

volume.sizeと同じ

Condition:
snapshots.expiry

新しく作ったスナップショットをいつ削除するかを制御(1M 2H 3d 4w 5m 6y のような式を期待)

Key: snapshots.expiry
Type:

string

Default:

volume.snapshots.expiryと同じ

Condition:

カスタムボリューム

この値は新しく作ったスナップショットの有効期限を算出するのに使います。 スナップショットが作られた日時にこの値が加算され、結果のタイムスタンプがスナップショットの個別の有効期限として保管されます。 この値を変更しても、変更後に作られたスナップショットのみに影響します。既存のスナップショットの有効期限は変更されません。

サポートされる単位はS(秒)、M(分)、H(時)、d(日)、w(週)、m(月) and y(年)です。 Mが分を意味し、mが月であることに注意してください。 それぞれの単位は1度だけ指定でき、月と年は固定の日数ではなくカレンダーの月として計算されます。

snapshots.expiry.manual

新しく作ったスナップショットをいつ削除するかを制御(1M 2H 3d 4w 5m 6y のような式を期待)

Key: snapshots.expiry.manual
Type:

string

Default:

volume.snapshots.expiry.manualと同じ

Condition:

カスタムボリューム

この値は新しく作ったスナップショットの有効期限を算出するのに使います。 スナップショットが作られた日時にこの値が加算され、結果のタイムスタンプがスナップショットの個別の有効期限として保管されます。 この値を変更しても、変更後に作られたスナップショットのみに影響します。既存のスナップショットの有効期限は変更されません。

サポートされる単位はS(秒)、M(分)、H(時)、d(日)、w(週)、m(月) and y(年)です。 Mが分を意味し、mが月であることに注意してください。 それぞれの単位は1度だけ指定でき、月と年は固定の日数ではなくカレンダーの月として計算されます。

snapshots.pattern

スナップショットの名前を表す Pongo2 テンプレート文字列 (スケジュールされたスナップショットと名前無しのスナップショットで使用) [1]

Key: snapshots.pattern
Type:

string

Default:

volume.snapshots.patternと同じかsnap%d

Condition:

カスタムボリューム

snapshots.schedule

Cron 表記 (<minute> <hour> <dom> <month> <dow>)、またはスケジュールエイリアスのカンマ区切りリスト(@hourly, @daily, @midnight, @weekly, @monthly, @annually, @yearly)、または自動スナップショットを無効にする場合は空文字(デフォルト)

Key: snapshots.schedule
Type:

string

Default:

volume.snapshots.scheduleと同じ

Condition:

カスタムボリューム