안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 Ansible 의 플레북에 대한 이야기를 해보려고 합니다. 필자가 속한 프로젝트에서는 Ansible을 주로 다수의 서버의 configuration 을 수정할 때 사용하고 있습니다. 즉, 1개의 master 파일을 수정하고 각 서버의 경로에 해당 파일로 copy 해주는 단순한 구조입니다.
필자가 있는 프로젝트에서는 다음과 같이 사용합니다 .
nginx conf 파일 변경
nginx map 파일 변경
nginx location 파일 변경
다음시간에 nginx conf 구조에 대해서 설명을 하겠지만, 우선 ansible의 가장 효과적인 부분이 다수의 host에서 작업이 가능한 것입니다.
플레이북을 매우 큰 하나의 파일로 작성하는 것도 가능하지만 (초기에 플레이북을 배우면서는 이렇게 하기도 합니다) 점차 플레이북을 재사용하거나 계층적으로 관리할 필요도 생깁니다.
1. Ansible include
만약 플레이북의 플레이에 있는 일련의 태스크를 재사용한다고 가정해봅니다. include 를 이용하여 이 작업을 하면 됩니다. 가져온 태스크 목록은 특정 역할(role)을 수행하기에 알맞습니다. 다시한번 강조하면 플레이북은 관리 대상 시스템 그룹에 다양한 역할을 매핑하는 작업입니다.
---
# possibly saved as tasks/foo.yml
- name: placeholder foo
command: /bin/foo
- name: placeholder bar
command: /bin/bar
tasks:
- include: tasks/foo.yml
분명 위와 아래는 확연히 달라집니다. 같은 내용이더라도, 파일을 include하는 구조가 훨씬 간단해 보입니다.
include 할 때 변수도 포함해서 가져올 수 있습니다. (parameterized include 라고 합니다)
include에 작접 패러미터를 전달하던 아니면 vars를 이용하던 상관없습니다.
include 되는 파일에서는
{{ wp_user }}
여러개의 하위 플레이북도 include 가 가능합니다.
- name: this is a play at the top level of a file
hosts: all
remote_user: root
tasks:
- name: say hi
tags: foo
shell: echo "hi..."
- include: load_balancers.yml
- include: webservers.yml
- include: dbservers.yml
2. Ansible Role
버전 1.2 이후
태스크와 핸들러에 관하여 알았으므로 이제는 플레이북을 어떻게 잘 구성하는가를 알아낼 차례입니다. Role을 이용 하면 됩니다. Role은 파일 구조에 따라 vars_files, tasks 와 핸들러 등을 자동으로 로딩하는 것입니다.
처음에 필자는 Role이라는 것 자체가 계정과 역할 이런것일줄 알았는데, 말그대로 어떤 업무 수행단위를 하는지를 Component화 해서 재사용할 수 있도록 하는것으로 보면 될 것 같습니다.
다음과 같은 프로젝트 구조가 되어 있다고 합시다.
/etc/ansible 경로에 playbook_docker_test.yml 파일을 생성한뒤, playbook을 실행합니다.
ansible-playbook playbook_docker_test.yml
- hosts: test
roles:
- geerlingguy.docker
실행결과 해석
PLAY [test] ************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : include_tasks] *****************************************************************************************************************************************************************************************
included: /etc/ansible/roles/geerlingguy.docker/tasks/setup-RedHat.yml for https_ids_a01
TASK [geerlingguy.docker : Ensure old versions of Docker are not installed.] ******************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : Add Docker GPG key.] ***********************************************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : Add Docker repository.] ********************************************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : Configure Docker Edge repo.] ***************************************************************************************************************************************************************************
[WARNING]: The value 0 (type int) in a string field was converted to u'0' (type string). If this does not look like what you expect, quote the entire value to ensure it does not change.
ok: [https_ids_a01]
TASK [geerlingguy.docker : Configure Docker Test repo.] ***************************************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : include_tasks] *****************************************************************************************************************************************************************************************
skipping: [https_ids_a01]
TASK [geerlingguy.docker : install the container-selinux rpm from a remote repo] **************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : Install Docker.] ***************************************************************************************************************************************************************************************
changed: [https_ids_a01]
TASK [geerlingguy.docker : Ensure containerd service dir exists.] **************************************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : Add shim to ensure Docker can start in all environments.] *******************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : Reload systemd daemon if template is changed.] ******************************************************************************************************************************************************************
skipping: [https_ids_a01]
TASK [geerlingguy.docker : Ensure Docker is started and enabled at boot.] ******************************************************************************************************************************************************************
changed: [https_ids_a01]
RUNNING HANDLER [geerlingguy.docker : restart docker] **************************************************************************************************************************************************************************************
changed: [https_ids_a01]
TASK [geerlingguy.docker : include_tasks] **************************************************************************************************************************************************************************************************
included: /etc/ansible/roles/geerlingguy.docker/tasks/docker-compose.yml for https_ids_a01
TASK [geerlingguy.docker : Check current docker-compose version.] **************************************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : Delete existing docker-compose version if it's different.] ******************************************************************************************************************************************************
skipping: [https_ids_a01]
TASK [geerlingguy.docker : Install Docker Compose (if configured).] ************************************************************************************************************************************************************************
ok: [https_ids_a01]
TASK [geerlingguy.docker : include_tasks] **************************************************************************************************************************************************************************************************
[DEPRECATION WARNING]: evaluating [] as a bare variable, this behaviour will go away and you might need to add |bool to the expression in the future. Also see CONDITIONAL_BARE_VARS configuration toggle.. This feature will be removed in
version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
skipping: [https_ids_a01]
PLAY RECAP *********************************************************************************************************************************************************************************************************************************
https_ids_a01 : ok=16 changed=3 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
제일 먼저, 위의 플레이북 실행 결과를 보면, task/main.yml이 실행 됩니다.
setup-RedHat.yml
도커 설치
docker-1809-shim.yml
도커 정상시작 체크
도커 방화벽 충돌체크
docker-compose.yml
docker-users.yml
Task의 구조는 위와 같고, 각 yml 파일들이 include되면서 수행이 됩니다.
4. 필자 Ansible 사용예시
포스트 서두에 말씀드렸듯이, 필자가 사용하는 방법은 nginx configuration 파일들에 대해서 변경해주고 재시작해주는 방식으로 사용하고 있습니다. 여기서 변경할때는 copy를 하게 되는데 nginx의 멱등성에 의거하여 변경점이 없으면, 업데이트를 안하게 됩니다.
두 개의 파일로 분할해 두었는데, role 로 task를 쪼개고 하나의 job으로 만드는 것도 좋을 것 같습니다.
5. 마치며..
오늘은 ansible의 role과 include에 대해서 알아봤습니다. ansible을 필자도 사용은 하지만, 아주 기초적인 수준으로 사용하고 있었다라는 것을 느꼈습니다. 이번기회에 role관리를 좀더 잘해보고, 특히 ansible-galaxy를 통해서 수준높은 role 관리에 대해서 학습을 좀 더 해보도록 하겠습니다.
다음 시간에는 ansible jinja2 에 대해서 알아보는 시간을 갖도록 하겠습니다.
워니즈 블로그워니즈 깃헙