๐Ÿ”ง

Ansible - register, until, shell/command ์‹ฌํ™”

์ตœ๋ฏผ์„ยท2026-03-18

ansible

register, until, shell/command ์‹ฌํ™”

๐Ÿ”ง Ansible ์‹ค์Šต ์‹œ๋ฆฌ์ฆˆ

์ด์ „ ์ฑ•ํ„ฐ๊นŒ์ง€ playbook์˜ ์‹คํ–‰ ํ๋ฆ„์„ ์ œ์–ดํ•˜๋Š” ๋ฐฉ๋ฒ•(๋ฉ€ํ‹ฐ play, serial, delegate_to)์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” task์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋  ๋•Œ๊นŒ์ง€ ์žฌ์‹œ๋„ํ•˜๋Š” ํŒจํ„ด์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.


register โ€” task ๊ฒฐ๊ณผ๋ฅผ ๋ณ€์ˆ˜์— ์ €์žฅ

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

command๋‚˜ shell ๋ชจ๋“ˆ๋กœ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด stdout, stderr, return code ๋“ฑ์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. register๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๊ฒฐ๊ณผ๋ฅผ ๋ณ€์ˆ˜์— ์ €์žฅํ•˜๊ณ  ์ดํ›„ task์—์„œ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

playbook/register_test.yml:

---
- name: register test
  hosts: managed
  gather_facts: false
  become: true

  tasks:
    - name: uptime
      command: uptime
      register: result
    - name: print
      debug:
        msg: "{{ result.stdout }}"

์‹คํ–‰ ๊ฒฐ๊ณผ

TASK [uptime] ********************************************************************
changed: [node2]
changed: [node3]
changed: [node1]

TASK [print] *********************************************************************
ok: [node1] => {
    "msg": " 08:50:26 up  2:11,  0 user,  load average: 1.01, 0.49, 0.25"
}
ok: [node2] => {
    "msg": " 08:50:26 up  2:11,  0 user,  load average: 1.01, 0.49, 0.25"
}
ok: [node3] => {
    "msg": " 08:50:26 up  2:11,  0 user,  load average: 1.01, 0.49, 0.25"
}

register๋œ ๋ณ€์ˆ˜์—๋Š” stdout ์™ธ์—๋„ ๋‹ค์–‘ํ•œ ํ•„๋“œ๊ฐ€ ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

ํ•„๋“œ ์„ค๋ช…
stdout ํ‘œ์ค€ ์ถœ๋ ฅ (๋ฌธ์ž์—ด)
stdout_lines ํ‘œ์ค€ ์ถœ๋ ฅ (์ค„ ๋‹จ์œ„ ๋ฆฌ์ŠคํŠธ)
stderr ํ‘œ์ค€ ์—๋Ÿฌ
rc return code (0์ด๋ฉด ์„ฑ๊ณต)
changed ๋ณ€๊ฒฝ ์—ฌ๋ถ€ (bool)

register + when โ€” ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋ถ„๊ธฐ

์กฐ๊ฑด๋ถ€ ์‹คํ–‰

register๋กœ ์ €์žฅํ•œ ๊ฒฐ๊ณผ๋ฅผ when ์กฐ๊ฑด์—์„œ ํ™œ์šฉํ•˜๋ฉด, ์ด์ „ task์˜ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋‹ค์Œ task์˜ ์‹คํ–‰ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

playbook/register_when.yml:

---
- name: register when test
  hosts: managed
  gather_facts: false
  become: true

  tasks:
    - name: print hostname
      command: cat /etc/hostname
      register: result

    - name: print
      debug:
        msg: "์ด ๋…ธ๋“œ๋Š” primary์ž…๋‹ˆ๋‹ค."
      when: result.stdout == "node1"

์‹คํ–‰ ๊ฒฐ๊ณผ

TASK [print hostname] ************************************************************
changed: [node3]
changed: [node1]
changed: [node2]

TASK [print] *********************************************************************
skipping: [node2]
ok: [node1] => {
    "msg": "์ด ๋…ธ๋“œ๋Š” primary์ž…๋‹ˆ๋‹ค."
}
skipping: [node3]

