플레이북이 길어지거나 복잡한 경우, 더 작은 파일로 나누면 관리하기가 좋다.  모듈식으로 여러개의 플레이북을 하나의 메인 플레이북에 결합하거나 파일의 작업 목록을 플레이에 삽입할 수 있다. 이런식으로 사용하면 일련의 프로젝트에서 play를 재사용하기 쉬워진다.

 

 

개념이해 : 가져오기, 포함하기

ansible에서 파일이나 role 등을 특정 playbook에서 읽어들일 때, import / include 2가지 방법이 있으며 이 방법은 약간의 차이가 있다.

 

* import : static re-use

role, task, playbook 등을 플레이북에 정적으로(statically) 삽입한다. ansible은 playbook을 처음 구문분석할 때 읽어들인 파일이나 role 등을 최상위 플레이북에서 작업을 실행하기 전에 사전처리한다. 따라서 imported 된 내용들은 최상위 플레이북의 다른 task에 영향을 받지 않는다.

 

* includes : dynamic re-use

role, task, 변수 등을 플레이북에 동적으로(dynamically) 삽입한다. Ansible은 file, role을 playbook에서 읽어들일 때 그것들을 include(포함)한다. included 된 컨텐츠는 최상위 플레이북의 이전 작업의 결과에 영향을 받는다. included 된 role 이나 task는 핸들러와 비슷하다. 그것들은 최상위 플레이북의 다른 task의 결과에 따라 실행될수도 있고 실행되지 않을수도 있다.

 

playbook 가져오기 - import_playbook

- play 목록이 포함된 외부 파일을 playbook으로 가져온다. (정적; static)

- 즉 특정 마스터 playbook에서 한 개 이상의 추가 playbook 자체를 가져오는 것이다.

- 가져오는 컨텐츠가 완전한 playbook이므로 import_playbook 지시문은 playbook의 최상위 수준에서만 사용하고, play 내에서는 사용할 수 없다.

- 여러개의 playbook을 가져오는 경우, 가져오는 순서대로 실행한다.

 

* 예시 : 두개의 추가 플레이북을 가져오는 마스터 플레이북

- 그냥 플레이북에 내용이 없고, 아래 두개만 딱 있음. 이것도 플레이북이다.

---
- name: prepare the web server
  import_playbook: web.yml
  
- name: Prepare the database server
  import_playbook: db.yml

 

* 예시 : 일반적인 플레이북에 import_playbook 추가

- name: play 1
  hosts: localhost
  tasks:
    - debug:
        msg: play 1
        
- name: import playbook
  import_playbook: play2.yml

- 위에서부터 순서대로 실행한다.

 

 

task 가져오기 - import_tasks

task 내용이 있는 파일을 import 방식으로 가져올 있다. 반복문은 import_task 함께 사용할 없다. 또한 변수를 사용하여 가져올 파일 이름을 지정할 , 호스트/그룹 인벤토리 변수를 사용할 없다.

 

* 예시

- name: install web server
  hosts: webservers
  tasks:
    - import_tasks: webserver_tasks.yml

 

task 포함하기 - include_tasks

task 내용이 있는 파일을 include 방식으로 가져올 있다.

 

* 예시

---
- name: install web server
  hosts: webservers
  tasks:
    - include_tasks: webserver_tasks.yml

 

 

파일을 따로 만들어서 쓰는 사용 사례

- 특정 일련의 작업을 playbook과 별도로 외부 파일로 관리하는 것이 유용할 수 있는 경우에 대해, 다음 예시를 참고한다.

 

1. 새 서버에 완전한 구성이 필요한 경우, 관리자는 사용자 생성, 패키지 설치, 서비스 구성, 권한 구성, 공유 파일시스템에 대한 액세스 설정, 서버 강화, 보안 업데이트 설치, 모니터링 에이전트 설치 등을 위해 여러 세트의 작업을 생성할 수 있다. 이러한 각 작업 세트는 별도의 자체 포함 작업 파일을 통해 관리할 수 있다.

2. 서버를 개발자, 시스템 관리자 및 데이터베이스 관리자가 전체적으로 관리하는 경우 모든 조직은 시스템 관리자가 검토하고 통합할 고유한 작업 파일을 작성할 수 있다.

3. 서버에 특정 구성이 필요한 경우 조건에 따라 (즉, 특정 조건을 충족하는 경우에만 작업 포함) 실행할 작업 세트로 통합할 수 있다.

4. 서버 그룹에서 특정 작업 또는 작업 세트를 실행해야 하는 경우 서버가 특정 호스트 그룹의 일부이면 작업을 서버에서만 실행할 수 있다.

 

* 작업 파일 관리하기

- 작업 파일을 관리할 때는, 작업 파일 전용 디렉토리를 생성하고 이 디렉토리에 모든 작업 파일을 저장할 수 있다.

- 그 후 해당 디렉토리에서 작업 파일을 간단하게 포함하거나 가져올 수 있다. 

- 참조되는 yml파일들은 메인파일의 들여쓰기에 맞출 필요 없이 맨 첫라인에서 자신의 들여쓰기 수준에 맞춰 작성하면 된다. 한마디로, 그냥 하면 된다.

 

 

 

재사용하기 좋게 만들기

- 위에서 언급한 가져오기, 포함하기 기능이 있기 때문에 playbook과 작업 파일을 재사용 할 수 있게 잘 만드는게 매우 중요해졌다.

- 재사용 가능성을 극대화하려면, 이러한 task와 play 파일을 최대한 일반화 해야한다.

- 변수를 사용하여 play 및 task 의 요소를 매개변수화하여 유연하게 사용할 수 있다.

 

<import tasks 관련 예시>

 

