Ansible: How can I set serial numbers for hosts

4.8k views Asked by At

I am trying to provision hosts on EC2, so I am working with Ansible Dynamic Inventory.

What I want to do is; to set serial number for each node.

For example: "myid" configuration of Zookeeper

Zookeeper requires serial number named "myid" for each node; 1 for hostA, 2 for hostB, 3 for hostC and so on.

Here is the part of my playbook that copies "myid" file to hosts.

- name: Set myid
  sudo: yes
  template: src=var/lib/zookeeper/myid.j2 dest=/var/lib/zookeeper/myid

And myid.j2 should be something like this below.

{{ serial_number }}

The question is: What should the variable "{{ serial_number }}" be like?

3

There are 3 answers

0
Jeremy On BEST ANSWER

I solved this by assigning a number to each EC2 instance as a tag when creating them. I then refer to that tag when creating the myid file. Below are the tasks I used to create my EC2 instances with all non-important fields left out for brevity.

- name: Launch EC2 instance(s)
  with_sequence: count="{{ instance_count }}"
  ec2:
    instance_tags:
      number: "{{ item }}"

Then when installing ZooKeeper on these servers, I use the dynamic inventory to obtain all the servers tagged with zookeeper and use the number tag in the myid file.

- name: Render and copy myid file
  copy: >
    content={{ ec2_tag_number }}
    dest=/etc/zookeeper/conf/myid

Note: when creating the EC2 instances, I needed to use with_sequence rather than the count field in the ec2 module. Otherwise I wouldn't have an index to capture for the tag.


If you want the playbook to handle being able to add nodes to the current cluster, you can query for the number of EC2 instances tagged with zookeeper and add that to the iteration index. This is fine to have normally because current_instance_count will be 0 if there aren't any.

- name: Determine how many instances currently exist
  shell: echo "{{ groups['tag_zookeeper'] | length }}"
  register: current_instance_count
- name: Launch EC2 instance(s)
  with_sequence: count="{{ instance_count }}"
  ec2:
    instance_tags:
      number: "{{ item|int + current_instance_count.stdout|int }}"
0
MarkNS On

I found a nice clean way to do this using Ansible's with_index_items syntax:

tasks:
  - name: Set Zookeeper Id
    set_fact: zk_id={{item.0 + 1}}
    with_indexed_items: "{{groups['tag_Name_MESOS_MASTER']}}"
    when: item.1 == "{{inventory_hostname}}"

/etc/zookeeper/conf/myid template can then be set to

{{zk_id}}

This assumes you are using AWS dynamic inventory.

0
Yu Huang On

There is no need to use template, you can directly assign the content of myid file in the playbook. Assume you have collect all ec2 instance into the group "ec2hosts".

- hosts: ec2hosts
  user: ubuntu
  sudo:Trues

  tasks:
    - name: Set Zookeeper Id
      copy: >
      content={{ item.0 + 1 }}
      dest=/var/lib/zookeeper/myid
      with_indexed_items: "{{groups['ec2hosts']}}"
      when: item.1 == "{{inventory_hostname}}"