node1์—์„œ๋งŒ debug ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜๊ณ , node2์™€ node3์€ skipping๋ฉ๋‹ˆ๋‹ค. ๊ฐ ๋…ธ๋“œ์—์„œ cat /etc/hostname์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— when ์กฐ๊ฑด์ด ๋…ธ๋“œ๋ณ„๋กœ ๋‹ค๋ฅด๊ฒŒ ํ‰๊ฐ€๋ฉ๋‹ˆ๋‹ค.

์—๋Ÿฌ: when์—์„œ ๋ฌธ์ž์—ด ๋น„๊ต ์‹œ ๋”ฐ์˜ดํ‘œ ๋ˆ„๋ฝ

์ฒ˜์Œ ์ž‘์„ฑํ•  ๋•Œ when: result.stdout == node1๋กœ ์“ฐ๋ฉด ๋‹ค์Œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค:

Error while evaluating conditional: 'node1' is undefined

์›์ธ: when์—์„œ ๋”ฐ์˜ดํ‘œ ์—†์ด node1์„ ์“ฐ๋ฉด ๋ณ€์ˆ˜๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค. node1์ด๋ผ๋Š” ๋ณ€์ˆ˜๋Š” ์ •์˜๋œ ์ ์ด ์—†์œผ๋ฏ€๋กœ undefined ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ: ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์€ ๋ฐ˜๋“œ์‹œ ๋”ฐ์˜ดํ‘œ๋กœ ๊ฐ์‹ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค:

when: result.stdout == "node1"

until โ€” ์กฐ๊ฑด ์ถฉ์กฑ๊นŒ์ง€ ์žฌ์‹œ๋„

์™œ ํ•„์š”ํ•œ๊ฐ€

์„œ๋น„์Šค ๋ฐฐํฌ ํ›„ "์ •์ƒ ์ƒํƒœ๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ"ํ•˜๋Š” ํŒจํ„ด์€ ๋งค์šฐ ํ”ํ•ฉ๋‹ˆ๋‹ค. Kubernetes์˜ readiness probe์ฒ˜๋Ÿผ, Ansible์—์„œ๋„ until๋กœ ํŠน์ • ์กฐ๊ฑด์ด ๋งŒ์กฑ๋  ๋•Œ๊นŒ์ง€ ์ฃผ๊ธฐ์ ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

playbook ์ž‘์„ฑ

playbook/until_test.yml:

---
- name: until  test
  hosts: managed
  gather_facts: false
  become: true

  tasks:
    - name: print non exist file
      shell: cat /tmp/ready.txt
      register: result
      ignore_errors: true
      until: "'ok' in result.stdout"
      retries: 5
      delay: 3
์˜ต์…˜ ์„ค๋ช…
until ์ด ์กฐ๊ฑด์ด true๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต
retries ์ตœ๋Œ€ ์žฌ์‹œ๋„ ํšŸ์ˆ˜ (๊ธฐ๋ณธ๊ฐ’: 3)
delay ์žฌ์‹œ๋„ ๊ฐ„๊ฒฉ โ€” ์ดˆ ๋‹จ์œ„ (๊ธฐ๋ณธ๊ฐ’: 5)
ignore_errors ์ตœ์ข… ์‹คํŒจ ์‹œ์—๋„ playbook์„ ์ค‘๋‹จํ•˜์ง€ ์•Š์Œ

์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ํŒŒ์ผ์ด ์—†์„ ๋•Œ (์‹คํŒจ)

/tmp/ready.txt๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ƒํƒœ์—์„œ ์‹คํ–‰ํ•˜๋ฉด 3์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ 5๋ฒˆ ์žฌ์‹œ๋„ํ•œ ๋’ค ์ตœ์ข… ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค:

TASK [print non exist file] ******************************************************
FAILED - RETRYING: [node1]: print non exist file (5 retries left).
FAILED - RETRYING: [node1]: print non exist file (4 retries left).
FAILED - RETRYING: [node1]: print non exist file (3 retries left).
FAILED - RETRYING: [node1]: print non exist file (2 retries left).
FAILED - RETRYING: [node1]: print non exist file (1 retries left).
fatal: [node1]: FAILED! => {"attempts": 5, "changed": true, ...
    "stderr": "cat: /tmp/ready.txt: No such file or directory", ...}
...ignoring

ignore_errors: true๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ์—๋Ÿฌ๋ฅผ ๋ฌด์‹œํ•˜๊ณ  playbook์€ ์ •์ƒ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค. PLAY RECAP์—์„œ ignored=1๋กœ ์ง‘๊ณ„๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ignore_errors๋Š” task ๋ ˆ๋ฒจ์— ๋ถ™์ด์„ธ์š”

