Ansible Playbook을 단일 컴퓨터로 안전하게 제한합니까?
소규모 컴퓨터 그룹에서 간단한 사용자 관리 작업에 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
깃발을 남기면 플레이 북이 어디에서나 실행됩니다. 이러한 도구는 가끔씩 만 사용되기 때문에 재생을 속이는 조치를 취할 가치가 있으므로 지금부터 몇 달 동안 실수로 핵을 피하지 않습니다.
플레이 북 실행을 단일 컴퓨터로 제한하는 가장 좋은 방법이 있습니까? 중요한 세부 사항이 빠진 경우 플레이 북은 무해해야합니다.
플레이 북에 호스트 이름을 직접 입력 할 수 있으므로 플레이 북을 실행하면 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
또한 중간 인벤토리없이 명령 줄에서 단일 호스트 (또는 여러 호스트)를 지정할 수있는 작은 트릭이 있습니다.
ansible-playbook -i "imac1-local," user.yml
끝에 쉼표 ( , )를 적어 둡니다 . 이것은 파일이 아니라 목록이라는 것을 나타냅니다.
실수로 실제 인벤토리 파일을 전달하면 보호되지 않으므로이 특정 문제에 대한 좋은 해결책이 아닐 수 있습니다. 하지만 알아두면 유용한 트릭입니다!
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!"
}
There's IMHO a more convenient way. You can indeed interactively prompt the user for the machine(s) he wants to apply the playbook to thanks to vars_prompt
:
---
- hosts: "{{ setupHosts }}"
vars_prompt:
- name: "setupHosts"
prompt: "Which hosts would you like to setup?"
private: no
tasks:
[…]
To expand on joemailer's answer, if you want to have the pattern-matching ability to match any subset of remote machines (just as the ansible
command does), but still want to make it very difficult to accidentally run the playbook on all machines, this is what I've come up with:
Same playbook as the in other answer:
# file: user.yml (playbook)
---
- hosts: '{{ target }}'
user: ...
Let's have the following hosts:
imac-10.local
imac-11.local
imac-22.local
Now, to run the command on all devices, you have to explicty set the target variable to "all"
ansible-playbook user.yml --extra-vars "target=all"
And to limit it down to a specific pattern, you can set target=pattern_here
or, alternatively, you can leave target=all
and append the --limit
argument, eg:
--limit imac-1*
ie. ansible-playbook user.yml --extra-vars "target=all" --limit imac-1* --list-hosts
which results in:
playbook: user.yml
play #1 (office): host count=2
imac-10.local
imac-11.local
AWS users using the EC2 External Inventory Script can simply filter by instance id:
ansible-playbook sample-playbook.yml --limit i-c98d5a71 --list-hosts
This works because the inventory script creates default groups.
I really don't understand how all the answers are so complicated, the way to do it is simply:
ansible-playbook user.yml -i hosts/hosts --limit imac-2.local --check
The check
mode allows you to run in dry-run mode, without making any change.
Since version 1.7 ansible has the run_once option. Section also contains some discussion of various other techniques.
We have some generic playbooks that are usable by a large number of teams. We also have environment specific inventory files, that contain multiple group declarations.
To force someone calling a playbook to specify a group to run against, we seed a dummy entry at the top of the playbook:
[ansible-dummy-group]
dummy-server
We then include the following check as a first step in the shared playbook:
- 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'
If the dummy-server shows up in the list of hosts this playbook is scheduled to run against (ansible_play_batch), then the caller didn't specify a group and the playbook execution will fail.
This shows how to run the playbooks on the target server itself.
This is a bit trickier if you want to use a local connection. But this should be OK if you use a variable for the hosts setting and in the hosts file create a special entry for localhost.
In (all) playbooks have the hosts: line set to:
- hosts: "{{ target | default('no_hosts')}}"
In the inventory hosts file add an entry for the localhost which sets the connection to be local:
[localhost]
127.0.0.1 ansible_connection=local
Then on the command line run commands explicitly setting the target - for example:
$ ansible-playbook --extra-vars "target=localhost" test.yml
This will also work when using ansible-pull:
$ ansible-pull -U <git-repo-here> -d ~/ansible --extra-vars "target=localhost" test.yml
If you forget to set the variable on the command line the command will error safely (as long as you've not created a hosts group called 'no_hosts'!) with a warning of:
skipping: no hosts matched
And as mentioned above you can target a single machine (as long as it is in your hosts file) with:
$ ansible-playbook --extra-vars "target=server.domain" test.yml
or a group with something like:
$ ansible-playbook --extra-vars "target=web-servers" test.yml
I have a wrapper script called provision forces you to choose the target, so I don't have to handle it elsewhere.
For those that are curious, I use ENV vars for options that my vagrantfile uses (adding the corresponding ansible arg for cloud systems) and let the rest of the ansible args pass through. Where I am creating and provisioning more than 10 servers at a time I include an auto retry on failed servers (as long as progress is being made - I found when creating 100 or so servers at a time often a few would fail the first time around).
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)/
'
참고URL : https://stackoverflow.com/questions/18195142/safely-limiting-ansible-playbooks-to-a-single-machine
'Programming' 카테고리의 다른 글
Visual Studio가 Internet Explorer 대신 기본 브라우저를 엽니 다 (0) | 2020.05.07 |
---|---|
dyld : 라이브러리가로드되지 않았습니다 : @ rpath / libswift_stdlib_core.dylib (0) | 2020.05.07 |
캐치 페이스트 입력 (0) | 2020.05.07 |
파이썬에서 PhantomJS를 사용하는 방법이 있습니까? (0) | 2020.05.07 |
아카이브 제출시 Xcode 6 충돌 (0) | 2020.05.07 |