在多台ECS实例内批量执行命令

在多台实例内批量执行命令。

背景

阿里云的客户远程在ECS内部执行命令是最常见的运维操作之一了,比如在ECS内安装卸载软件,启动停止某个进程,等等。很多情况下,还需要对一个ECS列表中的多台ECS,统一的执行某个相同的命令并汇聚执行的结果。

具体比如说对于业务应用,我们通过批量下放相关命令,可实现滚动升级更新运行时(Runtime)和执行代码(Code),这样能极大提高部署的可靠性。

一个可行的方案是利用SSH远程连接到ECS上执行命令,但是开放ECS的SSH端口给internet访问是危险的。客户可以通过自建跳板机来间接访问ECS以解决安全性的问题,但是这带来了复杂度和成本的上升。

Ansible是业界比较流行的开源的运维工具,但是其认证是独立于阿里云的账号体系之外的,无法通过阿里云的官方工具进行权限控制,其操作记录也无法在阿里云上进行审计。

如果用户使用的是Windows版本的ECS,虽然可以利用PowerShell远程执行命令,但配置和维护过程或许更加困难。

在此,我们向大家推荐阿里云官方的批量在多台ECS内执行命令的最佳实践:系统运维管理+云助手。云助手提供了在ECS内执行命令的原子能力,系统运维管理 OOS(CloudOps Orchestration Service)则附加了更丰富的批量、定时、事件驱动、自定义模板等特性,两者结合,可以让ECS运维工作变得既安全又简单高效。

准备工作

请确保在本地终端,您已安装并配置了阿里云命令行工具CLI,且版本号大于等于3.0.19。阿里云命令行工具CLI的GitHub下载链接为GitHub;快速配置指南请参见交互式配置(快速配置)

开始执行

我们直接先看一个例子,如要针对cn-beijing地域的["i-id45678zxcvb","i-id45679zxcvb"]这两台远程Linux ECS,执行“echo 123”这个Shell命令,只需要在本地的Shell终端里,输入命令:

aliyun oos StartExecution --region cn-hangzhou --TemplateName ACS-ECS-BulkyRunCommand --Parameters '{"commandType":"RunShellScript", "commandContent":"echo 123",  "targets":{"Type":"ResourceIds", "ResourceIds":["i-id45678zxcvb","i-id45679zxcvb"]}, "rateControl":{"maxErrors":0,"mode":"Concurrency"}, "OOSAssumeRole":"" }'

简单解释一下上面这个命令,它调用了oos的StartExecution的API,启动官方提供的公共模板ACS-ECS-BulkyRunCommand,传入包含了ECS实例列表(ResourceIds)和执行内容(commandContent)的参数。该命令会返回一个JSON结构,如果您能找到"ExecutionId":"exec-xxxxx",那么恭喜您,被指定的命令已经开始在远程执行了。请记录下ExecutionId,然后作为参数输入到下面的ListExecutions命令查询执行的过程和结果:

aliyun oos ListExecutions --region cn-hangzhou --ExecutionId "exec-id123456zxcvb"

如果命令正在运行中,您会看到类似如下的结果,Status是“Running”。TotalTasks是总的命令数,SuccessTasks是已经执行成功的命令数。两个数字的差,就是还待执行的命令数。

{
	"Execution": {
		"Outputs": {},
		"TemplateName": "ACS-ECS-BulkyRunCommand",
		"Parameters": {
			"commandType": "RunShellScript",
			"OOSAssumeRole": "",
			"rateControl": {
				"maxErrors": 0,
				"mode": "Concurrency"
			},
			"targets": {
				"ResourceIds": [
					"i-id45678zxcvb","i-id45679zxcvb"
				],
				"Type": "ResourceIds"
			},
			"commandContent": "echo 123"
		},
		"Counters": {
			"Failed": 0,
			"Success": 0,
			"Total": 0
		},
		"ExecutedBy": "aliyun-account1",
		"LoopMode": "Automatic",
		"Mode": "Automatic",
		"TemplateId": "t-123456zxcvb",
		"Status": "Running",
		"TemplateVersion": "v2",
		"SafetyCheck": "Skip",
		"StartDate": "2019-10-15T07:22:03Z",
		"ExecutionId": "exec-id123456zxcvb",
		"CurrentTasks": []
	},
	"RequestId": "1A9B1817-0530-470C-8640-BADADADB220BD"
}

您可以多次执行同样的ListExecutions命令进行查看,直到看到Outputs表示整个命令的结果,对于本例,为两台ECS上的标准输出:

进阶-自定义模板

在上面的例子里,命令的参数有点过于复杂,其实我可以自定义模板把参数固定下来,让执行的命令变得格外简单。自定义模板的命令如下,您可以根据自己的需要进行改写:

aliyun oos CreateTemplate --region cn-hangzhou --TemplateName sample123 --Content '{
"FormatVersion": "OOS-2019-06-01",
"Tasks": [
{
"Name": "runCommand",
"Action": "ACS::ECS::RunCommand",
"Properties": {
"commandContent": "echo 1234",
"instanceId": "{{ ACS::TaskLoopItem }}",
"commandType": "RunShellScript"
},
"Loop": {
"Items": ["i-id45678zxcvb","i-id45679zxcvb"],
"Outputs": {
"commandOutputs": {
"AggregateType": "Fn::ListJoin",
"AggregateField": "commandOutput"
}
}
},
"Outputs": {
"commandOutput": {
"Type": "String",
"ValueSelector": "invocationOutput"
}
}
}
],
"Outputs": {
"commandOutputs": {
"Type": "List",
"Value": "{{ runCommand.commandOutputs }}"
}
}
}'		

执行创建自定义模版命令后,您只需要执行如下命令就可以完成和前面一样的效果了。

aliyun oos StartExecution --region cn-hangzhou --TemplateName sample123 --Parameters '{}'		

此命令调用oos的StartExecution这个API,执行sample123这个自定义模板,不需要额外传入参数。当然,前面用CLI所做的一切操作,都可以在OOS控制台执行。

了解更多

系统运维管理 OOS(CloudOps Orchestration Service)OOS是阿里云的运维自动化平台,适用于批量、定时、事件驱动、跨区域运维等场景,除了在ECS内执行命令外,还可以完成ECS创建释放,启停,变配,网络带宽升级,挂载云盘等等各种操作。如果想了解更多,加入钉钉群“系统运维管理 OOS(CloudOps Orchestration Service)OOS支持群”,群号23330931。我们会有值班人员在线支持。

OOS管理控制台的链接:https://oos.console.aliyun.com