Tags

Tags

Ansible 태그(tags)를 쓰면 큰 플레이북 전체를 실행하는 대신 원하는 부분만 골라 실행하거나 건너뛸 수 있어요. 태그를 작업에 붙여두고, 플레이북을 실행할 때 특정 태그만 선택하거나 제외하는 방식으로 동작해요. 규모가 큰 자동화에서 재사용성과 실행 제어를 높이는 핵심 기능이에요.

출처: 문서

본문

플레이북이 커지면 전체를 실행하는 대신 일부만 실행하고 싶을 때가 있어요. 이럴 때 Ansible 태그를 사용하면 됩니다. 태그로 선택한 작업만 실행하거나 건너뛰는 과정은 두 단계로 이루어져요.

  • 작업에 태그를 추가한다. 개별적으로 추가하거나, 블록·플레이·롤·임포트로부터 태그 상속을 받을 수 있어요.
  • 플레이북을 실행할 때 실행하거나 건너뛸 태그를 선택한다.

Note

tags 키워드는 플레이북의 '전처리' 단계에 속하며, 실행할 작업을 결정할 때 높은 우선순위를 가져요.

tags 키워드로 태그 추가하기

단일 작업이나 include에 태그를 추가할 수 있어요. 블록, 플레이, 롤, 임포트 수준에서 정의하면 여러 작업에 동시에 태그를 추가할 수도 있어요. tags 키워드는 항상 태그를 정의해 작업에 더하는 역할만 하며, 실행할 작업을 선택하거나 건너뛰는 역할은 하지 않아요. 실행 여부 선택은 플레이북을 실행할 때 커맨드 라인에서 태그를 기준으로만 가능해요.

개별 작업에 태그 추가하기

가장 단순한 형태로, 개별 작업에 하나 이상의 태그를 적용할 수 있어요. 플레이북, 작업 파일, 롤 안 어디서든 작업에 태그를 달 수 있어요. 다음은 두 작업에 서로 다른 태그를 단 예시예요.

tasks:
- name: Install the servers
  ansible.builtin.yum:
    name:
    - httpd
    - memcached
    state: present
  tags:
  - packages
  - webservers

- name: Configure the service
  ansible.builtin.template:
    src: templates/src.j2
    dest: /etc/foo.conf
  tags:
  - configuration

같은 태그를 여러 개별 작업에 적용할 수도 있어요. 다음은 여러 작업에 같은 "ntp" 태그를 건 예시예요.

---
# file: roles/common/tasks/main.yml

- name: Install ntp
  ansible.builtin.yum:
    name: ntp
    state: present
  tags: ntp

- name: Configure ntp
  ansible.builtin.template:
    src: ntp.conf.j2
    dest: /etc/ntp.conf
  notify:
  - restart ntpd
  tags: ntp

- name: Enable and run ntpd
  ansible.builtin.service:
    name: ntpd
    state: started
    enabled: true
  tags: ntp

- name: Install NFS utils
  ansible.builtin.yum:
    name:
    - nfs-utils
    - nfs-util-lib
    state: present
  tags: filesharing

이 네 작업을 --tags ntp 로 실행하면, ntp 태그가 붙은 작업 세 개는 실행되고 태그가 없는 파일 공유 작업은 건너뛰어요.

핸들러(handlers)는 알림을 받았을 때만 실행되는 특수한 작업이라, 모든 태그를 무시하고 태그 기준으로 선택하거나 제외할 수 없어요.

플레이 안의 일부(전부는 아닌) 작업에 태그를 붙이려면 블록을 쓰고 그 수준에서 태그를 정의하면 돼요. 위 NTP 예시를 블록으로 바꾸면 다음과 같아요.

# myrole/tasks/main.yml
- name: ntp tasks
  tags: ntp
  block:
  - name: Install ntp
    ansible.builtin.yum:
      name: ntp
      state: present

  - name: Configure ntp
    ansible.builtin.template:
      src: ntp.conf.j2
      dest: /etc/ntp.conf
    notify:
    - restart ntpd

  - name: Enable and run ntpd
    ansible.builtin.service:
      name: ntpd
      state: started
      enabled: true

- name: Install NFS utils
  ansible.builtin.yum:
    name:
    - nfs-utils
    - nfs-util-lib
    state: present
  tags: filesharing

태그 선택이 블록 오류 처리 등 대부분의 다른 로직보다 우선한다는 점에 주의하세요. 블록의 작업에만 태그를 붙이고 rescue나 always 섹션에는 붙이지 않으면, 태그 선택이 해당 섹션의 작업을 포함하지 않을 때 그들이 실행되지 않을 수 있어요.

