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

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

    반응형

    댓글