15
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AWS-VPC内でROS2(FastDDS-Multicast-UDP)を使ったPub/Subを実行する【相性良い/悪い!?】

Last updated at Posted at 2021-12-03

要約

  • デフォルトで、AWS-VPC(以下、VPCと呼称する。)内の通信手段としてブロードキャスト・マルチキャストの利用は制限されています。
  • AWS Transit Gatewayのマルチキャスト機能」を使うとこの制約の一部を回避することが可能です。
  • ただし、「マルチキャスト・パケット転送」がカーネルビルド時に無効オプションがデフォルトとされており、それに起因して使いづらい部分もあること。
    • Dockerから使う場合などなど。

はじめに

ROS2元年!?

ROSCon JP 2021ROS World 2021の発表を見ると、その多くがROS2を使って実行されていることが分かります。ROS Noetic NinjemysのEOLは2025年5月と、移行の猶予時間はまだ残っている段階ですが、事例も増えてきておりROS2への理解も深めていくタイミングとしては2021年は良いタイミングと感じました。
そこで本記事では「ROS2のノードの一部(ROSbagとか!?)をクラウドサービス上で動かしたいなー」と考える方に向けて、選択肢の一つを提示できればと思います。

VPC(Virtual Private Cloud)ではブロードキャスト・マルチキャストが制限されている

VPCは、パブリッククラウド内に論理的に分離された仮想ネットワーク空間を提供します。我々、利用者はこの中にEC2(仮想マシン)、RDS(データベースサービス)などの各リソースを配置して「目的に応じたインフラを自由に構築」していくわけです。
自由に〜と書きつつも、制約もあります。その一つとして、「VPC内の通信手段としてブロードキャスト・マルチキャストの利用が制限せれている点」が挙げられます。※1
一般的には通信量の抑制のために必要な措置とされています。論理的に同一サブネットを構成しつつも、物理的にはそうなっていないわけです。ブロードキャストやマルチキャストはパケットを1つ飛ばすとみんなに届くという、オンプレでは省エネな通信方式ですが、これを物理的にはバラバラな状況下で忠実に再現するのはあまり現実的な選択肢でないことも頷けるかと思います。(例:クラスBのローカルアドレスだと65534個に送信…!)

Transit Gatewayのマルチキャスト機能

そんな中、登場したのが「AWS Transit Gatewayのマルチキャスト機能」です。
「Transit Gateway」は、クラウドルーターと総称される機能群を提供します。

Amazon VPC、AWS アカウント、オンプレミスネットワークを単一のゲートウェイに簡単に接続(引用:AWSのホームページのヘッダより)

その中で「マルチキャスト機能」は2019年の更新時に追加された比較的新しい機能です。当初はIGMPが使えず、マルチキャストグループに所属するEC2(それにアタッチしているENI)を、興味関心があるシステムとは別手動で管理せねばならず、使いづらいところがありました。
そんな中、2020年末にIGMPパケットへのサポートが発表され、2021年4月には、東京リージョンで使えるようになっていました。
東京リージョンに2つのAWS Transit Gateway アップデート: AWS Transit Gateway Connect と Internet Group Management Protocol (IGMP) Multicast | Amazon Web Services ブログ

IGMP(Internet Group Management Protocol)

IGMPについての解説の詳細は割愛するが、ROS2との関わりという視点で、本記事と関連がある部分を少しだけ見ていきます。
ROS2で一般的なDDS実装である、FastDDS及び、Cyclone DDS
では、Multicast-UDPモードで動作する場合、IGMPパケットを送出してから通信を開始していることを確認できます。

aws-tgw_Fig1.jpeg
(図1 ros2 run demo_nodes_cpp talkerパケットキャプチャ結果 - FastDDS(Multicast-UDP))