- block:
  - debug: msg=run with tag, but always fail
    failed_when: true
    tags: example

  rescue:
  - debug: msg=I always run because the block always fails, except if you select to only run 'example' tag

  always:
  - debug: msg=I always run, except if you select to only run 'example' tag

이 예시는 --tags 없이 실행하면 세 작업이 모두 실행되지만, --tags example로 실행하면 첫 번째 작업만 실행돼요.

플레이의 모든 작업에 같은 태그를 붙이려면 플레이 수준에서 태그를 정의하면 돼요. NTP 작업만 있는 플레이에 전체 태그를 붙이려면:

- hosts: all
  tags: ntp
  tasks:
  - name: Install ntp
    ansible.builtin.yum:
      name: ntp
      state: present

  - name: Configure ntp
    ansible.builtin.template:
      src: ntp.conf.j2
      dest: /etc/ntp.conf
    notify:
    - restart ntpd

  - name: Enable and run ntpd
    ansible.builtin.service:
      name: ntpd
      state: started
      enabled: true

- hosts: fileservers
  tags: filesharing
  tasks:
  # ...

Note

태그가 붙은 작업에는 롤에서 추가된 작업뿐 아니라 팩트 수집 같은 암묵적 작업도 모두 포함돼요.

롤에 태그를 추가하는 방법은 세 가지예요.

  • roles 아래에서 태그를 설정해 롤의 모든 작업에 같은 태그를 붙인다.
  • 플레이북의 정적 import_role에 태그를 설정해 롤의 모든 작업에 같은 태그를 붙인다.
  • 롤 내부의 개별 작업이나 블록에 태그를 붙인다. 이 방법만이 롤 안의 일부 작업을 선택하거나 건너뛰는 유일한 방법이에요. 롤 안의 작업을 선택·건너뛰려면 개별 작업이나 블록에 태그를 설정하고, 플레이북에서 동적 include_role을 쓰며, include에 같은 태그를 붙여야 해요. 이 방식으로 --tags foo 실행 시 include 자체와 롤 안에서 foo 태그가 있는 작업이 모두 실행돼요.

roles 키워드로 플레이북에서 롤을 정적으로 포함하면, 정의한 태그가 롤의 모든 작업에 붙어요. 예:

roles:
  - role: webserver
    vars:
      port: 5000
    tags: [ web, foo ]

또는:

---
- hosts: webservers
  roles:
    - role: foo
      tags:
        - bar
        - baz
    # using YAML shorthand, this is equivalent to:
    # - { role: foo, tags: ["bar", "baz"] }

Note

롤 수준에 태그를 추가하면 모든 작업에 태그가 붙을 뿐 아니라, 롤의 의존성(dependencies) 작업에도 태그가 붙어요.

플레이북에서 동적 include에 태그를 적용할 수 있어요. 개별 작업의 태그와 마찬가지로, include_* 작업의 태그는 include 자체에만 적용되며 포함된 파일이나 롤 안의 작업에는 적용되지 않아요. 동적 include에 mytag를 붙이고 --tags mytag로 실행하면, include 자체와 포함된 파일·롤 안에서 mytag가 붙은 작업을 실행하고, 그 태그가 없는 작업은 건너뛰어요.

---
# file: roles/common/tasks/main.yml

- name: Dynamic reuse of database tasks
  include_tasks: db.yml
  tags: db

롤의 동적 include에만 태그를 붙일 수도 있어요. 아래 예시에서 foo 태그는 bar 롤 안의 작업에는 적용되지 않아요.

---
- hosts: webservers
  tasks:
    - name: Include the bar role
      include_role:
        name: bar
      tags:
        - foo

정적 import_roleimport_tasks가 임포트하는 모든 작업에도 태그를 붙일 수 있어요.

---
- hosts: webservers
  tasks:
    - name: Import the foo role
      import_role:
        name: foo
      tags:
        - bar
        - baz

    - name: Import tasks from foo.yml
      import_tasks: foo.yml
      tags: [ web, foo ]

기본적으로 Ansible은 include_role·include_tasks로 하는 동적 재사용에는 태그 상속을 적용하지 않아요. include에 태그를 붙이면 그 태그는 include 자체에만 적용되고, 포함된 파일이나 롤의 작업에는 적용되지 않아요. 그래서 롤이나 작업 파일 안의 선택된 작업만 실행할 수 있어요.

