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 listとlinstor node listが同じノード名を表示する)ことを想定しています。Incusがスタンドアロンのサーバーとして動いている(クラスターではない)場合、ホスト名がノード名として使われます。IncusとLINSTORでノード名が一致しない場合、各Incusノードでstorage.linstor.satellite.nameを適切なLINSTORサテライトノード名に設定できます。
制限¶
linstorドライバーは以下の制限があります:
- インスタンス間でのカスタムボリュームの共有
content type
filesystemがあるカスタムストレージボリュームは通常異なるクラスタメンバー上の複数のインスタンスで共有できます。 しかし、LINSTORドライバーはcontent typefilesystemを持つボリュームをDRBDでレプリケートされたデバイス上にファイルシステムを持つことで「シミュレート」しているため、カスタムボリュームは一度に1つのインスタンスにしか割り当てられません。- Incusインストール環境間でのリソースグループの共有
複数のIncusインストール環境間で同じLINSTORリソースグループを共有するのはサポートされていません。
- より古いスナップショットの復元
LINSTORは最新のスナップショット以外の復元はサポートしていません。 しかし、古いスナップショットから新しいインスタンスを作ることはできます。 この方法により特定のスナップショットがあなたの必要とするものを含んでいるかを確認することができます。 正しいスナップショットを特定したら、新しいスナップショットを削除してあなたが欲しいスナップショットが最新のスナップショットにしてから復元できます。
別の方法として、復元の際にIncusがより新しいスナップショットを自動で破棄するように設定することもできます。 そうするには、
linstor.remove_snapshots設定オプションをボリューム(あるいは対応するvolume.linstor.remove_snapshots設定をプール内のすべてのボリュームのストレージプールに)設定します。
設定オプション¶
以下の設定オプションがlinstorドライバーを使うストレージプールとそれらのプール内のストレージボリュームで利用できます。
ストレージプール設定¶
drbd.auto_add_quorum_tiebreakerLINSTORが必要に応じて自動的にディスクレスリソースを作ってクオラムのタイブレーカーとして振る舞わせることを許可するかどうか(リソースグループに適用される)
| Key: | drbd.auto_add_quorum_tiebreaker |
| Type: | bool |
| Default: |
|
| Scope: | global |
| Key: | drbd.auto_diskful |
| Type: | string |
| Default: | |
| Scope: | global |
| Key: | drbd.on_no_quorum |
| Type: | string |
| Default: | |
| Scope: | global |
| Key: | linstor.raw.* |
| Type: | string |
| Scope: | global |
| Key: | linstor.resource_group.name |
| Type: | string |
| Default: |
|
| Scope: | global |
linstor.resource_group.place_countリソースグループ内のリソースのために作成されるべきディスクフルレプリカの数。すでにボリュームがあるプールでこのオプションの値を増やすと、LINSTORはすべての既存のリソースが新しい値に合致するように新しくディスクフルレプリカを作成することになります
| Key: | linstor.resource_group.place_count |
| Type: | int |
| Default: |
|
| Scope: | global |
| Key: | linstor.resource_group.storage_pool |
| Type: | string |
| Default: | |
| Scope: | global |
| Key: | linstor.volume.prefix |
| Type: | string |
| Default: |
|
| Scope: | global |
| Key: | source |
| Type: | string |
| Default: |
|
| Scope: | global |
| Key: | volatile.pool.pristine |
| Type: | string |
| Default: |
|
| Scope: | global |
Tip
これらの設定に加えて、ストレージボリューム設定のデフォルト値を設定できます。 ストレージボリュームのデフォルト値を変更する を参照してください。
ストレージボリューム設定¶
| Key: | block.create_options |
| Type: | string |
| Default: |
|
| Condition: | コンテントタイプ |
| Key: | block.filesystem |
| Type: | string |
| Default: |
|
| Condition: | コンテントタイプ |
| Key: | block.mount_options |
| Type: | string |
| Default: |
|
| Condition: | コンテントタイプ |
drbd.auto_add_quorum_tiebreakerLINSTORが必要に応じて自動的にディスクレスリソースを作ってクオラムのタイブレーカーとして振る舞わせることを許可するかどうか(リソースグループに適用される)
| Key: | drbd.auto_add_quorum_tiebreaker |
| Type: | bool |
| Default: |
|
| Condition: |
| Key: | drbd.auto_diskful |
| Type: | string |
| Default: | |
| Condition: |
| Key: | drbd.on_no_quorum |
| Type: | string |
| Default: | |
| Condition: |
| Key: | initial.gid |
| Type: | int |
| Default: |
|
| Condition: | コンテントタイプ |
| Key: | initial.mode |
| Type: | int |
| Default: |
|
| Condition: | コンテントタイプ |
| Key: | initial.uid |
| Type: | int |
| Default: |
|
| Condition: | コンテントタイプ |
| Key: | linstor.raw.* |
| Type: | string |
| Scope: | global |
| Key: | linstor.remove_snapshots |
| Type: | bool |
| Default: |
|
| Condition: |
| Key: | security.shifted |
| Type: | bool |
| Default: |
|
| Condition: | カスタムボリューム |
| Key: | security.unmapped |
| Type: | bool |
| Default: |
|
| Condition: | カスタムボリューム |
| Key: | snapshots.expiry |
| Type: | string |
| Default: |
|
| Condition: | カスタムボリューム |
この値は新しく作ったスナップショットの有効期限を算出するのに使います。 スナップショットが作られた日時にこの値が加算され、結果のタイムスタンプがスナップショットの個別の有効期限として保管されます。 この値を変更しても、変更後に作られたスナップショットのみに影響します。既存のスナップショットの有効期限は変更されません。
サポートされる単位はS(秒)、M(分)、H(時)、d(日)、w(週)、m(月) and y(年)です。
Mが分を意味し、mが月であることに注意してください。
それぞれの単位は1度だけ指定でき、月と年は固定の日数ではなくカレンダーの月として計算されます。
| Key: | snapshots.expiry.manual |
| Type: | string |
| Default: |
|
| Condition: | カスタムボリューム |
この値は新しく作ったスナップショットの有効期限を算出するのに使います。 スナップショットが作られた日時にこの値が加算され、結果のタイムスタンプがスナップショットの個別の有効期限として保管されます。 この値を変更しても、変更後に作られたスナップショットのみに影響します。既存のスナップショットの有効期限は変更されません。
サポートされる単位はS(秒)、M(分)、H(時)、d(日)、w(週)、m(月) and y(年)です。
Mが分を意味し、mが月であることに注意してください。
それぞれの単位は1度だけ指定でき、月と年は固定の日数ではなくカレンダーの月として計算されます。
| Key: | snapshots.pattern |
| Type: | string |
| Default: |
|
| Condition: | カスタムボリューム |
snapshots.scheduleCron 表記 (<minute> <hour> <dom> <month> <dow>)、またはスケジュールエイリアスのカンマ区切りリスト(@hourly, @daily, @midnight, @weekly, @monthly, @annually, @yearly)、または自動スナップショットを無効にする場合は空文字(デフォルト)
| Key: | snapshots.schedule |
| Type: | string |
| Default: |
|
| Condition: | カスタムボリューム |