记一次饱经挫折的阿里云ROS部署经历

前言

最近在参加的几个项目测评里,我发现**“一键部署”这功能真心好用,省下了不少宝贵时间和力气,再加上看到阿里云现在有个开源上云**的活动。趁着这波热潮,今天就聊聊怎么从头开始,一步步搞定阿里云的资源编排服务(ROS),希望能对刚接触这块的朋友有点帮助。咱们一块儿边学边实践,让云上的项目部署变得更简单高效。

资源编排

阿里云的资源编排服务(Resource Orchestration Service,简称ROS)是一种基础设施即代码(IaC)服务,它允许用户通过编写模板来定义和管理云上的各种资源。这些资源包括但不限于ECS( Elastic Compute Service)实例、RDS(Relational Database Service)数据库实例、SLB(Server Load Balancer)负载均衡器等。ROS的核心价值在于自动化部署及运维,它能自动处理资源的创建、配置及之间的依赖关系,从而极大地简化了云计算资源的管理过程。

在ROS中,用户根据ROS提供的模板规范,使用JSON或YAML格式编写资源栈模板。模板中不仅定义了所需的资源类型和数量,还明确了资源之间的逻辑依赖,确保资源按正确的顺序被创建和配置。这样,无论是新建环境、更新配置还是进行大规模的架构调整,都可通过执行模板脚本来实现,保证了操作的一致性和可重复性。

资源编排地址如下:https://ros.console.aliyun.com/cn-hangzhou/welcome

image.png

下面我们还是以实战为导向,从最基础的ROS脚本开始看起,一步步拆解。

ROS模板

首先我们先看一下ROS模板结构及参数说明。

