IoT Greengrass(MQTT) - 實戰AWS雲端至地端部署

Ivan Chiou
The Messiah Code 神碼技術共筆
9 min readAug 13, 2022

掃雷大作戰

承上篇文章因VPN設定雲端與地端連接的環境太過複雜,最後使用MQTT來互通兩端的訊息,並採用AWS提供的整合ROS+MQTT+CD(continuous development)的平台Greengrass。

主要是依照以下這篇文章來進行建置。

大致上按照以上步驟沒有什麼問題,除了robomaker的使用我們改成用自己地端的device以外,其他步驟都一樣。但仍要注意以下幾點問題:

(1) 將docker-compose指令開放給所有user ($sudo chmod 777 docker-compose),因為ggc_user無法access docker-compose指令的關係。

(2) 另外即便已修改docker-compose的權限,也有可能Greengrass並未成功指定其執行系統角色為ggc_user,因確實在deployment的時候指定角色為ggc_user。

(3) 如果遇到user root is not allowed錯誤,要修改/etc/sudoers的設定。

root    ALL=(ALL:ALL) ALL

(4) 如果最後還是遇到docker-compose command not found問題,除了將權限開放,並且要在recipe.yaml指定完整路徑。

Startup: |   /usr/local/bin/docker-compose -f {artifacts:path}/docker-compose.yaml up -d     
Shutdown: | /usr/local/bin/docker-compose -f {artifacts:path}/docker-compose.yaml down

路徑請依照要部署的設備,docker-compose所在路徑來設定。

/usr/local/bin/docker-compose

(5) 在修改recipe.yaml要注意 install的部分,docker tag的順序不要反了。一定要是docker tag <遠端ECR image的路徑> <地端image的路徑>

docker tag account_id.dkr.ecr.region.amazonaws.com/ros-foxy-greengrass-demo:latest ros-foxy-greengrass-demo:latest

如此應該能順利透過以下指令看見正確由Greengrass得到設備傳過來的訊息後,所回覆的訊息。

export ARTIFACT_DIR=/greengrass/v2/packages/artifacts/com.example.ros2.demo/1.0.0
sudo docker-compose -f $ARTIFACT_DIR/docker-compose.yaml logs --follow

並在Greengrass GUI console顯示Running。

用同樣方式對於另外一台地端做相同的部署,接著試著去修改docker-compose.yaml,讓兩台地端的devices,一個做publisher,一個做subscriber,藉此來驗證透過Greengrass真的把設備給串聯起來。

設備A —

version: "3"
services:
greengrass_demo_image:
build:
context: ./
image: ros-foxy-greengrass-demo:latest

talker:
image: ros-foxy-greengrass-demo:latest
command: ros2 run demo_nodes_cpp talker
greengrass_bridge:
image: ros-foxy-greengrass-demo:latest
command: ros2 launch greengrass_bridge greengrass_bridge.launch.py ros_topics:="['chatter']" iot_topics:="['chatter']"
environment:
- AWS_REGION
- SVCUID
- AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT
- AWS_CONTAINER_AUTHORIZATION_TOKEN
- AWS_CONTAINER_CREDENTIALS_FULL_URI
volumes:
- "/greengrass/v2/ipc.socket:/greengrass/v2/ipc.socket"

設備B —

version: "3"
services:
greengrass_demo_image:
build:
context: ./
image: ros-foxy-greengrass-demo:latest

listener:
image: ros-foxy-greengrass-demo:latest
command: ros2 run demo_nodes_cpp listener
greengrass_bridge:
image: ros-foxy-greengrass-demo:latest
command: ros2 launch greengrass_bridge greengrass_bridge.launch.py ros_topics:="['chatter']" iot_topics:="['chatter']"
environment:
- AWS_REGION
- SVCUID
- AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT
- AWS_CONTAINER_AUTHORIZATION_TOKEN
- AWS_CONTAINER_CREDENTIALS_FULL_URI
volumes:
- "/greengrass/v2/ipc.socket:/greengrass/v2/ipc.socket"

並將greengrass_bridge中的iot_topics改成與ros_topics相同,如此便會將該topic廣播給所有連上Greengrass相同group的devices。(但這樣的方式會造成channel相同產生自己傳給自己的狀況,增加latency)

或者在Greengrass上建立rule(SQL)將ros_topics轉送至iot_topics。

SELECT * FROM “chatter”

這樣的步驟的確比設定VPN簡單多XD。

接下來應該是把整個CI/CD串起來,完成devops的精神。

而Greengrass本身並未包含CI的部分,下篇將整合Jenkins CI+EKS與Greengrass的CD,達到最終完整IoT ROS based的CI/CD建置。

後話: AWS雖為雲端服務龍頭,網上有很大量的技術文件與多種服務混用的教學文章,但使用者介面仍然有許多需要改善的空間。其實滿多可以簡單透過提醒文字的修改,就能讓介面更friendly。

比如:

(1)EKS的naming與eksctl控制CloudFormation的naming衝突的問題,導致客戶需要重建EKS。

(2)每次使用任何服務的指令,都要輸入region,這實在很蠢,因為region對於用戶來說是無意義,我不會在乎我的機器要放在雲端的哪裡,你只要給我最快可以access到的機器就好。其他競爭對手是相對使用較為合理resource group來指定客戶之前就定義好的region,做為kubernetes要使用的cluster name的所在群組。

有關EKS的難用之處,這篇文章講得還滿忠肯的XD

而support center的technical consultant雖然對於AWS的指令與介面非常熟悉,回覆也非常迅速(可見AWS的support group非常龐大),但仍然很多時候的狀況,是無法親自協助客戶debug客戶所在的真實環境。

AWS提供強大的solution很好,但客戶有時候是需要快速地POC(proof of concept);有時候解決這些問題,不是要馬上用root cause來完整的呈現solution,workaround讓東西先work可以驗證是很重要的

AWS提供很多服務且專有名詞甚多,有靈活設定的系統彈性很好,但對於非極專業的網管架構人員,希望也能考量沒有AWS證照的人員,把介面設計的這些人也能操作。

--

--

Ivan Chiou
The Messiah Code 神碼技術共筆

Rich experience in multimedia integration, cross-functional collaboration, and dedicated to be a mentor for young developers.