2021年現在売られているスイッチングハブでは「IGMPスヌーピング機能」が有効化されている機種が非常に多くあります。これらは、IGMPパケットを盗み見(スヌーピング)して、どの送信元がどのマルチキャストグループに属しているかを、スイッチングハブ側でも把握することで、マルチキャストパケットの送信先を絞っています。やはりこちらも、Transit Gateway同様に不要な通信で帯域を無駄遣いしないための工夫です。※2

構築手順

公式のドキュメントはこちら。AWS上で図2のような簡単な環境を作って、ROS2のPub/Subを試してみましょう。なお、制限については公式ドキュメントに詳しく載っていますが、特に、Amazon EC2はニトロシステムに対応したインスタンス(t3、c5、m5など)を利用しなければならない点にご注意下さい。※3

(図2 AWS構成図)

これはいわゆる、「踏み台」を使った要塞構成と呼ばれるもので、AWSでもクイックスタートでおすすめしている風の構成です。詳しい構築方法はこちら。AWS での Linux 踏み台ホスト - クイックスタート
また、各EC2のOSがUbuntu20.04、ROS2 Foxyがインストールされているものとします。
ここでは、Transit Gatewayやセキュリティグループの設定を見ていきます。

Transit Gatewayの設定

  1. AWSの「コンソールのホーム」→「VPC」、左側メニュー「Transit Gateway」→「Transit Gateway」の順に進み、Transit Gatewayの設定画面を表示し、「Transit Gatewayを作成」ボタンをクリックします。
(図3 VPC画面の左側メニューのうちTransit Gateway部分を抜粋) 2. 「Transit Gatewayを作成」画面では、任意の名前タグ(ここではros2-mudp)を付与し、「Transit Gatewayを設定」→「マルチキャストサポート」チェックボックを有効にして、画面下部の「Transit Gatewayを作成」ボタンをクリックします。 (図4 「Transit Gatewayを作成」画面) 3. 「Transit Gateway」の一覧画面に遷移するので、左側メニュー「Transit Gateway アタッチメント」→「Transit Gateway アタッチメントを作成」ボタンをクリックします。 4. 「Transit Gateway アタッチメントを作成」画面-詳細ブロックでは、任意の名前タグ(ここではros2-mudp)、「Transit Gateway ID」セレクトボックスに対して先に作った「Transit Gateway ID」を指定し、「アタッチメントタイプ」セレクトボックスがVPCとなっていることを確認してください。 (図5 「Transit Gatewayアタッチメントを作成」画面) 5. 「Transit Gateway アタッチメントを作成」画面-VPCアタッチメントブロックでは、今回のターゲットとなるROS2が載ったEC2が所属する、VPCやそのサブネットを指定して下さい。詳細・VPCアタッチメントの各ブロックの入力内容に問題ないことを確認して、画面下部の「Transit Gateway アタッチメントを作成」ボタンをクリックします。 (図6 「Transit Gatewayアタッチメントを作成」画面) 6. 「Transit Gateway アタッチメント」の一覧画面に遷移するので、左側メニュー「Transit Gateway Multicast」→「Transit Gateway マルチキャストドメインを作成」ボタンをクリックします。 7. 「Transit Gateway マルチキャストドメインを作成」画面では、任意の名前タグ(ここではros2-mudp)を付与し、「Transit Gateway ID」セレクトボックスに対して先に作った「Transit Gateway ID」を指定し、「Transit Gateway マルチキャストドメインを設定」→「IGMPv2 のサポート」チェックボックスを有効にします。入力内容に問題ないことを確認して、画面下部の「Transit Gateway マルチキャストドメインを作成」ボタンをクリックします。 (図7 「Transit Gateway マルチキャストドメインを作成」画面) 8. 「Transit Gateway マルチキャストドメイン」の一覧画面に遷移するので、今回作成したマルチキャストドメイン(ros2-mudp)を選択し、下側メニュータブの「関連付け」タブをクリックして下さい。タブ画面が遷移した後に表示される「関連付けを作成」ボタンをクリックしてください。 (図8 マルチキャストドメインの関連付けを作成する) 9. 「関連付けを作成」画面では、「関連付けるアタッチメントを選択」セレクトボックスでは、先に作成したものを、「関連付けるサブネットを選択」セレクトボックスでは「Transit Gateway アタッチメント」と同様に予め作っておいたサブネットを関連付けます。入力内容に問題ないことを確認して、画面下部の「関連付けを」作成ボタンをクリックしてください。 (図9 「Transit Gateway マルチキャストドメイン - 関連付けを作成」画面)