play ๋ ˆ๋ฒจ์— ignore_errors: true๋ฅผ ์“ฐ๋ฉด ํ•ด๋‹น play์˜ ๋ชจ๋“  task์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค. ์˜๋„์น˜ ์•Š์€ ์—๋Ÿฌ๋ฅผ ๋†“์น  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ํ•„์š”ํ•œ task์—๋งŒ ๊ฐœ๋ณ„์ ์œผ๋กœ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ํŒŒ์ผ ์ƒ์„ฑ ํ›„ (์„ฑ๊ณต)

ad-hoc ๋ช…๋ น์œผ๋กœ ํŒŒ์ผ์„ ๋งŒ๋“  ๋’ค ๋‹ค์‹œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค:

ansible managed -m shell -a "echo ok > /tmp/ready.txt" -b
ansible-playbook playbook/until_test.yml
TASK [print non exist file] ******************************************************
changed: [node1]
changed: [node2]
changed: [node3]

์ฒซ ์‹œ๋„์—์„œ stdout์— "ok"๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ์žฌ์‹œ๋„ ์—†์ด ๋ฐ”๋กœ ์„ฑ๊ณตํ•ฉ๋‹ˆ๋‹ค.


shell vs command

command์™€ shell ๋ชจ๋“ˆ์€ ๋‘˜ ๋‹ค ์›๊ฒฉ ๋…ธ๋“œ์—์„œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์ง€๋งŒ, ์ค‘์š”ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:

command shell
์‰˜ ๊ฒฝ์œ  X (์ง์ ‘ ์‹คํ–‰) O (/bin/sh๋ฅผ ํ†ตํ•ด ์‹คํ–‰)
ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์น˜ํ™˜ ($HOME) X O
ํŒŒ์ดํ”„ (|), ๋ฆฌ๋‹ค์ด๋ ‰์…˜ (>) X O
๋ณด์•ˆ injection ์œ„ํ—˜ ์—†์Œ ์‰˜ ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ = injection ๊ฐ€๋Šฅ์„ฑ

์›์น™: ์‰˜ ๊ธฐ๋Šฅ(ํŒŒ์ดํ”„, ๋ฆฌ๋‹ค์ด๋ ‰์…˜, ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋“ฑ)์ด ํ•„์š” ์—†๋‹ค๋ฉด command๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ๋” ์•ˆ์ „ํ•˜๊ณ , ์˜๋„ํ•˜์ง€ ์•Š์€ ์‰˜ ํ•ด์„์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


์ •๋ฆฌ

๊ฐœ๋… ์—ญํ•  ํ™œ์šฉ ์˜ˆ์‹œ
register task ๊ฒฐ๊ณผ๋ฅผ ๋ณ€์ˆ˜์— ์ €์žฅ ์ด์ „ task ๊ฒฐ๊ณผ๋กœ ๋ถ„๊ธฐ, ์ถœ๋ ฅ ํ™•์ธ
register + when ์ €์žฅ๋œ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ์กฐ๊ฑด๋ถ€ ์‹คํ–‰ ํŠน์ • ๋…ธ๋“œ์—์„œ๋งŒ ์ถ”๊ฐ€ ์ž‘์—… ์ˆ˜ํ–‰
until + retries + delay ์กฐ๊ฑด ์ถฉ์กฑ๊นŒ์ง€ ์ฃผ๊ธฐ์  ์žฌ์‹œ๋„ ์„œ๋น„์Šค ๊ธฐ๋™ ๋Œ€๊ธฐ, ์ƒํƒœ ํ™•์ธ
command vs shell ์‰˜ ๊ฒฝ์œ  ์—ฌ๋ถ€ ์ฐจ์ด ์‰˜ ๊ธฐ๋Šฅ ๋ถˆํ•„์š” ์‹œ command ์šฐ์„  ์‚ฌ์šฉ

๋‹ค์Œ ์ฑ•ํ„ฐ์—์„œ๋Š” apt์˜ hold/unhold๋กœ ํŒจํ‚ค์ง€ ๋ฒ„์ „์„ ๊ณ ์ •ํ•˜๊ณ , block/rescue๋กœ ์—๋Ÿฌ๋ฅผ ๊ตฌ์กฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.