* 예시1 : 어떤 패키지든 명시해서 최신으로 설치, 서비스 시작, enable까지 수행하는 일반화된 task 파일

package_task.yml

---
- name: install the {{ package }} packge.
  yum:
    name: "{{ package }}"
    state: latest

- name: start the {{ service }} service.
  service:
    name: "{{ service }}"
    enabled: true
    state: started

* 예시2 : 위 task 파일을 메인 playbook에 포함하여 사용하기

---
- name: work
- hosts: all
- tasks: 
    - name: import task file ans set variables
      import_tasks: package_task.yml
      vars:
        package: httpd
        service: httpd

- 이렇게 하고, vars의 package: httpd, service: httpd 두가지 부분을 변수파일로 받아서 for 문을 돌릴수도 있다.

- 결국 이 파일이 최종적으로 내가 원하는 패키지들을 명시하는 구문이고, 위 예시는 명시한 패키지들을 설치하는 구문이 된다.

 

 

 

 

<import_playbook 관련 예시>

 

* 예시 : 일반화된 플레이북을 포함해서 사용하는 플레이북

- name: import play file and set the variable
  import_playbook: play.yml
  vars:
    package: mariadb

- 위 import tasks 관련 예시의 2번과 같은 맥락으로, 일반화되어 잘 만들어진 플레이북에 변수 mariadb만 적용하는 플레이북이다. 

 

 

# 참고

이전 버전의 ansible에서는 버전을 올리면서 include 라는 지시자가 정적 가져오기, 동적 가져오기 등으로 변경되었었는데 문제가 많았음. 그래서 2.4부터 include는 include_tasks, import_tasks, import_playbook 같은 새로운 지시문으로 대체되었다. 이제는 include 지시문을 쓰면 안된다. 다른 playbook을 볼 때 include라는 지시자를 볼 수도 있으니 참고만 할 것.

 

 

 

연습문제

- playbook 마스터파일1개, play파일 1개, task파일 3개가 있고, 마스터파일을 기준으로 각각의 play,task파일을 import하는 예시

 

 

playbook.yml (전체 마스터 파일)

# 메인 마스터 playbook 파일
---
- name: configure web server
  hosts: was.example.com
  tasks:

# 패키지 설치 및 서비스를 시작, enable을 수행하는 task 파일 삽입
    - name: import the environment task file ans set the variables
      import_tasks: environment.yml
      vars:
        package: httpd
        service: httpd
        
# 방화벽 소프트웨어를 설치 및 구성하는 task 파일 삽입
    - name: import the firewall task file and set the variable.
      import_tasks: firewall.yml
      vars:
        firewall_pkg: firewalld
        firewall_svc: firewalld
        rule: http

# 웹페이지 파일을 생성하는 task 파일 삽입
    - name: import the placeholder task file and set the variable
      import_tasks: placeholder.yml
      vars:
        file: /var/www/html/index.html

# 모든 작업 수행 후, 제대로 작동하는지 테스트하는 playbook 파일 삽입
- name: import test play file and set the variable
  import_playbook: test.yml
  vars:
    url: 'http://web1.example.com'

 

environment.yml (패키지 설치 및 서비스 시작, enable 수행)

---
  - name: install the {{ package }} packge.
    yum:
      name: "{{ package }}"
      state: latest
        
  - name: start the {{ service }} service.
    service:
      name: "{{ service }}"
      enabled: true
      state: started

 

firewall.yml (방화벽 소프트웨어 설치 및 구성)

---
  - name: Install the firewall
    yum:
      name: "{{ firewall_pkg }}"
      state: latest
  
  - name: start the firewall
    service:
       name: "{{ firewall_svc }}"
       enabled: true
       state: started
  
  - name: openm the port for {{ rule }}
    firewalld:
       service: "{{ rule }}"
       immediate: true
       permanent: true
       state: enabled

 

placeholder.yml (웹사이트 파일 생성)

--- 
  - name: create placeholder file
    copy:
      content: "{{ ansible_facts['fqdn'] }} has been customized using ansible. \n"
      dest: "{{ file }}"

 

test.yml (웹사이트 연결 테스트)

---
  - name: test web service
    hosts: localhost # was.example.com 자기 자신에 대해서 수행하는 것
    become: no
    tasks:
      - name: connect to internet web server
        uri:
          url: "{{ url }}"
          status_code: 200

 

결과

- 모두 changed 뜨고, (firewalld은 이미 start되어있는 서버였음) 웹페이지 내용도 잘 확인할 수 있다.

 

 

 

참조링크

 

import_tasks와 include_tasks 간의 작동 차이점

https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#applying-when-to-roles-imports-and-includes 

 

Conditionals — Ansible Documentation

In a playbook, you may want to execute different tasks, or have different goals, depending on the value of a fact (data about the remote system), a variable, or the result of a previous task. You may want the value of some variables to depend on the value

docs.ansible.com

포함하기 및 가져오기 ansible 설명서

https://docs.ansible.com/ansible/2.7/user_guide/playbooks_reuse_includes.html 

재사용 가능한 플레이북 만들기 ansible 설명서

https://docs.ansible.com/ansible/2.7/user_guide/playbooks_reuse.html

 

Creating Reusable Playbooks — Ansible Documentation

Docs » User Guide » Working With Playbooks » Creating Reusable Playbooks You are reading an unmaintained version of the Ansible documentation. Unmaintained Ansible versions can contain unfixed security vulnerabilities (CVE). Please upgrade to a maintain

docs.ansible.com

조건문 ansible 설명서

https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html 

 

Conditionals — Ansible Documentation

In a playbook, you may want to execute different tasks, or have different goals, depending on the value of a fact (data about the remote system), a variable, or the result of a previous task. You may want the value of some variables to depend on the value

docs.ansible.com

 

+ Recent posts