본문 바로가기
데이터 엔지니어링

Ansible Roles 사용 방법, 공식 문서

by 내기록 2023. 3. 19.
반응형

 

 

 

Roles

`Roles`을 사용하면 알려진 파일 구조를 기반으로 관련 변수, 파일, tasks, handlers 및 기타 Ansible artifacts를 자동으로 로드할 수 있습니다. content를 role로 그룹화하면, 쉽게 재사용할 수 있습니다.

 

Role directory structure

Ansible role은 8개의 주요 표준 디렉터리가 있는 정의된 데릭터리 구조가 있습니다. 적어도 각 역할에 표준 디렉터리 중 하나 이상은 포함해야 합니다. Role에서 사용하지 않는 디렉터리는 생략이 가능합니다.

# playbooks
site.yml
webservers.yml
fooservers.yml
roles/
    common/               # this hierarchy represents a "role"
        tasks/            #
            main.yml      #  <-- 필요한 경우 더 작은 파일을 포함할 수 있습니다.
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies
        library/          # roles can also include custom modules
        module_utils/     # roles can also include custom module_utils
        lookup_plugins/   # or other types of plugins, like lookup in this case

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""

기본적으로 Ansible은 role 내의 각 디렉토리에서 main.yml 파일을 찾습니다.(main.yaml or main도 포함)

 

  • tasks/main.yml : role이 실행되는 태스크들의 메인 리스트
  • handlers/main.yml : 핸들러는 해당 역할의 내부 또는 외부에서 사용할 수 있음
  • library/my_module.py : role 내에서 사용되는 모듈
  • defaults/main.yml : role에서 사용되는 default variables. 여기서의 variables는 가장 낮은 우선순위를 가지며 인벤토리 변수를 비롯한 다른 변수에 의해 쉽게 재정의가 가능
  • vars/main.yml : other variables for the role
  • files/main.yml : role이 배포하는 파일
  • templates/main.yml : role이 배포하는 템플릿
  • meta/main.yml : role의 메타데이터로 role의 종속성(dependency) 등을 포함합니다.

 

예를 들어, 플랫폼별 작업을 별도의 파일에 저장하고 `tasks/mail.yml` 파일에서 참조할 수 있습니다.

# roles/example/tasks/main.yml
- name: Install the correct web server for RHEL
  import_tasks: redhat.yml <<== redhat.yml 파일 참조
  when: ansible_facts['os_family']|lower == 'redhat'

- name: Install the correct web server for Debian
  import_tasks: debian.yml <<== debian.yml 파일 참조
  when: ansible_facts['os_family']|lower == 'debian'

# roles/example/tasks/redhat.yml
- name: Install web server
  ansible.builtin.yum:
    name: "httpd"
    state: present

# roles/example/tasks/debian.yml
- name: Install web server
  ansible.builtin.apt:
    name: "apache2"
    state: present

 

 

Storing and finding roles

기본적으로, Ansible은 아래 경로들에서 Role을 찾습니다.

  • 컬렉션을 사용하는 경우
  • roles/ 디렉터리에 있는 플레이북 관련 파일들
  • `roles_path` config의 경로 (default: ~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles)
  • 플레이북 파일이 위치한 디렉토리

만약, 다른 장소에 role을 저장하고 싶다면, `roles_path` 설정으로 변경할 수 있습니다. 

또는 아래와 같이 경로를 사용하여 role을 호출할 수도 있습니다.

---
- hosts: webservers
  roles:
    - role: '/path/to/my/roles/common'

 

참고로, 저희 프로젝트는 제일 마지막에 나온 경로 설정으로 role을 호출합니다.

예를 들어서 playbook 파일 내에서 아래처럼 사용합니다.

- name: Restart broker
  hosts: kafka:&broker
  serial: 1
  vars:
    target_service_type: broker
    target_service_port: 9092
  roles:
   - role: roles/kafka/restart
     tags: [kafak, broker]

 

Using roles

3가지 방식으로 role을 사용할 수 있습니다.

  • play level에서 `role` 옵션 : play에서 role을 사용하는 가장 일반적인 방법입니다.
  • task level에서 `include_role` : play의 task section에서 역할을 동적으로 재사용 할 수 있습니다.
  • task level에서 `import_role` : play의 task section에서 역할을 정적으로 재사용 할 수 있습니다.

 

Using roles at the play level

Role을 사용하는 일반적인 방법은 play에 roles 옵션을 사용하는 것입니다. (우리 프로젝트는 이 방법 사용)

---
- hosts: webservers
  roles:
    - common
    - webservers

 

`roles` 옵션에 여러 키워드를 넘길 수 있습니다.

---
- hosts: webservers
  roles:
    - common
    - role: foo_app_instance
      vars:
        dir: '/opt/a'
        app_port: 5000
      tags: typeA
    - role: foo_app_instance
      vars:
        dir: '/opt/b'
        app_port: 5001
      tags: typeB

`role` option에 tag를 추가하면, Ansible은 role에 속한 모든 task에 tag를 적용합니다.

플레이북의 `roles:`섹션에서 `vars:` 를 사용하면, 변수가 play 변수에 추가되어 role 전후에 play 내의 모든 task에서 사용할 수 있습니다.

 

Including roles: dynamic reuse

`include_role`을 사용하여 play의 task 섹션 어디에서나 역할을 동적으로 재사용할 수 있습니다. `roles` 섹션에 추가된 roles는 play의 다른 task보다 먼저 실행되지만, 포함된 role은 정의된 순서대로 실행됩니다. `include_role` task 앞에 다른 task가 있는 경우, 다른 task가 먼저 실행됩니다.

 

---
- hosts: webservers
  tasks:
    - name: Print a message
      ansible.builtin.debug:
        msg: "this task runs before the example role"

    - name: Include the example role
      include_role:
        name: example

    - name: Print a message
      ansible.builtin.debug:
        msg: "this task runs after the example role"

roles 내에 variables와 tag를 포함할 수 있습니다.

 

조건부로 role을 포함할 수도 있습니다.

---
- hosts: webservers
  tasks:
    - name: Include the some_role role
      include_role:
        name: some_role
      when: "ansible_facts['os_family'] == 'RedHat'"

 

 

Importing roles: static reuse

`import_role`을 사용하여 play의 task 섹션 어디에서나 role을 정적으로 재사용할 수 있습니다. roles 키워드를 사용하는 것과 동일하게 동작됩니다.

---
- hosts: webservers
  tasks:
    - name: Print a message
      ansible.builtin.debug:
        msg: "before we run our role"

    - name: Import the example role
      import_role:
        name: example

    - name: Print a message
      ansible.builtin.debug:
        msg: "after we ran our role"

 

import_role문에 task를 추가하면 Ansible은 role 내의 모든 task에 태그를 적용합니다.

 

 

Role argument validation

2.11 버전부터 매개변수(argument) 특성 유효성 검사를 사용할 수 있습니다.

이 특성 명세(specification)는 meta/argument_spaces.yml (or .yaml) 파일에 정의되어 있습니다. 매개변수의 특성이 정의되면, role이 실행될 때 새로운 task가 추가되어 role에 제공된 매개변수의 유효성을 검사합니다.

매개 변수의 유효성 검사가 실패하면, role 실행이 실패합니다.

 

Specification format

link 에서 자세한 내용을 확인할 수 있습니다.

 

Sample specification

# roles/myapp/meta/argument_specs.yml
---
argument_specs:
  # roles/myapp/tasks/main.yml entry point
  main:
    short_description: The main entry point for the myapp role.
    options:
      myapp_int:
        type: "int"
        required: false
        default: 42
        description: "The integer value, defaulting to 42."

      myapp_str:
        type: "str"
        required: true
        description: "The string value"

  # roles/myapp/tasks/alternate.yml entry point
  alternate:
    short_description: The alternate entry point for the myapp role.
    options:
      myapp_int:
        type: "int"
        required: false
        default: 1024
        description: "The integer value, defaulting to 1024."

 

 

Running a role multiple times in one play

role에 정의된 parameter가 각 정의마다 다르지 않는 한, role을 여러 번 정의하더라도 Ansible은 play에서 role을 한번만 실행합니다.

role의 parameter는 서로 다르게 정의되어 있습니다. 아래와 같이 적는다면, Ansible은 role `foo`를 play에서 한 번만 실행합니다.

---
- hosts: webservers
  roles:
    - foo
    - bar
    - foo

두 가지 옵션으로 Ansible이 role을 두 번 이상 실행하도록 강제할 수 있습니다.

 

Passing different parameters

각 role 정의에 parameter가 다르게 정의되어 있다면, Ansible은 role을 한 번 이상 실행합니다. 다른 변수 값을 제공하는 것은 다른 role 매개변수를 전달하는 것과 다릅니다. import_role과 include_role은 role 매개 변수를 허용하지 않으므로 roles 키워드에서만 동작합니다.