태그 상속이 필요하다면 임포트(import)를 쓰는 게 좋아요. 다만 한 플레이북에서 include와 import를 함께 쓰면 진단하기 어려운 버그가 생길 수 있어요. include로 롤·작업을 재사용하면서 특정 include에만 태그 상속이 필요하다면 두 가지 방법을 쓸 수 있어요. apply 키워드:

- name: Apply the db tag to the include and to all tasks in db.yml
  include_tasks:
    file: db.yml
    # adds 'db' tag to tasks within db.yml
    apply:
      tags: db
  # adds 'db' tag to this 'include_tasks' itself
  tags: db

또는 블록:

- block:
   - name: Include tasks from db.yml
     include_tasks: db.yml
  tags: db

특수 태그(Special tags)

Ansible은 특별한 동작을 위해 몇 가지 태그 이름을 예약하고 있어요: always, never, tagged, untagged, all. alwaysnever는 주로 작업 자체에 태그를 다는 데 쓰이고, 나머지 세 개는 실행하거나 건너뛸 태그를 선택할 때 사용해요.

always와 never

작업이나 플레이에 always 태그를 붙이면, 명시적으로 건너뛰지(--skip-tags always) 않는 한 Ansible은 항상 그 작업·플레이를 실행해요.

tasks:
- name: Print a message
  ansible.builtin.debug:
    msg: "Always runs"
  tags:
  - always

- name: Print a message
  ansible.builtin.debug:
    msg: "runs when you use specify tag1, all(default) or tagged"
  tags:
  - tag1

- name: Print a message
  ansible.builtin.debug:
    msg: "always runs unless you explicitly skip, like if you use ``--skip-tags tag2``"
  tags:
     - always
     - tag2

Warning

내부 팩트 수집 작업은 기본적으로 'always' 태그가 붙어 있어요. 하지만 플레이에 태그를 붙이고 직접 건너뛰거나(--skip-tags), --tags 사용 시 포함하지 않으면 간접적으로 건너뛸 수 있어요.

Warning

롤 인수 스펙 검증(role argument specification validation) 작업도 기본적으로 'always' 태그가 붙어 있어요. --skip-tags always를 쓰면 이 검증이 건너뛰어져요.

(버전 2.5에 추가됨)

작업이나 플레이에 never 태그를 붙이면, 명시적으로 요청하지 않는 한(--tags never 또는 해당 작업에 정의된 다른 태그) Ansible은 그 작업·플레이를 건너뛰어요.

tasks:
  - name: Run the rarely-used debug task, either with ``--tags debug`` or ``--tags never``
    ansible.builtin.debug:
     msg: '{{ showmevar }}'
    tags: [ never, debug ]

위 예시의 거의 쓰이지 않는 debug 작업은 debug나 never 태그를 명시적으로 요청할 때만 실행돼요.

플레이북을 실행할 때 태그 선택 또는 건너뛰기

작업, include, 블록, 플레이, 롤, 임포트에 태그를 추가했다면, ansible-playbook 실행 시 태그를 기준으로 작업을 선택적으로 실행·건너뛸 수 있어요. Ansible은 커맨드 라인에서 전달한 태그와 일치하는 태그가 있는 모든 작업을 실행하거나 건너뛰어요. 블록·플레이 수준에서 또는 roles, 임포트로 태그를 추가하면 그 태그는 블록, 플레이, 롤, 임포트된 롤·파일 안의 모든 작업에 적용돼요.

ansible-playbook은 다섯 가지 태그 관련 커맨드 라인 옵션을 제공해요:

  • --tags all — never가 아닌 한 태그 있는·없는 모든 작업 실행(기본 동작).
  • --tags tag1,tag2 — tag1 또는 tag2 태그가 있는 작업만 실행(always 태그도 포함).
  • --skip-tags tag3,tag4 — tag3 또는 tag4 또는 never 태그가 있는 작업 제외한 모든 작업 실행.
  • --tags tagged — 태그가 하나 이상 있는 작업만 실행(never가 우선).
  • --tags untagged — 태그가 없는 작업만 실행(always가 우선).

예를 들어 아주 긴 플레이북에서 configuration 또는 packages 태그가 붙은 작업과 블록만 실행하려면:

ansible-playbook example.yml --tags "configuration,packages"

packages 태그가 붙은 작업을 제외한 모든 작업을 실행하려면:

ansible-playbook example.yml --skip-tags "packages"

never 태그로 제외된 작업까지 포함해 모든 작업을 실행하려면:

ansible-playbook example.yml --tags "all,never"

tag1 또는 tag3이 있는 작업을 실행하되 tag4도 가진 작업은 건너뛰려면:

