본문 바로가기

Engineering/Ansible

[Ansible]10. Ansible Role

 

 

플레이북을 작성하다 보면 이전에 사용한 코드를 재활용할 여지가 많다. 하지만 플레이북 자체의 내용이 길고 복잡하다면 일일히 수정하기 어려워진다. 앤서블에서는 표준화된 디렉토리 구조로 컨텐츠들을 모듈화하여 코드 재사용 및 협업을 편리하게 할 수 있도록 Ansible role 이라는 기능을 제공한다. 또 Ansible galaxy를 통하여 작성한 롤을 공유할 수 있다.


 

앤서블 롤의 구조

앤서블 롤은 아래와 같은 표준화된 디렉토리 구조를 가진다. 최상위 디렉토리인 'role'은 롤 자체의 이름을 의미하며, 하위 디렉토리들은 롤에서 목적에 따라 정의된 역할을 수행한다. 각 files와 templates을 제외한 각 하위토리 안에는 main.yml 파일이 존재한다. 최종적으로 롤이 실행될 때, main.yml 파일의 내용을 참조하여 실행된다.

 ── role
    ├── defaults
    ├── files
    ├── handlers
    ├── meta
    ├── tasks
    ├── templates
    ├── tests
    └── vars

 

Directory Function
defaults 롤이 사용될 때 덮어쓸 수 있는 변수 기본 값이 포함된다.
files 롤 작업에서 참조할 정적 파일이 위치한다.
handlers 롤의 핸들러 작업이 정의된다.
meta 롤에 대한 메타데이터가 들어있다.
tasks 롤의 작업이 정의된다.
templates 롤 작업에서 참조할 동적 파일인 Jinja2 템플릿이 위치한다.
tests 롤을 플레이할 때 테스트 할 인벤토리와 플레이북이 포함된다.
vars 롤에서 사용할 변수 값을 정의한다.

 

ansible-galaxy role init {{ role-name }} 명령어를 통하여 기본 롤 디렉토리 구조를 생성할 수 있다. 생성 후, 필요없는 하위 디렉토리는 삭제해도 무방하다.


롤을 이용한 플레이북 개발

 

책의 예제에 나와있는 심플한 롤 플레이북을 작성해보도록 한다.

 

Procedure

  1. 'my-role'이라는 role을 생성
  2. 롤 호출 시 현재 호스트의 OS버전이 지원 목록에 포함되는지 유효성 체크
  3. httpd 관련 패키지 설치
  4. 설치가 끝나면 files 디렉토리 안에 준비해둔 'index.html' 파일을, 제어 노드의 특정 경로에 복사
  5. httpd restart

 


[01] tasks/main.yml

[root@Ansible-Controller my-role]# cat tasks/main.yml 
---
# tasks file for my-role

- name: install service {{ service_title }}
  ansible.builtin.dnf:
    name: "{{ item }}"
    state: latest
  loop: "{{ httpd_packages }}"
  when: ansible_facts.distribution in supported_distros

- name: copy html file
  ansible.builtin.copy:
    src: "{{ src_file_path }}"
    dest: "{{ dest_file_path }}"
  notify:
    - restart service

dnf 모듈을 이용하여 httpd 관련 패키지를 설치한다. 관련 변수들은 후에 vars 파일에서 선언해주기로하고, 변수에 포함되는 모든 패키지들이 설치되도록 loop문을 돌려준다. 이 때 팩트 변수에서 수집한 os 버전이 'supported_distros'라는 변수에 포함될 때만 수행하도록 when문을 사용하여 조건문을 달아준다. 설치가 끝나면 files 디렉토리에 위치한 파일을 제어 노드로 복사한다. 복사가 완료되면 notify문을 통해 restart service라는 핸들러를 호출한다.

 

[02] handlers/main.yml

[root@Ansible-Controller my-role]# cat handlers/main.yml      
---
# handlers file for my-role

- name: restart service
  ansible.builtin.service:
    name: "{{ service_name }}"
    state: restarted

restart service라는 핸들러가 호출되면 service 모듈을 이용하여 제어노드의 service 유닛을 재시작한다.

 

[03] files/index.html

[root@Ansible-Controller my-role]# cat files/index.html 
Hello Ansible World!

제어노드로 복사될 index.html 파일

 

[04] defaults/main.yml

[root@Ansible-Controller my-role]# cat defaults/main.yml 
---
# defaults file for my-role

service_title: "Apache Web Server"

외부로부터 변경될 수 있는 가변변수이다.

 

[05] vars/main.yml

[root@Ansible-Controller my-role]# cat vars/main.yml 
---
# vars file for my-role

service_name: httpd
src_file_path: ../files/index.html
dest_file_path: /var/www/html
httpd_packages:
  - httpd-tools
  - httpd-filesystem
  - httpd
supported_distros:
  - CentOS
  - Redhat
  - Rocky

tasks와 handlers의 main.yml에서 사용할 변수들을 선언한다.

 

[06] 플레이북에 롤 추가하기

롤을 실행하기 위해서는 ansible-playbook my-role과 같이 기존에 플레이북을 실행한 방식으로 실행할 수 없다. 따라서 롤을 실행하기 위한 플레이북을 따로 작성해주어야 한다.

[root@Ansible-Controller roles]# cat role-playing.yml 
---
- hosts: localhost

  tasks:
  - name: Print playbook execution
    ansible.builtin.debug:
      msg: "role-play"

  - name: Install Service by role
    ansible.builtin.import_role:
      name: my-role

import_role 모듈을 이용하여 실행할 role의 이름을 선언해준다.

 

[07] Execution

 

웹 브라우저를 통해 해당 호스트에 접근하여 Ansible role을 이용한 http와 index.html의 설정이 잘 적용된 것을 확인할 수 있다.