아래 play는 `foo`가 두 번 실행됩니다.

---
- hosts: webservers
  roles:
    - role: foo
      message: "first"
    - role: foo
      message: "second"

 

Using `allow_duplicates: true`

role에 대한 `meta/main.yml` 파일에 `allow_duplicates: true`를 추가합니다.

# playbook.yml
---
- hosts: webservers
  roles:
    - foo
    - foo

# roles/foo/meta/main.yml
---
allow_duplicates: true

 

Using role dependencies

Role 종속성(dependency)을 사용하면, 한 role을 사용할 때 다른 role을 자동으로 추가할 수 있습니다.

Role 종속성은 선행작업으로 엄밀히 말하자면 종속성이 아닙니다. Role은 parent/child 관계를 가지지 않습니다.

Ansible은 모든 roles 리스트를 로드하고, `dependencies`하위 role 리스트를 먼저 실행한 이후에 다른 role을 실행합니다.

Play object는 종속성 리스트에서 호출되는 role을 포함한 모든 role의 부모입니다.

 

Role 종속성은 role 디렉토리 내에 `meta/main.yml`에 저장됩니다. 이 파일에는 특정 role 앞에 넣을 role 리스트와 파라미터가 포함되어야 합니다.

 

# roles/myapp/meta/main.yml
---
dependencies:
  - role: common
    vars:
      some_parameter: 3
  - role: apache
    vars:
      apache_port: 80
  - role: postgres
    vars:
      dbname: blarg
      other_parameter: 12

Ansible은 종속성에 있는 role을 다른 role보다 먼저 실행합니다. Ansible은 `roles` 키워드를 사용할 때 이 패턴을 재귀적으로 실행합니다. 예를 들어, foo, bar, baz라는 roles가 있을 때, foo의 종속성에 bar이 들어가고 bar의 종속성에 baz가 들어간다면 실행 순서는 baz - bar - foo 가 됩니다.

 

Running role dependencies multiple times in one play

Ansible은 위에서 언급한 중복된 role 처럼 role 종속성에서도 중복된 role은 한 개로 간주합니다. (role에 정의된 매개변수, tag 또는 when 절이 각 정의마다 다른 경우 제외)

 

Play의 두 역할이 모두 세 번째 role을 종속성으로 나열하거나, 다른 매개변수나 tag를 사용하거나, when절을 전달하거나 `allow_duplicates:true`를 사용하지 않는 한 Ansible은 해당 Role 종속성을 한 번만 실행합니다.

아래 예시로 쭉 보겠습니다.

 

- 아래는 `car`이라는 role의 종속성입니다.

---
dependencies:
  - role: wheel
    n: 1
  - role: wheel
    n: 2
  - role: wheel
    n: 3
  - role: wheel
    n: 4

wheel에 두 개의 종속성 `tire`와 `brake`가 있습니다. `wheel`에 대한 `meta/main.yml` 파일에 아래와 같이 포함됩니다.

---
dependencies:
  - role: tire
  - role: brake

그리고 `tire`와 `brake`의 `meta/main.yml` 파일에 다음과 같이 추가합니다.

---
allow_duplicates: true

 

실행 결과는 순서대로 다음과 같이 나옵니다.

tire(n=1)
brake(n=1)
wheel(n=1)
tire(n=2)
brake(n=2)
wheel(n=2)
...
car

 

Role 종속성과 함께 `allow_duplicates:true`를 사용하려면 종속성을 가진 role이 아닌 종속성 아래에 나열된 role에 지정해야 합니다. 위 예제에서는 `tire`와 `brake` role의 `meta/main.yml`에 `allow_duplicates:true`를 설정합니다.

 

Enbedding mudules and plugins in roles

사용자 지정 모듈 또는 플러그인을 작성하는 경우 이를 role의 일부로 배포할 수 있습니다. 

예를 들어, 회사의 내부 소프트웨어를 구성하는 데 필요한 모듈을 조직의 다른 사람들이 사용할 수 있게 하고 싶지만, 모든 사람에게 Ansible 라이브러리 경로를 구성하는 방법을 알려주고 싶지 않은 경우, 내부 _config role에 모듈을 포함할 수 있습니다.

 

Role에 모듈이나 플러그인을 추가하려면 role의 `tasks` 및 `handlers` 구조에 `library`라는 디렉토리를 추가한 다음 이 디렉토리에 포함시킵니다.

 

roles/
    my_custom_modules/
        library/
            module1
            module2

 

 

References

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html#specification-format

반응형

댓글