맘가는 대로
Ansible 을 통해 파일 작성하기 본문
Ansible, 그리고 파일
파일 모듈, 그리고 활용
앤서블에서 파일 관련으로 대표적인 모듈들을 확인하고 직접 사용해본다.
앤서블 공식 문서 페이지에서는 감사하게도 모듈들에 대한 목록들을 잘 정렬해 두었는데, 출처에서 간단하게 확인할 수 있을 것이다.
- 간단히 복사하자, copy 모듈
/vagrant/test.txt 경로에 위와 같은 메시지를 입력하였다.
이제 파일을 복사하고 파일의 내용을 읽을 수 있도록 플레이북을 작성한다. 물론, 앤서블을 사용하기 때문에 이제 대상 노드로 직접 가서 무언가를 하지는 않을 것이기 때문에 파일을 읽는 것도 플레이북을 통해서 한다.
---
- hosts: all
become: true
tasks:
- name: Copy file from ansible node to test node
copy:
src: /vagrant/test.txt
dest: /tmp/test.txt
owner: vagrant
group: vagrant
mode: '0644'
- name: Read /tmp/test.txt
debug: var=item
with_file:
- /tmp/test.txt
위의 tasks 항목을 보면 바로 copy 모듈을 사용하는 것을 알 수 있다. src 는 앤서블이 작동하는 로컬호스트의 파일 경로를 의미하며, dest 는 대상 노드의 파일 경로를 의미한다. owner, group, mode 는 대상 노드로 복사된 파일의 권한을 지정해주는 것이다.
바로 다음의 모듈은 debug 인데, 변수나 파일 등의 내용을 표시해주거나 원하는 메시지를 표시하기 위해 사용된다. 여기서는 파일의 내용을 읽기 위해 사용되었다.
바로 사용해보자.
실행 결과를 쉘을 통해 표시해주었다.
차근차근 보면 처음 표시된 PLAY [all] 은모든 노드에서 실행하는 것을 의미한다.
TASK [Gathering Facts] 는 기본적으로 앤서블에서 대상 노드들에 대한 정보를 얻는 것을 의미한다. 나중에 설명하겠지만, 노드가 많아질수록 이렇게 노드 정보를 얻는 것만으로도 시간이 걸리기 때문에 의도적으로 끄는 경우도 있다.
이 다음부터는 직접 지정한 작업들이 나온다.
지정한 파일을 복사하고 읽는다. 파일의 내용은 TASK [Read /tmp/test.txt] 에서 확인이 가능하고, "item" 항목을 보면 test.txt 파일에 작성한 대로 바로 표시됨을 알 수 있다.
copy 모듈에는 설정이 더 있지만, 유념해야 할 것은 validate 와 content 가 있다.
validate 는 파일 복사를 완료하기 전에 우선 validate 로 표시된 확인 과정을 거친다. 주로 미들웨어나 시스템 설정이 작성된 파일들에 대해 복사를 마치기 전에 정상적으로 작성된 파일인지 확인하기 위해 사용된다. 이는 후에 다시 보기로 하자.
content 는 파일을 직접 복사하는 것이 아닌 파일의 내용을 바로 쓰는 것이다. 즉, 원본 파일이 없어도 사용할 수 있게 된다. motd 와 같은 서버 접속에 사용되는 환영 혹은 경고 메시지를 쓰는 것이 편할 수 있을 것이다.
- 파일을 조작하자, file 모듈
리눅스에서 파일을 조작한다는 것은 큰 의미를 갖는다. 리눅스에서 파일시스템은 모든 것을 파일로 다루기 때문이다.
앤서블의 file 모듈도 많은 설정이 있지만 간단하게 파일 삭제와 디렉토리 및 링크를 생성하는 것을 보자.
간단하게 바로 위에서 복사한 test.txt 를 삭제해보자.
---
- hosts: all
become: true
tasks:
- name: Remove /tmp/test.txt
file:
state: absent
path: /tmp/test.txt
비교적 간단하게 작성 가능하다. file 모듈을 사용하고, state 항목을 absent 로 작성하면 파일이 삭제됨을 의미하며, path 는 노드의 대상 파일 경로를 의미한다. 이를 통해 삭제가 가능하다.
불필요한 개별 파일은 이렇게 삭제가 가능하다.
디렉토리를 생성해보자.
위의 플레이북은 디렉토리를 생성하고 확인하는 것을 의미한다. file 모듈을 통해 /tmp/test/ 디렉토리를 생성한다. 그 다음부터는 확인을 위해 사용된 모듈이다. command 모듈을 통해 ls -lht /tmp 라는 명령어를 실행하고, result 라는 변수에 결과를 저장한다. 그리고 debug 모듈을 통해 result 의 값을 표시한다.
결과가 길어 확인 부분만 표시하였다.
"stdout_line" 라는 항목을 통해 command 모듈을 통해 얻은 값을 확인할 수 있으며, test 라는 디렉토리가 표시된 것을 알 수 있다. 나중에 단순히 값만 보기 위해서 필터링을 할 수 있는데, 이는 나중에 더 알아보기로 하자.
만약 디렉토리가 1 개가 아니고 자식 디렉토리도 만들어야 한다면 어떻게 해야 할까? 혹은 여러개의 디렉토리를 만들어야 한다면 어떻게 해야할까?
우선, 자식 디렉토리를 만드는 것은 설정을 통해 간단하게 할 수 있다.
---
- hosts: all
become: true
tasks:
- name: Create directory test on /tmp
file:
state: directory
path: /tmp/test/ch1/ch2/ch3/ch4
recurse: yes
- name: List /tmp/test/ch1/ch2/ch3/ch4
command: ls -lhtd /tmp/test/ch1/ch2/ch3/ch4
register: result
- name: Show /tmp
debug:
msg: "{{ result }}"
기존에 사용했던 file 모듈 사용법과 같지만, recurse 라는 설정을 한 줄 더 추가해줬다. 기본적으로 recurse 는 비활성화되었기 때문에 직접 설정을 추가해주어야 한다.
결과만 간단하게 보자면, 문제없이 자식 디렉토리들이 문제없이 생성되었다.
자, 그럼 수 많은 디렉토리를 생성해보자.
---
- hosts: all
become: true
tasks:
- name: Create directory test on /tmp
file:
state: directory
path: "/tmp/test-{{ item }}"
with_sequence: start=0 end=99 format=%02d
- name: List /tmp
command: ls -lht /tmp
register: result
- name: Show /tmp
debug:
msg: "{{ result }}"
마찬가지로 기존의 file 모듈과 크게 다르지 않다. 다만, with_sequence 를 통해 00 에서 99 까지 파일명에 사용될 수 있도록 주어졌다.
결과는 아래와 같다.
결과가 길기 때문에 일부만 첨부하였다.
동일한 원리로 with_items 설정을 통해 리스트가 주어지면 주어진 리스트내의 값과 같이 디렉토리를 생성해준다.
---
- hosts: all
become: true
tasks:
- name: Create directory test on /tmp
file:
state: directory
path: "/tmp/{{ item }}"
with_items:
- foo
- bar
- baz
- name: List /tmp
command: ls -lht /tmp
register: result
- name: Show /tmp
debug:
msg: "{{ result }}"
path 는 /tmp 디렉토리에 있는 디렉토리임을 나타내기 위해 변수와 경로를 혼합하여 사용하였다. 그리고 with_items 항목을 통해 만들고자 하는 디렉토리의 이름을 작성하였다.
사용한 모듈들에 대한 값만 표시하면 아래와 같다.
file 모듈을 통해 디렉토리를 하나 이상 만들어야 할 경우 굉장히 쉬운 것을 알 수 있다.
다음은 심볼릭 링크를 생성한다.
심볼릭 링크는 복잡 다단한 파일 경로를 단순하게 해주기 때문에 많이 사용되는 파일 형태이다.
시스템 로그를 자주 사용하기 때문에 /var/log 디렉토리를 바로 원하는 디렉토리에서 조회가 가능하도록 한다고 가정하고 /tmp 밑에 system-log 라는 심볼릭 링크로 표시하는 것을 진행해보자.
---
- hosts: all
become: true
tasks:
- name: Create directory test on /tmp
file:
state: link
src: /var/log
path: /tmp/system-log
- name: List /tmp
command: ls -lht /tmp
register: result
- name: Show /tmp
debug:
msg: "{{ result }}"
file 모듈에서 state 를 link 로 하고, 심볼릭 링크의 원본을 설정하기 위해 src 항목도 설정한 것을 볼 수 있다.
진행한 이후 결과를 보면 system-log 파일이 /var/log 디렉토리를 가리키는 것을 볼 수 있다.
이외에도 많은 설정이 있지만 대표적으로 많이 사용할 수 있는 동작을 살펴보았다.
- 파일을 가져오자, fetch 모듈
fetch 모듈은 copy 모듈과 비슷하지만, 다른 점은 대상 노드로 파일을 복사하는 것이 아닌, 대상 노드의 파일을 앤서블 노드로 복사하는 것이다. 즉, copy 모듈의 방향이 정반대인 것으로 이해할 수 있다.
예를 들어, 각 노드의 rsyslogd 의 설정을 알기 위해 설정 파일을 가져와서 확인한다고 해보자.
---
- hosts: all
become: true
tasks:
- name: Get the rsyslogd config file
fetch:
src: /etc/rsyslog.conf
dest: /tmp
fetch 파일을 사용하기 위해 src 와 dest 설정을 사용하는데, src 는 대상 노드의 파일 위치를, dest 는 앤서블을 실행하는 노드의 저장 디렉토리를 지정한다.
주의할 사항은 가져온 파일이 저장되는 방식은 <dest dir path>/<host name>/<src file path> 이다. 직접 확인해보자.
가져온 파일은 각 노드의 호스트명으로 된 디렉토리 이하에 저장되며, 가져온 파일은 지정된 파일 경로를 전부 복사한다. 물론, 각 노드에 대해 디렉토리로 구분해준다는 점은 편리하지만, 경우에 따라 불필요한 부모 디렉토리 경로까지 가져온다는 단점이 있다. 물론, 이를 해결하기 위한 방법이 있다.
---
- hosts: all
become: true
tasks:
- name: Get the rsyslogd config file
fetch:
src: /etc/rsyslog.conf
dest: /tmp/{{ inventory_hostname }}-rsyslog.conf
flat: true
fetch 모듈에서 flat 설정을 true 로 설정해준다. dest 또한 단순히 /tmp 디렉토리가 아니라 변수를 활용해서 별도의 파일명이 들어가도록 한다. 이렇게 한 이유는 간단하다. 가져온 파일명을 유지하기 때문에 동일한 파일명일 경우 같은 파일로 보고 덮어쓰기 때문이다. 그래서 다른 파일로 구분할 수 있기 위해 파일명을 구분해준 것이고, 고유하다고 볼 수 있는 호스트명을 사용한 것이다.
inventory_hostname 이라는 변수는 앤서블의 인벤토리 파일에서 지정된 호스트명을 사용한 것이다. 따라서 실제 서버의 호스트명과는 다를 수도 있다.
플레이북에서는 대부분 facts 모듈을 통해 가져온 변수들을 사용하며, setup 모듈을 통하여 확인이 가능하다. 앤서블 facts 에 대해서는 따로 다시 서술하도록 하겠다.
다시 flat 을 활용하여 가져온 파일들에 대해 실행 결과를 확인해 보자.
이전과는 다르게 각 노드에 따른 디렉토리가 아닌 파일을 직접 지정한 경로로 가져왔다.
fetch 모듈을 사용한다면 가장 기초적인 데이터 수집을 쉽게 할 수 있을 것이다.
- 파일내 문장을 수정하자, lineinfile 모듈과 replace 모듈
보통 파일내에서 간편하게 수정을 하기 위해 메모장이나 Vim 과 같은 편집기를 사용할 것이다. 다만, 이는 사람이 수동적으로 진행해야하기 때문에, 보통 sed 와 같은 프로그램을 이용하여 간단하게 목표한 단어나 문장들을 수정하였을 것이다.
lineinfile 모듈도 이름에 걸맞게 파일내의 문장들을 수정해주는 모듈이다.
간단하게 진행해보자. 우선 로미오와 줄리엣의 대본중 일부를 텍스트 파일로 사용할 것이다.
ACT I
PROLOGUE
Two households, both alike in dignity,
In fair Verona, where we lay our scene,
From ancient grudge break to new mutiny,
Where civil blood makes civil hands unclean.
From forth the fatal loins of these two foes
A pair of star-cross'd lovers take their life;
Whole misadventured piteous overthrows
Do with their death bury their parents' strife.
The fearful passage of their death-mark'd love,
And the continuance of their parents' rage,
Which, but their children's end, nought could remove,
Is now the two hours' traffic of our stage;
The which if you with patient ears attend,
What here shall miss, our toil shall strive to mend.
보통은 원래 있던 파일의 일부를 수정하지만, 여기서는 파일을 옮기고 수정을 하는 것으로 하며, 각 결과물도 한번씩 확인할 것이다.
---
- hosts: all
become: true
tasks:
- name: Copy file
copy:
src: /vagrant/romeo-juliet.txt
dest: /tmp
owner: vagrant
group: vagrant
mode: '0644'
- name: Check file content
debug: var=item
with_file: /tmp/romeo-juliet.txt
- name: Change line in file
lineinfile:
path: /tmp/romeo-juliet.txt
line: Line change test
regexp: PROLOGUE
- name: Check changed file
debug: var=item
with_file: /tmp/romeo-juliet.txt
코드는 간단하게 copy, lineinfile, debug 모듈을 사용하였다. copy 와 debug 는 파일을 복사하고 확인하는데에 사용하였다. lineinfile 은 path 를 통해 대상 파일을 지정하였고, line 을 통해 삽입하려는 문장을 지정하였다. 그리고 regexp 를 통해 바꾸려는 문장을 지정하였다. 여기서는 PROLOGUE 라고 다 표시하였지만, ^PROLOGUE$ 라고 표시하여 정말 원하는 문장을 지정할 수 있다. 이는 regexp 설정이 정규표현식과 맞는 모든 문장에 대해 진행을 하기 때문에 간단하면 간단할수록 많은 문장들이 바뀔 가능성이 있다.
아래는 확인 내용이다.
결과가 길어서 변경된 부분만 첨부하였다.
lineinfile 을 통해 쉽게 파일내의 문장을 바꿀수 있으며, copy 와 같이 validate 옵션을 통해 변경된 이후 확인 과정도 넣을 수 있다.
그렇다면 좀 더 흥미로운 수정을 해보도록 하자.
문장 전체를 바꾸는 것은 좀 더 명확하게 선택을 할 수 있지만, 단어나 구절만 변경하는 등의 좀 더 복잡하고 세심한 설정은 직접 문장을 다 표시해야 하는 만큼 부족하게 느껴질 수 있다. 이러한 것을 앤서블에서는 replace 모듈을 통해 해결이 가능하다.
다시 대상은 로미오와 줄리엣의 대본을 대상으로 하고, of 를 OF 로 바꿔보도록 하자.
---
- hosts: all
become: true
tasks:
- name: Copy file
copy:
src: /vagrant/romeo-juliet.txt
dest: /tmp
owner: vagrant
group: vagrant
mode: '0644'
- name: Check file content
debug: var=item
with_file: /tmp/romeo-juliet.txt
- name: Change line in file
replace:
path: /tmp/romeo-juliet.txt
regexp: of
replace: OF
- name: Check changed file
debug: var=item
with_file: /tmp/romeo-juliet.txt
replace 모듈에서 path 를 통해 대상 파일을, regexp 를 통해 바꾸려는 텍스트 대상을, replace 를 통해 바꾸려는 텍스트를 입력한다.
결과는 아래와 같다.
결과가 길어 일부만 첨부하였다.
의도한 대로 of 가 OF 로 변경되었다.
replace 모듈은 간단하게 교체도 가능하지만, 마찬가지로 validate 설정으로 변경전 확인이 가능하며, before 와 after 로 대상이 되는 문장들을 필터링하거나, regexp 에서 정규표현식의 그룹을 사용하면, replace 설정에서 해당 그룹을 다시 사용할 수 있다. 이는 문서의 예제에서 잘 나오지만 정확한 이해는 정규표현식에 대해 별도로 참고하기를 권한다.
파일은 중요하다. 앤서블에서도...
이 페이지에서는 앤서블에서 제공되는 파일 관련 모듈중에서도 중요하거나 많이 사용되는 모듈들을 살펴보았다.
출처
https://docs.ansible.com/ansible/latest/modules/modules_by_category.html
'자동화 > 앤서블' 카테고리의 다른 글
앤서블에서 변수 사용하기 (0) | 2019.11.23 |
---|---|
Ansible 로 LAMP 구성하기 (0) | 2019.09.29 |
앤서블 인벤토리 설정 (0) | 2019.06.09 |
앤서블 실습 환경 구성 (0) | 2019.06.08 |
앤서블의 구조와 작동 방식 (0) | 2019.06.02 |