Amazon ec2 Ansible:尝试一次在多个区域中创建多个EC2实例
我正在尝试创建一个AWS EC2 ansible剧本: 1) 首先在以下三个区域分别分配一个VPC: 美国西部1号、亚太东北1号和欧盟西部1号 2) 查找每个区域的最新ubuntu AMI(ec2_AMI_搜索) 3) 然后使用1)和2)中发现的结果, 使用最新的ubuntu AMI为每个区域创建一个EC2实例(针对该区域) 可用区为us-west-1a、ap-northeast-1a 和eu-west-1a 对于Ansible,我对第1)步和第2)步没有问题,这两步很简单:Amazon ec2 Ansible:尝试一次在多个区域中创建多个EC2实例,amazon-ec2,ansible,ansible-playbook,Amazon Ec2,Ansible,Ansible Playbook,我正在尝试创建一个AWS EC2 ansible剧本: 1) 首先在以下三个区域分别分配一个VPC: 美国西部1号、亚太东北1号和欧盟西部1号 2) 查找每个区域的最新ubuntu AMI(ec2_AMI_搜索) 3) 然后使用1)和2)中发现的结果, 使用最新的ubuntu AMI为每个区域创建一个EC2实例(针对该区域) 可用区为us-west-1a、ap-northeast-1a 和eu-west-1a 对于Ansible,我对第1)步和第2)步没有问题,这两步很简单: >
>
tasks:
- name: create a vpc
ec2_vpc:
state: present
region: "{{ item.region }}"
internet_gateway: True
resource_tags: { env: production}
cidr_block: 10.0.0.0/16
subnets:
- cidr: 10.0.0.0/24
az: "{{ item.az }}"
resource_tags:
env: production
tier: public
route_tables:
- subnets:
- 10.0.0.0/24
routes:
- dest: 0.0.0.0/0
gw: igw
with_items:
- region: us-west-1
az: us-west-1a
- region: ap-northeast-1
az: ap-northeast-1a
- region: eu-west-1
az: eu-west-1a
...
- name: Get the ubuntu trusty AMI
ec2_ami_search: distro=ubuntu release=trusty virt=hvm region={{ item }}
with_items:
- us-west-1
- ap-northeast-1
- eu-west-1
register: ubuntu_image
...
>
以及使用调试模块输出的ubuntu_image变量:
TASK: [print out ubuntu images] ***********************************************
ok: [localhost] => {
"ubuntu_image": {
"changed": false,
"msg": "All items completed",
"results": [
{
"aki": null,
"ami": "ami-b33dccf7",
"ari": null,
"changed": false,
"invocation": {
"module_args": "distro=ubuntu release=trusty virt=hvm region=us-west-1",
"module_name": "ec2_ami_search"
},
"item": "us-west-1",
"serial": "20150629",
"tag": "release"
},
{
"aki": null,
"ami": "ami-9e5cff9e",
"ari": null,
"changed": false,
"invocation": {
"module_args": "distro=ubuntu release=trusty virt=hvm region=ap-northeast-1",
"module_name": "ec2_ami_search"
},
"item": "ap-northeast-1",
"serial": "20150629",
"tag": "release"
},
{
"aki": null,
"ami": "ami-7c4b0a0b",
"ari": null,
"changed": false,
"invocation": {
"module_args": "distro=ubuntu release=trusty virt=hvm region=eu-west-1",
"module_name": "ec2_ami_search"
},
"item": "eu-west-1",
"serial": "20150629",
"tag": "release"
}
]
}
}
但是,我不知道如何执行步骤3)
从ubuntu_图像寄存器变量获取结果
然后确定给定EC2实例所属的3个AMI和子网中的哪一个。
请参见下文,作为解决方法,我手动硬编码了ami和子网值
我只是从上面的ubuntu_图像打印输出中得到:
- name: start the instances
ec2:
image: "{{ item.ami }}" # MANUALLY HARDCODED
region: "{{ item.region }}"
instance_type: "{{ instance_type }}"
assign_public_ip: True
key_name: "{{ item.name }}"
group: ["http deployment", "ssh deployment", "outbound deployment"]
instance_tags: { Name: "{{ item.name }}", type: ss, env: production}
exact_count: "{{ count }}"
count_tag: { Name: "{{ item.name }}" }
vpc_subnet_id: "{{ item.subnet }}" #MANUALLY HARDCODED
wait: yes
register: ec2
with_items:
- region: us-west-1
name: ss12
ami: ami-b33dccf7 # MANUALLY HARDCODED
subnet: subnet-35a22550 # MANUALLY HARDCODED
- region: ap-northeast-1
name: ss21
ami: ami-9e5cff9e # MANUALLY HARDCODED
subnet: subnet-88c47dff # MANUALLY HARDCODED
- region: eu-west-1
name: ss32
ami: ami-7c4b0a0b # MANUALLY HARDCODED
subnet: subnet-23f59554 # MANUALLY HARDCODED
当ami/子网硬编码工作时,您能为我想出一个解决方案来避免这种ami/子网硬编码吗?
我试图将set_fact弄乱,但没有用,因为我无法使它成为“region-to-ami”值映射的字典请记住,
Ansible
是一个“可插入”系统,因此很容易为自己定制它。有时,它甚至比使用“本机”模块寻找解决方案更容易、更快
在您的情况下,您可以轻松编写自己的自定义查找\u插件
,用于搜索正确的子网
例如:
lookup\u plugins
的文件夹ansible.cfg
lookup\u plugins
中创建名为subnets.py的文件
import boto.vpc
class LookupModule(object):
def __init__(self, basedir=None, **kwargs):
self.basedir = basedir
self.plugin_name = 'subnets'
def run(self, regions, variable=None, **kwargs):
if not isinstance(regions, list):
regions = [regions]
for region in regions:
return [boto.vpc.connect_to_region(region).get_all_subnets()[0].id]
上面的简单代码将查找给定区域中的子网。当然,您可以根据需要自定义它
然后在您的playbook中引用此插件以查找正确的子网:
例如:
- hosts: localhost
gather_facts: no
tasks:
- name: Start instance
debug: msg="Starting instance {{ item.ami }} in {{ item.region }} in {{ item.subnet }}"
with_items:
- region: us-west-1
name: ss12
ami: ami-b33dccf7
subnet: "{{ lookup('subnets', 'us-west-1') }}"
- region: ap-northeast-1
name: ss21
ami: ami-9e5cff9e
subnet: "{{ lookup('subnets', 'ap-northeast-1') }}"
- region: eu-west-1
name: ss32
ami: ami-7c4b0a0b
subnet: "{{ lookup('subnets', 'ap-northeast-1') }}"
在您的情况下,您可能需要引用正确的AMI
和相关的区域
,如果您仍然想在没有其他模块帮助的情况下执行此操作,您可以计算服务器和子网长度的模“%”:
"{{subnets[item.0 | int % subnets | length | int].aws_ec2_subnets}}"
示例代码
变量:
任务:
我就是这样做的。
launchNodes.yml只是一个带有一些标记的简单ec2
- debug:
msg: "launching {{ nodeCount }} nodes in these subnets {{ec2SubnetIds}}"
- name: clear finalSubnetList
set_fact:
finalSubnetList: []
- name: build final list
set_fact:
finalSubnetList: "{{ finalSubnetList }} + [ '{{ ec2SubnetIds[ ( ec2subnet|int % ec2SubnetIds|length)|int ] }}' ]"
with_sequence: count={{nodeCount}}
loop_control:
loop_var: ec2subnet
- debug:
msg: "finalSubnetList {{finalSubnetList}} "
- include_tasks: launchNodes.yml
ec2SubnetId="{{ finalSubnetList[index|int -1] }}"
nodeCount=1
with_sequence: count="{{ finalSubnetList|length }}"
loop_control:
loop_var: index
subnets:
- {zone: "us-east-1a", aws_ec2_subnets: 'subnet-123'}
- {zone: "us-east-1b", aws_ec2_subnets: 'subnet-456'}
- {zone: "us-east-1d", aws_ec2_subnets: 'subnet-789'}
server_list:
- server1
- server2
- server3
- name: Create new ec2 instance
ec2:
profile: "{{aws_profile}}"
key_name: "{{aws_key_name}}"
group_id: "{{aws_security_group}}"
instance_type: "{{aws_instance_type}}"
image: "{{aws_ami}}"
region: "{{region}}"
exact_count: "1"
#instance_profile_name: none
wait: yes
wait_timeout: 500
volumes: "{{volumes}}"
monitoring: no
vpc_subnet_id: "{{subnets[item.0 | int % subnets | length | int].aws_ec2_subnets}}"
assign_public_ip: no
tenancy: default
termination_protection: yes
instance_tags:
App: "{{app_name}}"
Environment: "{{environment_type}}"
Platform: "{{platform_name}}"
Name: "{{item.1}}"
count_tag:
App: "{{app_name}}"
Environment: "{{environment_type}}"
Platform: "{{platform_name}}"
Name: "{{item.1}}"
register: ec2_new_instance
with_indexed_items:
- "{{server_list}}"
- debug:
msg: "launching {{ nodeCount }} nodes in these subnets {{ec2SubnetIds}}"
- name: clear finalSubnetList
set_fact:
finalSubnetList: []
- name: build final list
set_fact:
finalSubnetList: "{{ finalSubnetList }} + [ '{{ ec2SubnetIds[ ( ec2subnet|int % ec2SubnetIds|length)|int ] }}' ]"
with_sequence: count={{nodeCount}}
loop_control:
loop_var: ec2subnet
- debug:
msg: "finalSubnetList {{finalSubnetList}} "
- include_tasks: launchNodes.yml
ec2SubnetId="{{ finalSubnetList[index|int -1] }}"
nodeCount=1
with_sequence: count="{{ finalSubnetList|length }}"
loop_control:
loop_var: index