ネットワークACL、セキュリティグループ

マルチキャストのルーティング - Amazon Virtual Private Cloudを参考に、自身のセキュリティポリシーに応じて、適切なルールを宣言する必要があります。Transit Gatewayと同様に、AWSの「コンソールのホーム」→「VPC」、左側メニュー「セキュリティ」より設定可能です。
ひとつ、つまずきやすいポイントとしては、セキュリティグループの「ソース」はネットワークIPもしくはCIDRで指定する必要があるようです。(セキュリティグループ指定はできません。)

EC2でIGMPの設定を変更する

IGMP 設定を管理するには以下の通りの記載があります。

EC2 のデフォルトの IGMP バージョンは IGMPv3 です。すべての IGMP グループメンバーのバージョンを変更する必要があります。以下のコマンドを実行できます。
sudo sysctl net.ipv4.conf.eth0.force_igmp_version=2

ということで、コンソールで各EC2にログインし、上記コマンドを実行しておいて下さい。

動作確認

では、実際にROS2のデモおなじみの「demo_nodes_cpp」を動かしてみましょう。ROS-Baseとかでインストールした方は、おそらくインストールされていないので、お試し頂きたい場合は、以下コマンドで追加することも可能です。

sudo apt install ros-foxy-demo-nodes-cpp -y

では、こちらが実際に動かした様子です。ここではRMW_IMPLEMENTATIONは特に指定しません。(=デフォルトのFastDDSを使う)
端末A

ros2 run demo_nodes_cpp talker

端末B

ros2 run demo_nodes_cpp listener

2c1ab24cb2a94200ba0bd062ac773293.gif
(図10 ROS2のデモプログラムによる動作確認)

この時、「Transit Gateway マルチキャストドメイン」の画面で、今回作成したマルチキャストドメイン(ros2-mudp)を選択し、下側メニュータブの「グループ」タブをクリックして下さい。すると、FastRTPSのデフォルトのマルチキャストグループである「239.255.0.1」によるグループが作成されていることが確認できます。

(図11 AWSのコンソールでマルチキャストグループを確認する)

ちなみに、「239.0.0.0/8」に該当するアドレスはプライベートスコープとして定められたアドレスです。RFC2365によって組織内で使用するためのプライベートアドレスとして割り当てられています。

ベンチマーク

ここでは、iperfを使って軽く実行したパフォーマンス測定結果を掲示します。頻度、データサイズ、インスタンスを変えた場合、同一AZ、オンプレとの比較をして考察を添えるべきかと思いますが、時間切れになってしまいました。。。。
データ無しで語る雰囲気としては、TransitGatewayを介しているからといってAWSのネットワーク性能が落ちている訳ではないように感じます。また、AZを跨いだ厳しい測定条件にも関わらずレイテンシーが3σで2〜5msで収まっているのはさすがだなというところ。
数字として今回は取れていませんが、Discoverが少し遅い点は少し気になる人もいるかもしれません。(実機でやっているときより2〜3秒遅いという肌感覚)

条件

  • 東京リージョン(ap-northeast-1bと1c)
  • EC2インスタンス:t3.medium
    • 2vCPU(Xeon Platinum 8000  ブーストで@3.1GHz)
    • 4GiB
    • ネットワークバースト幅:5Gbps

1Hz - 20Mbpsを5並列

基本統計量

