[Linux] Resilient RDMA IP Addresses

原文はこちら。
https://blogs.oracle.com/linux/resilient-rdma-ip-addresses

RDSのResilient RDMA IP機能をアップストリームへ導入するために実施している作業に関する記事を、Oracle Linuxカーネルの開発者Sudhakar Dindukurtiが寄稿しました。このコードは現在、OracleのオープンソースのUEKカーネルで管理されており、これを上流のLinuxソースコードに統合する作業を進めています。

1.0 Introduction to Resilient RDMA IP

Resilient RDMAIPモジュールは、InfiniBandおよびRoCEアダプタのフェールオーバー、フェールバック、および負荷分散を行うために、ULP(RDMA上位レベルプロトコル)を支援します。

RDMAIPは、Oracle LinuxのRDMA接続の機能です。active-active bondingとも呼ばれるこの機能を有効にすると、Resilient RDMAIPモジュールはアダプタのポート間にアクティブなbondingグループを作成します。正常時には利用可能な全帯域幅を使用しながら、ネットワークアダプターが失われた場合、そのポート上のIPは、アプリケーション用にHAを自動的に提供しながら、別のポートに移動されます。

Reliable Datagram Sockets (RDS) は、データグラム伝送のための高パフォーマンスで低レイテンシな信頼できるコネクションレスソケットです。RDSは、2ノード間で信頼性の高い単一のトランスポートを使用して、信頼性の高い順序付けされたデータグラム配信を提供します。RDSプロトコルの詳細については、RDSのドキュメントを参照してください。
RDS Wire Specification 3.1
http://oss.oracle.com/projects/rds/dist/documentation/rds-3.1-spec.html
RDS RDMAは、Resilient RDMAIPモジュールを使用してHAサポートを提供します。RDS RDMAモジュールは、Resilient RDMAIPモジュールが提供するRDMA CMアドレス変更イベントを待ち受けます。RDSは、アドレス変更イベントを受信した場合、接続に失敗したポートに関連付けられているすべてのRC接続を削除し、次回データを送信する前に新しいRC接続を再確立します。

透過的な高可用性は、標準のNIC(ネットワーク・インタフェース・カード)と比較して、RDMA対応NICアダプタにとって重要な問題です。標準的なNICの場合、IP層は、パケット送信のためにどの経路またはどのnetdevインタフェースを使用するかを決定できます。これは、ハードウェアを特定のポートとパスに結び付けるという、セキュリティとパフォーマンス上の理由から、RDMA対応アダプターでは不可能です。RDMAを使用してリモートノードにデータパケットを送信するには、いくつかの手順があります。
  1. クライアントアプリケーションはメモリをRDMAアダプタに登録し、RDMAアダプタは登録されたメモリ領域のR_Keyをクライアントに返す。
    (注意)登録情報はRDMAアダプタに保存される。
  2. クライアントはこの "R_key"をリモートサーバーに送信する。
  3. クライアントへのRDMA_READ/RDMA_WRITEを要求時には、サーバにはこのR_keyが含まれる
  4. クライアント側のRDMAアダプタは、"R_key"を使用してメモリ領域を見つけ出し、トランザクションを進める。"R_key"は特定のRDMAアダプタにバインドされているため、同じR_KEYを使用して別のRDMAアダプタでデータを送信することはできない。また、RDMAアプリケーションはカーネルをバイパスして直接ハードウェアと通信できるため、 (カーネルに備わる)これまでのbondingがHAを提供できない。
Resilient RDMAIPは、カーネルULPまたはOSバイパスアプリケーションに対して透過的なフェールオーバーを提供しませんが、RDMA対応アダプターでのULPのフェールオーバー、フェイルバック、およびロードバランスを可能にします。RDS(Reliable Datagram Sockets)プロトコルは、Resilient RDMAIPモジュールサポートを使用してHAを提供している最初のクライアントです。以下のセクションでは、さまざまな機能に対するResilient RDMAIPの役割について説明します。

1.1 Load balancing

Active-Active bondingグループに含まれる全てのインターフェースには個別のIPアドレスがあります。RDMAコンシューマは1個以上のインターフェースを利用して、同時にデータを送信することができ、全てのアクティブなインターフェース間で負荷を分散させる責任があります。

