亚马逊现货实例部署反模式
Amazon spot instance deployment antipattern
我很确定我做事的方式是错误的,我想知道正确的方式。
我面临的问题是:
- 我有一个分布式批处理作业
- 我用AWS现货实例来实现
- 总是一次性请求(所以我寻求简单的解决方案)
- 实例需要一些配置和设置,并且需要向它们发送任务来完成
我通常这样解决:
- 启动一个 worker 并配置它
- 保存它的图像
- 然后调出所有其他实例
- 然后我会做一个大而烦人的复制粘贴工作,基本上创建一个像这样的 shell 脚本:
$HOST=123.123.123.1 $TASK=task1 ssh ubuntu@$HOST task_runner $TASK &
$HOST=123.123.123.2 $TASK=task2 ssh ubuntu@$HOST task_runner $TASK &
$HOST=123.123.123.3 $TASK=task3 ssh ubuntu@$HOST task_runner $TASK &
...
我想做得更好,所以我想办法让它更容易:
- 设置 AWS 实例。有时有一个启动时代码需要 运行,这意味着像上面那样的更大的任务
- 获取实例列表。不再复制粘贴!
- 运行 所有实例上的所有任务。
- 完成后关闭它们
理想情况下,我想涵盖整个生命周期,端到端。
最后,我想要一些非常简单的东西。因为这是一次性任务,所以我真的不想处理一大堆配置选项和接线。
您可以使用 Ansible 来相当简单地完成此操作。
您的 Ansible 剧本将类似于:
- name: Stage instance(s)
hosts: local
connection: local
gather_facts: false
vars:
keypair: mykeypair
instance_type: m1.small
security_group: sg-123456abc
image: ami-123456abc
vpc_subnet_id: subnet-123456abc
count: 5
tasks:
- name: Create spot instance
ec2:
spot_price: 0.24
spot_wait_timeout: 600
keypair: {{ keypair }}
group_id: {{ security_group }}
instance_type: {{ instance_type }}
image: {{ image }}
vpc_subnet_id: {{ vpc_subnet_id }}
assign_public_ip: no
count: {{ count }}
wait: yes
register: ec2
- name: Add new instances to host group
add_host: hostname={{item.private_ip}} groupname=task_minions
with_items: ec2.instances
- name: Wait for the instances to boot by checking the ssh port
wait_for: host={{item.private_dns_name}} port=22 delay=60 timeout=320 state=started
with_items: ec2.instances
- name: Configure instance(s)
hosts: task_minions
remote_user: ec2-user
tasks:
- name: Some configuration
yum:
...
- name: Run tasks
hosts: task_minions
remote_user: ec2-user
tasks:
- name: Run all tasks on all task_minions
command:
task_runner {{ item }}
with_items:
- task_1
- task_2
...
- name: Terminate instance(s)
hosts: localhost
connection: local
tasks:
- name: Terminate instances that were previously launched
ec2:
state: 'absent'
instance_ids: '{{ ec2.instance_ids }}'
我对其他配置管理工具的经验较少,但我相信它们也可以使用。
有几件事要尝试/考虑:
1) 您应该研究构建一个 AMI,其中包含您从映像中获得的一切所需 + 运行启动时间代码的挂钩。这应该允许您使用此 AMI 启动映像而不必担心构建它
2) 使用SQS 队列来调度任务。这样工作人员就可以从那个队列中拉出来,你可以很容易地知道他们什么时候完成了。 (队列变为 0,没有正在发送的消息)。
3) 更棒。将 SQS 调度与自动缩放相结合:http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/as-using-sqs-queue.html 这样,只要有工作,您就可以让自动缩放 up/spin 关闭您的实例。您唯一需要做的就是将事情推入队列。
4) 超级棒。执行以上所有 3 项 + 将所有内容放入 CloudFormation 模板并启动 Cloudformation 堆栈。如果您需要修改设置(更改图像、队列、配置等),您只需调整模板并重新部署即可。
希望对您有所帮助。
我很确定我做事的方式是错误的,我想知道正确的方式。
我面临的问题是:
- 我有一个分布式批处理作业
- 我用AWS现货实例来实现
- 总是一次性请求(所以我寻求简单的解决方案)
- 实例需要一些配置和设置,并且需要向它们发送任务来完成
我通常这样解决:
- 启动一个 worker 并配置它
- 保存它的图像
- 然后调出所有其他实例
- 然后我会做一个大而烦人的复制粘贴工作,基本上创建一个像这样的 shell 脚本:
$HOST=123.123.123.1 $TASK=task1 ssh ubuntu@$HOST task_runner $TASK & $HOST=123.123.123.2 $TASK=task2 ssh ubuntu@$HOST task_runner $TASK & $HOST=123.123.123.3 $TASK=task3 ssh ubuntu@$HOST task_runner $TASK & ...
我想做得更好,所以我想办法让它更容易:
- 设置 AWS 实例。有时有一个启动时代码需要 运行,这意味着像上面那样的更大的任务
- 获取实例列表。不再复制粘贴!
- 运行 所有实例上的所有任务。
- 完成后关闭它们
理想情况下,我想涵盖整个生命周期,端到端。
最后,我想要一些非常简单的东西。因为这是一次性任务,所以我真的不想处理一大堆配置选项和接线。
您可以使用 Ansible 来相当简单地完成此操作。
您的 Ansible 剧本将类似于:
- name: Stage instance(s)
hosts: local
connection: local
gather_facts: false
vars:
keypair: mykeypair
instance_type: m1.small
security_group: sg-123456abc
image: ami-123456abc
vpc_subnet_id: subnet-123456abc
count: 5
tasks:
- name: Create spot instance
ec2:
spot_price: 0.24
spot_wait_timeout: 600
keypair: {{ keypair }}
group_id: {{ security_group }}
instance_type: {{ instance_type }}
image: {{ image }}
vpc_subnet_id: {{ vpc_subnet_id }}
assign_public_ip: no
count: {{ count }}
wait: yes
register: ec2
- name: Add new instances to host group
add_host: hostname={{item.private_ip}} groupname=task_minions
with_items: ec2.instances
- name: Wait for the instances to boot by checking the ssh port
wait_for: host={{item.private_dns_name}} port=22 delay=60 timeout=320 state=started
with_items: ec2.instances
- name: Configure instance(s)
hosts: task_minions
remote_user: ec2-user
tasks:
- name: Some configuration
yum:
...
- name: Run tasks
hosts: task_minions
remote_user: ec2-user
tasks:
- name: Run all tasks on all task_minions
command:
task_runner {{ item }}
with_items:
- task_1
- task_2
...
- name: Terminate instance(s)
hosts: localhost
connection: local
tasks:
- name: Terminate instances that were previously launched
ec2:
state: 'absent'
instance_ids: '{{ ec2.instance_ids }}'
我对其他配置管理工具的经验较少,但我相信它们也可以使用。
有几件事要尝试/考虑:
1) 您应该研究构建一个 AMI,其中包含您从映像中获得的一切所需 + 运行启动时间代码的挂钩。这应该允许您使用此 AMI 启动映像而不必担心构建它
2) 使用SQS 队列来调度任务。这样工作人员就可以从那个队列中拉出来,你可以很容易地知道他们什么时候完成了。 (队列变为 0,没有正在发送的消息)。
3) 更棒。将 SQS 调度与自动缩放相结合:http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/as-using-sqs-queue.html 这样,只要有工作,您就可以让自动缩放 up/spin 关闭您的实例。您唯一需要做的就是将事情推入队列。
4) 超级棒。执行以上所有 3 项 + 将所有内容放入 CloudFormation 模板并启动 Cloudformation 堆栈。如果您需要修改设置(更改图像、队列、配置等),您只需调整模板并重新部署即可。
希望对您有所帮助。