Latency_avg Latency_min Latency_max Latency_stdev Jitter
平均 3.535268041 平均 3.491902062 平均 6.062958763 平均 0.135654639 平均 0.02357732
標準誤差 0.00964557 標準誤差 0.00933292 標準誤差 0.117311208 標準誤差 0.00733046 標準誤差 0.001129145
中央値 (メジアン) 3.5295 中央値 (メジアン) 3.4945 中央値 (メジアン) 6.322 中央値 (メジアン) 0.1205 中央値 (メジアン) 0.019
最頻値 (モード) 3.467 最頻値 (モード) 3.559 最頻値 (モード) 3.921 最頻値 (モード) 0.029 最頻値 (モード) 0.019
標準偏差 0.134347243 標準偏差 0.129992529 標準偏差 1.633956059 標準偏差 0.10210149 標準偏差 0.015727165
分散 0.018049182 分散 0.016898058 分散 2.669812402 分散 0.010424714 分散 0.000247344
尖度 -0.791325596 尖度 -0.770579324 尖度 -1.133331214 尖度 0.386623598 尖度 5.888190464
歪度 0.005190191 歪度 -0.063748029 歪度 0.173594446 歪度 0.931138478 歪度 2.262671108
範囲 0.527 範囲 0.527 範囲 5.808 範囲 0.432 範囲 0.084
最小 3.278 最小 3.222 最小 3.666 最小 0.019 最小 0.006
最大 3.805 最大 3.749 最大 9.474 最大 0.451 最大 0.09
合計 685.842 合計 677.429 合計 1176.214 合計 26.317 合計 4.574
標本数 194 標本数 194 標本数 194 標本数 194 標本数 194
最大値(1) 3.805 最大値(1) 3.749 最大値(1) 9.474 最大値(1) 0.451 最大値(1) 0.09
最小値(1) 3.278 最小値(1) 3.222 最小値(1) 3.666 最小値(1) 0.019 最小値(1) 0.006
信頼区間(99.0%) 0.02509336 信頼区間(99.0%) 0.024279987 信頼区間(99.0%) 0.305190097 信頼区間(99.0%) 0.019070503 信頼区間(99.0%) 0.002937518

レイテンシー

ジッター

おまけ:iRobot ROS2 performance evaluation framework

一応計測しましたが、同一マシン上でのパフォーマンステストではTransitGatewayを介さないっぽいですね。FASTRTPS_DEFAULT_PROFILES_FILE環境変数で指定したプロファイルXMLを使ってSHMを無効化して測定したのですが、それにしては速すぎるような。(よく分かっていないのでオマケ扱い。この辺の詳しい情報をお持ちの方がおられましたら教えて頂ければ幸いです。)