1.2 Failover

Active-Active Bondingグループに属する任意のインターフェースがダウンした場合、Resilient RDMAIPモジュールはインターフェイスのIPアドレスを同じグループ内の他のインターフェイスに移動し、また、RDMA CM(Communication Manager)アドレス変更イベントをRDMAカーネルULPに送信します。HA対応のRDMAカーネルULPは、ダウンしたインターフェイスの使用を停止し、他のアクティブなインターフェイスの使用を開始します。例えば、ダウンしたインターフェースでReliable Connection(RC)が確立されている場合、ULPはこれらの接続をすべて閉じて、フェールオーバーインターフェイスで再確立できます。

1.3 Failback

ダウンしたインターフェイスが(フェールオーバする前に)先に復旧した場合、Resilient RDMAIPモジュールはIPアドレスを元のインターフェイスに戻し、RDMA CMアドレス変更イベントをカーネルコンシューマに再度送信します。RDMAカーネルのコンシューマは、アドレス変更イベントを受信するとアクションを実行します。例えば、RDMAコンシューマは、フェールオーバーの一環で移動された接続を移動します。

2.0 Resilient RDMAIP module provides the below module parameters

  • rdmaip_active_bonding_enabled

    • Active-Active bondingを有効化する場合は1を設定
    • Active-Active bondingを無効化する場合は0を設定
デフォルトでは、Active-Active bondingは無効化されていますが、有効化すると、Resilient RDMAIPモジュールは、同じRDMAアダプタのポート間でアクティブなbondingグループを作成します。例えば、Infiniband(ib0とib1)とRoCE(eth5とeth5)のそれぞれに2つのポートを有する、2つのRDMAアダプタがあるシステムを考えてみましょう。この設定では、2つのアクティブなbondingグループが作成されます。
1)ib0とib1(Bond 1)
2)eth4とeth5(Bond 2)
  • rdmaip_ipv4_exclude_ips_list

    • このパラメータに記載のあるIPの場合、アクティブbonding機能は無効
デフォルトでは、リンクローカルアドレスはResilient RDMAIPによって除外されます。

3.0 How it works ?

Active-Active Bonding

上図で、1個の2ポートInfiniband HCAを備えた2つのノードがあり、HCAの各ポートは図のように異なるスイッチに接続されています。図に示すように、ポートごとに1つずつ、2つのIPoIBインターフェイス(ib0およびib1)が作成されます。Active-Active bondingを有効化すると、Resilient RDMAIPモジュールは自動的にInfiniband HCAの2つのポート間にbondingを作成します。

1) 全てのIBインターフェースが起動していて構成済み

#ip a
---
ib0: <broadcast,multicast,up,lower_up> mtu 2044 qdisc pfifo_fast state UP qlen 256
    link/infiniband 80:00:02:08:fe:80:00:00:00:00:00:00:00:10:e0:00:01:29:65:01 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
    inet 10.10.10.92/24 brd 10.10.10.255 scope global ib0
       valid_lft forever preferred_lft forever
  
  
ib1: <broadcast,multicast,up,lower_up> mtu 2044 qdisc pfifo_fast state UP qlen 256
    link/infiniband 80:00:02:09:fe:80:00:00:00:00:00:00:00:10:e0:00:01:29:65:02 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
    inet 10.10.10.102/24 brd 10.10.10.255 scope global secondary ib0:P06
       valid_lft forever preferred_lft forever </broadcast,multicast,up,lower_up></broadcast,multicast,up,lower_up>

2) Node 1のPort 2がダウンすると、ib1のIP '10.10.10.102'がPort 1(ib0)に移動する(フェールオーバ)

#ip a
--------------
 ib0: <broadcast,multicast,up,lower_up> mtu 2044 qdisc pfifo_fast state UP qlen 256
    link/infiniband 80:00:02:08:fe:80:00:00:00:00:00:00:00:10:e0:00:01:29:65:01 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
    inet 10.10.10.92/24 brd 10.10.10.255 scope global ib0
       valid_lft forever preferred_lft forever
    inet 10.10.10.102/24 brd 10.10.10.255 scope global secondary ib0:P06
       valid_lft forever preferred_lft forever
    inet6 fe80::210:e000:129:6501/64 scope link
       valid_lft forever preferred_lft forever
