要約
- デフォルトで、AWS-VPC(以下、VPCと呼称する。)内の通信手段としてブロードキャスト・マルチキャストの利用は制限されています。
- 「AWS Transit Gatewayのマルチキャスト機能」を使うとこの制約の一部を回避することが可能です。
- ただし、「マルチキャスト・パケット転送」がカーネルビルド時に無効オプションがデフォルトとされており、それに起因して使いづらい部分もあること。
- Dockerから使う場合などなど。
はじめに
ROS2元年!?
ROSCon JP 2021やROS 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パケットを送出してから通信を開始していることを確認できます。
(図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の設定
- AWSの「コンソールのホーム」→「VPC」、左側メニュー「Transit Gateway」→「Transit Gateway」の順に進み、Transit Gatewayの設定画面を表示し、「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
この時、「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 ではブロードキャストがサポートされないため、このアドレスを予約します。
※3 NITROについてはメチャクチャ詳しい記事がありました。
AWS Nitro とは何かを理解する | Powering next-gen Amazon EC2: Deep dive on the Nitro System #CMP301 #reinvent | DevelopersIO!