从零开始使用 ROS CDK 搭建云上解决方案
作者: 金湛
前言
資源編排服務ROS(Resource Orchestration Service)是阿里云提供的一項簡化云計算資源管理的服務。開發者和管理員可以編寫模板,在模板中定義所需的阿里云資源(例如:ECS實例、RDS數據庫實例)、資源間的依賴關系等。ROS的編排引擎將根據模板自動完成所有資源的創建和配置,實現自動化部署及運維。
??為什么選擇ROS資源編排
企業云上大量的資源管理需求帶來了效率、合規和成本方面的挑戰,ROS可以幫助您輕松管理多個資源:
- 采用基礎設施即代碼(Infrastructure as Code, IaC)的設計理念,模板的管理融入CI/CD流程,確保合規性。
- 無需手動創建多個資源,使用模板一鍵部署多個資源。
- 提供大量模板示例和解決方案示例,幫助企業客戶部署復雜解決方案。
- 利用云上彈性,按需批量部署和釋放資源,節省成本。
更多選擇理由,請參見產品優勢和應用場景。
本文將以一個小白視角,探索如何根據阿里云的文檔從0開始寫一篇ROS資源編排的代碼。
1??Part1: 工具準備
注:本次教程所有的操作均基于macos,其他平臺的操作請自行稍作修改
1. ROS CDK安裝
阿里云ROS CDK(Cloud Development Toolkit)是資源編排(ROS)提供的一種命令行工具,幫助您使用多種編程語言定義云資源。您無需使用繁瑣的JSON或YAML模板語法,即可使用ROS CDK完成資源的創建和配置,實現自動化部署及運維。寫一篇ROS自動化測試腳本的第一步是安裝ROS CDK工具。如何安裝ROS在幫助文檔中已經寫得非常詳細。
https://help.aliyun.com/zh/ros/developer-reference/install-ros-cdk?spm=a2c4g.11186623.0.i1
2. python環境安裝
a. 使用Anaconda(推薦)
ⅰ. 開源、免費,強大的python環境管理軟件,社區版包含很多常用軟件
?
ⅱ. 簡單、方便的環境隔離與虛擬環境創建
ⅲ. Anaconda 還附帶了一個叫做 Navigator(導航)的桌面 GUI 工具,可以直觀地創建和管理環境,安裝、刪除擴展包
ⅳ. 下載鏈接:https://repo.anaconda.com/archive/Anaconda3-2023.09-0-MacOSX-arm64.pkg
b. 直接安裝python
ⅰ. 下載鏈接:https://www.python.org/downloads/release/python-3120/
3. IDE、代碼編輯器推薦
a. VScode(推薦)
?
ⅰ. 開源免費、輕量的代碼編輯器
ⅱ. 社區生態好、更新快
ⅲ. 插件生態眾多,推薦部分插件
- Python
- Atom Material Icons
- GitLens — Git supercharged
- IntelliCode
ⅳ. 下載鏈接:https://az764295.vo.msecnd.net/stable/1a5daa3a0231a0fbba4f14db7ec463cf99d7768e/VSCode-darwin-universal.zip
b. pycharm
?
ⅰ. 開箱即用、功能強大的IDE
ⅱ. 補全、代碼檢查等功能做得較好
ⅲ. 下載鏈接:https://download.jetbrains.com.cn/python/pycharm-community-2023.2.4-aarch64.dmg
4. AI編碼插件
使用AI編碼插件可以大幅提升代碼編寫效率,最經典的插件是Github Copilot,功能包括行/函數級自動續寫、自然語言生成代碼、生成單元測試、生成代碼注釋等等,然而這是一個收費插件(10美元/月),有很多免費版的插件可以平替,這里推薦幾個
a. 通義靈碼
ⅰ. 通義千問系列產品,目前已經開放公測,阿里云賬號可以直接使用
ⅱ. 功能簡介與下載鏈接:https://tongyi.aliyun.com/lingma
ⅲ. 代碼解釋,詢問一段代碼是什么意思,幫忙理解代碼邏輯,這里給出一段阿里云ROS的代碼,但是插件給出的解釋是AWS的CDK,但是除了這一點錯誤,其余的代碼解釋都是正確的
ⅳ. AI代碼生成(根據注釋生成代碼),這里我只寫了注釋「#創建安全組」,插件自動幫我生成了一段代碼來放開80端口
b. Amazon CodeWhisperer
ⅰ. AWS出品的AI編碼工具,免費
ⅱ. 功能簡介與下載鏈接:https://aws.amazon.com/cn/codewhisperer/
c. CodeGeeX
ⅰ. 模型開源:https://github.com/THUDM/CodeGeeX2
ⅱ. 功能簡介與下載鏈接:https://codegeex.cn/
2??Part2: 環境準備
1. 創建工程目錄并初始化工程
進入終端,執行以下命令,創建工程目錄并初始化工程。每個ROS CDK應用都要求創建在一個獨立的工程目錄下,且該應用需要使用獨立工程目錄中模塊的依賴項。所以在創建應用之前,需要先創建一個工程目錄并進行初始化。
#創建iac-ros-cdk文件夾
mkdir iac-ros-cdk
#進入iac-ros-cdk文件夾
cd iac-ros-cdk
#使用ros cdk初始化項目
ros-cdk init --language=python --generate-only=true
2. 創建虛擬環境
Python工程的運行依賴于虛擬環境(virtualenv),所以在初始化Python工程之后需要創建一個屬于當前工程的虛擬環境。
python3 -m venv .venv
3. 進入虛擬環境
source .venv/bin/activate
4. 測試環境是否創建成功
在終端執行以下命令,測試環境是否創建成功
python
若出現此界面則說明你的虛擬環境已經創建成功,此時的項目應該是這樣的
5. 在編譯器中配置環境
打開項目中的一個示例python文件「iac_ros_cdk_stack.py」,在VScode中選擇python解釋器,開始編寫python代碼
6. 安裝需要的包
此時無法解析編譯器無法解析「ros_cdk_core」,表明當前python環境「.venv」里沒有這個包
在VScode中新建終端,終端會自動執行命令切換到當前目錄并激活「.venv」環境
將pip源換成清華大學的源,加速pip安裝包的速度(可選),然后執行pip install xx,在「.venv」環境中安裝包
示例,換源并安裝「ros_cdk_core」這個包
以上安裝方式對應的是單次安裝一個包的情況,如果你需要安裝很多包,可以在「requirements.txt」中添加你需要的包
然后在終端中執行如下命令來安裝「requirements.txt」中寫的所有包
#安裝requirements.txt中寫的包
pip install -r requirements.txt
7. 配置阿里云憑證信息
# 將pip的源換為國內的清華源,加速下載,這一步為可選項
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 安裝ros_cdk_core
pip install ros_cdk_core
登錄阿里云官網,獲取當前賬號的AK信息
執行以下命令,配置阿里云憑證信息。
ros-cdk config
根據界面提示輸入配置信息。
endpoint(optional, default:https://ros.aliyuncs.com):
defaultRegionId(optional, default:cn-hangzhou):cn-hangzhou
[1] AK
[2] StsToken
[3] RamRoleArn
[4] EcsRamRole
[0] CANCEL
Authenticate mode [1...4 / 0]: 1
accessKeyId:************************
accessKeySecret:******************************
? Your cdk configuration has been saved successfully!
配置內容說明:
- endpoint:ROS服務地址。默認值為https://ros.aliyuncs.com。
- defaultRegionId:ROS資源棧部署的地域。默認值為cn-hangzhou。
- Authenticate mode:鑒權方式。本示例的鑒權方式為AccessKey,您需要輸入AccessKey ID和AccessKey Secret。關于如何獲取AccessKey,請參見交互式配置(快速配置)。
3??Part3: 代碼編寫演示
1. 代碼文件建立與命名規范
找到需要轉成 CDK 的技術解決方案文檔,這里有一個示例
https://help.aliyun.com/zh/ecs/use-cases/build-an-ftp-site-on-an-instance-that-runs-alibaba-cloud-linux
完整代碼如下
https://github.com/XiaoTianJianJun/ROS_JINZ_DEV/blob/master/examples/documents/ros/usage-examples/python/python_cdk/ECS/deploy_FTP_on_ECS_460772.py
新建文件,可注意以下規范
-
文件正確歸類—計算的ROS代碼應該放在ECS目錄下
-
文件正確命名—deploy_FTP_on_ECS_460772.py
- 「deploy_FTP_on_ECS」描述文檔測試內容,在ECS上部署FTP服務
- 「460772」該文檔的id
-
類的正確命名
- 類名應遵循 CapWords 約定 (https://copyprogramming.com/howto/capwords-conventions-get-myclass-or-get-my-class)
- 類名應該能體現當前類的功能,比如「DeployFTP」
2. 找尋文檔描述的前提條件
一般文檔會描述實驗前需要部署的資源,比如本篇文檔規定了以下內容
- 實例規格:ecs.g6.large
- 操作系統:Alibaba Cloud Linux 3.2104 LTS 64位
現在已經知道需要首先建立一個ECS,建立ECS需要以下依賴資源
- VPC
- Vswitch
- 安全組
那么已經可以明確你的ROS代碼需要編排的資源清單
3. 分步驟編寫代碼
如果是沒用過的資源怎么找必填參數、怎么填寫參數(通過文檔,比如https://help.aliyun.com/zh/ros/developer-reference/datasource-cs-clusternodepools)
a. 建立VPC
# 創建VPC
vpc = ecs.Vpc(
self,
"VPC",
ecs.VPCProps(
cidr_block="10.0.0.0/8",
vpc_name="ftp-ros-cdk-vpc",
description="This is ros python cdk from jinzhan",
),
)
b. 建立VSwitch
# 創建交換機
vswitch = ecs.VSwitch(
self,
"VSwitch",
ecs.VSwitchProps(
zone_id=zone_id_param,
vpc_id=vpc.resource.ref,
cidr_block="10.0.0.0/20",
),
)
c. 創建ECS
ⅰ. 首先定義ECS的密碼
# 設置ECS實例密碼
ecs_password_param = core.RosParameter(
self,
"ECS_password",
type=core.RosParameterType.STRING,
association_property="ALIYUN::ECS::Instance::Password",
default_value="Jinz_Aliyun1",
)
ⅱ. 定義ECS使用的鏡像
# 設置ECS實例鏡像
image_id_param = core.RosParameter(
self,
"ImageId",
default_value="aliyun_3_x64_20G_alibase_20230629.vhd",
type=core.RosParameterType.STRING,
description={"zh-cn": "鏡像ID", "en": "Image ID"},
label="公共鏡像Alibaba Cloud Linux 3.2104 LTS 64位",
)
ⅲ. 設置ECS的實例類型
# 設置ECS實例類型
instance_type_param = core.RosParameter(
self,
"InstanceType",
association_property="ALIYUN::ECS::Instance::InstanceType",
association_property_metadata={"ZoneId": "ZoneId"},
default_value="ecs.g6.large",
label="Instance Type",
type=core.RosParameterType.STRING,
description={},
)
ⅳ. 設置ECS的區域
# 地區id類型
zone_id_param = core.RosParameter(
self,
"ZoneId",
type=core.RosParameterType.STRING,
association_property="ALIYUN::ECS::Instance::ZoneId",
default_value="cn-hangzhou-k",
)
ⅴ. 創建ECS實例,按照文檔的要求在ECS上執行命令
# 創建ECS實例
ecs_instance = ecs.Instance(
self,
"ECS-demo",
ecs.InstanceProps(
instance_name="ecs-jinzhan-agent-ros-python-cdk",
vpc_id=vpc.resource.ref,
v_switch_id=vswitch.resource.ref,
security_group_id=sg.resource.ref,
image_id=image_id_param,
instance_type=instance_type_param,
instance_charge_type="PayAsYouGo",
password=ecs_password_param,
allocate_public_ip=True,
user_data=core.FnReplace(
value=[
{"ros-notify": wait_condition_handle_param.attr_curl_cli},
{
"Fn::Join": [
"",
[
"#!/bin/bash\n",
"dnf install -y vsftpd\n",
"systemctl enable vsftpd.service\n",
"systemctl start vsftpd.service\n",
"netstat -antup | grep ftp\n",
"adduser ftptest\n",
# 將ftp用戶密碼設置為abc123
"sudo chpasswd <<< "ftptest:abc123"\n",
"mkdir /var/ftp/test\n",
"touch /var/ftp/test/testfile.txt\n",
"chown -R ftptest:ftptest /var/ftp/test\n",
"sudo echo '#!/bin/bash' | sudo tee update_vsftpd_conf.sh\n",
'''sudo echo 'if [ -f "/etc/vsftpd/vsftpd.conf" ]; then \n sed -i "s/^anonymous_enable=.*/anonymous_enable=NO/" /etc/vsftpd/vsftpd.conf \n sed -i "s/^local_enable=.*/local_enable=YES/" /etc/vsftpd/vsftpd.conf\n sed -i "s/^listen=.*/listen=YES/" /etc/vsftpd/vsftpd.conf\n echo "修改成功!"\nelse\n echo "vsftpd.conf文件不存在。"\nfi' | sudo tee -a update_vsftpd_conf.sh'''
"\n",
"sudo chmod +x update_vsftpd_conf.sh\n",
"sudo ./update_vsftpd_conf.sh\n",
# 在行首添加#注釋掉listen_ipv6=YES,關閉監聽IPv6 sockets
"sudo sed -i 's/^listen_ipv6=YES/#&/' /etc/vsftpd/vsftpd.conf\n",
"sudo tee -a /etc/vsftpd/vsftpd.conf << EOF\n",
"#設置本地用戶登錄后所在目錄。\n"
"local_root=/var/ftp/test\n",
"#全部用戶被限制在主目錄。\n",
"chroot_local_user=YES\n",
"#啟用例外用戶名單。\n",
"chroot_list_enable=YES\n",
"#指定例外用戶列表文件,列表中用戶不被鎖定在主目錄。\n",
"chroot_list_file=/etc/vsftpd/chroot_list\n",
"#開啟被動模式。\n",
"pasv_enable=YES\n",
"allow_writeable_chroot=YES\n",
"#本教程中為Linux實例的公網IP。\n",
"EOF\n",
# 創建update_vsftpd_conf_ip.sh腳本,將獲取本機ip并替換pasv_address=<本機ftp地址>
"echo '#!/bin/bash' > update_vsftpd_conf_ip.sh\n",
"echo '' >> update_vsftpd_conf_ip.sh\n",
"echo 'public_ip=$(curl -s ifconfig.me)' >> update_vsftpd_conf_ip.sh\n"
"echo '' >> update_vsftpd_conf_ip.sh\n",
'''echo 'sudo sh -c "echo "pasv_address=$public_ip" >> /etc/vsftpd/vsftpd.conf"' >> update_vsftpd_conf_ip.sh\n''',
"echo '' >> update_vsftpd_conf_ip.sh\n",
"chmod +x update_vsftpd_conf_ip.sh\n",
"./update_vsftpd_conf_ip.sh\n",
"sudo tee -a /etc/vsftpd/vsftpd.conf << EOF\n",
"#設置被動模式下,建立數據傳輸可使用的端口范圍的最小值。\n",
"#建議您把端口范圍設置在一段比較高的范圍內,例如50000~50010,有助于提高訪問FTP服務器的安全性。\n",
"pasv_min_port=50000\n",
"#設置被動模式下,建立數據傳輸可使用的端口范圍的最大值。\n",
"pasv_max_port=50010\n",
"EOF\n",
"touch /etc/vsftpd/chroot_list\n",
"systemctl restart vsftpd.service\n"
],
]
},
]
),
),
)
d. 創建安全組
# 創建安全組
sg = ecs.SecurityGroup(
self,
"SecurityGroup",
ecs.SecurityGroupProps(
vpc_id=vpc.resource.ref,
),
)
e. 添加安全組入方向端口
# 添加安全組入方向端口
sg_ingress_50000_50010 = ecs.SecurityGroupIngress(
self,
"SecurityGroupIngress_80",
ecs.SecurityGroupIngressProps(
security_group_id=sg.resource.ref,
source_cidr_ip="0.0.0.0/0",
ip_protocol="tcp",
nic_type="intranet",
port_range="50000/50010",
),
)
sg_ingress_21 = ecs.SecurityGroupIngress(
self,
"SecurityGroupIngress_8080",
ecs.SecurityGroupIngressProps(
security_group_id=sg.resource.ref,
source_cidr_ip="0.0.0.0/0",
ip_protocol="tcp",
nic_type="intranet",
port_range="21/21",
),
)
sg_ingress_22 = ecs.SecurityGroupIngress(
self,
"SecurityGroupIngress_22",
ecs.SecurityGroupIngressProps(
security_group_id=sg.resource.ref,
source_cidr_ip="0.0.0.0/0",
ip_protocol="tcp",
nic_type="intranet",
port_range="22/22",
),
)
f. 使用云助手運行命令
# 安全組:入方向添加安全組規則并放行50000/50010、22、21端口
install_ftp = ecs.RunCommand(
self,
"InstallFTP",
ecs.RunCommandProps(
instance_ids=[ecs_instance.attr_instance_id],
type="RunShellScript",
sync=True,
timeout=600,
command_content=""
),
)
# 如果開了安全組,才運行installftp
install_ftp.add_dependency(sg_ingress_50000_50010)
install_ftp.add_dependency(sg_ingress_22)
install_ftp.add_dependency(sg_ingress_21)
g. 添加輸出
# Output
core.RosOutput(self, "FTP URL",
value=core.FnJoin("", ["ftp://", ecs_instance.attr_public_ip, ":21"]), description="FTP User:ftptest, FTP Password:abc123, port:21, 50000/50010")
h. 更改app.py文件
修改app.py文件,導入你剛剛寫好的文件,起個名字,這里起名叫「FTP-stack」
#!/usr/bin/env python3 ***
import ros_cdk_core as core
from python_cdk.ECS.deploy_FTP_on_ECS_460772 import DeployFTP
app = core.App()
DeployFTP(app, "FTP-stack")
app.synth()
4. 如何創建shell腳本來執行復雜命令
此文檔中有一些復雜操作,無法使用簡單的一兩句命令來實現,這時候需要使用shell腳本來完成操作,例如這里需要使用vim來更改文件,在文件末尾添加參數并且注釋某些行,顯然這里已經無法使用簡單的命令行來完成了。
這時候比較考驗你的代碼能力,如果你實在不清楚shell腳本怎么編寫,這時候應該拿出我們的最強AI編碼工具Chatgpt。使用Chatgpt來輔助我們編寫代碼。
此時GPT給出了一個實現此功能的腳本,但是此腳本需要你手動創建文件,在ROS中我們需要純命令完成,那要如何解決?
現在gpt給出了純命令行版本,你只需要將這段命令添加上引號,按照python中的代碼規范填入user_data中,這段任務就完成了。其他比較復雜的操作類似
4??Part4: 使用代碼部署資源
1. 使用ROS CDK部署資源
打開終端,執行如下命令,其中「FTP-stack」是你在app.py中起的名字
ros-cdk synth FTP-stack -j
ros-cdk deploy FTP-stack --sync=true
看到如下輸出說明第一行執行成功
看到如下輸出說明第二行執行成功
2. 檢查資源部署情況
從控制臺打開資源編排,查看事件。如果你的資源狀態沒有任何回滾,說明至少此次的資源部署是成功的
5??Part5: 驗證任務是否完成
1. 進入ECS查詢日志文件
連接你創建的ECS,執行如下命令,查看每一步命令是否都執行成功
less /var/log/cloud-init-output.log
比方說我此時看到的結果如下,認真查看發現沒有報錯,那可以暫時確定ECS上所有的命令都成功執行
2. 手動驗證任務是否完成
此文檔的最終目的是建立一個FTP服務器,那么需要我們手動驗證服務器是否建立成功,文檔原文如下
現在已經完成資源部署,ECS上的命令也已經按照文檔全部執行完成。最后還需要手動驗證一下FTP服務器是否建立成功,可以在自己的電腦上連接創立的FTP服務器,檢查FTP服務是否正常運行
可以看到成功連接服務器,并且服務器上有文件,那么此次ROS文檔測試完成。
3. 當你確定你此次任務完成,請及時銷毀資源
ros-cdk destroy FTP-stack --sync=true
4. 將完成的代碼更新推送到Github上
初次配置git
https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%88%9D%E6%AC%A1%E8%BF%90%E8%A1%8C-Git-%E5%89%8D%E7%9A%84%E9%85%8D%E7%BD%AE
git常用命令
https://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
# 初始化git
git init
# 將本地倉庫與遠程倉庫關聯
git remote add origin https://github.com/XiaoTianJianJun/ROS_JINZ_DEV/tree/master
# 創建名為jinz_dev的分支
git checkout -b jinz_dev
# 添加本次修改的內容
git add .
# 簡要介紹一下本次修改的內容
git commit -m "Initial commit"
# 將更改推送到代碼倉庫
git push origin jinz_dev
6??Part6: 彈藥庫
- ROS CDK官方文檔是一個很好的學習途徑
- OpenAPI CDK:cdk的代碼示例可以查看openapi對應產品的cdk頁面,可以動態根據輸入參數輸出運行示例
- 模版示例
- Chatgpt
總結
??核心內容:未接觸過ROS資源部署的新人如何快速上手
-
全流程演示ROS資源編排:本文詳細描述了從零開始完成一次ROS資源編排的代碼編寫的過程。它包含了可能遇到的大部分問題,并致力于讓初學者也能夠快速上手。
-
ROS的優勢:ROS資源編排能夠提高云資源的管理效率和穩定性,減少人工操作和錯誤,同時提供了可視化的監控和安全可靠的保障。
-
寫代碼遇到困難如何解決:
- 善用搜索引擎,自行解決問題
- 使用AI工具,提升編碼效率
- 遇到不懂的問題時,積極向他人請教
總結
以上是生活随笔為你收集整理的从零开始使用 ROS CDK 搭建云上解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 女人梦见给猫喂食是什么预兆
- 下一篇: 梦见自己与陌生人结婚是什么意思