rmw_zenoh 實戰
看到這邊,也許你會有個疑問,到底 rmw_zenoh 可以實際帶來什麼好處呢? 對於 DDS 在無線網路下的問題,如果沒有實際碰到可能感受沒有那麼深,因此我們這邊就來列舉一些 rmw_zenoh 實際獨特的功能。
共享記憶體 (Shared Memory)
對於效能要求比較高的使用場景,常常我們會要求機內通訊可以直接利用共享記憶體來傳輸,避免訊息還要經過作業系統的網路層以及多次拷貝。 Zenoh 除了一般的網路以外,也支援共享記憶體的通訊。 Zenoh 會自動偵測是否通訊雙方都能用共享記憶體,如果可以就用共享記憶體,不行的話就切回原來網路。 預設 rmw_zenoh 的共享記憶體是關閉的,我們需要另外將其打開,設定並不複雜。
- 修改 Router 和 Session 內部的設定檔
- 當然更簡單的方法是直接在所有 terminal 都加上
ZENOH_CONFIG_OVERRIDE
安全通訊 (Security)
資安的重要性在怎麼強調也不為過,當然 Zenoh 也支援相關功能。 當然 rmw_zenoh 也支援 SROS 功能,但如果只是單純要加密跨機通訊的話,我們可以直接利用 mTLS 的方式來確保流量離開網路都是有加密的。
Warning
請注意這邊我們不考慮中間人攻擊的情況,如果真的要避免這個問題,我們會需要有個專門 CA 來認證憑證才行。
假設我們有一台機器人和一台筆電,我們希望兩者之間的通訊是加密的
- 產生憑證與金鑰
mkdir -p tls
# 建立 root CA 憑證和金鑰
docker run -it --init -v $PWD/tls:/home/step smallstep/step-cli \
step certificate create --profile root-ca "Example Root CA" root_ca.crt root_ca.key \
--no-password --insecure
# 產生給機器人的憑證和金鑰,並用 root CA 簽署
docker run -it --init -v $PWD/tls:/home/step smallstep/step-cli \
step certificate create robot.local robot.crt robot.key \
--ca ./root_ca.crt --ca-key ./root_ca.key --no-password --insecure
# 產生給筆電的憑證和金鑰,並用 root CA 簽署
docker run -it --init -v $PWD/tls:/home/step smallstep/step-cli \
step certificate create control.local control.crt control.key \
--ca ./root_ca.crt --ca-key ./root_ca.key --no-password --insecure
- 修改機器人上的設定檔 (Router 部份)
// ...
listen: {
// ...
endpoints: [
// 本地端內部還是用 TCP 方式連線
"tcp/localhost:7447",
// 遠端連進來的話則是用 TLS 來連線
"tls/192.168.1.1:7447"
],
// ...
},
// ...
tls: {
root_ca_certificate: "path/to/tls/root_ca.crt", // CA 憑證
listen_private_key: "path/to/tls/robot.key",
listen_certificate: "path/to/tls/robot.crt",
enable_mtls: true, // 啟動 mTLS
connect_private_key: "path/to/tls/robot.key",
connect_certificate: "path/to/tls/robot.crt",
verify_name_on_connect: false, // 要不要驗證憑證上的 hostname,為簡化先不要
// ...
},
// ...
- 修改筆電上的設定檔 (假設我們是用 client mode 來連接到機器人,這邊只需要修改 Session 部份)
// ...
connect: {
// ...
endpoints: [
// 用 TLS 來連到機器人的 Zenoh Router
"tls/192.168.1.1:7447"
],
// ...
},
// ...
tls: {
root_ca_certificate: "path/to/tls/root_ca.crt", // CA 憑證
listen_private_key: "path/to/tls/control.key",
listen_certificate: "path/to/tls/control.crt",
enable_mtls: true, // 啟動 mTLS
connect_private_key: "path/to/tls/control.key",
connect_certificate: "path/to/tls/control.crt",
verify_name_on_connect: false, // 要不要驗證憑證上的 hostname,為簡化先不要
// ...
},
// ...
權限控管 (Access Control)
既然 rmw_zenoh 的對外通訊需要經過 Zenoh Router,其實我們就可以在 Zenoh Router 上面做一些手腳,例如限制某些 topic 無法對外連接。 這個可以有效保護一些敏感資訊不被洩漏,也可以降低網路上的封包數量,減輕整體系統負擔。
啟動方式主要是修改 Zenoh Router 的 Router 設定檔,假設我們現在要擋掉 camera/image_raw
這個 topic
access_control: {
enabled: true,
default_permission: "allow", // 沒有特別被限制,就是允許
rules:
[
{
id: "deny_topics",
permission: "deny", // 限制符合該 key expression 的規則
messages: [ // 所有格式都要擋下
"put", "delete", "declare_subscriber",
"query", "reply", "declare_queryable",
"liveliness_token", "liveliness_query", "declare_liveliness_subscriber",
],
flows:["egress", "ingress"], // 進出都要限制
key_exprs: [
"*/camera/image_raw/**", // 我們要檔下的 topic,注意這邊要用 Zenoh 的 key expression,可以參考我們前面提到的 ROS 2 topic 和 Zenoh key expression 對應方式
"*/camera/image_raw/**/@adv/**", // 如果該 topic 是 TRANSIENT_LOCAL 的話
],
},
],
subjects:
[
{
id: "ALL",
},
],
policies:
[
{
id: "policy_id",
rules: ["deny_topics"],
subjects: ["ALL"],
},
]
},
Downsampling
另外一個降低網路上封包流量的方法是降低流出的頻率,我們一樣可以在 Zenoh Router 上面進行流量設定。
假設我們想要把 camera/image_raw
這這個 topic 降到 2Hz。
一樣要調整 Zenoh Router 上的 Router config:
downsampling: [
{
messages: ["put", "reply"],
flows: ["egress"], // 限制對外才要調整
rules: [
{ key_expr: "*/camera/image_raw/**", freq: 2.0 }, // 限制只需要 2 Hz
{ key_expr: "*/camera/image_raw/**/@adv/**", freq: 2.0 }, // 如果 topic 是使用 TRANSIENT_LOCAL 的話
],
},
],
跨網際網路連接 (Internet)
Zenoh 跟 DDS 最大的不同在於可以很輕易的跨出網路,我們假設現在機器人和筆電在不同網路下,且都是 private IP,代表兩者無法建立直接連線。 這時候我們可以在另外一個有 public IP 的地方運行獨立的 Zenoh Router,然後讓機器人和筆電可以同時連到它,Zenoh Router 可以幫忙轉發訊息。
-
先運行 Zenoh Router,假設 IP 為 1.2.3.4
- 值得注意的是,我們不一定需要用 ROS 2 的方式來跑 zenohd,直接用 Zenoh 的方式來跑也可以
-
機器人的 Router 設定檔
- 筆電的 Session 設定檔,一樣假設是 client mode
ROSCon 工作坊
ZettaScale 其實在過去幾年 ROSCon 的工作坊都有一步步針對 rmw_zenoh 的練習教學。 有興趣可以嘗試看看,可以幫助我們更加了解 rmw_zenoh 運作: