Ansible Playbook을 단일 컴퓨터로 안전하게 제한합니까?


227

소규모 컴퓨터 그룹에서 간단한 사용자 관리 작업에 Ansible을 사용하고 있습니다. 현재 플레이 북을 설정했으며 hosts: all호스트 파일은 모든 컴퓨터가 나열된 단일 그룹입니다.

# file: hosts
[office]
imac-1.local
imac-2.local
imac-3.local

하나의 머신을 자주 타겟팅해야한다는 것을 알게되었습니다. 이 ansible-playbook명령은 다음과 같이 재생을 제한 할 수 있습니다.

ansible-playbook --limit imac-2.local user.yml

그러나 이는 잠재적으로 파괴적인 플레이 북에 있어서는 매우 약해 보입니다. limit깃발을 남기면 플레이 북이 어디에서나 실행됩니다. 이 도구는 가끔씩 만 사용되기 때문에 재생을 속이는 조치를 취할 가치가 있으므로 지금부터 몇 달 동안 우연히 핵무기를하지 않습니다.

플레이 북 실행을 단일 컴퓨터로 제한하는 가장 좋은 방법이 있습니까? 중요한 세부 사항이 빠진 경우 플레이 북은 무해해야합니다.

답변:


209

플레이 북에 호스트 이름을 직접 입력 할 수 있으므로 플레이 북을 실행하면 hosts: imac-2.local정상적으로 작동합니다. 그러나 그것은 어색합니다.

더 나은 솔루션은 변수를 사용하여 플레이 북의 호스트를 정의한 다음 다음을 통해 특정 호스트 주소를 전달하는 것입니다 --extra-vars.

# file: user.yml  (playbook)
---
- hosts: '{{ target }}'
  user: ...

플레이 북 실행 :

ansible-playbook user.yml --extra-vars "target=imac-2.local"

만약 {{ target }}정의되지 않은 플레이 북은 아무 작업도 수행하지 않습니다. 필요한 경우 hosts 파일의 그룹도 전달할 수 있습니다. 전반적으로, 이것은 잠재적으로 파괴적인 플레이 북을 구성하는 훨씬 안전한 방법 인 것 같습니다.

단일 호스트를 대상으로하는 플레이 북 :

$ ansible-playbook user.yml --extra-vars "target=imac-2.local" --list-hosts

playbook: user.yml

  play #1 (imac-2.local): host count=1
    imac-2.local

호스트 그룹이있는 플레이 북 :

$ ansible-playbook user.yml --extra-vars "target=office" --list-hosts

playbook: user.yml

  play #1 (office): host count=3
    imac-1.local
    imac-2.local
    imac-3.local

호스트를 정의하는 것을 잊어 버리는 것이 안전합니다!

$ ansible-playbook user.yml --list-hosts

playbook: user.yml

  play #1 ({{target}}): host count=0

52
이것은--limit office[0]
NG

4
변수는 인용이 필요합니다 – 즉 : -docs.ansible.com/…'{{ target }}' 에 따르면
Limbo Peng

9
이것은 다른 것들과 달리 "실패 안전"답변입니다. 만약 당신이 무언가를 남겨두면 아무것도하지 않을 것입니다. Ansible 1.7을 사용하는 하나의 호스트에서만 실행하는 run_once것은 여전히 ​​파괴적 일 수 있으므로 그렇게 좋은 생각은 아닙니다.
RichVel

4
당신이 짧은 명령을 원하는 경우, -e등가의입니다--extra-vars
윌리엄 터렐

1
사용 가능한 구성에서 호스트를 비우거나 정의 할 수 없어야하는 경우 jinja 필터와 결합 된 변수를 사용하면 다음과 같이 작동합니다.hosts: "{{ target | default('no_hosts')}}"
Zach Weg

178

또한 중간 인벤토리없이 명령 줄에서 단일 호스트 (또는 여러 호스트)를 지정할 수있는 귀여운 방법이 있습니다.

ansible-playbook -i "imac1-local," user.yml

끝에 쉼표 ( , )를 적어 둡니다 . 이것은 파일이 아니라 목록이라는 것을 나타냅니다.

실수로 실제 인벤토리 파일을 전달하면 보호되지 않으므로 특정 문제에 대한 좋은 해결책이 아닐 수 있습니다. 하지만 알아두면 유용한 트릭입니다!


2
그 놀라운. 나는 정기적으로 -l 플래그를 사용하는데, 이는 etc / ansible / hosts (EC2 감지 API를 사용하여 채워짐)와 작동하지만 때로는 단일 머신 만 필요합니다. 감사합니다!
Vic

3
이 트릭은 hosts 파일을 사용해야합니까? AWS EC2 시스템의 동적 인벤토리로 호스트를 사용하고 있으며 다음을 반환합니다 skipping: no hosts matched. 아마도이 트릭은 더 이상 작동하지 않습니다 --limit.
hamx0r

1
이 트릭은 나를 위해 작동하지 않았습니다. 그러나 이것은 효과가 있었다 : $ ansible-playbook -kK --limit=myhost1 myplaybook.yml. Marwan의 답변을 참조하십시오.
Donn Lee

2
이것이 작동하기 위해서는 호스트가 all플레이에서 설정되어야한다는 것을 언급해야합니다 .-알아내는 데 시간이 걸렸습니다 ...
Remigius Stalder

83

play_hosts 변수 를 검사하여 둘 이상의 호스트가 제공되면이 방법이 종료됩니다 . 실패 모듈은 단일 호스트 조건이 충족되지 않을 경우 종료하는 데 사용됩니다. 아래 예제는 두 개의 호스트 alice와 bob이있는 호스트 파일을 사용합니다.

user.yml (플레이 북)

---
- hosts: all
  tasks:
    - name: Check for single host
      fail: msg="Single host check failed."
      when: "{{ play_hosts|length }} != 1"
    - debug: msg='I got executed!'

호스트 필터없이 플레이 북 실행

$ ansible-playbook user.yml
PLAY [all] ****************************************************************
TASK: [Check for single host] *********************************************
failed: [alice] => {"failed": true}
msg: Single host check failed.
failed: [bob] => {"failed": true}
msg: Single host check failed.
FATAL: all hosts have already failed -- aborting

단일 호스트에서 플레이 북 실행

$ ansible-playbook user.yml --limit=alice

PLAY [all] ****************************************************************

TASK: [Check for single host] *********************************************
skipping: [alice]

TASK: [debug msg='I got executed!'] ***************************************
ok: [alice] => {
    "msg": "I got executed!"
}

1
확실히 가장 좋은 --limit방법은 갈 길입니다
berto

7
play_hostsAnsible 2.2에서는 더 이상 사용되지 않으며로 대체되었습니다 ansible_play_hosts. 필요없이 한 호스트에서 실행하려면을 --limit사용할 수 있습니다 when: inventory_hostname == ansible_play_hosts[0].
Trevor Robinson

[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{ play_hosts|length }} == ''Ansible 2.8.4에서.
토마스

32

IMHO가 더 편리한 방법입니다. 실제로 다음과 같은 덕분에 플레이 북을 적용하려는 컴퓨터를 대화 형으로 사용자에게 프롬프트 할 수 있습니다 vars_prompt.

---

- hosts: "{{ setupHosts }}"
  vars_prompt:
    - name: "setupHosts"
      prompt: "Which hosts would you like to setup?"
      private: no
  tasks:
    […]

2
매우 시원합니다. 또한 플레이 북이 인벤토리 파일에만 국한되지 않는다는 이점이 있습니다.
Erfan

2
편집을위한 Thx! 입력이 기본적으로 "암호 스타일"로 처리 된 이유가 궁금했습니다. 나는 문서에서 그것을 놓쳤다 :)
Buzut

이 플레이 북의 프롬프트를 없애기 위해 명령 줄에서 호스트 var를 설정할 수 있습니까?
andig

1
와 @andig --extra-vars... 당신의 작전에서 정상 VAR
Buzut