ansible-playbook example.yml --tags "tag1,tag3" --skip-tags "tag4"

태그 우선순위

건너뛰기(skipping)가 명시적 태그보다 항상 우선해요. 예를 들어 --tags--skip-tags를 함께 지정하면 후자가 우선해요. --tags tag1,tag3,tag4 --skip-tags tag3은 tag1이나 tag4 태그가 있는 작업만 실행하고, 다른 태그가 있더라도 tag3이 있는 작업은 실행하지 않아요.

태그 사용 결과 미리 보기

롤이나 플레이북을 실행할 때 어떤 작업에 어떤 태그가 있는지, 또는 어떤 태그가 존재하는지 모를 수 있어요. Ansible은 두 가지 커맨드 라인 플래그를 제공해요:

  • --list-tags — 사용 가능한 태그 목록 생성.
  • --list-tasks--tags tagname 또는 --skip-tags tagname과 함께 쓰면 태그된 작업 미리보기 생성.

예를 들어 configuration 작업의 태그가 config인지 conf인지 모른다면, 아무 작업도 실행하지 않고 사용 가능한 태그를 모두 표시할 수 있어요:

ansible-playbook example.yml --list-tags

configuration과 packages 태그가 있는 작업이 뭔지 모른다면, 그 태그를 전달하고 --list-tasks를 추가하면 됩니다. Ansible은 작업을 나열만 하고 실행하지는 않아요.

ansible-playbook example.yml --tags "configuration,packages" --list-tasks

이 커맨드 라인 플래그는 동적으로 포함된 파일이나 롤 안의 태그·작업은 표시하지 못하는 제한이 있어요.

재사용 파일에서 태그된 작업 선택 실행

작업·블록 수준에서 태그가 정의된 롤이나 작업 파일이 있다면, 정적 임포트 대신 동적 include를 쓰면 플레이북에서 그 태그된 작업을 선택적으로 실행하거나 건너뛸 수 있어요. 포함된 작업과 include 문에 같은 태그를 써야 해요. 예를 들어 태그가 있는 작업과 없는 작업이 섞인 파일을 만들 수 있어요:

# mixed.yml
tasks:
- name: Run the task with no tags
  ansible.builtin.debug:
    msg: this task has no tags

- name: Run the tagged task
  ansible.builtin.debug:
    msg: this task is tagged with mytag
  tags: mytag

- block:
  - name: Run the first block task with mytag
    # ...
  - name: Run the second block task with mytag
    # ...
  tags:
  - mytag

그리고 플레이북에서 위 작업 파일을 include할 수 있어요:

# myplaybook.yml
- hosts: all
  tasks:
  - name: Run tasks from mixed.yml
    include_tasks:
      name: mixed.yml
    tags: mytag

ansible-playbook -i hosts myplaybook.yml --tags "mytag"로 실행하면, 태그가 없는 작업은 건너뛰고, 태그된 개별 작업과 블록의 두 작업을 실행해요. 팩트 수집(암묵적 작업)은 always 태그가 있어 실행될 수도 있어요.

태그 상속: 여러 작업에 태그 추가

모든 작업에 tags 줄을 넣지 않고 여러 작업에 같은 태그를 적용하고 싶다면, 플레이·블록 수준에서 또는 롤·파일 임포트 시 태그를 정의하면 돼요. Ansible은 의존성 체인을 따라 모든 하위 작업에 태그를 적용해요. 롤·임포트에서는 roles 섹션·임포트가 설정한 태그를 롤·임포트된 파일 안의 개별 작업·블록 태그에 덧붙여요. 이를 태그 상속이라 해요. 모든 작업에 태그를 일일이 달지 않아도 되므로 편리해요.

플레이, 블록, role 키워드, 정적 임포트에서는 태그 상속이 적용되어 정의한 태그가 플레이·블록·롤·임포트된 파일 안의 모든 작업에 더해져요. 하지만 태그 상속은 include_role·include_tasks로 하는 동적 재사용에는 적용되지 않아요. 동적 재사용(include)에서는 정의한 태그가 include 자체에만 적용돼요. 태그 상속이 필요하면 정적 임포트를 쓰세요. 나머지 플레이북이 include를 쓰기 때문에 임포트를 쓸 수 없다면, 앞서 설명한 블록이나 apply 키워드 방법으로 우회할 수 있어요.

전역적으로 태그 구성하기

특정 태그를 기본적으로 실행하거나 건너뛰려면 Ansible 구성의 TAGS_RUNTAGS_SKIP 옵션으로 기본값을 설정할 수 있어요.

더 알아보기 (Learn more)