问题
I have group tgt-cluster
includes 3 hosts. I have written down role to deploy container which is executing on tgt-cluster
group. I am controlling the number of containers to deploy with with_sequence
. My tasks looks like this.
- name: Deploy Container
docker_container:
name: "C{{ item }}"
image: "{{ image_name }}:{{ image_tag }}"
recreate: yes
detach: yes
tty: yes
interactive: yes
with_sequence: count="{{ number_of_container_to_deploy }}"
If I want to deploy one container, currently playbook is executing on all 3 hosts in tgt-cluster
group and I end up with 3 containers. So How should I created nested loop in this case to control the task execution on hosts on round robin fashion.
Say if we want to deploy 4 container.. 1st container should be deployed on 1st host in group, 2nd container should be deployed on 2nd container in group, 3rd should be deployed on 3rd hosts in group and 4th container should be deployed back to the 1st host in group.
I have updated my variable file with following, and count_per_hosts
variable is assigned to with_sequence
. While executing I was getting error stating "can't parse arg count=u'' as integer". So I updated with_sequence: count="{{ count_per_hosts | int }}"
and it's not throwing error but It is not executing tasking not skipping it.
the_hosts: "{{ groups['tgt-cluster']}}"
num_hosts: "{{ the_hosts | length }}"
count_per_hosts: >
"{% for x in range(number_of_container_to_deploy) %}
- set idx = x % num_hosts
set cc = assignment.get(the_hosts[idx], 0)
set _ = assignment.update({the_hosts[idx]: cc + 1})
{% endfor %}"
Currently my execution looks like this. deploy_container : Deploy Process
tasks should create container but we don't see any logs over there.
Also, I tried to move the_hosts
and num_hosts
inside count_per_hosts
same syntax as indicated in answers but execution does not spill any output.
PLAY [bin installation] **************************************************************************************************************************************************************************************
META: ran handlers
TASK [deploy_container : Deploy Process] *************************************************************************************************************************************************************
task path: /home/tg/Documents/playbooks/roles/deploy_container/tasks/main.yml:3
META: ran handlers
META: ran handlers
PLAY RECAP *****************************************************************************************************************************************************************************************************
br1.lab : ok=0 changed=0 unreachable=0 failed=0
br2.lab : ok=0 changed=0 unreachable=0 failed=0
br3.lab : ok=0 changed=0 unreachable=0 failed=0
Also, I tried default(0)
but ansible is throwing error.
{
"msg": "can't parse arg count=u\"#' # ' idx = x % num_hosts\\ncc = assignment.get(the_hosts[idx], 0)\\n_ = assignment.update({the_hosts[idx]: cc + 1})\\nidx = x % num_hosts\\ncc = assignment.get(the_hosts[idx], 0)\\n_ = assignment.update({the_hosts[idx]: cc + 1})\\n'\\n\" as integer"
}
Current playbook looks like this,
- name: bin installation
hosts: tgt-cluster
user: "{{ user }}"
gather_facts: no
become: yes
vars:
count_per_hosts: |
{% set the_hosts = groups["tgt-cluster"] %}
{% set num_hosts = the_hosts | length %}
{% set result = {} %}
{% for x in range(number_of_process_to_deploy) %}
{% set idx = x % num_hosts %}
{% set h = the_hosts[idx] %}
{% set cc = result.get(h, 0) %}
{% set _ = result.update({h: cc + 1}) %}
{% endfor %}
{{ result }}
roles:
- deploy_container
output with with_sequence: count="{{ count_per_hosts }}"
if we specify with_sequence: count="{{ count_per_hostsget(ansible_hostname, 0) }}"
we get fatal: [br1.lab]: FAILED! => {"msg": "'ansible_hostname' is undefined"}
TASK [deploy_container : Deploy Process] ***************************************************************************
fatal: [br1.lab]: FAILED! => {"msg": "can't parse arg count=u\"{u'br1.lab': 1, u'br2.lab': 1}\" as integer"}
fatal: [br2.lab]: FAILED! => {"msg": "can't parse arg count=u\"{u'br1.lab': 1, u'br2.lab': 1}\" as integer"}
fatal: [br3.lab]: FAILED! => {"msg": "can't parse arg count=u\"{u'br1.lab': 1, u'br2.lab': 1}\" as integer"}
I tried to register the output and check and ran debug
on that to see the content and found it's not able to pick the host from group.
ok: [br1.lab] => {
"my_content": {
"changed": false,
"results": [],
"skipped": true,
"skipped_reason": "No items in the list"
}
}
回答1:
You will be much happier just doing the count assignment by yourself:
vars:
the_hosts: "{{ groups['tgt-cluster']}}"
num_hosts: "{{ the_hosts | length }}"
count_per_hosts: |
{% set result = {} %}
{% for x in range(number_of_container_to_deploy) %}
{% set idx = x % num_hosts %}
{% set h = the_hosts[idx] %}
{% set cc = result.get(h, 0) %}
{% set _ = result.update({h: cc + 1}) %}
{% endfor %}
{{ result }}
Then in the actual docker_container:
task, you are now able to have the with_sequence:
be a count per host, and some of them may be zero:
- name: Deploy Container
docker_container:
name: "C{{ item }}"
image: "{{ image_name }}:{{ image_tag }}"
recreate: yes
detach: yes
tty: yes
interactive: yes
with_sequence:
count: "{{ count_per_hosts.get(ansible_hostname, 0) }}"
来源:https://stackoverflow.com/questions/53683136/ansible-iterate-over-inventory-groups