2020.4.20 추가
Ansible은 인벤토리라고 하는 목록 or 목록 그룹을 사용해 인프라의 여러 managed node(or host)에 대해 동시에 작동한다. 인벤토리가 정의되면 패턴을 사용해 Ansible을 실행할 호스트 또는 그룹을 선택한다.
인벤토리의 기본 위치는 /etc/ansible/hosts
이다. -i <path>
옵션을 사용하여 command line에서 다른 인벤토리 파일을 지정할 수 있다. 동적 인벤토리 작업에 설명된 대로 여러 인벤토리 파일을 동시에 사용하거나 동적 or 클라우드 소스 or 다른 형식(YAML, ini 등)에서 인벤토리를 가져올 수도 있다. 버전 2.4에 도입된 Ansible에는 유연하고 사용자 정의가 가능한 인벤토리 플러그인이 있다.
인벤토리 파일은 보유한 인벤토리 플러그인에 따라 여러 포맷 중 하나 일 수 있다. 가장 일반적인 형식은 INI 및 YAML이다. 기본 INI etc/ansible/hosts
는 다음과 같다.
mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
괄호 안 제목은 그룹 이름으로, 호스트를 분류하고 어느 시간에 어떤 목적으로 어떤 호스트를 제어하는지 결정하는데 사용된다.
YAML 형식의 동일한 기본 인텐토리 파일을 다음과 같다.
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
디폴트 그룹에는 두가지가 있다 : all
, ungrouped
.
all 그룹은 모든 호스트가 포함돼있다. ungrouped 그룹은 다른 그룹을 제외한 모든 호스트가 포함된다. (The ungrouped group contains all hosts that don’t have another group aside from all) 모든 호스트는 항상 2개 이상의 그룹(all
과 ungrouped
or all
과 또 다른 그룹)에 속한다. all
과 ungrouped
이 항상 존재할지라도, 이는 암시적일 수 있으며 group_names
와 같은 그룹 목록에 나타나지 않는다.
각 호스트를 둘 이상의 그룹에 넣을 수 있다. 예를 들어 Atlanta의 데이터 센터에 있는 프로덕션 웹 서버는 [prod], [atlanta], [webservers]라는 그룹에 동시에 포함될 수 있다.
다음을 추적하는 그룹을 만들 수 있다.
이전 YAML 인벤토리를 확장하여 다음과 같은 what, when, where을 포함시킨다 :
all:
hosts:
mail.example.com:
children:
webservers: //what
hosts:
foo.example.com:
bar.example.com:
dbservers: //what
hosts:
one.example.com:
two.example.com:
three.example.com:
east: //where
hosts:
foo.example.com:
one.example.com:
two.example.com:
west: //where
hosts:
bar.example.com:
three.example.com:
prod: //when
hosts:
foo.example.com:
one.example.com:
two.example.com:
test: //when
hosts:
bar.example.com:
three.example.com:
one.example.com
에 존재하는 dbservers
, east
, prod
그룹을 확인할 수 있다.
또한 동일한 결과를 위해 중첩된 그룹을 사용하여 이 인벤토리에서 prod
와 test
를 단순화 할 수도 있다.
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
east:
hosts:
foo.example.com:
one.example.com:
two.example.com:
west:
hosts:
bar.example.com:
three.example.com:
prod:
children:
east: //중첩
test:
children:
west: //중첩
어떻게 인벤토리를 구성하고 호스트를 그룹화하는 가에 대한 다양한 예시를 여기에서 확인할 수 있다.
유사한 패턴을 가진 호스트가 많은 경우 각 호스트 이름을 별도로 나열하지 않고 범위로 추가 할 수 있다.
INI:
[webservers]
www[01:50].example.com
YAML:
...
webservers:
hosts:
www[01:50].example.com:
숫자 패턴의 경우 원하는대로 선행 0을 포함하거나 제거 할 수 있다.
알파벳 범위를 정의 할 수도 있다. :
[databases]
db-[a:f].example.com
인벤토리의 특정 호스트나 그룹과 관련된 변수 값을 저장할 수 있다. 이를 시작하기 위해 메인 인벤토리 파일의 호스트나 그룹에 변수를 직접 추가할 수 있다. 하지만 Ansible 인벤토리에 더 많은 managed node를 추가함에 따라 변수를 별도의 호스트 및 그룹 변수 파일에 저장할 수 있다.
✔️하나의 머신에 변수할당하기
단일 호스트에 변수를 할당한 뒤 플레이북에서 사용가능하다.
INI:
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
YAML:
atlanta:
host1:
http_port: 80
maxRequestsPerChild: 808
host2:
http_port: 303
maxRequestsPerChild: 909
비표준 SSH 포트와 같은 고유한 값은 호스트 변수로 잘 작동한다. 호스트 이름 뒤에 포트 번호를 콜론으로 추가해 Ansible인벤토리에 추가할 수 있다.
badwolf.example.com:5309 //port 번호 바로 붙임
연결 변수는 호스트 변수로도 잘 작동한다.
[targets]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_user=myuser
other2.example.com ansible_connection=ssh ansible_user=myotheruser
SSH 구성 파일에 비표준 SSH 포트를 나열하면
openssh
커넥션은 이를 찾고 사용할 수 있는 반면에paramiko
커넥션은 그렇게 하지 못한다.
인벤토리에서 별칭을 정의 할 수 있다.
YAML:
...
hosts:
jumper: //<- aliase
ansible_port: 5555
ansible_host: 192.0.2.50
📌위의 예에서 호스트의 별칭 'jumper'에 대해 Ansible을 실행 → 5555 port에서 192.0.2.50에 연결된다.
이는 고정 IP가 있거나 터널을 통해 연결될 때만 작동한다.
일반적으로 이것이 시스템 정책을 설명하는 변수를 정의하기에 가장 좋은 방법은 아니다. 메인 인벤토리 파일에서 변수를 설정하는 것은 간단하다. host_vars 디렉토리의 개별 파일에 변수 값을 저장하는 것에 대한 지침은 호스트 및 그룹 변수 구성을 참조하라.
✔️여러 머신에 변수할당하기 : 그룹 변수
📌그룹의 모든 호스트가 변수 값을 공유하면 해당 변수를 전체 그룹에 한 번에 적용 할 수 있다.
INI:
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
YAML:
atlanta:
hosts: //그룹화된 호스트 = group이름 atlanta
host1:
host2:
vars: //그룹화된 변수 = atlanta.vars
ntp_server: ntp.atlanta.example.com
proxy: proxy.atlanta.example.com
그룹 변수는 변수를 한 번에 여러 호스트에 적용할 수 있는 편리한 방법이다.
✔️변수 값 상속 : 그룹의 하위 그룹을 위한 그룹 변수*
INI의 접미사 :children
또는 YAML의 children:
항목을 사용해 그룹의 하위 그룹을 만들 수 있다.
:vars
또는 vars:
를 사용해 그룹의 하위 그룹에 변수를 적용할 수 있다.
INI:
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children] //southesat의 child가 atlanta, raleigh
atlanta
raleigh
[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2
[usa:children] //usa의 child가 southeast, northeast, southwest, northwest
southeast
northeast
southwest
northwest
YAML:
all:
children:
usa:
children:
southeast:
children:
atlanta:
hosts:
host1:
host2:
raleigh:
hosts:
host2:
host3:
vars:
some_server: foo.southeast.example.com
halon_system_timeout: 30
self_destruct_countdown: 60
escape_pods: 2
northeast:
northwest:
southwest:
목록 또는 해시 데이터를 저장해야하거나 호스트 및 그룹의 특정 변수를 인벤토리 파일과 별도로 유지하려면 호스트 및 그룹 변수 구성을 참조하라.
하위 그룹에는 다음과 같은 몇 가지 속성이 있다.
기본 인벤토리 파일에 변수를 저장할 수도 있지만 별도의 호스트 및 그룹 변수 파일을 저장하면 ✔️변수값을 쉽게 구성할 수 있다. 호스트 및 그릅 변수 파일은 YAML 구문을 사용해야한다. 유효한 파일 확장자는 '.yml', '.yaml', '.json'이며 파일 확장자가 없는 경우도 가능하다. YAML을 처음 사용하는 경우 YAML 구문을 참조하라.
Ansible은 인벤토리 파일 또는 플레이북 파일과 관련된 경로를 검색하여 호스트 및 그룹 변수 파일을 로드한다. /etc/ansible/hosts
에 위치한 인벤토리 파일이 raleigh
과 webservers
라는 두 그룹에 속하는 foosball
이라는 호스트를 포함한 경우, 해당 호스트는 다음 위치에서 YAML 파일의 변수를 사용한다.
/etc/ansible/group_vars/raleigh #'.yml', '.yaml', '.json'를 붙이는 것은 옵션이다.
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
예를 들어, 인벤토리에서 호스트를 데이터 센터별로 그룹화하고 각 데이터 센터가 자체 NTP 서버 및 데이터베이스 서버를 사용한다면 raleigh
그룹의 변수를 저장하기 위해 /etc/ansible/group_vars/raleigh
파일을 생성하면 된다
---
ntp_server: acme.example.org
database_server: storage.example.org
그룹이나 호스트의 이름을 딴 디렉토리를 만들 수도 있다. Ansible은 이 디렉토리의 모든 파일을 사전 순서대로 읽는다. 'raleigh' 그룹의 경우 :
/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings
raleigh
그룹의 모든 호스트는 이 파일에 정의된 변수를 사용할 수 있다. 단일 파일이 너무 커지거나 일부 그룹변수에서 Ansible Vault를 사용하려는 경우, 변수를 체계적으로 유지하는데 매우 유용할 수 있다.
또한 플레이북 디렉토리를 위한 group_vars/
, host_vars/
를 추가할 수도 있다.
ansible-playbook
커멘드는 기본적으로 현재 작업 디렉토리에서 이러한 형태의 디렉토리를 찾는다.ansible
, ansible-console
등)은 인벤토리 디렉토리 내의 group_vars/
, host_vars/
디렉토리를 찾는다.--playbook-dir
옵션을 반드시 제공해야한다.인벤토리 파일과 변수를 gir repo(또는 다른 버전 관리)에 유지하면 인벤토리 및 호스트 변수의 변경 사항을 추적 할 수 있다.
기본적으로 변수는 play가 실행되기 전에 특정 호스트로 병합/평준화 된다. 이렇게 하면 Ansible이 Host 및 Task에 집중하게 되므로 그룹은 실제로 인벤토리와 호스트 매칭 밖에서는 존재할 수 없다.(This keeps Ansible focused on the Host and Task, so groups don’t really survive outside of inventory and host matching.)
기본적으로 Ansible은 그룹 and/or 호스트(DEFAULT_HASH_BEHAVIOUR 참조)에 정의된 변수를 포함해 변수를 덮어쓴다. 순서와 우선 순위는 다음과 같다 (낮은 순위부터 높은 순위) :
기본적으로 Ansible은
같은 레벨의 그룹을 병합하는 순서를 바꾸는 그룹 변수인 ansible_group_priority
를 셋팅함으로써 이 행동을 바꿀 수 있다. (부모/자식 순서가 해결된 후)
숫자가 클수록 나중에 병합된다. 즉, 우선순위가 높아진다. 이를 설정하지 않는 경우 이 변수의 기본값은 1
이다.
a_group:
testvar: a
ansible_group_priority: 10
b_group:
testvar: b
이 예에서 두 그룹의 우선 순위가 같으면 결과는 보통 testvar == b
이지만, a_group
이 우선 순위가 높으므로 결과는 testvar == a.
이다.
ansible_group_priority
변수는 group_var의 로딩시에 사용되므로group_vars/
가 아닌 인벤토리 소스에서만 설정할 수 있다.
커멘드 라인에서 멀티 인벤토리 매개 변수를 제공하거나 ANSIBLE_INVENTORY
를 구성하여 여러 인벤토리 소스(디렉토리, 동적 인벤토리 스크립트, 인벤토리 플러그인에서 지원하는 파일)를 동시에 타겟팅 할 수 있다. 이는 특정 작업에 대해 staging 또는 프로덕션과 같이 일반적으로 별도의 환경을 동시에 대상으로 하려는 경우 유용 할 수 있다.
다음과 같이 커멘드 라인에서 두 가지 소스를 대상으로 지정한다. :
ansible-playbook get_logs.yml -i staging -i production
인벤토리에 변수 충돌이 있는 경우 How variables are merged와 Variable precedence: Where should I put a variable?에 설명된 규칙에 따라 해결된다.
병합 순서는 인벤토리 소스 파라미터의 순서에 따라 제어된다. 만약 staging 인벤토리의 [all:vars]가 myvar = 1을 정의하고 프로덕션 인벤토리는 myvar = 2로 정의 돼있다면 플레이북은 myvar = 2로 실행된다. -i production -i staging.
로 선언했다면 결과는 반대이다.
📌커멘드를 쓰는 순서에 따라서 결과가 달라진다. → 앞부터 읽고 뒤에 나오는 파일이 동일한 값을 가지고 있으면 덮어쓴다.
✔️디렉토리를 사용한 인벤토리 소스 집계
디렉토리 아래에 여러 인벤토리 소스와 소스 유형을 결합하여 인벤토리를 생성 할 수도 있다. 이는 정적 및 동적 호스트를 결합하고 이를 하나의 인벤토리로 관리하는데 유용할 수 있다. 다음 인벤토리는 인벤토리 플러그인 소스, 동적 인벤토리 스크립트, 정적 호스트가 있는 파일을 결합한다.
inventory/
openstack.yml # OpenStack 클라우드에서 호스트를 가져 오도록 인벤토리 플러그인 구성
dynamic-inventory.py # 동적 인벤토리 스크립트로 추가 호스트 추가
static-inventory # 정적 호스트 및 그룹 추가
group_vars/
all.yml # 모든 호스트에 변수를 할당
이 인벤토리 디렉토리를 다음과 같이 간단하게 타겟팅 할 수 있다.
ansible-playbook example.yml -i inventory
다른 인벤토리 소스에 대한 다양한 충돌이나 하위 그룹으로써 종속성이 있는 경우 인벤토리 소스의 병합 순서를 제어하는 것이 유용할 수 있다.
📌파일 이름에 따라 인벤토리가 알파벳 순서로 병합되므로 파일에 접두사를 추가하여 결과를 제어 할 수 있다.
inventory/
01-openstack.yml # OpenStack 클라우드에서 호스트를 가져 오도록 인벤토리 플러그인 구성
02-dynamic-inventory.py # 동적 인벤토리 스크립트로 추가 호스트 추가
03-static-inventory # 정적 호스트 및 그룹 추가
group_vars/
all.yml # 모든 호스트에 변수를 할당
만약 01-openstack.yml
이 all
그룹에 대해 myvar = 1
을 정의하고, 02-dynamic-inventory.py
이 myvar = 2
, 03-static-inventory
이 myvar = 3
을 정의하고 있다면 플레이북은 myvar = 3
를 가지고 실행된다.
인벤토리 플러그인 및 동적 인벤토리 스크립트에 대한 자세한 내용은 Inventory Plugins and Working with dynamic inventory.를 참조하라
✔️호스트 연결 : 인벤토리 파라미터의 행동에 관하여
위에서 설명한대로 다음 변수를 설정하면 Ansible이 원격 호스트와 상호 작용하는 방식을 제어할 수 있다.
Ansible은 ssh 연결 플러그인(default)을 사용할 때 ssh 키를 해독하기 위해 사용자와 ssh 프로세스 간의 통신이 수동으로 비밀번호를 승인하도록 채널을 노출시키지 않는다.
ssh-agent
의 사용을 적극 권장한다.
✔️호스트 연결 :
ansible_connection
✔️모든 연결에 대한 일반 사항:
ansible_host : 연결하려는 호스트 이름과 다른 경우 연결할 호스트 이름
ansible_port : 기본값(ssh인 경우 22)이 아닌 경우 연결 포트 번호
ansible_user : 호스트에 연결할 때 사용할 사용자 이름
ansible_password : 호스트 인증에 사용하는 비밀번호 (이 변수는 일반 텍스트로 저장하지 말고 항상 볼트를 사용하도록 한다.📌)
✔️SSH 연결에만 해당하는 것:
ansible_ssh_private_key_file : ssh가 사용하는 개인 키파일, 여러 키를 사용하고 SSH 에이전트를 사용하지 않은려는 경우에 유용하다.
ansible_ssh_common_args : 이 설정은 항상 sftp, scp, ssh의 디폴트 커맨드 라인에 추가된다. 특정 호스트나 그룹을 위해 ProxyCommand
를 구성하는데 유용한다.
ansible_sftp_extra_args : 이 설정은 항상 sftp 커맨드 라인에 추가된다.
ansible_scp_extra_args : 이 설정은 항상 scp 커맨드 라인에 추가된다.
ansible_ssh_extra_args : 이 설정은 항상 ssh 커맨드 라인에 추가된다.
ansible_ssh_pipelining : SSH 파이프라이닝을 사용할지 여부를 결정한다. ansible.cfg.
내의 pipelining
설정을 덮어 쓸 수 있다.
ansible_ssh_executable (added in version 2.2) : 시스템 ssh를 사용하기 위한 기본 동작을 덮어쓴다. ansible.cfg.
내의 ssh_executable
설정을 덮어 쓸 수 있다.
2020.04.21 추가
✔️권한 확대 (자세한 내용은 Ansible Privilege Escalation 참조):
ansible_become
ansible_sudo
또는 ansible_su
와 동일하다. 권한 확대를 강제한다.
ansible_become_method
권한 확대 방법을 설정할 수 있다.
ansible_become_user
ansible_sudo_user
또는 ansible_su_user
와 동일하다. 권한을 확대시킬 사용자를 설정할 수 있다.
ansible_become_password
ansible_sudo_password
또는 ansible_su_password
와 동일하다. 권한 확대에 필요한 패스워드를 설정할 수 있다. (절대로 일반 텍스트 문서에 이 변수를 저장하면 안된다. 항상 Vault를 사용하도록 한다.)
ansible_become_exe
ansible_sudo_exe
또는 ansible_su_exe
와 동일하다. 사용자가 선택한 권한 확대 메소드에 대한 실행 파일을 설정할 수 있다.
ansible_become_flags
ansible_sudo_flags
또는 ansible_su_flags
와 동일하다. 선택한 권한 확대 메소드에 전달 될 플래그를 설정할 수 있다. sudo_flags
옵션의 ansible.cfg
에서 전역으로 설정 할 수도 있다.
✔️리모트 호스트 환경 파라미터:
ansible_shell_type
sh
-style 구문으로 형식이 지정된다.csh
또는 fish
로 설정하면 대상 시스템에서 실행된 커맨드가 sh
-style 대신 해당 쉘의 구문을 따른다.ansible_python_interpreter
ansible_*_interpreter
버전 2.1의 새로운 기능 :
ansible_shell_executable
ansible.cfg
의 실행 파일을 대체한다.Ansible-INI host file의 예시:
some_host ansible_port=2222 ansible_user=manager
aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
freebsd_host ansible_python_interpreter=/usr/local/bin/python
ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3
이전 섹션에서 언급했듯이 Ansible은 SSH를 통해 플레이북을 실행하지만 이 커넥션 유형으로 제한되지는 않는다. 호스트 특성 파라미터인 ansible_connection=<connector>
를 사용하면 커넥션 유형을 변경할 수 있다. non-SSH 기반 커넥터는 다음과 같다.
local
이 커넥터를 사용해 플레이북을 제어 시스템 자체에 배포 할 수 있다.
docker
이 커넥터는 로컬 Docker 클라이언트를 사용해 플레이북을 도커 컨테이너에 직접 배포한다. 다음의 매개 변수를 처리한다.
true
, become_user
로 설정하면 컨테이너 내에서 작동하는데 사용된다.생성된 컨테이너에 즉시 배포하는 방법의 예는 다음과 같다. :
- name: create jenkins container
docker_container:
docker_host: myserver.net:4243
name: my_jenkins
image: jenkins
- name: add container to inventory
add_host:
name: my_jenkins
ansible_connection: docker
ansible_docker_extra_args: "--tlsverify --tlscacert=/path/to/ca.pem --tlscert=/path/to/client-cert.pem --tlskey=/path/to/client-key.pem -H=tcp://myserver.net:4243"
ansible_user: jenkins
changed_when: false
- name: create directory for ssh keys
delegate_to: my_jenkins
file:
path: "/var/jenkins_home/.ssh/jupiter"
state: directory
사용 가능한 플러그인과 예제가 포함된 전체 목록은 플러그인 리스트를 참조하라.
처음부터 문서를 읽는 경우, 이는 Ansible 플레이북의 첫 번째 예제일 수 있다. 이것은 인벤토리 파일이 아니다. 플레이북은 나중에 자세히 다룰 것이다.
여러 환경을 관리해야하는 경우 인벤토리 별로 단일 환경의 호스트만 정의하는 것이 나은 경우가 있다. 예를 들어, 실제로 일부 "staging" 서버를 업데이트 하려고 할 때 "test" 환경 내의 노드 상태를 우연히 변경하기는 어렵다.
위의 예에서 inventory_test
파일 :
[dbservers]
db01.test.example.com
db02.test.example.com
[appservers]
app01.test.example.com
app02.test.example.com
app03.test.example.com
이 파일에는 "test" 환경의 일부인 호스트만 포함된다. 그리고 다음과 같은 다른 파일 inventory_staging
에 "staging" 시스템을 정리한다. :
[dbservers]
db01.staging.example.com
db02.staging.example.com
[appservers]
app01.staging.example.com
app02.staging.example.com
app03.staging.example.com
테스트 환경의 모든 앱 서버에 호출된 site.yml
플레이북을 적용하려면 다음 명령을 사용한다.
ansible-playbook -i inventory_test site.yml -l appservers
이전 섹션에서는 이미 동일한 기능을 가진 호스트를 클러스터링하기 위해 그룹을 사용하는 예를 보았다.
아래는 데이터베이스 서버에 영향을 주지 않고 플레이북 또는 role 내에서 방화벽 규칙을 정의하는 예이다 :
- hosts: dbservers
tasks:
- name: allow access from 10.0.0.1
iptables:
chain: INPUT
jump: ACCEPT
source: 10.0.0.1
다른 task를 특정 호스트의 위치에 중점을 둘 수 있다.
db01.test.example.com
와 app01.test.example.co
가 DC1
에 있고, db02.test.example.com
가 DC2
에 있는 경우 :
[dc1]
db01.test.example.com
app01.test.example.com
[dc2]
db02.test.example.com
실제로는 어떤 날에는 특정 데이터 센터의 모든 노드를 업데이트하고, 다른 날에는 위치에 관계없이 모든 애플리케이션 서버를 업데이트해야 한다면 이런 설정을 모두 혼합해 사용할 수도 있다.
📌플레이북 : ad-hoc
task 실행 모드와 Ansible을 사용하는 방법이 완전히 다르며 강력하다.
간단히 말해, 플레이북은 기존의 것과는 달리 복잡한 구성 관리 및 다중 시스템 배포 시스템을 위한 기초이며 복잡한 응용 프로그램을 배포하는데 매우 적합하다.
플레이북은 configuration을 선언 할 수 있는 것은 당연하고 또한 머신 셋 사이에 서로 다른 단계를 반복하면서 특정 순서를 지켜야하는 경우에도 수동 오더 프로세스의 단계를 조정할 수 있다. task를 동기식 또는 비동기식으로 시작할 수 있다.
✏️ad-hoc
task를 위한 메인 /usr/bin/ansible
프로그램을 실행할 수 있지만, 플레이북은 소스 제어 상태로 유지되어 configuration을 푸시하거나 원격 시스템의 구성이 사양에 맞는지 확인하는데 사용된다.
ansible-examples repository에 이러한 기술을 설명하는 전체 플레이북 세트로 있다. 계속 진행하면서 다른 탭에서 해당 항목을 살펴 보도록 하여라
플레이북은 YAML 형식으로 표현되며 최소한의 구문을 가진다. 의도적으로 프로그래밍 언어나 스크립트가 아닌 configuration 또는 프로세스의 모델이 된다.
일부 에디터에는 플레이북의 깔끔한 TAML구문을 작성하는데 도움이 되는 add-ons이 있다. 자세한 내용은 기타 도구 및 프로그램을 참조하라.
각 플레이북은 목록에서 하나 이상의 '플레이'로 구성된다.
'플레이'의 목표는 호스트 그룹을 잘 정의된 role에 매핑하는 것이다. 기본적으로 task는 단순히 Ansible 모듈을 호출하는 것이다.
여러 '플레이'의 플레이북을 구성하면
1. 웹 서버 그룹의 모든 컴퓨터에서 특정 단계를 실행한 다음
2. 데이터베이스 서버 그룹에서 특정 단계를 실행한 다음
3. 웹 서버 그룹에서 더 많은 명령을 실행
하는 등, 멀티 머신 배포를 조정할 수 있다.
'플레이'는 스포츠에 비유될 수 있다. 당신은 시스템에 영향을 끼침으로써 다른 일을 하는 많은 플레이가 가능하다. 하나의 특정 상태 또는 모델을 정의하는 것만이 아니라 다른 시간에 다른 플레이를 실행할 수 있다.
우선, 여기 verify-apache.yml
에는 한 번의 플레이만 포함된 플레이북이 있다. :
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service:
name: httpd
state: started
handlers:
- name: restart apache
service:
name: httpd
state: restarted
플레이북에는 여러 플레이가 포함될 수 있다. 먼저 웹 서버를 대상으로 한다음 데이터베이스 서버를 대상으로하는 플레이북이 있을 수 있다. :
---
- hosts: webservers #첫 번째 플레이
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
- hosts: databases #두 번째 플레이
remote_user: root
tasks:
- name: ensure postgresql is at the latest version
yum:
name: postgresql
state: latest
- name: ensure that postgresql is started
service:
name: postgresql
state: started
이 방법을 사용해 대상 호스트 그룹, 원격 서버에 로그인하는 사용자 이름, sudo 여부 등을 전환 할 수 있다. 플레이는 task 처럼 플레이북에 지정된 순서대로 실행된다.: 위에서 아래로
아래에는 플레이북 언어의 다양한 기능을 설명한다.
플레이북의 각 플레이에 대해 인프라에서 대상으로 지정할 머신과 단계(tasks)를 완료할 리모드 유저를 선택할 수 있다.
hosts
라인은 콜론으로 구분되는 하나 이상의 그룹 또는 호스트 패턴의 목록이다. (참조 : Patterns: targeting hosts and groups ) remote_user
는 단순히 사용자 계정의 이름이다.
---
- hosts: webservers
remote_user: root
remote_user
매개변수는user
로 불렸다. Ansible 1.4에서 유저 모듈(리모트 시스템에서 사용자를 만드는데 사용됨)과 구별되도록 이름이 변경되었다.
task 별로 리모트 유저를 정의할 수도 있다.
---
- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: yourname
✏️아래 예제들에 become
이 많이 사용되므로 잠깐 보고 넘어가도록 하겠다. 자세한 내용은 여기를 클릭하면 된다. 현재는 최소한의 이해를 돕기위한 정도만 해석하도록 하겠다.
play나 task 지시문, 커넥션 변수, 커멘드 라인에서 become
을 사용해 제어할 수 있다.
여러가지 방법으로 권한 확대 특성을 설정하는 경우 the general precedence rules를 검토하고 사용할 설정을 이해하라.
Ansible에 포함된 모든 플러그인의 전체 목록은 플러그인 목록에서 찾을 수 있다.
✏️Become 지시어
play나 task 수준에서 become
을 제어하기 위한 지시문을 설정할 수 있다. 호스트마다 다른 연결 변수를 설정하여 이를 대체 할 수 있다. 이러한 변수와 지시문은 독립적이다. 예를 들어 become_user
를 설정해도 become
이 설정되지 않는다.
become : yes
로 설정하면 권한 확대를 활성화한다.
become_user : 로그인할 때의 사용자가 아닌 원하는 권한을 가진 사용자로 설정한다.become:yes
를 의미하지 않는다-호스트 수준에서 설정 할 수 있게한다. 기본값은 root이다.
become_method : (play 또는 task 수준에서) the Become Plugins을 사용하기로 설정된 ansible.cfg
의 디폴트 메소드 설정을 덮어쓴다.
become_flags : (play 또는 task 수준에서) tasks나 role에 특정 플래그를 사용할 수 있다. 쉘이 로그인 없음으로 설정된 경우 일반적으로 사용자를 nobody로 변경하는 것으로 사용된다. Ansible2.2에 추가되었다.
예를 들어, non-root
유저로 연결됐을 때, root
권한이 요구되는 시스템 서비스를 관리하기 위해 become_user(root)
를 기본값으로 사용 할 수 있다.
- name: Ensure the httpd service is running
service:
name: httpd
state: started
become: yes
apache
유저로써 커맨드를 수행하는 경우 :
- name: Run a command as the apache user
command: somecommand
become: yes
become_user: apache
셀이 로그인 없음(nologin) 일 때, nobody
로 어떤 일을 하는 경우 :
- name: Run a command as nobody
command: somecommand
become: yes
become_method: su
become_user: nobody
become_flags: '-s /bin/sh'
Become connection varia
다른 유저로 작업을 실행할 수 있는 기능도 지원된다. (see Understanding privilege escalation: become):
---
- hosts: webservers
remote_user: yourname
become: yes
전체 플레이 대신 특정 task에 become
키워드를 사용할 수도 있다.
---
- hosts: webservers
remote_user: yourname
tasks:
- service:
name: nginx
state: started
become: yes
become_method: sudo
또한 로그인 한 다음 root가 아닌 다른 유저가 될 수도 있다.
---
- hosts: webservers
remote_user: yourname
become: yes
become_user: postgres
su와 같은 다른 권한 확대 방법을 사용 할 수도 있다.
---
- hosts: webservers
remote_user: yourname
become: yes
become_method: su
sudo를 위한 암호를 지정해야하는 경우 ansible-playbook
을 --ask-become-pass
또는 -K
와 함께 실행하도록 하여라.
만약 become
을 활용해 플레이북을 실행하고 플레이북이 정지(hang) 된 것처럼 보이면, 이는 권한 확대 프롬프트에서 멈췄을 수도 있다. 이는 Control-C 를 사용하여 중지 할 수 있으며, 적절한 비밀번호를 추가하여 플레이북을 다시 실행할 수 있다.
✏️권한 확대
권한 확대 (privilege escalation)는 보통 애플리케이션이나 사용자에 대해 보호되는 자원들에 대한 상승된 접근을 얻기 위해서 운영체제나 소프트웨어 애플리케이션에서 버그나 설계결함, 또는 설정을 익스플로잇하는 행동을 말한다. 이것에 의한 결과는 애플리케이션이 개발자나 시스템 관리자가 의도한 것보다 높은 수준의 권한을 얻어서 비허가 행동을 할 수 있게 된다.
❗️중요❗️
become_user
를 root 이외의 사용자에게 사용하는 경우, 모듈 argument는/tmp
의 임시 파일에 간단히 기록된다. 이는 'bob'에서 'root'로 이동하거나 'bob' 또는 'root'로 직접 로그인 할 때가 아니라 'bob'과 같은 사용자의 권한을 'timmy'로 변경하는 경우에만 발생한다. 이 데이터가 간단하게 읽힐 수 있는(쓰기는 불가능하다) 것이 우려된다면 암호화되지 않은 비밀번호(with become_user set)를 전송하면 안된다. 다른 경우에서/tmp
는 사용되지 않으며 play에 들어가지 않는다. 또한 Ansible은 비밀번호 파라미터를 로그하지 않도록 주의하고 있다.
new in version 2.4.
호스트가 실행되는 순서를 제어 할 수도 있다. 디폴트 값은 인벤토리에서 제공한 오더를 따르는 것이다.
- hosts: all
order: sorted
gather_facts: False
tasks:
- debug:
var: inventory_hostname
order에 설정 가능한 값은 다음과 같다:
value | description |
---|---|
inventroy | (default) 인벤토리에 의해 '제공된대로' 정렬 |
reverse_inventory | 인벤토리에서 '제공한' 순서의 반대로 정렬 |
sorted | 이름-알파벳 순으로 정렬 |
reverse_sorted | 이름-알파벳 역순으로 정렬 |
shuffle | 매번 무작위로 정렬 |
각 플레이에는 task 목록이 포함되어 있다. 📌다음 작업으로 넘어가기 전에 호스트 패턴과 일치하는 모든 시스템에 대해 task가 한 번에 하나씩 순서대로 실행된다. 플레이에서 모든 호스트는 동일한 task 지시문을 가져야함을 이해하는 것이 중요하다. 선택된 호스트를 task에 매핑하는 것이 플레이의 목적이다.❗️
위에서 아래로 실행되는 플레이북을 실행할 시 실패한 task가 있는 호스트는 전체 플레이북의 로테이션에서 제외된다. 즉, task에 실패하면 플레이북 파일을 수정하고 재실행해야한다.
각 task의 목표는 매우 구체적인 파라미터로 모듈을 실행하는 것이다.
변수는 모듈에 대한 파라미터로 사용될 수 있다.
모듈은 멱등성이 있어야한다. 즉, 순서대로 모듈을 여러번 실행하면 한 번만 실행하는 것과 같은 효과가 있다.
멱등성 (idempotent)
멱등법칙(冪等法則) 또는 멱등성(冪等性, 영어: idempotent)은 수학이나 전산학에서 연산의 한 성질을 나타내는 것으로, 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다.
멱등원을 달성하는 한 가지 방법은 모듈이 원하는 최종 상태가 이미 달성되었는지 확인하고 해당 상태가 달성된 경우 어떤 액션도 취하지 않고 종료하는 것이다. 플레이북을 사용하는 모든 모듈이 멱등원인 경우, 플레이북 자체는 멱등원인 가능성이 있으므로 플레이북을 재실행하는 것이 안전해야할 것이다.
command가 chmod
또는 setsebool
등과 같은 경우에 이는 정상이며, command와 shell 모듈은 같은 command로 재실행된다. 비록 모듈들을 멱등원으로 만드는데 사용하기 위한 create
플래그가 있음에도 말이다.
모든 task는 플레이북 실행 결과를 포함하는 name
을 가진다. 이것은 사람이 읽을 수 있는 출력인데, 각 task 단계에 대한 설명이므로 적절히 선정하는 것이 좋다. name이 제공되지 않으면 action
의 값이 출력에 사용된다.
레거시 action: module options
형식을 사용하여 작업을 선언 할 수 있지만 보다 일반적인 형식인 module: options
을 사용하는 것이 좋다. 이러한 권장 형식은 도큐먼트 전체에서 사용되지만 일부 플레이북에는 이전 형식이 나타날 수 있다.
기본 task는 다음과 같다. 대부분의 모듈과 마찬가지로 서비스 모듈은 다음과 같은 key=value
argument를 사용한다.
tasks:
- name: make sure apache is running
service:
name: httpd
state: started
command
와 shell
모듈은 key=value
형식을 사용하는 대신 argument 목록을 가져오는 유일한 모듈이다.
tasks:
- name: enable selinux
command: /sbin/setenforce 1
command
와 shell
모듈은 리턴코드에 관해 관리하므로 성공적인 종료 코드가 0이 아닌 command를 가진다면 다음과 같이 수행할 수 있다.
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
혹은
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
액션 라인이 너무 길어 가독성에 좋지않다면, 이를 끊고 연속 라인으로 들어쓰기가 가능하다.
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
액션 라인에서 변수를 사용할 수 있다. vars
섹션에서 vhost
라 불리는 변수를 정의했다고 가정한다면 다음처럼 수행할 수 있다.
tasks:
- name: create a virtual host file for {{ vhost }}
template:
src: somefile.j2
dest: /etc/httpd/conf.d/{{ vhost }}
동일한 변수를 템플릿에서 사용 가능한데, 이는 나중에 자세히 살펴보도록한다.
이제 매우 기본적인 플레이북에서 모든 task가 해당 플레이에 직접 나열될 것이다. 하지만 재사용 가능한 플레이북 만들기에 설명 된대로 작업을 분리하는 것이 더 합리적이다.
New in version 0.8.
Ansible은 다음과 같은 모듈 나열을 선호한다.
template:
src: templates/foo.j2
dest: /etc/foo.conf
Ansible 초기 버전은 다음 형식을 사용했으며, 여전히 작동한다.
action: template src=templates/foo.j2 dest=/etc/foo.conf
앞에서 언급했듯이 모듈은 멱등원이어야하며 리모트 시스템에서 변경했을 때 relay 할 수 있다. 플레이북은 이를 인식하고 변화에 대응하는데 사용 가능한 기본 이벤트 시스템을 가지고 있다.
이러한 'notify' 액션은 플레이의 각 task 블록의 끝에서 트리거되며 여러 다른 작업에서 알림을 받았더라도 한 번만 트리거된다.
예를 들어, 여러 resource가 configuration 파일을 변경했기 때문에 아파치를 다시 시작해야 함을 나타낼 수 있지만, 불필요한 재시작을 피하기 위해 아파치는 한 번만 바운스된다.
파일 내용이 변경 될 때 두 서비스를 재시작하는 예는 다음과 같다.(오로지 파일 변경시에만):
- name: template configuration file
template:
src: template.j2
dest: /etc/foo.conf
notify: #변화 감지해서 아래 핸들러 실행
- restart memcached
- restart apache
task의 notify
에 나열된 것을 핸들러라고 부른다.
핸들러는 일반적으로 인반 task와 다르지 않은 task 목록으로, 전역으로 고유한 이름으로 참조되고 nofitier에 의해 알려진다. 핸들러에 아무것도 알리지 않으면 이는 실행되지 않는다. 핸들러에 알려진 작업 수에 관계없이 특정 작업에서 모든 작업이 완료된 후 한 번만 실행된다.
핸들러 섹션의 예는 다음과 같다.
handlers:
- name: restart memcached #nofity에서 변화를 감지해 알려줄 핸들러의 이름
service:
name: memcached
state: restarted
- name: restart apache
service:
name: apache
state: restarted
Ansible 핸들러가 변수를 사용하도록 할 수 있다. 예를 들어, 서비스 이름이 배포에 따라 약간 다른 경우 출력에 각 대상 시스템에 대해 재시작된 서비스의 정확한 이름이 표시되게하려고 한다. 핸들러 이름에 변수를 배치해선 안된다. 핸들러 이름은 초기에 템플릿화되므로 Ansible은 다음과 같이 핸들러 이름에 사용할 수 있는 값을 가지고 있지 않을 수도 있다.
handlers:
# this handler name may cause your play to fail!
- name: restart "{{ web_service_name }}"
핸들러 이름에 사용된 변수를 사용할 수 없으면 전체 플레이가 실패한다. 플레이가 수행되던 중에 변수가 변경된다해도 새로 생성된 핸들러는 생성되지 않는다.
📌대신 핸들러의 task 파라미터에 변수를 배치하도록 한다. 다음 예제에서의 include_vars
와 같이 사용해 값을 로드 할 수 있다.
tasks:
- name: Set host variables based on distribution
include_vars: "{{ ansible_facts.distribution }}.yml"
handlers:
- name: restart web service
service:
name: "{{ web_service_name | default('httpd') }}"
state: restarted
Ansible 2.2부터 핸들러는 generic topics를 수신(listen)할 수 있으며 task는 다음과 같이 해당 topic에 알릴 수 있다.
handlers:
- name: restart memcached
service:
name: memcached
state: restarted
listen: "restart web services" # 아래 notify와 동일 → 수신
- name: restart apache
service:
name: apache
state: restarted
listen: "restart web services" # 아래 notify와 동일 → 수신
tasks:
- name: restart everything
command: echo "this task will restart the web services"
notify: "restart web services" # 변경 시 알릴 것
이렇게하면 여러 핸들러를 보다 쉽게 트리거 할 수 있다. 또한 핸들러를 자신의 이름에서 분리함으로써 플레이북과 역할(특히 Galaxy와 같은 공유 소스에서 3rd party roles를 사용하는 경우)간에 핸들러를 쉽게 공유 할 수 있다.
- notify 핸들러는
notify-statament
에 나열된 순서가 아닌 정의된 순서대로 실행된다. listen이 사용되는 경우에도 마찬가지이다.- 핸들러의 이름과 listen topic은 전역 네임스페이스에 존재한다.
- 핸들러의 이름은 템플릿화(templatable) 가능하나 listen topics은 그렇지 않다.
- 고유한 핸들러 이름을 사용하라. 이름이 같은 핸들러를 두 개 이상 트리거하면 첫 번째 핸들러를 (뒤의 것이) 덮어 쓴다. 즉, 마지막으로 정의 된 것만 실행된다.
include
내부에 정의된 핸들러에 통지(notify)하는 것은 불가능하다. Ansible 2.1부터는 작동하지만include
는 정적이여야한다.
role은 나중에 설명하지만 다음을 짚어보는 것이 좋다.
pre_tasks
, tasks
, post_tasks
섹션에 notify된 핸들러는 notify된 섹션의 끝에서 자동으로 플러시된다.roles
섹션 내에서 notify된 핸들러는 tasks
종료 섹션에서 자동으로 플러시되지만 tasks
핸들러보다 우선된다.모든 핸들러 명령을 즉시 플러시하려면 다음을 수행하라:
tasks:
- shell: some tasks go here
- meta: flush_handlers
- shell: some other tasks
위의 예에서 대기중인 모든 핸들러는 meta
명령문에 도달하기 전에 처리된다. 이것은 별로 없는 사례이지만 때때로 유용할 수 있다.
플레이북 구문을 배웠으므로 플레이북을 실행해본다. 간단하게 병렬 레벨 10을 사용해 플레이북을 실행하도록 하겠다.
ansible-playbook playbook.yml -f 10
Ansible 아키텍처를 뒤집기 원한다면 노드가 구성을 푸시하지 않고 중앙에서 체크인하도록 할 수 있다.
ansible-pull
은 git에서 configuration 명령의 저장소를 확인한 다음 해당 내용에 대해 ansible-playbook
을 실행하는 스크립트이다.
체크아웃 위치를 로드 밸런싱한다고 가정하면, ansible-pull
스케일은 기본적으로 무한대로 확장된다.
자세한 내용은 ansible-pull --help
를 실행해라.
push
모드의 crontab
을 통해 ansible-pull
을 구성 할 수 있는 영리한 플레이북도 존재한다.
ansible-lint를 사용하여 플레이북을 실행하기 전에 세부 사항을 확인 시킬 수 있다.
예를 들어, 이 섹션의 앞부분에서 소개한 verify-apache.yml playbook에서 ansible-lint
를 실행하면 다음과 같은 결과가 나타난다.
$ ansible-lint verify-apache.yml
[403] Package installs should not use latest
verify-apache.yml:8
Task/Handler: ensure apache is at the latest version
The ansible-lint default rules page는 각 오류에 대해 설명한다. [403]
에 대한 권장 수정 사항을 플레이북안에서 state: latest
를 state: present
로 변경하는 것이다.
플레이북을 확인하는데 사용할 수 있는 자세한 도구 목록은 플레이북 유효성 검사 도구를 참조하라. 고려해야할 다른 것들은 아래와 같다.
--syntax-check
플래그를 ansible-playbook
와 함께 사용해라. 포함된 파일, role 등에 구문 오류가 없는지 확인하기 위해 parser를 통해 플레이북 파일을 실행한다.--verbose
플래그를 사용해라. Ansible 0.5 이상에서 사용할 수 있다.ansible-playbook playbook.yml --list-hosts
New in version 1.2.
Role은 알려진 파일 구조에 따라 특정 vars_files, tasks, 핸들러를 자동으로 로드하는 방법이다. Role에 따라 컨텐츠를 그룹화하면 다른 사용자와 role을 쉽게 공유 할 수 있다.
프로젝트 구조 예 :
site.yml
webservers.yml
fooservers.yml
roles/
common/
tasks/
handlers/
files/
templates/
vars/
defaults/
meta/
webservers/
tasks/
defaults/
meta/
Role은 파일이 특정 디렉토리 이름에 들어있을 것이라고 예상한다. Role은 이러한 디렉토리 중 하나 이상이 포함되어야하지만 사용되지 않는 디렉토리는 제외해도 된다. 사용중인 각 디렉토리는 관련 컨텐츠를 가지고 있는 main.yml
파일을 반드시 포함해야한다.:
다른 YAML 파일이 특정 디렉토리에 포함될 수 있다. 예를 들어, tasks/main.yml
파일에 플랫폼 별 작업을 포함시키는 것이 일반적이다.
# roles/example/tasks/main.yml
- name: added in 2.4, previously you used 'include'
import_tasks: redhat.yml
when: ansible_facts['os_family']|lower == 'redhat'
- import_tasks: debian.yml
when: ansible_facts['os_family']|lower == 'debian'
# roles/example/tasks/redhat.yml
- yum:
name: "httpd"
state: present
# roles/example/tasks/debian.yml
- apt:
name: "apache2"
state: present
role에는 모듈 및 기타 플러그인이 포함될 수도 있다. 자세한 내용은 아래의 Embedding Modules and Plugins In Roles 섹션을 참조하라.
role을 사용하는 고정적인 (오리지날) 방법은 주어진 플레이에 roles:
옵션을 사용하는 것이다.
---
- hosts: webservers
roles:
- common
- webservers
각 role 'x'에 대해 다음 동작을 지정한다.
이런 방식이 사용되는 경우 플레이북의 실행 순서는 다음과 같다.
1. play에 정의된 pre_task
2. 지금까지 트리거된 모든 핸들러가 실행된다.
3. roles
에 나열된 각각의 role이 차례로 실행된다. roles
의 meta/main.yml에 정의된 모든 role 종속성이 태크 필터링 및 조건에 따라 먼저 실행된다.
4. play에 정의된 tasks
5. 지금까지 트리거된 모든 핸들러가 실행된다.
6. play에 정의된 post_tasks
7. 지금까지 트리거된 모든 핸들러가 실행된다.
role 종속성에 대한 자세한 내용은 아래를 참조하라
task가 포함된 태그를 사용하는 경우 (나중에 플레이북의 일부만 실행하는 수단으로 설명한다.) pre_tasks, post_tasks, role 종속성이 중단창(outage window) 제어나 로드 밸런싱을 모니터링하는데 사용되는 경우 pre_tasks, post_tasks, role 종속성에 태그를 지정하고 이를 전달하라.
Ansible 2.4부터 import_role
이나 include_role
을 사용해 다른 task와 함께 인라인 role로 사용할 수 있다. (As of Ansible 2.4, you can now use roles inline with any other tasks using import_role or include_role:)
---
- hosts: webservers
tasks:
- debug:
msg: "before we run our role"
- import_role:
name: example
- include_role:
name: example
- debug:
msg: "after we ran our role"
role이 이전 방식으로 정의되면 정적 import로 처리되고 플레이북 구문 분석 중에 처리된다.
이
include_role
옵션은 Ansible 2.3.에서 도입되었다. include (동적) vs. import (정적) 사용방식에 따라 사용법이 Ansible 2.4에서 약간 변경되었다. 자세한 내용은 Dynamic vs. Static을 참조해라
role에 사용되는 이름은 간단한 이름이거나 (아래의 Role Search Path 참조) 정규화 된 경로 일 수 있다.
---
- hosts: webservers
roles:
- role: '/path/to/my/roles/common'
role은 다른 키워드를 허용할 수 있다.
---
- hosts: webservers
roles:
- common
- role: foo_app_instance
vars:
dir: '/opt/a'
app_port: 5000
- role: foo_app_instance
vars:
dir: '/opt/b'
app_port: 5001
최신 구문을 사용할 경우 :
---
- hosts: webservers
tasks:
- include_role:
name: foo_app_instance
vars:
dir: '/opt/a'
app_port: 5000
...
조건부로 role을 가져와 해당 작업을 실행할 수 있다.
---
- hosts: webservers
tasks:
- include_role:
name: some_role
when: "ansible_facts['os_family'] == 'RedHat'"
마지막으로, 지정한 role 내의 task에 태그를 할당 할 수 있다.
---
- hosts: webservers
roles:
- role: foo
tags:
- bar
- baz
# YAML 구문을 이용해 다음과 같이 표현도 가능하다.
- { role: foo, tags: ["bar", "baz"] }
최신 구문으로 작성할 경우:
---
- hosts: webservers
tasks:
- import_role:
name: foo
tags:
- bar
- baz
해당 태그는 지정된 태그로 해당 role의 모든 task에 태그를 지정하여, role 내부에 지정된 tag에 추가한다.
반면에 role 자체의 import에 태그를 지정하고 싶은 경우에는 다음처럼 작성한다. :
---
- hosts: webservers
tasks:
- include_role:
name: bar
tags:
- foo
이 예제의 태그는
include_role
내부의 task에 추가되지 않는다. 둘 다 수행하기 위해서block
지시문을 사용할 수 있다.
실행할 태그의 하위 셋을 지정하는 동안 role을 import하는 기능이 없다. 많은 태그가 있는 role을 만들고 다른 시간에 role의 하위 셋을 호출하려는 경우, 해당 role을 여러 role로 분할하는 것을 고려해야한다.
2020.04.22 추가
Ansible은 role에 정의된 파라미터가 각 정의마다 다르지 않은 경우에는 여러번 정의 된 경우에도 role을 한 번만 실행할 수 있다. 예를 들면 다음과 같다.
---
- hosts: webservers
roles:
- foo
- foo
위의 경우 role foo
는 한 번만 실행된다.
role을 여러번 실행하려면 두 가지 옵션이 있다.
1. 각 role 정의에서 다른 매개 변수를 전달한다.
2. allow_duplicates: true
를 role의 meta/main.yml
파일에 추가한다.
예1 - 다른 매개 변수 전달:
---
- hosts: webservers
roles:
- role: foo
vars:
message: "first" # 같은 role인 foo이지만, message 파라미터가 다르다
- { role: foo, vars: { message: "second" } }
이 예에서 각 role 정의에 서로 다른 파라미터를 가지므로 foo
는 두 번 실행된다.
예2 - allow_duplicates: true
사용:
# playbook.yml
---
- hosts: webservers
roles:
- foo
- foo
# roles/foo/meta/main.yml
---
allow_duplicates: true
이 예에서는 명시적으로 중복을 허용했으므로 foo
가 두 번 실행된다.
New in version 1.3.
role의 디폴트 변수를 사용하면 포함되거나 종속된 role에 대한 디폴트 변수를 설정할 수 있다.(아래 참조) 디폴트 값을 작성하려면 defaults/main.yml
파일을 role 디렉토리에 추가한다. 이 변수들은 사용 가능한 모든 변수 중 우선 순위가 가장 낮으며 인벤토리 변수를 포함한 다른 변수로 쉽게 재정의 가능하다.
New in version 1.3.
role 종속성을 사용하면 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
role 종속성은 이전의 role 정의 방식을 사용해야한다.
role 종속성은 이를 포함하는 role보다 항상 앞에서 실행되며 재귀적일 수 있다. 종속성의 위에 지정된 복제 규칙(동일한 role은 한 번만 수행)을 따른다. 다른 role도 종속적이게 나열한다면 이는 위에 제공된 것과 동일한 규칙을 기반으로 하므로 재실행되지 않는다. 자세한 내용은 Galaxy 역할 종속성을 참조하라.
allow_duplicates: true
를 사용할 때, 이는 항상 부모가 아닌 종속된 role의meta/main.yml
에 있어야한다.
예를들어 car
라는 role은 wheel
이라는 role에 종속성을 다음과 같이 가지고 있을 때 이는 각각 다르다:
---
dependencies:
- role: wheel
vars:
n: 1
- role: wheel
vars:
n: 2
- role: wheel
vars:
n: 3
- role: wheel
vars:
n: 4
그리고 wheel
은 tire
와 brake
라는 두 가지 role에 종속된다. 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
wheel
은 각각 다른 파라미터 값을 가지고 있으므로 allow_duplicates: true
를 사용할 필요는 없다.
변수 상속 및 범위는 변수 사용에 자세히 설명되어있다.
이는 대부분의 사용자와 관련이 없는 고급 주제이다.
This is an advanced topic that should not be relevant for most users.
If you write a custom module (see Should you develop a module?) or a plugin (see Developing plugins), you may wish to distribute it as part of a role. Generally speaking, Ansible as a project is very interested in taking high-quality modules into ansible core for inclusion, so this shouldn’t be the norm, but it’s quite easy to do.
A good example for this is if you worked at a company called AcmeWidgets, and wrote an internal module that helped configure your internal software, and you wanted other people in your organization to easily use this module – but you didn’t want to tell everyone how to configure their Ansible library path.
Alongside the ‘tasks’ and ‘handlers’ structure of a role, add a directory named ‘library’. In this ‘library’ directory, then include the module directly inside of it.
Assuming you had this:
roles/
my_custom_modules/
library/
module1
module2
The module will be usable in the role itself, as well as any roles that are called after this role, as follows:
---
- hosts: webservers
roles:
- my_custom_modules
- some_other_role_using_my_custom_modules
- yet_another_role_using_my_custom_modules
This can also be used, with some limitations, to modify modules in Ansible’s core distribution, such as to use development versions of modules before they are released in production releases. This is not always advisable as API signatures may change in core components, however, and is not always guaranteed to work. It can be a handy way of carrying a patch against a core module, however, should you have good reason for this. Naturally the project prefers that contributions be directed back to github whenever possible via a pull request.
The same mechanism can be used to embed and distribute plugins in a role, using the same schema. For example, for a filter plugin:
roles/
my_custom_filter/
filter_plugins
filter1
filter2
They can then be used in a template or a jinja template in any role called after ‘my_custom_filter’
Ansible은 다음과 같은 방식으로 role을 검색한다.
1. 플레이북 파일에 상대 경로인 roles/
디렉토리
2. 디폴트는 /etc/ansible/roles
Ansible 1.4 이상에서는 role을 검색하기 위한 추가적인 roles_path
를 구성 할 수 있다. 이를 사용해 모든 공통 role을 한 위치에서 확인하고 여러 플레이북 프로젝트 간에 쉽게 공유 할 수 있다. ansible.cfg
에서 이를 설정하는 방법에 대한 자세한 내용은 Configuring Ansible를 참조하라.
Ansible Galaxy는 모든 종류의 커뮤니티가 개발한 Ansible role을 찾고, 다운로드하고, 평가하고, 검토할 수 있는 무료 사이트이다. 이는 자동화 프로젝트를 시작하는 좋은 방법이 될 수 있다.
클라이언트 ansible-galaxy는 Ansible에 포함되어 있다. galaxy 클라이언트는 'Ansible Galaxy'에서 role을 다운로드 받을 수 있게 해주며, 또한 자신만의 role을 만들기 위한 훌륭한 기본 프레임워크를 제공한다.