在 AWS EC2 VPC 中创建 n 个新实例,然后配置它们
Creating n new instances in AWS EC2 VPC and then configuring them
我很难完成看似相当标准的任务,所以我希望有人能帮助我。我疯狂地用谷歌搜索了这个,大多数示例不在 VPC 中,或者使用了不推荐使用的结构,这使得它们在我的用例中是错误的或不可用的。
这是我的目标:
- 我想在我的 VPC 中启动一大堆新实例(相同的
下面的代码有 3 个,但也有可能是 100 个)
- 我想等待那些实例出现
- 然后我想配置这些实例(ssh 进入它们,更改
主机名、启用某些服务等)
现在我可能可以在 2 个任务中完成。我可以在 1 个剧本中创建实例。等他们安定下来。然后 运行 第二个剧本来配置它们。这可能是我现在要做的,因为我想开始行动 - 但对此必须有一个一次性的答案。
这是我目前的剧本
---
- hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Provision Lunch
with_items:
- hostname: eggroll1
- hostname: eggroll2
- hostname: eggroll3
ec2:
region: us-east-1
key_name: eggfooyong
vpc_subnet_id: subnet-8675309
instance_type: t2.micro
image: ami-8675309
wait: true
group_id: sg-8675309
exact_count: 1
count_tag:
Name: "{{ item.hostname }}"
instance_tags:
Name: "{{ item.hostname }}"
role: "supper"
ansibleowned: "True"
register: ec2
- name: Wait for SSH to come up
wait_for: host={{ item.private_ip }} port=22 delay=60 timeout=900 state=started
with_items: '{{ec2.instances}}'
- name: Update hostname on instances
hostname: name={{ item.private_ip }}
with_items: '{{ec2.instances}}'
那是行不通的。我得到的是
TASK [Wait for SSH to come up] *************************************************
[DEPRECATION WARNING]: Skipping task due to undefined Error, in the future this will be a fatal error.. This feature will be removed in a future release. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
TASK [Update hostname on instances] ********************************************
[DEPRECATION WARNING]: Skipping task due to undefined Error, in the future this will be a fatal error.. This feature will be removed in a future release. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
这让我很难过。现在这是我对那本剧本的最新化身。但是我尝试使用我在互联网上可以找到的每个示例重写它。他们中的大多数 with_items 以不同的方式编写,但 ansible 告诉我这种方式被贬低了,然后失败了。
到目前为止,ansible 既有趣又简单,但这让我想把我的笔记本电脑扔到街对面。
有什么建议吗?我应该使用 register 和 with_items 吗?我会更好地使用这样的东西吗:
add_host: hostname={{item.public_ip}} groupname=deploy
相反?我很乐意在这里重写。我打算把它写成两本剧本,很乐意得到建议。
谢谢!
****编辑****
现在它才刚刚开始感到破碎或严重改变。我在谷歌上搜索了数十个示例,它们都是以相同的方式编写的,并且都因相同的错误而失败。这是我现在的简单剧本:
---
- hosts: localhost
connection: local
gather_facts: False
vars:
builderstart: 93
builderend: 94
tasks:
- name: Provision Lunch
ec2:
region: us-east-1
key_name: dakey
vpc_subnet_id: subnet-8675309
instance_type: t2.micro
image: ami-8675309
wait: True
group_id: sg-OU812
exact_count: 1
count_tag:
Name: "{{ item }}"
instance_tags:
Name: "{{ item }}"
role: "dostuff"
extracheese: "True"
register: ec2
with_sequence: start="{{builderstart}}" end="{{builderend}}" format=builder%03d
- name: the newies
debug: msg="{{ item }}"
with_items: "{{ ec2.instances }}"
真的再简单不过了。无论我如何编写,无论我如何改变它,我都会得到相同的基本错误:
[DEPRECATION WARNING]: Skipping task due to undefined Error, in the
future this will be a fatal error.: 'dict object' has no attribute
'instances'.
看来是 with_items: "{{ ec2.instances }}" 行导致了错误。
我已经使用调试打印出 ec2,该错误看起来很准确。看起来结构对我改变了。看起来 ec2 现在包含一个字典,其中结果作为另一个字典对象的键,而 instances 是该字典中的键。但是我找不到访问数据的合理方法。
为了它的价值,我已经尝试在 2.0.1、2.0.2 和 2.2 中访问它,但在每种情况下我都会遇到同样的问题。
你们其他人使用的是 1.9 还是什么?我在任何地方都找不到可行的例子。很郁闷。
再次感谢您的帮助。
为了实现这个目标,我写了一个非常小的过滤器插件get_ec2_info
。
创建名为 filter_plugins
的目录
创建一个插件文件 get_ec2_info.py
,内容如下:
from jinja2.utils import soft_unicode
class FilterModule(object):
def filters(self):
return {
'get_ec2_info': get_ec2_info,
}
def get_ec2_info(list, ec2_key):
ec2_info = []
for item in list:
for ec2 in item['instances']:
ec2_info.append(ec2[ec2_key])
return ec2_info
然后你可以在你的剧本中使用这个:
---
- hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Provision Lunch
ec2:
region: us-east-1
key_name: eggfooyong
vpc_subnet_id: subnet-8675309
instance_type: t2.micro
image: ami-8675309
wait: true
group_id: sg-8675309
exact_count: 1
count_tag:
Name: "{{ item.hostname }}"
instance_tags:
Name: "{{ item.hostname }}"
role: "supper"
ansibleowned: "True"
register: ec2
with_items:
- hostname: eggroll1
- hostname: eggroll2
- hostname: eggroll3
- name: Create SSH Group to login dynamically to EC2 Instance(s)
add_host:
hostname: "{{ item }}"
groupname: my_ec2_servers
with_items: "{{ ec2.results | get_ec2_info('public_ip') }}"
- name: Wait for SSH to come up on EC2 Instance(s)
wait_for:
host: "{{ item }}"
port: 22
state: started
with_items: "{{ ec2.results | get_ec2_info('public_ip') }}"
# CALL THE DYNAMIC GROUP IN THE SAME PLAYBOOK
- hosts: my_ec2_servers
become: yes
remote_user: ubuntu
gather_facts: yes
tasks:
- name: DO YOUR TASKS HERE
额外信息:
- 使用 ansible 2.0.1.0
- 假设您正在启动 ubuntu 个实例,如果不是,则更改
remote_user: ubuntu
中的值
- 假设 ssh 密钥配置正确
请查阅这些 github 存储库以获得更多帮助:
不要这样做:
- name: Provision Lunch
with_items:
- hostname: eggroll1
- hostname: eggroll2
- hostname: eggroll3
ec2:
region: us-east-1
因为通过使用它,您可以清除项目中来自 ec2 的所有信息。
您收到以下输出:
TASK [Launch instance] *********************************************************
changed: [localhost] => (item={u'hostname': u'eggroll1'})
changed: [localhost] => (item={u'hostname': u'eggroll2'})
但项目应该是这样的:
changed: [localhost] => (item={u'kernel': None, u'root_device_type': u'ebs', u'private_dns_name': u'ip-172-31-29-85.ec2.internal', u'public_ip': u'54.208.138.217', u'private_ip': u'172.31.29.85', u'id': u'i-003b63636e7ffc27c', u'ebs_optimized': False, u'state': u'running', u'virtualization_type': u'hvm', u'architecture': u'x86_64', u'ramdisk': None, u'block_device_mapping': {u'/dev/sda1': {u'status': u'attached', u'delete_on_termination': True, u'volume_id': u'vol-37581295'}}, u'key_name': u'eggfooyong', u'image_id': u'ami-fce3c696', u'tenancy': u'default', u'groups': {u'sg-aabbcc34': u'ssh'}, u'public_dns_name': u'ec2-54-208-138-217.compute-1.amazonaws.com', u'state_code': 16, u'tags': {u'ansibleowned': u'True', u'role': u'supper'}, u'placement': u'us-east-1d', u'ami_launch_index': u'1', u'dns_name': u'ec2-54-208-138-217.compute-1.amazonaws.com', u'region': u'us-east-1', u'launch_time': u'2016-04-19T08:19:16.000Z', u'instance_type': u't2.micro', u'root_device_name': u'/dev/sda1', u'hypervisor': u'xen'})
尝试使用下面的代码
- name: Create a sandbox instance
hosts: localhost
gather_facts: False
vars:
keypair: eggfooyong
instance_type: t2.micro
security_group: ssh
image: ami-8675309
region: us-east-1
subnet: subnet-8675309
instance_names:
- eggroll1
- eggroll2
tasks:
- name: Launch instance
ec2:
key_name: "{{ keypair }}"
group: "{{ security_group }}"
instance_type: "{{ instance_type }}"
image: "{{ image }}"
wait: true
region: "{{ region }}"
vpc_subnet_id: "{{ subnet }}"
assign_public_ip: no
count: "{{ instance_names | length }}"
register: ec2
- name: tag instances
ec2_tag:
resource: '{{ item.0.id }}'
region: '{{ region }}'
tags:
Name: '{{ item.1 }}'
role: "supper"
ansibleowned: "True"
with_together:
- '{{ ec2.instances }}'
- '{{ instance_names }}'
- name: Wait for SSH to come up
wait_for: host={{ private_ip }} port=22 delay=60 timeout=320 state=started
with_items: '{{ ec2.instances }}'
假设您的 ansible 主机位于 VPC 内
我认为这对调试很有帮助。
ec2
寄存器是 dict
类型。它有一个键 results
.
results
键有很多元素,包括 dict
和 list
,如下所示:
{
"msg": {
"results": [
{
"invocation": {
},
"instances": [],
"changed": false,
"tagged_instances": [
{
}
],
"instance_ids": null,
"failed": false,
"item": [
],
"ansible_loop_var": "item"
}
],
"msg": "All items completed",
"changed": false
},
"_ansible_verbose_always": true,
"_ansible_no_log": false,
"changed": false
}
因此,您可以使用 .
获取所需的数据,例如 item.changed
具有 false
布尔值。
- debug:
msg: "{{ item.changed }}"
loop: "{{ ec2.results }}"
我很难完成看似相当标准的任务,所以我希望有人能帮助我。我疯狂地用谷歌搜索了这个,大多数示例不在 VPC 中,或者使用了不推荐使用的结构,这使得它们在我的用例中是错误的或不可用的。
这是我的目标:
- 我想在我的 VPC 中启动一大堆新实例(相同的 下面的代码有 3 个,但也有可能是 100 个)
- 我想等待那些实例出现
- 然后我想配置这些实例(ssh 进入它们,更改 主机名、启用某些服务等)
现在我可能可以在 2 个任务中完成。我可以在 1 个剧本中创建实例。等他们安定下来。然后 运行 第二个剧本来配置它们。这可能是我现在要做的,因为我想开始行动 - 但对此必须有一个一次性的答案。
这是我目前的剧本
---
- hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Provision Lunch
with_items:
- hostname: eggroll1
- hostname: eggroll2
- hostname: eggroll3
ec2:
region: us-east-1
key_name: eggfooyong
vpc_subnet_id: subnet-8675309
instance_type: t2.micro
image: ami-8675309
wait: true
group_id: sg-8675309
exact_count: 1
count_tag:
Name: "{{ item.hostname }}"
instance_tags:
Name: "{{ item.hostname }}"
role: "supper"
ansibleowned: "True"
register: ec2
- name: Wait for SSH to come up
wait_for: host={{ item.private_ip }} port=22 delay=60 timeout=900 state=started
with_items: '{{ec2.instances}}'
- name: Update hostname on instances
hostname: name={{ item.private_ip }}
with_items: '{{ec2.instances}}'
那是行不通的。我得到的是
TASK [Wait for SSH to come up] *************************************************
[DEPRECATION WARNING]: Skipping task due to undefined Error, in the future this will be a fatal error.. This feature will be removed in a future release. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
TASK [Update hostname on instances] ********************************************
[DEPRECATION WARNING]: Skipping task due to undefined Error, in the future this will be a fatal error.. This feature will be removed in a future release. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
这让我很难过。现在这是我对那本剧本的最新化身。但是我尝试使用我在互联网上可以找到的每个示例重写它。他们中的大多数 with_items 以不同的方式编写,但 ansible 告诉我这种方式被贬低了,然后失败了。
到目前为止,ansible 既有趣又简单,但这让我想把我的笔记本电脑扔到街对面。
有什么建议吗?我应该使用 register 和 with_items 吗?我会更好地使用这样的东西吗:
add_host: hostname={{item.public_ip}} groupname=deploy
相反?我很乐意在这里重写。我打算把它写成两本剧本,很乐意得到建议。
谢谢!
****编辑**** 现在它才刚刚开始感到破碎或严重改变。我在谷歌上搜索了数十个示例,它们都是以相同的方式编写的,并且都因相同的错误而失败。这是我现在的简单剧本:
---
- hosts: localhost
connection: local
gather_facts: False
vars:
builderstart: 93
builderend: 94
tasks:
- name: Provision Lunch
ec2:
region: us-east-1
key_name: dakey
vpc_subnet_id: subnet-8675309
instance_type: t2.micro
image: ami-8675309
wait: True
group_id: sg-OU812
exact_count: 1
count_tag:
Name: "{{ item }}"
instance_tags:
Name: "{{ item }}"
role: "dostuff"
extracheese: "True"
register: ec2
with_sequence: start="{{builderstart}}" end="{{builderend}}" format=builder%03d
- name: the newies
debug: msg="{{ item }}"
with_items: "{{ ec2.instances }}"
真的再简单不过了。无论我如何编写,无论我如何改变它,我都会得到相同的基本错误:
[DEPRECATION WARNING]: Skipping task due to undefined Error, in the future this will be a fatal error.: 'dict object' has no attribute 'instances'.
看来是 with_items: "{{ ec2.instances }}" 行导致了错误。
我已经使用调试打印出 ec2,该错误看起来很准确。看起来结构对我改变了。看起来 ec2 现在包含一个字典,其中结果作为另一个字典对象的键,而 instances 是该字典中的键。但是我找不到访问数据的合理方法。
为了它的价值,我已经尝试在 2.0.1、2.0.2 和 2.2 中访问它,但在每种情况下我都会遇到同样的问题。
你们其他人使用的是 1.9 还是什么?我在任何地方都找不到可行的例子。很郁闷。
再次感谢您的帮助。
为了实现这个目标,我写了一个非常小的过滤器插件get_ec2_info
。
创建名为 filter_plugins
创建一个插件文件 get_ec2_info.py
,内容如下:
from jinja2.utils import soft_unicode
class FilterModule(object):
def filters(self):
return {
'get_ec2_info': get_ec2_info,
}
def get_ec2_info(list, ec2_key):
ec2_info = []
for item in list:
for ec2 in item['instances']:
ec2_info.append(ec2[ec2_key])
return ec2_info
然后你可以在你的剧本中使用这个:
---
- hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Provision Lunch
ec2:
region: us-east-1
key_name: eggfooyong
vpc_subnet_id: subnet-8675309
instance_type: t2.micro
image: ami-8675309
wait: true
group_id: sg-8675309
exact_count: 1
count_tag:
Name: "{{ item.hostname }}"
instance_tags:
Name: "{{ item.hostname }}"
role: "supper"
ansibleowned: "True"
register: ec2
with_items:
- hostname: eggroll1
- hostname: eggroll2
- hostname: eggroll3
- name: Create SSH Group to login dynamically to EC2 Instance(s)
add_host:
hostname: "{{ item }}"
groupname: my_ec2_servers
with_items: "{{ ec2.results | get_ec2_info('public_ip') }}"
- name: Wait for SSH to come up on EC2 Instance(s)
wait_for:
host: "{{ item }}"
port: 22
state: started
with_items: "{{ ec2.results | get_ec2_info('public_ip') }}"
# CALL THE DYNAMIC GROUP IN THE SAME PLAYBOOK
- hosts: my_ec2_servers
become: yes
remote_user: ubuntu
gather_facts: yes
tasks:
- name: DO YOUR TASKS HERE
额外信息:
- 使用 ansible 2.0.1.0
- 假设您正在启动 ubuntu 个实例,如果不是,则更改
remote_user: ubuntu
中的值- 假设 ssh 密钥配置正确
请查阅这些 github 存储库以获得更多帮助:
不要这样做:
- name: Provision Lunch
with_items:
- hostname: eggroll1
- hostname: eggroll2
- hostname: eggroll3
ec2:
region: us-east-1
因为通过使用它,您可以清除项目中来自 ec2 的所有信息。
您收到以下输出:
TASK [Launch instance] *********************************************************
changed: [localhost] => (item={u'hostname': u'eggroll1'})
changed: [localhost] => (item={u'hostname': u'eggroll2'})
但项目应该是这样的:
changed: [localhost] => (item={u'kernel': None, u'root_device_type': u'ebs', u'private_dns_name': u'ip-172-31-29-85.ec2.internal', u'public_ip': u'54.208.138.217', u'private_ip': u'172.31.29.85', u'id': u'i-003b63636e7ffc27c', u'ebs_optimized': False, u'state': u'running', u'virtualization_type': u'hvm', u'architecture': u'x86_64', u'ramdisk': None, u'block_device_mapping': {u'/dev/sda1': {u'status': u'attached', u'delete_on_termination': True, u'volume_id': u'vol-37581295'}}, u'key_name': u'eggfooyong', u'image_id': u'ami-fce3c696', u'tenancy': u'default', u'groups': {u'sg-aabbcc34': u'ssh'}, u'public_dns_name': u'ec2-54-208-138-217.compute-1.amazonaws.com', u'state_code': 16, u'tags': {u'ansibleowned': u'True', u'role': u'supper'}, u'placement': u'us-east-1d', u'ami_launch_index': u'1', u'dns_name': u'ec2-54-208-138-217.compute-1.amazonaws.com', u'region': u'us-east-1', u'launch_time': u'2016-04-19T08:19:16.000Z', u'instance_type': u't2.micro', u'root_device_name': u'/dev/sda1', u'hypervisor': u'xen'})
尝试使用下面的代码
- name: Create a sandbox instance
hosts: localhost
gather_facts: False
vars:
keypair: eggfooyong
instance_type: t2.micro
security_group: ssh
image: ami-8675309
region: us-east-1
subnet: subnet-8675309
instance_names:
- eggroll1
- eggroll2
tasks:
- name: Launch instance
ec2:
key_name: "{{ keypair }}"
group: "{{ security_group }}"
instance_type: "{{ instance_type }}"
image: "{{ image }}"
wait: true
region: "{{ region }}"
vpc_subnet_id: "{{ subnet }}"
assign_public_ip: no
count: "{{ instance_names | length }}"
register: ec2
- name: tag instances
ec2_tag:
resource: '{{ item.0.id }}'
region: '{{ region }}'
tags:
Name: '{{ item.1 }}'
role: "supper"
ansibleowned: "True"
with_together:
- '{{ ec2.instances }}'
- '{{ instance_names }}'
- name: Wait for SSH to come up
wait_for: host={{ private_ip }} port=22 delay=60 timeout=320 state=started
with_items: '{{ ec2.instances }}'
假设您的 ansible 主机位于 VPC 内
我认为这对调试很有帮助。
ec2
寄存器是 dict
类型。它有一个键 results
.
results
键有很多元素,包括 dict
和 list
,如下所示:
{
"msg": {
"results": [
{
"invocation": {
},
"instances": [],
"changed": false,
"tagged_instances": [
{
}
],
"instance_ids": null,
"failed": false,
"item": [
],
"ansible_loop_var": "item"
}
],
"msg": "All items completed",
"changed": false
},
"_ansible_verbose_always": true,
"_ansible_no_log": false,
"changed": false
}
因此,您可以使用 .
获取所需的数据,例如 item.changed
具有 false
布尔值。
- debug:
msg: "{{ item.changed }}"
loop: "{{ ec2.results }}"