Hi Renaud,
I totally get what you are looking to achieve. Perhaps you've achieved it
already in the past year. Assuming that you are happy with specifying a start
index = x and a count = N to produce machines with names containing x, x+1,
x+2, ... x+N, I think the following playbook example will be instructive. I
had the same requirement and this is what I was able to produce:
# ansible-playbook create-web.yml --extra-vars "count=n startindex=x
env=production"
# provisions n web servers in prod env with indices x, x+1, x+2, ... x+n
---
- name: "create and provision web servers in {{ env }} environment"
hosts: localhost
gather_facts: False
tasks:
- name: launch instances
local_action:
module: ec2
key_name: "{{ launch_key.ec2_classic }}"
instance_type: "{{ instance.web[env] }}"
volumes:
- device_name: /dev/sda1
volume_size: 512
delete_on_termination: true
- device_name: "{{ ephemeral[0] }}"
ephemeral: ephemeral0
- device_name: "{{ ephemeral[1] }}"
ephemeral: ephemeral1
# ephemerals are deleted by default on termination
region: "{{ region }}"
image: "{{ os.amazon.ami_id }}"
wait: yes
group: "web-{{ env }}"
count: "{{ count }}"
wait_timeout: 1000
register: created
tags:
- create
- name: write instance ids and public dns of the instances to local
hosts file
local_action:
module: lineinfile
dest: ./hosts
line: "{{ item.id }} {{ item.public_dns_name }}"
create: yes
with_items: created.instances
tags:
- create
- name: create identifier sequence for tagging
debug: msg="{{ item }}"
with_sequence: start="{{ startindex }}" count="{{ count }}"
format=%02d
no_log: true # mute output
register: sequence
tags:
- tag
- name: tag instances
no_log: true
local_action: >-
ec2_tag
resource={{ item.0.id }}
region={{ region }}
args:
tags:
Name: "Web {{ env|title }} {{ item.1.msg }}"
Env: "{{ env }}"
Type: server
Function: web
OS: "{{ os.amazon.name }}"
Region: "{{ region }}"
ID: "{{ item.1.msg }}"
with_together:
- created.instances
- sequence.results
tags:
- tag
- name: update dns records
route53: >-
command=create
zone=yoursite.com
record=web.{{ item.1.msg }}.{{ env }}.server.yoursite.com
type=CNAME
ttl=300
value={{ item.0.public_dns_name }}
overwrite=true
with_together:
- created.instances
- sequence.results
tags:
- deploy
- name: register instances with load balancers
local_action: ec2_elb
args:
instance_id: "{{ item.id }}"
ec2_elbs: "{{ elb_names.web[env] }}"
region: "{{ region }}"
state: present
wait: no
with_items: created.instances
tags:
- deploy
- name: add instances to an in-memory group
no_log: true
local_action: add_host hostname="{{ item.public_dns_name }}"
groupname=fresh
with_items: created.instances
tags:
- create
- name: wait for ssh to come up
local_action: wait_for host="{{ item.public_dns_name }}" port=22
delay=60 timeout=320 state=started
with_items: created.instances
tags:
- create
- name: provision the instances
hosts: fresh
user: "{{ os.amazon.user }}"
vars:
user: "{{ os.amazon.user }}"
roles:
- common
- swap
- python
tags:
- configure
- name: summary of created instances
hosts: fresh
gather_facts: false
sudo: no
tasks:
- name: Get instance ec2 facts
action: ec2_facts
no_log: true # mute output
register: ec2_facts
- name: Get resource tags from ec2 facts
sudo: false
no_log: true # mute output
local_action: >-
ec2_tag
resource={{ ec2_facts.ansible_facts.ansible_ec2_instance_id }}
region={{ region }}
state=list
register: ec2_tags
- debug: msg="{{ ec2_facts.ansible_facts.ansible_ec2_instance_id }} |
{{ ec2_facts.ansible_facts.ansible_ec2_instance_type }} | {{
ec2_tags.tags.Name }} | {{
ec2_facts.ansible_facts.ansible_ec2_public_hostname }}"
tags:
- create
Yes, parts of it are *very* contrived, but it gets the job done the way I
want it to.
@Others: Yes, the cattle model is the way to go, but while we're getting
there, ansible must still do what we want. And thus continue our Sisyphian
labours ;)
On Wednesday, 27 November 2013 11:36:12 UTC-6, Renaud Guerin wrote:
>
> Nice tool !
>
> But your ssh example shows how a unique name is still unavoidable
> sometimes, be it Tags or DNS based.
>
> If I left instances with their EC2 birth names, I couldn’t just make up «
> ansible-ec2 ssh --name web1 » when I need to log into a web server, I’d
> have to « ansible-ec2 list » first with a raw group name to find web
> servers, then pick one and ssh into it.
>
> Also, some tools just rely on a nice hostname being set (the New Relic
> server dashboard would be unreadable with ec2-xxxx host names all mixed up)
> RabbitMQ for instance, names its task queues after the current hostname
> and warns against changing it. I know it’s bad practice and not autoscaling
> friendly, but it’s just how it is in some occasions.
>
> So, I’ll forget about CNAMEs in Route53 but I think my original feature
> request is still relevant : being able to pass a list of names to the EC2
> module to be added to the Name tag of each created instance.
> If I submitted such a patch, would you guys merge it ?
>
>
> On 27 novembre 2013 at 16:38:31, Peter Sankauskas ([email protected]
> <javascript:>) wrote:
>
> Actually yes. You can tag AWS resources and find them using tags. For
> example, an Amazon Linux instance with tag Name=foo could be SSHed into
> using
>
> ansible-ec2 ssh --name foo -u ec2-user
>
>
> You can find the code here:
>
> https://github.com/pas256/ansible-ec2
>
>
> It uses Ansible's EC2 inventory plugin to do the lookup of public DNS name
> (or whatever you configure it to).
>
> One further tip. In a distributed environment, debugging can be tough
> because you don't know which server is causing issues. Get all of the
> logging out of the instances and into some central and searchable location.
> There are plenty of SaaS providers (Loggly, Splunk, Sumologic, Papertrail)
> and open source (logstash, etc) options available.
>
> --
> Kind regards,
> Peter Sankauskas
> Answers for AWS <http://answersforaws.com>
>
>
>
> On Wednesday, November 27, 2013 6:48:35 AM UTC-8, Renaud Guerin wrote:
>>
>> Hi Peter,
>>
>> Very interesting talk and this is probably the better approach, thanks.
>>
>> You do need to address individual servers from time to time though :
>> ssh’ing into them to debug something, for instance.
>>
>> In this case, finding and copying the public_dns_name for a box sounds
>> like a pain, and a big usability regression from a human-readable naming
>> convention and DNS CNAMEs.
>>
>> Am I missing a clever way to use ansible to provide « vagrant ssh »
>> functionality basically ?
>> Or do you know of any wrapper tools to do something similar ?
>>
>> Just to belabor the point:
>>
>> https://www.youtube.com/watch?v=lQUdjPBJX5c
>>
>>
>>
>> On Sunday, November 24, 2013 10:34:39 AM UTC-8, Peter Sankauskas wrote:
>>>
>>> Hi Renaud,
>>>
>>> People that have been using AWS for a while don't really use it this
>>> way, or at least, they shouldn't. Treat servers like cattle, not pets.
>>>
>>> If you haven't yet, take a look at AutoScaling Groups:
>>>
>>> http://aws.amazon.com/autoscaling/
>>> <http://www.google.com/url?q=http%3A%2F%2Faws.amazon.com%2Fautoscaling%2F&sa=D&sntz=1&usg=AFQjCNHbyMw92ut0c-QkheWMVy34vCXxgw>
>>>
>>> ... and think about how to architect your application to run on dynamic
>>> infrastructure.
>>>
>>> --
>>> Kind regards,
>>> Peter Sankauskas
>>> Answers for AWS
>>> <http://www.google.com/url?q=http%3A%2F%2Fanswersforaws.com&sa=D&sntz=1&usg=AFQjCNFQbg6M0Bmr2rMpccgv3xl_aiQukg>
>>>
>>>
>>>
>>>
>>>
>>> On Saturday, November 23, 2013 8:55:34 AM UTC-8, Renaud Guerin wrote:
>>>>
>>>> Thanks Michael,
>>>>
>>>> I know (and mentioned) I’ll need to use the route53 module, that’s not
>>>> the difficulty here.
>>>> I did some more research and it looks like ‘with_together' is what I
>>>> was looking for.
>>>>
>>>> If anyone is looking to do the same (it's a quite common provisioning
>>>> pattern) :
>>>>
>>>> - provide an « instances_names » list
>>>> - create the required number of instances using the ec2 module,
>>>> register the result.
>>>> - Use ec2_tag, add_host and route53 for, respectively: setting the AWS
>>>> Name tag, adding the host to the inventory with its desired hostname (not
>>>> the default EC2 name), adding a CNAME DNS entry for hostname -> EC2
>>>> public_dns_name
>>>> -For each of the modules above, use « with_together » to iterate
>>>> through both the created instances list (returned by the EC2 module), and
>>>> the hostnames list you provided.
>>>>
>>>> This would be slightly easier if the ec2 module would take an optional
>>>> « instances_names » list as a parameter; and used it to set different EC2
>>>> Name tags for each of the created instances.
>>>> I can look at adding this functionality if it’s likely to be accepted
>>>> and merged in. What do you think ?
>>>>
>>>>
>>>> On 23 novembre 2013 at 16:38:27, Michael DeHaan (
>>>> [email protected]) wrote:
>>>>
>>>> http://ansibleworks.com/docs/modules.html#route53
>>>> <http://www.google.com/url?q=http%3A%2F%2Fansibleworks.com%2Fdocs%2Fmodules.html%23route53&sa=D&sntz=1&usg=AFQjCNFTh6HnQAujtPzc-rzPWZkkzhvrKw>
>>>>
>>>>
>>>> On Thu, Nov 21, 2013 at 2:14 PM, Renaud Guérin <[email protected]
>>>> > wrote:
>>>>
>>>>> On 21 novembre 2013 at 18:47:46, James Tanner ([email protected])
>>>>> wrote:
>>>>>
>>>>> > The EC2 module's docs show how to create several instances at once
>>>>> > using the "count" variable, and register the results into another
>>>>> > variable ("ec2").
>>>>> >
>>>>> > You can then iterate on the created instances and do stuff (like add
>>>>>
>>>>> > them to an inventory group) using "with_items: ec2.instances"
>>>>> >
>>>>> > However, I can't figure out how to do the following :
>>>>> >
>>>>> > 1) Have the user provide a "names" list ( { "web1", "web2", "web3" }
>>>>>
>>>>> > ). Or better yet, a naming prefix ("web"), a count (3) and a start
>>>>> > index (1).
>>>>> > 2) Create them using the ec2 module, register results into "ec2" to
>>>>>
>>>>> > keep precious info like ec2.instances.public_dns_name.
>>>>> > 3) Here's the tricky bit : add a route53 DNS entry that CNAMEs
>>>>> > together each entry in the "names" list with the public_dns_name
>>>>> > values in "ec2.instances".
>>>>>
>>>>> Can you give an example for what you are trying to convey here? I'm a
>>>>>
>>>>> bit confused.
>>>>>
>>>>> Thanks for replying James,
>>>>>
>>>>> I’m trying to create a fleet of (for instance) web servers on EC2, and
>>>>> would like to give them meaningful ansible hostnames (web1, web2, etc)
>>>>> instead of the AWS generated public DNS names (
>>>>> ec2-xxxxx.compute-1.amazonaws.com
>>>>> <http://www.google.com/url?q=http%3A%2F%2Fec2-xxxxx.compute-1.amazonaws.com&sa=D&sntz=1&usg=AFQjCNFQ3DgG9MKPa_vN9SR9cR3eHWeSTA>
>>>>> )
>>>>>
>>>>> I’d also like to create a CNAME DNS record (using the route53 module)
>>>>> pointing their chosen name (web1, web2, etc) to the EC2 DNS record (
>>>>> ec2-xxxxx.compute-1.amazonaws.com
>>>>> <http://www.google.com/url?q=http%3A%2F%2Fec2-xxxxx.compute-1.amazonaws.com&sa=D&sntz=1&usg=AFQjCNFQ3DgG9MKPa_vN9SR9cR3eHWeSTA>).
>>>>>
>>>>> The latter is accessible in the « instances.public_dns_name »
>>>>>
>>>>> Ideally, I would just need to provide the ec2 module with a list of
>>>>> hostnames for the instances it’s going to create (internally it just
>>>>> needs
>>>>> to set the « Name » EC2 tag), and I’d get back the « item.hostname »
>>>>> (web1,web2) alongside each « item.public_dns_name » (
>>>>> ec2-xxxxx.compute-1.amazonaws.com
>>>>> <http://www.google.com/url?q=http%3A%2F%2Fec2-xxxxx.compute-1.amazonaws.com&sa=D&sntz=1&usg=AFQjCNFQ3DgG9MKPa_vN9SR9cR3eHWeSTA>)
>>>>>
>>>>> when using "with_items: ec2"
>>>>>
>>>>> The more I think of it, the more it sounds like just a few changes are
>>>>> needed in the ec2 module. I can try and have a go at it, but I’d like to
>>>>> know if there’s something similar already.
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "Ansible Project" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to [email protected].
>>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Michael DeHaan <[email protected]>
>>>> CTO, AnsibleWorks, Inc.
>>>> http://www.ansibleworks.com/
>>>> <http://www.google.com/url?q=http%3A%2F%2Fwww.ansibleworks.com%2F&sa=D&sntz=1&usg=AFQjCNEn7XMcb-1wMxliSyOhlnyBBlDaQg>
>>>>
>>>> --
>>>> You received this message because you are subscribed to a topic in the
>>>> Google Groups "Ansible Project" group.
>>>> To unsubscribe from this topic, visit
>>>> https://groups.google.com/d/topic/ansible-project/9geyZDmbrtU/unsubscribe
>>>> .
>>>> To unsubscribe from this group and all its topics, send an email to
>>>> [email protected].
>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>
>>>>
>> --
>> You received this message because you are subscribed to a topic in the
>> Google Groups "Ansible Project" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/d/topic/ansible-project/9geyZDmbrtU/unsubscribe
>> .
>> To unsubscribe from this group and all its topics, send an email to
>> [email protected].
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>>
>> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Ansible Project" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/ansible-project/9geyZDmbrtU/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected] <javascript:>.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
--
You received this message because you are subscribed to the Google Groups
"Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/ansible-project/6f7cd7cf-06ca-4d37-948f-3f43cec62e54%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.