$ FASTRTPS_DEFAULT_PROFILES_FILE=fastrtps-profile.xml ./irobot-benchmark topology/sierra_nevada.json --ipc off
〜略〜
node           topic          size[b]   received[#]    late[#]   too_late[#]    lost[#]   mean[us]  sd[us]    min[us]   max[us]   freq[hz]  duration[s]
lyon           amazon         36        501            0         0              0         86        63        46        902       100       5
hamburg        danube         8         501            1         0              0         92        181       45        3506      100       5
hamburg        ganges         16        501            0         0              0         62        49        38        935       100       5
hamburg        nile           16        501            0         0              0         71        46        43        851       100       5
hamburg        tigris         16        500            1         0              0         105       104       49        2074      100       5
osaka          parana         12        501            0         0              0         74        108       44        1662      100       5
mandalay       danube         8         501            1         0              0         113       187       63        3649      100       5
mandalay       salween        48        50             0         0              0         79        36        50        305       10        5
ponce          danube         8         501            1         0              0         124       188       68        3663      100       5
ponce          missouri       10000     50             0         0              0         113       198       63        1430      10        5
ponce          volga          8         10             0         0              0         78        59        43        245       2         5
barcelona      mekong         100       10             0         0              0         82        8         62        92        2         5
georgetown     lena           50        50             0         0              0         107       210       58        1556      10        5
geneva         congo          16        50             0         0              0         77        25        48        196       10        5
geneva         danube         8         501            1         0              0         132       189       74        3675      100       5
geneva         parana         12        501            0         0              0         92        112       55        1711      100       5
arequipa       arkansas       16        50             0         0              0         111       277       54        2043      10        5

Publishers stats:
node           topic          size[b]   received[#]    late[#]   too_late[#]    lost[#]   mean[us]  sd[us]    min[us]   max[us]   freq[hz]  duration[s]
montreal       amazon         36        0              0         0              0         19        12        6         107       100       5
montreal       danube         8         0              0         0              0         30        159       5         3419      100       5
montreal       ganges         16        0              0         0              0         13        9         3         98        100       5
montreal       nile           16        0              0         0              0         16        11        3         108       100       5
lyon           tigris         16        0              0         0              0         24        24        3         203       100       5
hamburg        parana         12        0              0         0              0         16        13        5         118       100       5
osaka          salween        48        0              0         0              0         16        11        5         64        10        5
mandalay       missouri       10000     0              0         0              0         21        13        13        92        10        5
ponce          congo          16        0              0         0              0         16        8         9         39        10        5
ponce          mekong         100       0              0         0              0         17        2         12        21        2         5
barcelona      lena           50        0              0         0              0         16        14        6         107       10        5
georgetown     volga          8         0              0         0              0         16        16        5         64        2         5
geneva         arkansas       16        0              0         0              0         14        7         6         53        10        5

System total:
received[#]    mean[us]  late[#]   late[%]   too_late[#]    too_late[%]    lost[#]   lost[%]
5279           95        5         0.09471   0              0              0         0

制約事項

要約で記した通り、「マルチキャスト・パケット転送」がカーネルビルド時に無効オプションがデフォルトとされており、それに起因してDockerなどの仮想ネットワークから本機能を使うことが基本的には出来ないようになっています。Dockerから使う場合は「hostネットワーク」を有効にして、ホスト側のネットワークに頼るというような対応を取る必要があります。
あくまでも、コンテナにこだわる場合はKubernetesでUDPマルチキャストに対応したクラスターネットワーク(例えば、WeaveNet)を使うという手もあります。ただし、現状でAWSのマネージドKubernetesサービスであるAmazon Elastic Kubernetes Service (EKS)でWeaveNetを使うと、マネージドな有り難みを9割方スポイルしてしまうという問題もあります。
んー難しい。。。。

おわりに

面倒・制約が残るものの、AWSのネイティブなネットワーク(トンネリング技術を使わないという意味で)でROS2(FastDDS-Multicast-UDP)を使ったPub/Subが行えることが分かりました。

  • ユニットテストやシステムテストをAWS上で実行する
  • ROSBagとかをデータ耐久性の高いクラウドストレージでバックアップする

などに使えないだろうか!?
また、EC2のARMプロセッサーのインスタンスであるGravition2シリーズのコスパが物凄いことになってきています。

x86のインスタンスと比較して40%の価格性能比

先日のre:Invent2021ではGravition3も発表されており、クラウド高いなーとも言えない状況が出来つつある気がしました。ロボット系の皆様に於かれましては、クラウドも含めてオールARMプロセッサーっていうこともありうるのでは!?と思ったりもしています。

と妄想を膨らませつつ記事を締めたいと思います。


補足

※1 公式ドキュメントでその旨が「主題として」書かれているドキュメントを探すことが出来ませんでした。以下のような感じでさらっと書いてあるところとかは見つけましたが。この制限は暗黙の了解だったのでしょうか。
VPC とサブネット - Amazon Virtual Private Cloud

10.0.0.255: ネットワークブロードキャストアドレスです。VPC ではブロードキャストがサポートされないため、このアドレスを予約します。

※2 マルチキャスト - IGMPスヌーピングとは

※3 NITROについてはメチャクチャ詳しい記事がありました。
AWS Nitro とは何かを理解する | Powering next-gen Amazon EC2: Deep dive on the Nitro System #CMP301 #reinvent | DevelopersIO!

15
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?