
사용자가 입력한 호스트 목록에서 호스트 이름과 IP 주소를 가져와 해당 정보를 중앙 서버로 보내려고 합니다. 제가 겪고 있는 주요 문제는 호스트 수가 상당히 다양할 수 있다는 것입니다. 예를 들어 첫 번째 실행에서 사용자는 호스트 이름 1개를 입력하고 두 번째 실행에서는 30을 입력하고 다음 실행에서는 5를 입력할 수 있습니다. 사용자가 호스트를 1개 또는 100개 입력하는지 여부에 관계없이 단일 플레이북을 사용할 수 있기를 원합니다.
Ansible Tower 템플릿이 실행될 때 "추가 변수" 프롬프트를 통해 호스트 이름이 수집됩니다.
client_hosts: 'host1,host2'
그런 다음 플레이북에서 참조됩니다.
- name: Gather client information
hosts:
- "{{ client_hosts | default(omit) }}"
tasks:
- name: Grab client hostname
shell: cat /etc/hostname
register: client_hostname
- name: Grab client IP address
shell: hostname -i | sed -n '1 p'
register: client_ip
플레이북을 더 자세히 살펴보면 해당 IP + 호스트 이름을 특정 중앙 서버의 파일에 추가하고 싶습니다(서버 호스트 이름은 변경되지 않음).
- name: Update server
hosts: central.server
tasks:
- name: Update client host list
lineinfile:
path: /path/to/file
line: "{{ hostvars['client_hosts']['client_ip'] }} - {{ hostvars['client_hosts']['client_hostname'] }}"
위의 내용은 단일 호스트에 대해 잘 작동하지만 둘 이상의 호스트가 지정되면(예: client_hostname[1,2,*]?) 변수 등록을 통해 어떻게 반복하고 어떻게 해야 할지 모를 때 해당 값으로 서버를 업데이트합니다. 많은 호스트가 미리 입력될 예정인가요?
답변1
이 사용 사례는 세 부분으로 구성됩니다. 1) 재고 관리, 2) 수집클라이언트_호스트 이름그리고클라이언트_IP, 3) 중앙서버에 보고합니다.
1. 재고 관리
재고를 관리하고 수집하는 방법에는 다양한 옵션이 있습니다.클라이언트_호스트 이름그리고클라이언트_IP. 예를 들어호스트 범위 추가. host001, hosts002, ..., host999
예를 들어 아래 인벤토리에 다음을 추가하세요.중앙 서버, 단순화를 위한 localhost 및 그룹의 100개 호스트시험
shell> cat inventory/01-hosts
central_server ansible_host=localhost
[test]
host[001:100]
[test:vars]
ansible_connection=ssh
ansible_user=admin
ansible_become=yes
ansible_become_user=root
ansible_become_method=sudo
ansible_python_interpreter=/usr/local/bin/python3.8
인벤토리를 간단히 테스트해 보세요.
- hosts: all
gather_facts: false
tasks:
- debug:
var: ansible_play_hosts|length
run_once: true
요약하다
ansible_play_hosts|length: '101'
전체 인벤토리를 표시하려면 아래 명령을 실행하십시오.
shell> ansible-inventory -i inventory --list --yaml
그런 다음 호스트를 선택하는 방법에 대한 다양한 옵션이 있습니다. 보다패턴: 호스트 및 그룹 타겟팅. 예를 들어,한계특정 호스트 또는 그룹에 대한 인벤토리. 아래의 간단한 플레이북으로 테스트해 보세요.
shell> cat pb1.yml
- hosts: all
gather_facts: false
tasks:
- debug:
var: inventory_hostname
주다
shell> ansible-playbook -i inventory pb1.yml -l host001,host002
PLAY [all] ***********************************************************************************
TASK [debug] *********************************************************************************
ok: [host001] =>
inventory_hostname: host001
ok: [host002] =>
inventory_hostname: host002
PLAY RECAP ***********************************************************************************
host001: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host002: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
인벤토리 플러그인 사용구성된인벤토리를 더 큰 호스트 그룹으로 제한하려는 경우. 보다
shell> ansible-doc -t inventory constructed
예를 들어, 추가 변수개수_호스트아래 예에서는 그룹을 생성하는 데 사용됩니다.나의 그룹이 변수의 값으로 제한되는 호스트로 구성됩니다.
shell> cat inventory/02-constructed.yml
plugin: constructed
strict: true
use_extra_vars: true
compose:
my_group_count: count_hosts|default(0)
groups:
my_group: inventory_hostname[-2:]|int < my_group_count|int
테스트해 보세요
shell> ansible-playbook -i inventory pb.yml -e count_hosts=10 -l my_group
PLAY [all] ***********************************************************************************
TASK [debug] *********************************************************************************
ok: [host001] =>
ansible_play_hosts|length: '11'
PLAY RECAP ***********************************************************************************
host001: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
전체 인벤토리를 표시하려면 아래 명령을 실행하십시오.
shell> ansible-inventory -i inventory -e count_hosts=10 --list --yaml
의 도움으로구성된플러그인을 사용하면 복잡한 조건을 만들 수 있습니다. 예를 들어 호스트를 특정 간격으로 제한하고 그룹을 만듭니다.내_그룹2
shell> cat inventory/02-constructed.yml
plugin: constructed
strict: true
use_extra_vars: true
compose:
my_group_count: count_hosts|default(0)
my_group_start: start_hosts|default(0)
my_group_stop: stop_hosts|default(0)
groups:
my_group1: inventory_hostname[-2:]|int < my_group_count|int
my_group2: inventory_hostname[-2:]|int >= my_group_start|int and
inventory_hostname[-2:]|int < my_group_stop|int
테스트해 보세요
shell> ansible-playbook -i inventory pb1.yml -e start_hosts=10 -e stop_hosts=15 -l my_group2
PLAY [all] ***********************************************************************************
TASK [debug] *********************************************************************************
ok: [host010] =>
inventory_hostname: host010
ok: [host011] =>
inventory_hostname: host011
ok: [host012] =>
inventory_hostname: host012
ok: [host013] =>
inventory_hostname: host013
ok: [host014] =>
inventory_hostname: host014
...
2. 수집클라이언트_호스트 이름그리고클라이언트_IP
모듈 중 하나를 사용할 수 있습니다설정아니면 스스로 사실을 수집하세요. 휴대성 때문에설정선호되어야합니다.
모듈 보기설정원격 호스트에 대한 정보를 수집하는 방법에 대해 설명합니다. 예를 들어, 아래 플레이북은 다음에 대한 사실을 수집합니다.기계그리고회로망그리고 변수를 생성합니다클라이언트_호스트 이름그리고클라이언트_IP
shell> cat pb2.yml
- hosts: all
gather_facts: false
tasks:
- setup:
gather_subset:
- machine
- network
- set_fact:
client_hostname: "{{ ansible_hostname }}"
- debug:
var: client_hostname
- debug:
var: ansible_default_ipv4
- debug:
var: ansible_all_ipv4_addresses
- set_fact:
client_ip: "{{ ansible_all_ipv4_addresses|last }}"
- debug:
var: client_ip
주다
shell> ansible-playbook -i inventory -l host011 pb2.yml
PLAY [all] ***********************************************************************************
TASK [setup] *********************************************************************************
ok: [host011]
TASK [set_fact] ******************************************************************************
ok: [host011]
TASK [debug] *********************************************************************************
ok: [host011] =>
client_hostname: test_11
TASK [debug] *********************************************************************************
ok: [host011] =>
ansible_default_ipv4: {}
TASK [debug] *********************************************************************************
ok: [host011] =>
ansible_all_ipv4_addresses:
- 10.1.0.61
TASK [set_fact] ******************************************************************************
ok: [host011]
TASK [debug] *********************************************************************************
ok: [host011] =>
client_ip: 10.1.0.61
PLAY RECAP ***********************************************************************************
host011: ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
사실의 구조와 형식은 운영 체제에 따라 다를 수 있습니다.
사실을 직접 수집할 수 있습니다. 예를 들어 아래 플레이북은
shell> cat pb3.yml
- hosts: all
gather_facts: false
tasks:
- name: Grab client hostname
command: cat /etc/hostname
register: out
- set_fact:
client_hostname: "{{ out.stdout }}"
- debug:
var: client_hostname
- name: Grab client IP address
shell: hostname -i | sed -n '1 p'
register: out
- set_fact:
client_ip: "{{ out.stdout|split|last }}"
- debug:
var: client_ip
Linux에서 실행 제공
shell> ansible-playbook -i inventory -l central_server pb3.yml
PLAY [all] ***********************************************************************************
TASK [Grab client hostname] ******************************************************************
changed: [central_server]
TASK [set_fact] ******************************************************************************
ok: [central_server]
TASK [debug] *********************************************************************************
ok: [central_server] =>
client_hostname: central_server
TASK [Grab client IP address] ****************************************************************
changed: [central_server]
TASK [set_fact] ******************************************************************************
ok: [central_server]
TASK [debug] *********************************************************************************
ok: [central_server] =>
client_ip: 10.1.0.22
PLAY RECAP ***********************************************************************************
central_server: ok=6 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
유틸리티의 출력은 운영 체제에 따라 다를 수 있습니다.
3) 중앙서버에 보고
Jinja를 사용하여 구조를 만듭니다. 작업을 한 번 실행하고 다른 사용자에게 위임합니다.중앙 서버
shell> cat pb4.yml
- hosts: all
gather_facts: false
tasks:
- setup:
gather_subset:
- machine
- network
- set_fact:
client_hostname: "{{ ansible_hostname }}"
client_ip: "{{ ansible_all_ipv4_addresses|last }}"
- copy:
dest: /tmp/test_host_ip.txt
content: |
{% for host in ansible_play_hosts %}
{{ hostvars[host]['client_hostname'] }} - {{ hostvars[host]['client_ip'] }}
{% endfor %}
run_once: true
delegate_to: central_server
주다
shell> ansible-playbook -i inventory -l host011,host013 pb4.yml
PLAY [all] ***********************************************************************************
TASK [setup] *********************************************************************************
ok: [host013]
ok: [host011]
TASK [set_fact] ******************************************************************************
ok: [host011]
ok: [host013]
TASK [copy] **********************************************************************************
changed: [host011 -> central_server(localhost)]
PLAY RECAP ***********************************************************************************
host011: ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host013: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
플레이북이 다음 위치에 파일을 생성했습니다.중앙 서버
shell> cat /tmp/test_host_ip.txt
test_11 - 10.1.0.61
test_13 - 10.1.0.63
모듈 사용라인 파일파일에 줄을 추가하려는 경우. 아래 플레이북은 멱등적입니다.
shell> cat pb5.yml
- hosts: all
gather_facts: false
tasks:
- setup:
gather_subset:
- machine
- network
- set_fact:
client_hostname: "{{ ansible_hostname }}"
client_ip: "{{ ansible_all_ipv4_addresses|last }}"
- lineinfile:
path: /tmp/test_host_ip.txt
line: |-
{{ hostvars[item]['client_hostname'] }} - {{ hostvars[item]['client_ip'] }}
loop: "{{ ansible_play_hosts }}"
run_once: true
delegate_to: central_server
동일한 호스트에서 반복적으로 실행하면 변경 사항이 없습니다.
shell> ansible-playbook -i inventory -l host011,host013 pb5.yml
PLAY [all] ***********************************************************************************
TASK [setup] *********************************************************************************
ok: [host011]
ok: [host013]
TASK [set_fact] ******************************************************************************
ok: [host011]
ok: [host013]
TASK [lineinfile] ****************************************************************************
ok: [host011 -> central_server(localhost)] => (item=host011)
ok: [host011 -> central_server(localhost)] => (item=host013)
PLAY RECAP ***********************************************************************************
host011: ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host013: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
플레이북이 새 호스트에서 실행되면 파일에 새 줄이 추가됩니다.
shell> ansible-playbook -i inventory -l central_server pb5.yml
PLAY [all] ***********************************************************************************
TASK [setup] *********************************************************************************
ok: [central_server]
TASK [set_fact] ******************************************************************************
ok: [central_server]
TASK [lineinfile] ****************************************************************************
changed: [central_server] => (item=central_server)
PLAY RECAP ***********************************************************************************
central_server: ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
새 줄이 파일에 추가되었습니다.
shell> cat /tmp/test_host_ip.txt
test_11 - 10.1.0.61
test_13 - 10.1.0.63
central_server - 10.1.0.184
답변2
플레이북에서 with_items 지시문을 사용하여 client_hosts 변수를 반복할 수 있습니다. 그런 다음 루프의 항목 변수를 사용하여 각 개별 호스트를 참조할 수 있습니다.
다음은 여러 호스트를 처리하기 위해 플레이북을 수정하는 방법의 예입니다.
- name: Gather client information
hosts: "{{ client_hosts | default(omit) }}"
tasks:
- name: Grab client hostname and IP address
shell: |
hostname -i | sed -n '1 p' > /tmp/client_ip
cat /etc/hostname > /tmp/client_hostname
register: gather_client_info
become: true
- name: Set client hostname and IP address as variables
set_fact:
client_hostname: "{{ hostvars[item]['gather_client_info'].stdout_lines[1] }}"
client_ip: "{{ hostvars[item]['gather_client_info'].stdout_lines[0] }}"
with_items: "{{ client_hosts | default(omit) }}"
- name: Update server
hosts: central.server
tasks:
- name: Update client host list
lineinfile:
path: /path/to/file
line: "{{ client_ip }} - {{ client_hostname }}"
with_items: "{{ client_hosts | default(omit) }}"
이 플레이북은 client_hosts 변수의 각 호스트를 반복하고 셸 모듈을 사용하여 호스트 이름과 IP 주소를 수집합니다. 그런 다음 set_fact 모듈을 사용하여 이러한 값을 변수로 설정합니다. 마지막으로 client_hosts 변수를 다시 반복하고 lineinfile 모듈을 사용하여 각 호스트의 호스트 이름과 IP 주소로 중앙 서버의 파일을 업데이트합니다.
도움이 되었기를 바랍니다.