실제로, 나는 이것을 작동시키지 못했습니다- {{ hosts }}값이 입력되기 전에 평가 된 것 같습니다 -또는 특별한 트릭이 있습니까?
Remigius Stalder

18

joemailer의 답변을 확장하려면 원격 컴퓨터의 하위 집합과 일치하는 패턴 일치 기능을 원할 경우 ansible 명령 원하지만 모든 컴퓨터에서 실수로 플레이 북을 실행하기가 매우 어려워지는 경우 내가 생각해 낸 것 :

다른 답변과 동일한 플레이 북 :

# file: user.yml  (playbook)
---
- hosts: '{{ target }}'
  user: ...

다음과 같은 호스트가 있습니다 :

imac-10.local
imac-11.local
imac-22.local

이제 모든 장치에서 명령을 실행하려면 대상 변수를 "all"로 명시해야합니다.

ansible-playbook user.yml --extra-vars "target=all"

특정 패턴으로 제한하기 위해 target=pattern_here

또는 다음 target=all과 같이 --limit인수를 그대로두고 추가 할 수 있습니다 .

--limit imac-1*

즉. ansible-playbook user.yml --extra-vars "target=all" --limit imac-1* --list-hosts

결과 :

playbook: user.yml

  play #1 (office): host count=2
    imac-10.local
    imac-11.local


13

나는 모든 답변이 얼마나 복잡한 지 이해하지 못합니다. 그 방법은 간단합니다.

ansible-playbook user.yml -i hosts/hosts --limit imac-2.local --check

check모드를 사용하면 변경하지 않고 드라 이런 모드로 실행할 수 있습니다.


7
아마도 대답에 대해 궁금해하기 때문에 실수로 매개 변수를 생략 할 때 실행을 방지하는 방법을 요청한 질문을 놓쳤습니다. 요구 사항에 맞는 더 많은 매개 변수를 추가하는 것이 좋습니다.
techraf

2
아, 물론, 사람들이 저를 찬성했다면 깃발에 대해 알지 못하는 (아무도 대답을 썼을 때와 같이) Ansible 초보자이기 때문에 이것이 --check문서화에 도움이 된다고 생각합니다. 이 질문은 매우 될 수있다 googlable
knocte

6

EC2 외부 인벤토리 스크립트를 사용하는 AWS 사용자는 인스턴스 ID별로 간단히 필터링 할 수 있습니다.

ansible-playbook sample-playbook.yml --limit i-c98d5a71 --list-hosts

이것은 인벤토리 스크립트 가 기본 그룹을 생성 하기 때문에 작동 합니다 .


4
--limit 옵션은 EC2로 제한되지 않으며 인벤토리의 이름을 호스트 / 그룹화하는 데 사용할 수 있습니다. 감사.
martinezdelariva

5

다수의 팀이 사용할 수있는 일반적인 플레이 북이 있습니다. 또한 여러 그룹 선언이 포함 된 환경 별 인벤토리 파일도 있습니다.

플레이 북을 호출하는 누군가가 그룹을 지정하도록 강요하기 위해 플레이 북 상단에 더미 항목을 시드합니다.

[ansible-dummy-group]
dummy-server

그런 다음 공유 플레이 북에서 첫 번째 단계로 다음 확인 사항을 포함시킵니다.

- hosts: all
  gather_facts: False
  run_once: true
  tasks:
  - fail:
      msg: "Please specify a group to run this playbook against"
    when: '"dummy-server" in ansible_play_batch'

더미 서버가이 플레이 북에 대해 (ansible_play_batch) 실행되도록 예약 된 호스트 목록에 표시되면 호출자가 그룹을 지정하지 않아 플레이 북 실행이 실패합니다.


ansible_play_batch현재 배치 만 나열하므로 배치를 사용할 때 여전히 안전하지 않습니다. ansible_play_hosts대신 사용하는 것이 좋습니다.
토마스

그 외에도,이 속임수는 요청 된 것에 가장 단순하고 가장 가까운 것 같습니다. 나는 그것을 채택하고있다!
토마스