ib1: <no-carrier,broadcast,multicast,up> mtu 2044 qdisc pfifo_fast state DOWN qlen 256
    link/infiniband 80:00:02:09:fe:80:00:00:00:00:00:00:00:10:e0:00:01:29:65:02 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
----------------
</no-carrier,broadcast,multicast,up></broadcast,multicast,up,lower_up>

3) Node 1のPort 2が復旧すると、Port 2 (ib1)にIP '10.10.10.102'が戻る(フェールバック)

#ip a
---
ib0: <broadcast,multicast,up,lower_up> mtu 2044 qdisc pfifo_fast state UP qlen 256
    link/infiniband 80:00:02:08:fe:80:00:00:00:00:00:00:00:10:e0:00:01:29:65:01 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
    inet 10.10.10.92/24 brd 10.10.10.255 scope global ib0
       valid_lft forever preferred_lft forever
  
  
 ib1: <broadcast,multicast,up,lower_up> mtu 2044 qdisc pfifo_fast state UP qlen 256
    link/infiniband 80:00:02:09:fe:80:00:00:00:00:00:00:00:10:e0:00:01:29:65:02 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
      inet 10.10.10.102/24 brd 10.10.10.255 scope global secondary ib0:P06
       valid_lft forever preferred_lft forever
</broadcast,multicast,up,lower_up></broadcast,multicast,up,lower_up>

Example: RDS Implementation

フェイルオーバーおよびフェールバック中に発生するシーケンスを次に示します。ノード1のPort 1のIP1とノード2のIP3との間にRDSソケットを確立するRDSアプリケーションを考えます。この場合、RDSカーネルレベルでは、IP1とIP3の間に1つのRC接続が存在します。

Case 1: Node 1のPort 1がダウン

  • Resilient RDMAIPモジュールがIPアドレスIP1をポート1からポート2に移動
  • ポート2は2つのIP(IP1とIP2)を持つ
  • Resilient RDMAIPモジュールは、RDMA CMアドレス変更イベントをRDSに送信
  • RDS RDMAドライバは、アドレス変更イベントの処理の一環で、IP1(Port 1)とIP3の間のIB接続を切断
  • RDS RDMAドライバは、IP1からIP3への新たな送信リクエストを受信すると、IP1(Port 2)とIP3との間で新しいRC接続を作成
  • フェイルオーバー後、RDSがIP1を解決すると、IP1がPort 2にバインドされるため、RDSはPort 2のパスレコードを取得

Case 2: Node 1のPort 1が復旧

  • Resilient RDMAIPモジュールは、IPアドレスIP1をPort 2からPort 1に移動
  • Resilient RDMAIPモジュールは、RDMA CMアドレス変更イベントをRDSに送信
  • RDS RDMAドライバは、アドレス変更イベントの処理の一環で、IP1(Port 2)とIP3の間のIB接続を切断
  • RDS RDMAドライバは、IP1からIP3への新しい送信要求を受信すると、IP1(Port 1)からIP3への新しいRC接続を作成
  • フェールバック後、RDSがIP1を解決すると、IP1がPort 1にバインドされるため、RDSはPort 1のパスレコードを取得

4.0 Future work

Resilient RDMAIPモジュールの現在の実装は、ネットワークスタック実装と密接に結びついていません。例えば、RDMAカーネルコンシューマは、アクティブなBondingグループを作成する方法を有しておらず、また、アクティブなBondingグループやどのインターフェースがアクティブなBondingグループで構成されているのかをRDMAコンシューマに通知できるAPIはありません。結果として、現在の設計や実装はアップストリームに導入するには適していません。そのため、このモジュールのアップストリームのLinuxに提出可能なバージョンの開発に現在取り組んでいます。しかしながら、それまでの間はRDASIPのコードはoss.oracle.comとgithub上にあります。
Oracle Linux UEK: Unbreakable Enterprise Kernel
http://github.com/oracle/linux-uek

0 件のコメント:

コメントを投稿