{"ROSTemplateFormatVersion" : "2015-09-01","Description" : "模板描述信息,可用于说明模板的适用场景、架构说明等。","Metadata" : {// 关于模板的元数据信息,例如存放用于可视化的布局信息。},"Parameters" : {// 定义创建资源栈时,用户可以定制化的参数。},"Mappings" : {// 定义映射信息表,映射信息是一种多层的Map结构。},"Conditions": {// 使用内部条件函数定义条件。这些条件确定何时创建关联的资源。},"Resources" : {// 所需资源的详细定义,包括资源间的依赖关系、配置细节等。},"Outputs" : {// 用于输出一些资源属性等有用信息。可以通过API或控制台获取输出的内容。}
}

【参数说明】:

  • ROSTemplateFormatVersion必选,ROS支持的模板版本号,当前版本号:2015-09-01。

  • Description:可选,模板的描述信息。可用于说明模板的适用场景、架构说明等。通常情况下,对模板进行详细描述,有利于用户理解模板的内容。

  • Metadata:可选,模板编写者可以使用Metadata来存放与模板相关的元数据信息,内容可以为JSON格式。

  • Parameters:可选,定义创建资源栈时,模板用户可以定制化的参数。通常,模板的编辑者会把ECS的规格设计成一个参数。参数支持默认值。使用参数可以增强模板的灵活性,提高复用性。使用模板创建资源栈时,可以根据实际的评估结果来选择合适的规格。更多详细信息,请参见参数(Parameters)。

  • Mappings:可选,Mappings定义了一个多层的映射表,可以通过Fn::FindInMap函数来选择Key对应的值,或根据不同的输入参数值作为Key来查找映射表。例如,您可以根据Region不同,自动查找Region-镜像映射表,从而找到适用的镜像。更多详细信息,请参见映射(Mappings)。

  • Conditions:可选,Conditions使用Fn::And、Fn::Or、Fn::Not、Fn::Equals定义条件。多个条件之间使用半角逗号(,)隔开。在创建或更新资源栈时,系统先计算模板中的所有条件,然后再创建资源。创建与true条件关联的所有资源,忽略与false条件关联的所有资源。更多详细信息,请参见条件(Conditions)。

  • Resources:可选,用于详细定义使用该模板创建的资源栈所包含的资源,包括资源间的依赖关系、配置细节等。更多详细信息,请参见资源(Resources)。

  • Outputs:可选,用于输出一些资源属性等有用信息。可以通过API或控制台获取输出的内容。更多详细信息,请参见输出(Outputs)。

通过上面可以看出最核心、最关键的部分其实是ParametersResources , 因为这两个决定了模板设计者定义一系列可配置的参数和将要创建或管理的所有云资源及其配置,是直接涉及资源创建和配置的核心逻辑参数。

下面我们来创建第一个案例。

基于ROS模板创建VPC

在创建之前,我们需要先知道ROS支持的所有资源类型,这里需要查看资源类型索引。

image.png

如果在这个列表中没有出现的产品,就是暂时不支持采用ROS来创建的,这是需要明确的第一点。

如上图,我们看到VPC是支持使用ROS来创建的,接下来我们再开展第二步,点击这个蓝色链接位置,查看它的详细语法、属性及返回值。

image.png

到这里,我们基本就明白它的语法格式及书写方式了,下面第三步,上手开写。

回到资源编排界面,点击【我的模板】→【创建模板】,进去ROS在线编辑界面开始编辑。

image.png

初始的模板如下,我们选择为yaml格式来进行编写。

image.png

下面咱们一行行的分析:

ROSTemplateFormatVersion

默认版本号,这里不用修改,直接过

ROSTemplateFormatVersion: '2015-09-01'

Description

这里不是必填,不过也可以填一下,暂且起名为my first VPC-test

Description: my first VPC-test

Parameters

这里到重头戏了,几乎所有的可定制化参数都是在这里修改的,在比较复杂的ROS脚本中几乎都会用到,但是这里为了方便演示,也选择暂时不填写,等下后面测试时再填写后对比。

Parameters: {}

Resources

这里是用来详细定义使用该模板创建的资源栈所包含的资源,包括资源间的依赖关系、配置细节等,是必填项

而其具体的格式,可以看到如下:

image.png

这里我们沿用该格式,并且剔除一些不需要的参数,最终命令如下:

 VPC:Type: ALIYUN::ECS::VPCProperties:VpcName: VPC-testCidrBlock: 192.168.0.0/24

这里面就只包含了最基础的CidrBlock(专有网络网段)和VpcName(专有网络名称)。

Mappings、Metadata、Conditions

这里也暂时不涉及,可以直接删除掉。

Outputs

这里用于输出一些资源属性等有用信息,这里我们可以尝试输出一下VPC的ID和关联的虚拟路由器ID

Outputs:VPCId:Value:Fn::GetAtt:- VPC- VRouterIdVRouterId:Value:Fn::GetAtt:- VPC- VRouterId

参照返回示例如下

image.png

最终ROS的整体脚本如下:

ROSTemplateFormatVersion: '2015-09-01'
Description: my first VPC-test
Resources:VPC:Type: ALIYUN::ECS::VPCProperties:VpcName: VPC-testCidrBlock: 192.168.0.0/24
Outputs:VPCId:Value:Fn::GetAtt:- VPC- VRouterIdVRouterId:Value:Fn::GetAtt:- VPC- VRouterId

点击预览,查看资源架构,我们可以看到如图所示的架构:

image.png

确定之后点击保存模板,命名后可在模板空间中查看和直接创建栈:

image.png
image.png

选择失败时回滚,点击创建:

image.png

此时可以看到开始创建资源栈,等待一段时间:

image.png

创建成功后如下图所示:

image.png

点击输出,我们可以看到outputs中设定的输出的关键字

image.png

而假如我们不需要使用了,也可以直接点击删除资源栈:

image.png

以上是手动编写脚本的流程了,在实际调试中还是有一些复杂的,下面我们就来结合案例,完成这次参赛的ROS部署作品。

基于ROS部署MaxKB

MaxKB

MaxKB是基于LLM大语言模型的知识库问答系统,旨在成为企业的最强大脑。它支持开箱即用,无缝嵌入到第三方业务系统,并提供多模型支持,包括主流大模型和本地私有大模型,为用户提供智能问答交互体验和灵活性。

image.png

另外说一句,我的关于知识库侧测评的文章也已经快写完了,这几个月参加护网有点太累了,几乎没时间来写,抱歉抱歉!

编写ROS 模板

这里我们还是一步步的来,逐步解析。

ROSTemplateFormatVersion

老规矩,不变。

ROSTemplateFormatVersion: '2015-09-01'

Description

因为是参赛的作品,所以我这里也写的详细一点吧,下面也是带上了中英的描述。

Description:en: Setting up the large language model-based knowledge base question and answer system, MaxKB, on an ECS (Elastic Compute Service) instance.zh-cn:ECS实例上搭建大语言模型的知识库问答系统MaxKB。

Parameters

这里涉及到的就比较复杂了,因为此处是必须要进行一些自定义参数设置的,我们进到ECS的语法下面详细查看。

说实话,有点吓人,居然这么多!

image.png

我们按照下面这个表格来一一排查:

image.png

ZoneId

这里首先申明ZoneId , 至于为什么先申明ZoneId呢?这是因为区域(Zone)的选择对创建的云资源(如ECS实例、RDS数据库等)有着直接的影响,且下面在申明实例规格时会用到。

ZoneId:Type: StringLabel:en: Availability Zonezh-cn: 可用区IDAssociationProperty: ALIYUN::ECS::Instance:ZoneId

AssociationProperty 说明ZoneId参数与ECS实例的ZoneId属性关联。这意味着在模板中使用此参数的地方,我们所选择的值将会直接应用于创建ECS实例时的可用区选择。这样的设计确保了模板的逻辑与阿里云ECS服务的实际属性紧密集成,提高了模板的准确性和易用性。

InstanceType

ECS实例规格 ,必填项 ,这里需要参考实例规格族。

 InstanceType:Type: StringLabel:en: Instance Typezh-cn: 实例类型AssociationProperty: ALIYUN::ECS::Instance::InstanceTypeAssociationPropertyMetadata:ZoneId: ${ZoneId}DefaultValueStrategy: recent

同样,这里的 AssociationProperty 是指明参数与ECS实例的InstanceType属性关联;而 AssociationPropertyMetadata 则是表示实例类型的可用性依赖于ZoneId中选择的区域ID,且当用户没有明确指定实例类型时,系统会选择最近常用或推荐的实例类型作为默认选项。

SystemDiskCategory

下面定义ECS实例系统盘的类型,其中,AssociationPropertyMetadata 里面包含了一些元数据来指导和约束系统盘类型的选择:

SystemDiskCategory:Type: StringLabel:en: System Disk Typezh-cn: 系统盘类型AssociationProperty: ALIYUN::ECS::Disk::SystemDiskCategoryAssociationPropertyMetadata:LocaleKey: DiskCategoryZoneId: ${ZoneId}InstanceType: ${InstanceType}AutoSelectFirst: trueAutoChangeType: falseDefault: cloud_essd
InstancePassword

下面定义了用于登录ECS实例的密码规则,确保了安全性的同时也提供了一定的灵活性:

InstancePassword:Type: StringLabel:en: Instance Passwordzh-cn: 实例密码Description:en: Server login password, Length 8-30, must contain three(Capital letters,lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbolin).zh-cn: 服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。ConstraintDescription:en: Length 8-30, must contain three(Capital letters, lowercase letters, numbers,()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in).zh-cn: 长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。AssociationPropertyMetadata:Visible:Condition:Fn::Equals:- ${SelectInstance}- falseDefault:AllowedPattern: '[0-9A-Za-z\_\-\&:;''<>,=%`~!@#\(\)\$\^\*\+\|\{\}\[\]\.\?\/]+$'MinLength: 8MaxLength: 30NoEcho: true

所以Parameters此处的完整脚本如下:

Parameters:ZoneId:Type: StringLabel:en: Availability Zonezh-cn: 可用区IDAssociationProperty: ALIYUN::ECS::Instance:ZoneIdInstanceType:Type: StringLabel:en: Instance Typezh-cn: 实例类型AssociationProperty: ALIYUN::ECS::Instance::InstanceTypeAssociationPropertyMetadata:ZoneId: ${ZoneId}DefaultValueStrategy: recentSystemDiskCategory:Type: StringLabel:en: System Disk Typezh-cn: 系统盘类型AssociationProperty: ALIYUN::ECS::Disk::SystemDiskCategoryAssociationPropertyMetadata:LocaleKey: DiskCategoryZoneId: ${ZoneId}InstanceType: ${InstanceType}AutoSelectFirst: trueAutoChangeType: falseDefault: cloud_essdInstancePassword:Type: StringLabel:en: Instance Passwordzh-cn: 实例密码Description:en: Server login password, Length 8-30, must contain three(Capital letters,lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbolin).zh-cn: 服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。ConstraintDescription:en: Length 8-30, must contain three(Capital letters, lowercase letters, numbers,()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in).zh-cn: 长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。AssociationPropertyMetadata:Visible:Condition:Fn::Equals:- ${SelectInstance}- falseDefault:AllowedPattern: '[0-9A-Za-z\_\-\&:;''<>,=%`~!@#\(\)\$\^\*\+\|\{\}\[\]\.\?\/]+$'MinLength: 8MaxLength: 30NoEcho: true

Resources

这里开始创建资源,分析架构所需,涉及产品如下:

VPC

定义一个虚拟私有云(VPC)资源,192.168.0.0/16 指定了VPC的IP地址范围。

Vpc:Type: ALIYUN::ECS::VPCProperties:CidrBlock: 192.168.0.0/16
VSwitch

定义一个虚拟交换机(VSwitch)的配置:Ref: ZoneId 表示虚拟交换机将被创建在指定的可用区(Zone)中,这里的ZoneId是一个引用,其实际值需要在模板的参数或映射部分提前定义或通过外部参数传入;Ref: Vpc 指明该虚拟交换机隶属于哪个VPC。这里同样使用了引用,意味着VSwitch将与之前定义的VPC关联。确保在模板中已经定义了VPC资源或者通过参数传递了正确的VPC ID;192.168.0.0/24 定义了虚拟交换机的IP地址范围。

 VSwitch:Type: ALIYUN::ECS::VSwitchProperties:ZoneId:Ref: ZoneIdVpcId:Ref: VpcCidrBlock: 192.168.0.0/24
SecurityGroup

创建安全组:Ref: Vpc 指定该安全组将被创建在哪个VPC中,这里通过引用之前定义的VPC资源(Vpc),确保安全组与目标VPC正确关联。这一步是必要的,因为每个安全组都必须绑定到一个特定的VPC。

SecurityGroup:Type: ALIYUN::ECS::SecurityGroupProperties:VpcId:Ref: Vpc
SecurityGroupIngress_80

定义了入站规则:Ref: SecurityGroup 引用了之前定义的安全组ID,这条入站规则将被添加到该安全组中;0.0.0.0/0 指定任何IP地址(全网段)都可以作为流量的来源,这意味着对于这条规则,不限制访问的来源IP地址;**tcp **指定了该规则适用的协议类型,这里是TCP;intranet 表示这条规则仅适用于VPC内部的通信;80/80 定义了允许访问的端口范围,这里只开放了TCP 80端口,通常用于HTTP服务。

SecurityGroupIngress_80:Type: ALIYUN::ECS::SecurityGroupIngressProperties:SecurityGroupId:Ref: SecurityGroupSourceCidrIp: 0.0.0.0/0IpProtocol: tcpNicType: intranetPortRange: 80/80
InstanceGroup

定义实例群组:引用上面创建的Vpc、VSwitch和SecurityGroupId实例;指定使用CentOS 7.9的镜像;设置了实例的名称为MaxKB;后面继续引入实例类型、系统盘的类别和密码

InstanceGroup:Type: ALIYUN::ECS::InstanceGroupProperties:VpcId:Ref: VpcVSwitchId:Ref: VSwitchSecurityGroupId:Ref: SecurityGroupImageId: centos_7_9InstanceName: MaxKBInstanceType:Ref: InstanceTypeSystemDiskCategory:Ref: SystemDiskCategoryPassword:Ref: InstancePasswordIoOptimized: optimizedMaxAmount: 1
DS_Instances

通过DS_Instances数据源来获取通过InstanceGroup创建的ECS实例列表。

 DS_Instances:Type: DATASOURCE::ECS::InstancesProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIds
InstallMaxKB

这里使用到Formation模板中的ALIYUN::ECS::RunCommand资源类型配置,用于在特定的ECS实例上执行一系列Shell脚本命令。

InstallMaxKB:
Type: ALIYUN::ECS::RunCommandProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIdsType: RunShellScriptSync: trueTimeout: 1800CommandContent: |#!/bin/bashecho "#########################"echo "# Install Docker"echo "#########################"wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repoyum -y install docker-cesystemctl start dockersystemctl enable dockerecho "#########################"echo "# Install MaxKB"echo "#########################"yum -y install jqDOCKER_DAEMON_JSON="/etc/docker/daemon.json"sudo jq --arg registry "$NEW_REGISTRY" '. + { "registry-mirrors": [https://0jt38sli.mirror.aliyuncs.com] }' $DOCKER_DAEMON_JSON > ${DOCKER_DAEMON_JSON}.temp && sudo mv ${DOCKER_DAEMON_JSON}.temp $DOCKER_DAEMON_JSONsudo systemctl daemon-reloadsudo systemctl restart dockerdocker run -d --name=maxkb -p 8080:8080 -v ~/.maxkb:/var/lib/postgresql/data 1panel/maxkb

最终,Resources下脚本如下:

Resources:Vpc:Type: ALIYUN::ECS::VPCProperties:CidrBlock: 192.168.0.0/16VSwitch:Type: ALIYUN::ECS::VSwitchProperties:ZoneId:Ref: ZoneIdVpcId:Ref: VpcCidrBlock: 192.168.0.0/24SecurityGroup:Type: ALIYUN::ECS::SecurityGroupProperties:VpcId:Ref: VpcSecurityGroupIngress_80:Type: ALIYUN::ECS::SecurityGroupIngressProperties:SecurityGroupId:Ref: SecurityGroupSourceCidrIp: 0.0.0.0/0IpProtocol: tcpNicType: intranetPortRange: 80/80InstanceGroup:Type: ALIYUN::ECS::InstanceGroupProperties:VpcId:Ref: VpcVSwitchId:Ref: VSwitchSecurityGroupId:Ref: SecurityGroupImageId: centos_7_9InstanceName: difyInstanceType:Ref: InstanceTypeSystemDiskCategory:Ref: SystemDiskCategoryPassword:Ref: InstancePasswordIoOptimized: optimizedMaxAmount: 1DS_Instances:Type: DATASOURCE::ECS::InstancesProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIds
InstallMaxKB:
Type: ALIYUN::ECS::RunCommandProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIdsType: RunShellScriptSync: trueTimeout: 1800CommandContent: |#!/bin/bashecho "#########################"echo "# Install Docker"echo "#########################"wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repoyum -y install docker-cesystemctl start dockersystemctl enable dockerecho "#########################"echo "# Install MaxKB"echo "#########################"yum -y install jqDOCKER_DAEMON_JSON="/etc/docker/daemon.json"sudo jq --arg registry "$NEW_REGISTRY" '. + { "registry-mirrors": [https://0jt38sli.mirror.aliyuncs.com] }' $DOCKER_DAEMON_JSON > ${DOCKER_DAEMON_JSON}.temp && sudo mv ${DOCKER_DAEMON_JSON}.temp $DOCKER_DAEMON_JSONsudo systemctl daemon-reloadsudo systemctl restart dockerdocker run -d --name=maxkb -p 8080:8080 -v ~/.maxkb:/var/lib/postgresql/data 1panel/maxkb

Outputs

定义了名为 MaxKBUrl 的输出项,用于提供MaxKB服务的默认访问地址:

Outputs:MaxKBUrl:Description: MaxKB default address.Value:Fn::Sub:- http://${IP}- IP:Fn::Jq:- First- if .[0].PublicIpAddress != [] then .[0].PublicIpAddress[0] else .[0].EipAddress.IpAddressend- Fn::GetAtt:- DS_Instances- Instances

Metadata

添加了一个标签来描述此模板的功能和背景,按照比赛要求是需要采用“手机尾号-模板用途”来编写。

Metadata:ALIYUN::ROS::Interface:TemplateTags:- acs:developer:gitee:0147-ECS实例上搭建大语言模型的知识库问答系统MaxKB。

整体脚本

ROSTemplateFormatVersion: '2015-09-01'
Description:en: Setting up the large language model-based knowledge base question and answer system, MaxKB, on an ECS (Elastic Compute Service) instance.zh-cn:ECS实例上搭建大语言模型的知识库问答系统MaxKB。
Parameters:ZoneId:Type: StringLabel:en: Availability Zonezh-cn: 可用区IDAssociationProperty: ALIYUN::ECS::Instance:ZoneIdInstanceType:Type: StringLabel:en: Instance Typezh-cn: 实例类型AssociationProperty: ALIYUN::ECS::Instance::InstanceTypeAssociationPropertyMetadata:ZoneId: ${ZoneId}DefaultValueStrategy: recentSystemDiskCategory:Type: StringLabel:en: System Disk Typezh-cn: 系统盘类型AssociationProperty: ALIYUN::ECS::Disk::SystemDiskCategoryAssociationPropertyMetadata:LocaleKey: DiskCategoryZoneId: ${ZoneId}InstanceType: ${InstanceType}AutoSelectFirst: trueAutoChangeType: falseDefault: cloud_essdInstancePassword:Type: StringLabel:en: Instance Passwordzh-cn: 实例密码Description:en: Server login password, Length 8-30, must contain three(Capital letters,lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbolin).zh-cn: 服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。ConstraintDescription:en: Length 8-30, must contain three(Capital letters, lowercase letters, numbers,()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in).zh-cn: 长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。AssociationPropertyMetadata:Visible:Condition:Fn::Equals:- ${SelectInstance}- falseDefault:AllowedPattern: '[0-9A-Za-z\_\-\&:;''<>,=%`~!@#\(\)\$\^\*\+\|\{\}\[\]\.\?\/]+$'MinLength: 8MaxLength: 30NoEcho: true
Resources:Vpc:Type: ALIYUN::ECS::VPCProperties:CidrBlock: 192.168.0.0/16VSwitch:Type: ALIYUN::ECS::VSwitchProperties:ZoneId:Ref: ZoneIdVpcId:Ref: VpcCidrBlock: 192.168.0.0/24SecurityGroup:Type: ALIYUN::ECS::SecurityGroupProperties:VpcId:Ref: VpcSecurityGroupIngress_80:Type: ALIYUN::ECS::SecurityGroupIngressProperties:SecurityGroupId:Ref: SecurityGroupSourceCidrIp: 0.0.0.0/0IpProtocol: tcpNicType: intranetPortRange: 80/80InstanceGroup:Type: ALIYUN::ECS::InstanceGroupProperties:VpcId:Ref: VpcVSwitchId:Ref: VSwitchSecurityGroupId:Ref: SecurityGroupImageId: centos_7_9InstanceName: MaxKBInstanceType:Ref: InstanceTypeSystemDiskCategory:Ref: SystemDiskCategoryPassword:Ref: InstancePasswordIoOptimized: optimizedMaxAmount: 1DS_Instances:Type: DATASOURCE::ECS::InstancesProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIdsInstallMaxKB:Type: ALIYUN::ECS::RunCommandProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIdsType: RunShellScriptSync: trueTimeout: 1800CommandContent: |#!/bin/bashecho "#########################"echo "# Install Docker"echo "#########################"wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repoyum -y install docker-cesystemctl start dockersystemctl enable dockerecho "#########################"echo "# Install MaxKB"echo "#########################"yum -y install jqDOCKER_DAEMON_JSON="/etc/docker/daemon.json"sudo jq --arg registry "$NEW_REGISTRY" '. + { "registry-mirrors": [https://0jt38sli.mirror.aliyuncs.com] }' $DOCKER_DAEMON_JSON > ${DOCKER_DAEMON_JSON}.temp && sudo mv ${DOCKER_DAEMON_JSON}.temp $DOCKER_DAEMON_JSONsudo systemctl daemon-reloadsudo systemctl restart dockerdocker run -d --name=maxkb -p 8080:8080 -v ~/.maxkb:/var/lib/postgresql/data 1panel/maxkbOutputs:MaxKBUrl:Description: MaxKB default address.Value:Fn::Sub:- http://${IP}- IP:Fn::Jq:- First- if .[0].PublicIpAddress != [] then .[0].PublicIpAddress[0] else .[0].EipAddress.IpAddressend- Fn::GetAtt:- DS_Instances- Instances
Metadata:ALIYUN::ROS::Interface:TemplateTags:- acs:developer:gitee:0147-ECS实例上搭建大语言模型的知识库问答系统MaxKB

部署测试

回到我的模板中,点击我的模板,查看对应的资源框架,确认基本无误后点击保存。

image.png

命名为MaxKB。

image.png

点击创建栈:

image.png

由于我在上述ROS脚本中申明了可用区、CPU内存配置、系统盘类型等,所以这里都需要进行选择:

image.png

选择失败时回滚,点击创建,需保证账户余额大于100元

image.png

在创建界面的资源处,可以看到ROS中定义的实例正在逐一被创建:

image.png

构建MaxKB需要花费一些时间,创建完成后如下图所示:

image.png

但是意外的是,事件里面出现执行失败了。

进入事件,点击前面的实例链接。

image.png

查看实例的日志,发现是docker超时了。

image.png

于是我增加了一个测试下载的hello-world的案例,发现是正常的:

sudo docker run hello-world

image.png

于是乎,我换到我自己的电脑上尝试,很奇怪的是,即使添加了一堆镜像源依然下载报错。。。

image.png

感觉有点不对劲了,开始尝试用git方式部署,对照着文档学习了一下,采用git本地编译部署对环境要求极为苛刻。。。转化成一键部署的脚本更是麻烦。

image.png

最后尝试了半天无果,还是放弃MaxKB的搭建吧。。。没事,咱们换个别的,反正这次重点在于ROS编写上。

既然上面我们把基本框架都搭建完了,那么理论上只需要找个能跑的脚本就可以了,思来想去,考虑到综合使用频率和实用性,我这里还是决定来试一试部署Dify。

这里在查安装方法的时候,突然看到阿里的ROS官方已经发过一篇了。。。。流汗黄豆。。。

整体的内容也是大差不差,区别就在于Dify的本地编译很方便,而MaxKB需要规定版本的python环境,很麻烦。

ROSTemplateFormatVersion: '2015-09-01'
Description:en: Build the large language model (LLM) application development platform Dify onthe ECS instance (CentOS 7).zh-cn:ECS实例(CentOS 7)上搭建大语言模型(LLM) 应用开发平台Dify。
Parameters:ZoneId:Type: StringLabel:en: Availability Zonezh-cn: 可用区IDAssociationProperty: ALIYUN::ECS::Instance:ZoneIdInstanceType:Type: StringLabel:en: Instance Typezh-cn: 实例类型AssociationProperty: ALIYUN::ECS::Instance::InstanceTypeAssociationPropertyMetadata:ZoneId: ${ZoneId}DefaultValueStrategy: recentSystemDiskCategory:Type: StringLabel:en: System Disk Typezh-cn: 系统盘类型AssociationProperty: ALIYUN::ECS::Disk::SystemDiskCategoryAssociationPropertyMetadata:LocaleKey: DiskCategoryZoneId: ${ZoneId}InstanceType: ${InstanceType}AutoSelectFirst: trueAutoChangeType: falseDefault: cloud_essdInstancePassword:Type: StringLabel:en: Instance Passwordzh-cn: 实例密码Description:en: Server login password, Length 8-30, must contain three(Capital letters,lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbolin).zh-cn: 服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。ConstraintDescription:en: Length 8-30, must contain three(Capital letters, lowercase letters, numbers,()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in).zh-cn: 长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。AssociationPropertyMetadata:Visible:Condition:Fn::Equals:- ${SelectInstance}- falseDefault:AllowedPattern: '[0-9A-Za-z\_\-\&:;''<>,=%`~!@#\(\)\$\^\*\+\|\{\}\[\]\.\?\/]+$'MinLength: 8MaxLength: 30NoEcho: true
Resources:Vpc:Type: ALIYUN::ECS::VPCProperties:CidrBlock: 192.168.0.0/16VSwitch:Type: ALIYUN::ECS::VSwitchProperties:ZoneId:Ref: ZoneIdVpcId:Ref: VpcCidrBlock: 192.168.0.0/24SecurityGroup:Type: ALIYUN::ECS::SecurityGroupProperties:VpcId:Ref: VpcSecurityGroupIngress_80:Type: ALIYUN::ECS::SecurityGroupIngressProperties:SecurityGroupId:Ref: SecurityGroupSourceCidrIp: 0.0.0.0/0IpProtocol: tcpNicType: intranetPortRange: 80/80InstanceGroup:Type: ALIYUN::ECS::InstanceGroupProperties:VpcId:Ref: VpcVSwitchId:Ref: VSwitchSecurityGroupId:Ref: SecurityGroupImageId: centos_7_9InstanceName: difyInstanceType:Ref: InstanceTypeSystemDiskCategory:Ref: SystemDiskCategoryPassword:Ref: InstancePasswordIoOptimized: optimizedMaxAmount: 1DS_Instances:Type: DATASOURCE::ECS::InstancesProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIdsInstallDify:Type: ALIYUN::ECS::RunCommandProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIdsType: RunShellScriptSync: trueTimeout: 1800CommandContent: |#!/bin/bashecho "#########################"echo "# Install Docker"echo "#########################"wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repoyum -y install docker-cesystemctl start dockersystemctl enable dockerecho "#########################"echo "# Install Dify"echo "#########################"yum -y install gitgit clone --depth 1 https://github.com/langgenius/dify.git /opt/difycd /opt/dify/dockerdocker compose up -ddocker compose ps
Outputs:DifyUrl:Description: Dify default address.Value:Fn::Sub:- http://${IP}- IP:Fn::Jq:- First- if .[0].PublicIpAddress != [] then .[0].PublicIpAddress[0] else .[0].EipAddress.IpAddressend- Fn::GetAtt:- DS_Instances- Instances
Metadata:ALIYUN::ROS::Interface:TemplateTags:- acs:developer:gitee:0147-ECS实例上搭建大语言模型的知识库问答系统MaxKB

最后结果是创建成功了,但是网站打不开,我一查日志,给我看笑了。

image.png

官方文档给出的部署方式同样出现了docker超时的情况,这下估计docker真指望不到了。

离了个大谱,还是自己来吧。

先写了个部署nginx的脚本:

#!/bin/bash
#提前解决编译时所需的依赖环境、库文件;
yum install -y wget gzip gcc tar make
yum install -y pcre pcre-devel zlib-devel
#下载Nginx软件包;
wget -c http://nginx.org/download/nginx-1.24.0.tar.gz -P /usr/src/
#Cd切换/usr/src/;
cd /usr/src/
ls -l nginx-1.24.0.tar.gz
#通过Tar工具对其解压;
tar -xzvf nginx-1.24.0.tar.gz
#Cd切换至Nginx源代码目录;
cd nginx-1.24.0/
#提前创建www用户和组;
useradd -s /sbin/nologin www -M
#预编译;
./configure --prefix=/usr/local/nginx/ --user=www --group=www --with-http_stub_status_module
#编译;
make -j4
#安装;
make -j4 install
#查看Nginx软件服务是否部署成功;
ls -l /usr/local/nginx/
#启动Nginx服务进程;
/usr/local/nginx/sbin/nginx
#查看Nginx进程状态;
ps -ef|grep -aiE nginx
#Firewalld防火墙对外开放80端口;
firewall-cmd --add-port=80/tcp --permanent
systemctl reload firewalld.service 

直接丢里面执行,部署完了如下所示:

image.png
image.png

这里可以看到nginx还是部署成功了的,看来只是docker存在一些莫名奇妙的问题罢了。将这里的nginx脚本替换之前的MaxKB或者Dify的shell脚本处,勉强算是制作出第一个ROS脚本了,虽然一点用处都没有。。。

总结

如果不是这次亲手尝试来写ROS脚本也没想到会碰到那么多问题,本来其实听起来很简单的,整个逻辑也能理解,但是实际上手后,由于不熟悉,搞得这也是问题那也是问题,反反复复折腾。

第二点就是,官网上给的脚本居然也会出现执行错误的情况,这是我没想到的。

不过,也正是这些问题和挑战,让我深刻体会到了理论与实践之间的差距,也促使我更加深入地学习和探索。每解决一个问题,都是对云计算领域理解的一次深化,对ROS及背后资源编排理念的掌握也愈发熟练。

过程充满挑战,但每一次解决问题都是一次宝贵的学习机会,让我的技术栈更加坚实,也让我在云原生和DevOps的道路上迈出了坚实的一步。这种从实战中获得的经验,是任何教科书或理论学习都无法替代的。


2024年7月13日更新

昨晚研究了一晚,又写了一个部署2048游戏的ROS脚本。

ROSTemplateFormatVersion: '2015-09-01'
Description:en: Set up the 2048 game on an ECS instance..zh-cn:ECS实例上搭建2048小游戏。
Parameters:ZoneId:Type: StringLabel:en: Availability Zonezh-cn: 可用区IDAssociationProperty: ALIYUN::ECS::Instance:ZoneIdInstanceType:Type: StringLabel:en: Instance Typezh-cn: 实例类型AssociationProperty: ALIYUN::ECS::Instance::InstanceTypeAssociationPropertyMetadata:ZoneId: ${ZoneId}DefaultValueStrategy: ecs.e-c1m2.large
Resources:Vpc:Type: ALIYUN::ECS::VPCProperties:CidrBlock: 192.168.0.0/16VSwitch:Type: ALIYUN::ECS::VSwitchProperties:ZoneId:Ref: ZoneIdVpcId:Ref: VpcCidrBlock: 192.168.0.0/24SecurityGroup:Type: ALIYUN::ECS::SecurityGroupProperties:VpcId:Ref: VpcSecurityGroupIngress_80:Type: ALIYUN::ECS::SecurityGroupIngressProperties:SecurityGroupId:Ref: SecurityGroupSourceCidrIp: 0.0.0.0/0IpProtocol: tcpNicType: intranetPortRange: 80/80InstanceGroup:Type: ALIYUN::ECS::InstanceGroupProperties:VpcId:Ref: VpcVSwitchId:Ref: VSwitchSecurityGroupId:Ref: SecurityGroupImageId: centos_7_9InstanceName: GAMEInstanceType:Ref: InstanceTypeSystemDiskCategory : cloud_essdIoOptimized: optimizedMaxAmount: 2DS_Instances:Type: DATASOURCE::ECS::InstancesProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIdsInstallGAME:Type: ALIYUN::ECS::RunCommandProperties:InstanceIds:Fn::GetAtt:- InstanceGroup- InstanceIdsType: RunShellScriptSync: trueTimeout: 1800CommandContent: |#!/bin/bashyum install -y httpd wgetsystemctl start httpdwget 'https://computenest-artifacts-cn-hangzhou.oss-cn-hangzhou-internal.aliyuncs.com/1853370294850618/cn-beijing/1697533575326/2048.tgz' -O 2048.tgztar xvf 2048.tgzmv 2048/* /var/www/html && rm -rf 2048Outputs:GAMEUrl:Description: GAME default address.Value:Fn::Sub:- http://${IP}- IP:Fn::Jq:- First- if .[0].PublicIpAddress != [] then .[0].PublicIpAddress[0] else .[0].EipAddress.IpAddressend- Fn::GetAtt:- DS_Instances- Instances
Metadata:ALIYUN::ROS::Interface:TemplateTags:- acs:developer:gitee:0147-在ECS实例上搭建2048小游戏

这里实测是完全没有任何问题的。

image.png

image.png

image.png

下面我把脚本上传到我的gitee中,新建一个仓库,命名为阿里云ROS:

image.png

由于只有一个脚本,所以直接创建文件然后复制进去就可以了:

image.png

最终地址如下:

image.png

我们来尝试直接一键部署,前面引入ROS的部署的链接地址:

https://ros.console.aliyun.com/region/stacks/create?hideStepRow=true&hideStackConfig=true&disableRollback=false&isSimplified=true&disableNarue&productNavBar=disabled&templateUrl=

后面拼接自己的gitee地址:

https://gitee.com/a156da16/aliyunros/blob/master/GAME.yaml

所以最终一键部署链接如下:

https://ros.console.aliyun.com/cn-hangzhou/stacks/create?hideStepRow=true&hideStackConfig=true&disableRollback=false&isSimplified=true&disableNarue&productNavBar=disabled&templateUrl=https://gitee.com/a156da16/aliyunros/blob/master/GAME.yaml

尝试了一下,有个很逆天的地方,一直显示访问被拒绝。具体原因也一直没找到,在群里找专家问了:

image.png

为了避免版本不一致,我直接复制gitee里上传的那个版本,进入ROS中进行创建,是能够识别模板参数的:

image.png

但是通过官方给的链接就是一直报错。。。

这篇就这样吧,反正总之把脚本也是写出来了,刚开始接触不是很熟悉,只能从简单的开始了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/45994.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【持续集成_06课_Jenkins高级pipeline应用】

一、创建项目选择pipeline的风格 它主要是以脚本&#xff08;它自己的语言&#xff09;的方式进行运行&#xff0c;一般由运维去做的事情&#xff0c;作为测试而言。了解即可。 --- 体现形式全部通过脚本去实现&#xff1a;执行之前&#xff08;拉取代码&#xff09;执行&…

Linux:Linux网络总结(附下载链接)

文章目录 下载链接网络问题综合问题访问一个网页的全过程&#xff1f;WebSocket HTTPHTTP基本概念GET与POSTHTTP特性HTTP缓存技术HTTP的演变HTTP1.1 优化 HTTPSHTTP与HTTPS有哪些区别&#xff1f;HTTPS解决了HTTP的哪些问题&#xff1f;HTTPS如何解决的&#xff1f;HTTPS是如何…

# Redis 入门到精通(二)通用指令

Redis 入门到精通&#xff08;二&#xff09;通用指令 一、redis 通用指令-key 基本操作 1、key 特征 key是一个字符串&#xff0c;通过key获取redis中保存的数据。 2、key 应该设计哪些操作? 对于 key 自身状态的相关操作&#xff0c;例如:删除&#xff0c;判定存在&…

企业网络实验(vmware虚拟机充当DHCP服务器)所有IP全部保留,只为已知mac分配固定IP

文章目录 需求实验修改dhcp虚拟机配置文件测试PC获取IP查看user-bind 需求 (vmware虚拟机充当DHCP服务器)所有IP全部保留&#xff0c;只为已知mac分配固定IP 实验 前期配置&#xff1a; https://blog.csdn.net/xzzteach/article/details/140406092 后续配置均在以上配置的前…

keepalive和haproxy

1、keepalive 1.1概念 调度器的高可用 vip地址主备之间的切换&#xff0c;主在工作时&#xff0c;vip地址只在主上&#xff0c;主停止工作&#xff0c;vip漂移到备服务器 在主备的优先级不变的情况下&#xff0c;主恢复工作&#xff0c;vip会飘回到主服务器 1、配优先级 …

【RabbitMQ】一文详解消息可靠性

目录&#xff1a; 1.前言 2.生产者 3.数据持久化 4.消费者 5.死信队列 1.前言 RabbitMQ 是一款高性能、高可靠性的消息中间件&#xff0c;广泛应用于分布式系统中。它允许系统中的各个模块进行异步通信&#xff0c;提供了高度的灵活性和可伸缩性。然而&#xff0c;这种通…

.NET MAUI开源架构_1.学习资源分享

最近需要开发Android的App&#xff0c;想预研下使用.NET开源架构.NET MAUI来开发App程序。因此网上搜索了下相关资料&#xff0c;现在把我查询的结果记录下&#xff0c;方便后面学习。 1.官方文档 1.1MAUI官方学习网站 .NET Multi-Platform App UI 文档 - .NET MAUI | Micro…

Open-TeleVision——通过VR沉浸式感受人形机器人视野:兼备远程控制和深度感知能力

前言 7.3日&#xff0c;我司七月在线(集AI大模型职教、应用开发、机器人解决方案为一体的科技公司)的「大模型机器人(具身智能)线下营」群里的一学员发了《Open-TeleVision: Teleoperation with Immersive Active Visual Feedback》这篇论文的链接&#xff0c;我当时快速看了一…

shell脚本之if/case语句

一、条件测试 1、1 返回码 $? $? :返回码&#xff0c;用来判断命令或者脚本是否执行成功。 0 &#xff1a;表示true &#xff0c;成功&#xff1b;非0 则表示flase &#xff0c;失败。 1、2 test命令 可以进行条件测试&#xff0c;然后根据返回值来判断条件是否成立 -e…

RISC-V异常处理流程概述(2):异常处理机制

RISC-V异常处理流程概述(2):异常处理机制 一、异常处理流程和异常委托1.1 异常处理流程1.2 异常委托二、RISC-V异常处理中软件相关内容2.1 异常处理准备工作2.2 异常处理函数2.3 Opensbi系统调用的注册一、异常处理流程和异常委托 1.1 异常处理流程 发生异常时,首先需要执…

4、linux相关基础知识

1、gcc编译过程 .c通过编译生成.o文件&#xff0c;.out目标文件进过链接生成.so库文件。 2、在C中可以使用system(("mkdir -p "path).c_str())创建目录。c_str()把string转化为c字符串&#xff0c;便于system命令识别&#xff0c;system命令会新启动一个进程来创建文…

移动硬盘有盘符打不开:深度解析与高效恢复指南

在数字化信息爆炸的今天&#xff0c;移动硬盘作为便捷的数据存储与传输工具&#xff0c;其重要性不言而喻。然而&#xff0c;当您遇到移动硬盘有盘符却无法正常打开的情况时&#xff0c;无疑会给您的工作和生活带来不小的困扰。本文将深入探讨移动硬盘有盘符打不开的原因&#…

东软“引战”国家队 通用技术“补链”大国重器

向来低调温和的东软创始人刘积仁&#xff0c;这一次抛出了“王炸”级的资产交易。 7月3日&#xff0c;《多肽链》获得一则足以引爆国内医疗设备行业的投资信息&#xff1a;被东软集团视为核心资产、掌上明珠的东软医疗&#xff0c;成功引入通用技术集团资本有限公司与中国国有…

BI佐罗,居然抄袭洗稿我的文章

必须曝光此博主不当行径。 4月2日这天发表的原创文章&#xff1a;BI报表系统建设10大坑&#xff0c;因为都是切身的实际项目经验总结&#xff0c;获得了很多人的关注。 我觉得写文章要写的是亲身、真的做过的专业的项目经验&#xff0c;而不是信口开河随口忽悠。 如果有些博…

Fancybox: 号称世界上最流行的灯箱脚本!这款“花盒“为什么与众不同?

今天要分享的是一个灯箱脚本库&#xff1a;Fancybox。最近了不起刚好用到它。这里就和大家分享下。 简介 Fancybox 是终极的 JavaScript 灯箱替代品&#xff0c;为多媒体显示中的优质用户体验设定了标准。支持图像、视频、地图、内联内容、iframe 和任何其他 HTML 内容。 此…

如何在SpringCloud中使用Kafka Streams实现实时数据处理

使用Kafka Streams在Spring Cloud中实现实时数据处理可以帮助我们构建可扩展、高性能的实时数据处理应用。Kafka Streams是一个基于Kafka的流处理库&#xff0c;它可以用来处理流式数据&#xff0c;进行流式计算和转换操作。 下面将介绍如何在Spring Cloud中使用Kafka Streams实…

Pytorch中nn.Sequential()函数创建网络的几种方法

1. 创作灵感 在创建大型网络的时候&#xff0c;如果使用nn.Sequential&#xff08;&#xff09;将几个有紧密联系的运算组成一个序列&#xff0c;可以使网络的结构更加清晰。 2.应用举例 为了记录nn.Sequential&#xff08;&#xff09;的用法&#xff0c;搭建以下测试网络&…

数字电路-建立时间和保持时间详解

对于数字系统而言&#xff0c;建立时间&#xff08;setup time&#xff09;和保持时间&#xff08;hold time&#xff09;是数字电路时序的基础。数字电路系统的稳定性&#xff0c;基本取决于时序是否满足建立时间和保持时间。我自己在初学时一度很难理解清楚他们的概念&#x…

基于JAVA+SpringBoot+Vue+uniApp小程序的心理健康测试平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 该系统由三个核心角色…

【PVE】新增2.5G网卡作为主网卡暨iperf测速流程

【PVE】新增2.5G网卡作为主网卡暨iperf测速流程 新增网卡 新增网卡的首先当然需要关闭PVE母机&#xff0c;把新网卡插上&#xff0c;我用淘宝遥现金搞了个红包&#xff0c;花了26元买了块SSU的2.5G网卡。说实话这个价位连散热片都没有&#xff0c;确实挺丐的。稍后测下速度看…