4

1.7 버전 이후 ansible에는 run_once 옵션이 있습니다. 섹션에는 다양한 다른 기술에 대한 설명도 포함되어 있습니다.


4

대상 서버 자체에서 플레이 북을 실행하는 방법을 보여줍니다.

로컬 연결을 사용하려면 조금 까다 롭습니다. 그러나 호스트 설정에 변수를 사용하고 호스트 파일에서 localhost에 대한 특수 항목을 작성하는 경우 이는 정상입니다.

(모든) 플레이 북에서 hosts : 행을 다음과 같이 설정합니다.

- hosts: "{{ target | default('no_hosts')}}"

자원 명세 호스트 파일에서 연결을 로컬로 설정하는 localhost에 대한 항목을 추가하십시오.

[localhost]
127.0.0.1  ansible_connection=local

그런 다음 명령 행에서 대상을 명시 적으로 설정하는 명령을 실행하십시오. 예를 들면 다음과 같습니다.

$ ansible-playbook --extra-vars "target=localhost" test.yml

ansible-pull을 사용할 때도 작동합니다.

$ ansible-pull -U <git-repo-here> -d ~/ansible --extra-vars "target=localhost" test.yml

명령 행에서 변수를 설정하는 것을 잊어 버린 경우 경고 메시지와 함께 'no_hosts'라는 호스트 그룹을 만들지 않은 한 명령이 안전하게 오류가 발생합니다.

skipping: no hosts matched

위에서 언급했듯이 다음을 사용하여 단일 시스템 (hosts 파일에있는 한)을 대상으로 지정할 수 있습니다.

$ ansible-playbook --extra-vars "target=server.domain" test.yml

또는 다음과 같은 그룹 :

$ ansible-playbook --extra-vars "target=web-servers" test.yml

0

provision이라는 래퍼 스크립트가 있으므로 대상을 선택해야하므로 다른 곳에서는 처리 할 필요가 없습니다.

궁금한 사람들에게는 ENV vars를 사용하여 내 vagrantfile이 사용하는 옵션 (클라우드 시스템에 해당하는 argable arg 추가)을 사용하고 나머지 ansible args는 통과시킵니다. 한 번에 10 개 이상의 서버를 생성하고 프로비저닝하는 경우 실패한 서버에서 자동 재 시도를 포함합니다 (진행이 진행되는 한-한 번에 100 개 정도의 서버를 만들 때 처음 몇 개가 실패 할 경우가 있음을 발견했습니다) ).

echo 'Usage: [VAR=value] bin/provision [options] dev|all|TARGET|vagrant'
echo '  bootstrap - Bootstrap servers ssh port and initial security provisioning'
echo '  dev - Provision localhost for development and control'
echo '  TARGET - specify specific host or group of hosts'
echo '  all - provision all servers'
echo '  vagrant - Provision local vagrant machine (environment vars only)'
echo
echo 'Environment VARS'
echo '  BOOTSTRAP - use cloud providers default user settings if set'
echo '  TAGS - if TAGS env variable is set, then only tasks with these tags are run'
echo '  SKIP_TAGS - only run plays and tasks whose tags do not match these values'
echo '  START_AT_TASK - start the playbook at the task matching this name'
echo
ansible-playbook --help | sed -e '1d
    s#=/etc/ansible/hosts# set by bin/provision argument#
    /-k/s/$/ (use for fresh systems)/
    /--tags/s/$/ (use TAGS var instead)/
    /--skip-tags/s/$/ (use SKIP_TAGS var instead)/
    /--start-at-task/s/$/ (use START_AT_TASK var instead)/
'

0

약간 다른 해결책은 현재 Ansible 실행을위한 CLI 옵션 ansible_limit의 내용 인 특수 변수를 사용하는 것 --limit입니다.

- hosts: "{{ ansible_limit | default(omit) }}"

여기에 추가 변수를 정의 할 필요가 없습니다 --limit. 플래그 와 함께 플레이 북을 실행하십시오 .

ansible-playbook --limit imac-2.local user.yml
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.