Asible에서 파일을 관리하는 가장 강력한 방법은 템플릿을 만드는 것이다. 템플릿을 사용하면 가능한 변수와 팩트를 사용하여 파일이 배포될 때 관리 호스트에 대해 자동으로 사용자 정의되는 템플릿 구성 파일을 작성할 수 있다.
▪ Python의 매우 강력하고 고급 템플릿 언어
▪ 매우 빠르고 안정적이며 동적 데이터를 생성하는 데 널리 사용
▪ 텍스트 기반 템플릿 언어이므로 모든 마크업과 소스 코드를 생성하는 데 사용할 수 있음
▪ {{ . . . . }}
▪ {% . . . . %}
▪ {# . . . . #}
vi temp1.yml
- name: template test
hosts: AA
vars:
site_name: goorm_world
tasks:
- template:
src: test1.j2
dest: /tmp/test
---------------------------------------------
vi test1.j2
Welcome {{ site_name }}
This node is {{ ansible_hostname }}
# 결과 확인
ansible-playbook temp1.yml
ssh ansi-node1 ls /tmp
ssh ansi-node1 cat /tmp/test
ssh ansi-node2 cat /tmp/test
vi temp2.yml
- name: temp test
hosts: AA
tasks:
- name: Create dir
file:
state: directory
dest: /etc/ansible/facts.d
recurse: yes
- name: Create fact file
template:
src: factfile.j2
dest: /etc/ansible/facts.d/test.fact
- setup:
- name: Print local facts
debug:
msg: "{{ ansible_local }}"
-----------------------------------------------
vi factfile.j2
{# local_fact_config #}
[test1]
hostname= {{ansible_hostname}}
ip_address={{ ansible_all_ipv4_addresses[1] }}
ansible-playbook temp2.yml
ssh ansi-node1 ls /etc/ansible/facts.d
ssh ansi-node1 cat /etc/ansible/facts.d/test.fact
ssh ansi-node2 cat /etc/ansible/facts.d/test.fact
vi temp3.yml
- name: template test
hosts: ABC
# gather_facts: no
tasks:
- template:
src: hostname.j2
dest: /home/vagrant/hostname.txt
-----------------------------------------------
vi hostname.j2
{% for i in range(1,4) %}
ansi-node{{ i }} 192.168.56.2{{ i }}
{% endfor %}
ansible-playbook temp3.yml
ssh ansi-node1 cat /home/vagrant/hostname.txt
vi hosts.j2
127.0.0.1 localhost
{# hostname #}
{{ ansible_facts.enp0s8.ipv4.aABCress }} {{ ansible_facts.hostname }}
{# other hostanames #}
192.168.56.11 ansi-master1
{% for i in range(1,4) %}
192.168.56.2{{ i }} ansi-node{{ i }}
{% endfor %}
vi temp5.yml
- name: template
hosts: ABC
gather_facts: no
tasks:
- template:
src: hosts.j2
dest: /etc/hosts
핸들러(Handler)는 작업을 실행하고 시스템의 변경(Changed)이 있을 때에 별도의 작업을 호출하고 실행하는 작업이다.
즉 제어 노드가 원하는 상태가 되도록 하기 위해 플레이북과 해당 작업을 변경하지 않아도 되는 경우, 적절하게 작성된 플레이북에서 제어노드를 변경하지 않고 플레이북과 해당 작업을 여러번 실행 가능
# apache2 수정시 재시작
vi temp.yml
- name: handler test
hosts: ansi-node1
tasks:
- copy:
content: "{{ ansible_hostname }} handler test\ntest2\n"
dest: /var/www/html/index.html
notify:
- Restart web service
handlers:
- name: Restart web service
service:
name: apache2
state: restarted
vi html1.j2
{{ ansible_hostname }} is handlers test1
---------------------------------------------
vi handler.yml
- name: handler test
hosts: ansi-node3
tasks:
- name: Install Pakage
apt:
name:
- apache2
- firewalld
update_cache: yes
state: present
- name: Config index.html
template:
src: html1.j2
dest: /var/www/html/indx.html
notify:
- Restart web service
- Restart firewalld service
handlers:
- name: Restart web service #위 notify의 이름과 같아야 함
service:
name: apache2
state: restarted
- name: Restart firewalld service
service:
name: firewalld
state: restarted
ansible-playbook handler.yml
ansible-playbook handler.yml
$ ssh ansi-node3 cat /var/www/html/index.html
ansi-node3 is handlers test1
처음 실행
두번째 실행
handler.yml의 내용을 다음과 같이 수정해서 진행해도 같은 결과가 나옴
핸들러는 항상 플레이의 handlers 섹션에서 지정한 순서대로 실행
작업의 notify 문에 따라 나열한 순서나 작업이 핸들러에 통지하는 순서대로 실행되지는 않음.
핸들러는 일반적으로 플레이에서 다른 모든 작업이 완료된 후에 실행
플레이북의 tasks 부분의 작업에서 호출한 핸들러는 tasks 아래에 있는 모든 작업이 처리될 때까지 실행되지 않음
핸들러 이름은 글로벌 네임스페이스에 있음.
두 핸들러에 같은 이름이 잘못 지정되면 한 핸들러만 실행
둘 이상의 작업에서 한 핸들러에게 알리는 경우 해당 핸들러가 한번만 실행
작업에서 핸들러에게 알리지 않는 경우 핸들러가 실행되지 않음.
notify문을 포함한 작업이 chaged 결과를 보고하지 않으면 핸들러에 알리지 않음
다른 작업에서 이 핸들러에게 알라지 않으면 이 핸들러를 건너띔
Ansible은 작업이 change 상태를 보고하는 경우에만 핸들러에게 알림.
핸들러는 작업이 제어노드를 변경할 때 추가 조치를 수행하기 위한 것으로 정상적인 작업을 대체하기 위해서 사용해서는 안됨.
핸들러는 작업의 알림과 핸들러의 이름이 일치해야지만 알림을 받을 수 있기 때문에 핸들러의 작업에는 반드시 이름을 선언해야 함.
Ansible은 팩트를 수집하고 hosts플레이북의 라인과 일치하는 머신에서 모든 작업을 실행하는데 위임(Delegation)은 플레이 또는 일부 작업을 로컬(제어 노드)이나 다른 관리노드에서 작업을 실행할 수 있다.
위임을 사용하면 상호 관련된 환경을 정확하고 효율적으로 관리할 수 있음
예를 들어 웹 서버를 업데이트할 때 부하 분산 풀에서 일시적으로 제거해야 할 수 있습니다. 웹 서버 자체에서는 이 작업을 수행할 수 없습니다. 작업을 localhost에 위임함으로써 모든 작업을 동일한 플레이 내에 유지
vi delegate.yml
- name: delegate test
hosts: ansi-node1
tasks:
- command: hostname
register: hostname_result1
- debug:
msg: "{{ hostname_result1.stdout }}"
- command: hostname
register: hostname_result2
delegate_to: ansi-node2
- debug:
msg: "{{ hostname_result2.stdout }}"
ansible-playbook delegate.yml
vi delegate_facts.yml
- name: delegate_fact test
hosts: ansi-node1
gather_facts: no
tasks:
- setup:
delegate_to: ansi-node2
delegate_facts: yes
- name: delegate ansi-node2
hosts: andi-node2
gather_facts: no
tasjs:
- debug:
msg: "{{ ansible_hostname }}"
다른 호스트를 참조하여 한 호스트에서 작업을 수행하려면 작업에서 delegate_to키워드를 사용
이는 로드 밸런싱된 풀에서 노드를 관리하거나 중단 기간을 제어하는 데 이상적
직렬 키워드 와 함께 위임을 사용 하여 한 번에 실행되는 호스트 수를 제어할 수 있음
블록은 플레이에 하나 이상의 작업을 논리적으로 그룹화 할 수 있다.
대부분의 프로그래밍 언어에 있듯이 예외 처리 기능을 제공
- name: block example
hosts: ansi-node2
vars:
pkg_list:
- apache2
- firewalld
# gather_facts: no
become: no
tasks:
- name: Web Service Block
block:
- name: Install Packages
apt:
name: "{{ pkg_list }}"
state: latest
update_cache: yes
- name: Start Packages
service:
name: "{{ item }}"
state: started
loop: "{{ pkg_list }}"
- name: Open Port
firewalld:
service: http
permanent: yes
immediate: yes
state: enabled
when: ansible_distribution == 'Ubuntu'
ignore_errors: yes
become: yes
- name: block example
hosts: ansi-node3
vars:
pkg_list:
- apache2
- firewalld
# gather_facts: no
tasks:
- name: Web Service Block
block:
- name: Install Packages
apt:
name: "{{ pkg_list }}"
state: latest
rescue:
- name: Reinstall Packages
apt:
name: "{{ pkg_list }}"
state: latest
update_cache: yes
always:
- name: Start Packages
service:
name: "{{ item }}"
state: started
loop: "{{ pkg_list }}"
- name: Open Port
firewalld:
service: http
permanent: yes
immediate: yes
state: enabled
블록의 모든 작업은 블록 수준에서 적용된 지시문을 상속
단일 작업에 적용할 수 있는 대부분(반복문(loop) 제외)은 블록 수준에서 적용할 수 있으므로 블록을 사용하면 작업에 공통적인 데이터나 지시문을 훨씬 쉽게 설정 가능
지시문은 블록 자체에 영향을 미치지 않으며 블록으로 묶인 작업에 의해서만 상속
예를 들어 when 문은 블록 자체가 아니라 블록 내의 작업에 적용
rescue및 always섹션이 있는 블록을 사용하여 Ansible이 작업 오류에 응답하는 방식을 제어할 수 있음
복구 블록은 블록의 이전 작업이 실패할 때 실행할 작업을 지정
: 접근 방식은 많은 프로그래밍 언어의 예외 처리와 유사
Ansible은 작업이 '실패' 상태를 반환한 후에만 복구 블록을 실행
: 잘못된 작업 정의와 연결할 수 없는 호스트는 복구 블록을 트리거하지 않음
블록의 작업 중 하나라도 실패가 있으면, Rescue 섹션의 작업이 실행
: 블록의 작업 중 실패가 없으면, Rescue 섹션은 실행 X
예) rescue
tasks:
- name: Handle the error
block:
- name: Print a message
debug:
msg: 'I execute normally'
- name: Force a failure
command: /bin/false
- name: Never print this
debug:
msg: 'I never execute, due to the above task failing, :-('
rescue:
- name: Print when errors
debug:
msg: 'I caught an error, can do stuff here to fix it, :-)'
...
예) always
- name: Always do X
block:
- name: Print a message
debug:
msg: 'I execute normally'
- name: Force a failure
command: /bin/false
- name: Never print this
debug:
msg: 'I never execute :-('
always:
- name: Always do this
debug:
msg: "This always executes, :-)"
예) rescue & always
- name: Attempt and graceful roll back demo
block:
- name: Print a message
debug:
msg: 'I execute normally'
- name: Force a failure
command: /bin/false
- name: Never print this
debug:
msg: 'I never execute, due to the above task failing, :-('
rescue:
- name: Print when errors
debug:
msg: 'I caught an error'
- name: Force a failure in middle of recovery! >:-)
command: /bin/false
- name: Never print this
debug:
msg: 'I also never execute :-('
always:
- name: Always do this
debug:
msg: "This always executes"
=> 블록의 작업이 반환 failed되면 rescue섹션은 오류를 복구하기 위해 작업을 실행
=> 블록 구문의 실패가 있을 때만 Rescue 섹션이 실행되며, always 섹션은 항상 실행
=> 블록에서 오류가 발생하고 rescure 작업이 성공하면 Ansible은 실행에 대한 원래 작업의 실패 상태를 되돌리고 원래 작업이 성공한 것처럼 재생을 계속 실행
많은 작업이 있는 플레이북의 경우 플레이북 전체를 실행하는 대신 특정 일부 만 실행하는 것이 유용할 수 있다.
▪ Ansible 태그로 특정 작업만 실행하거나, 특정 작업을 실행하지 않을 수 있음
▪ 태그는 플레이, 블록, 역할, 작업에 설정하고, 플레이북 실행 시 태그를 선택
vi tag1.yml
- name: tag test
hosts: ansi-node1
gather_facts: no
tags: play1
tasks:
- block:
- name: task 1-1
debug:
msg: task 1-1
tags: task1
- name: task 1-2
debug:
msg: task 1-2
tags: task1
- name: task 2-1
debug:
msg: task 2-1
tags: task2
- name: task 2-2
debug:
msg: task 2-2
tags: task2
tags: block1
- name: task 3
debug:
msg: task 3
tags: task3
- name: play2
hosts: ansi-node2
tasks:
- name: task 4
debug:
msg: task4
tags: task4
# --tag 를 이용하여 tag를 지정한 항목에 대한 검색이 가능
ansible-playbook tag1.yml --tags 'task1'
# 태그하지 않은 항목 출력
ansible-playbook tag1.yml --tags untagged
# 모든 항목 출력
ansible-playbook tag1.yml --tags tagged
ansible-playbook tag1.yml --tags all