가시다님 주관 A101 스터디에 대한 정리 - 1주차 입니다.
이번 주차에는 Ansible 기본 개념에 대해 정리합니다.
Ansible이란?
Ansible은 Python module 및 ssh를 사용하여 원격 호스트에 명령을 수행할 수 있도록 도와주는 CM(Configuration Management) 도구이다.
별도의 Agent를 설치하지 않아도 되며 단순히 SSH 접속이 가능하면 편리하게 사용할 수 있다.
(내부적으로 Python을 사용하게 되는데 대부분의 Linux에는 Python이 기본적으로 설치되어 있다.)
필자는 Ansible을 사용할 때 일반적으로 다음의 과정들을 거친다.
[1] ansible.cfg 파일 작성 및 확인
[2] inventory 파일 생성, 그룹 변수 생성, 호스트 변수 생성 등
[3] ansible-inventory 명령어를 활용하여 정상적으로 호스트 및 그룹 등록이 완료되었는지 확인
[4] ansible -m ping {{그룹 | 호스트}} 명령어로 Master 노드에서 원격 노드로 Ping 모듈이 성공하는지 확인
[5] 간단한 Playbook 작성
[6] Playbook 간단히 테스트
[6.1.] --list-hosts , --list-tasks , --check
(Optional) 필요하다면 ansible-vault를 활용하여 암호화까지도 적용할 수 있다.
여기서 Ansible을 사용하기 위해 다양한 키워드들이 나왔다. ansible.cfg, host 변수, group 변수, inventory, playbook, ansible-vault, ..
추가로 기본적인 linux 지식 또한 이해하고 있으면 ansible을 사용하는데 많은 도움이 될 것이다.
위에서 나열한 개념들과 그 외 개념들을 하나씩 알아보고자 한다.
Ansible 동작 방식
Ansible은 'Controller 노드'에서 'Remote 노드'에 연결하여 'Ansible module'이라는 작은 프로그램을 실행하고 완료되면 제거하는 방식으로 작동된다.
Master(Controller) 노드 : 원격 노드에 접속해서 Module을 실행시키는 Machine
Remote 노드 : Controller 노드에 의해 처리 / 제어되는 Machine
Controller 노드는 Remote 노드에 연결하여 Module을 이 때 필요한게 '인증 처리'이다.
인증 처리에는 SSH Protocol을 사용하는데 이에 대한 내용은 아래에 작성해보겠다.
ansible.cfg (플레이북 환경 설정 파일)
자세한 내용은 위 공식 문서를 참고하자.
ansible.cfg 파일을 통해 앤서블 설정을 적용할 수 있다.
[1] 우선순위
ansible.cfg 파일은 다음의 우선순위를 가지고 있다.
이 우선순위는 ansible.cfg 뿐 만 아니라 inventory 및 Host 변수, Group 변수 등 다른 곳에서도 유사하게 적용된다.
대부분 환경변수가 가장 큰 우선순위를 가지며 그 다음으로 동일 경로에 있는 ansible.cfg, 그 다음에는 해당 user의 home directory에 있는 ~/.ansible.cfg, 그 다음 /etc/ansible/ansible.cfg 파일을 바라보게 된다.
필자는 일반적으로 ./ansible.cfg에 등록하는 것 같다.
[2] ansible.cfg 파일 구조
섹션 제목과 각 색션 내에는 키 - 값 쌍으로 정의된 설정값이 포함되어 있다.
다음은 ansible.cfg 파일의 예시이다.
cat ansible.cfg
[defaults]
inventory = ./inventory
remote_user = root
ask_pass = false
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
[defaults] 섹션 : 앤서블 작업을 위한 기본값 설정
inventory는 inventory 파일의 위치를 지정하는 것이고
remote_user는 원격 노드에 접속할 때 어떤 user로 접속할 것인지 정의하는 부분이며
ask_pass는 SSH 암호를 묻는 메시지 표시 여부를 지정하는 것이다.
위 내용을 어떤 섹션에 어떤 Key를 넣어야할지 모르겠다면 공식문서를 확인해보면 자세히 나오므로 참고하자.
[privilege_escalation] 섹션 : 보안/감사로 인해 원격 호스트에 권한 없는 사용자 연결 후 에스컬레이션하여 루트 사용자로 가져올 시 사용하는 설정이다.
become : true | false 중 하나로 권한 에스컬레이션을 활성화할것인지 안할것인지 정의하는 key이다.
become_method : 권한 에스컬레이션 시 사용자 전환 방식
become_user : Remote 노드에서 전환할 사용자를 지정하는 부분
become_ask_pass : 위에 ask_pass와 동일하게 become_user로 에스컬레이션 시 암호를 묻는지에 대한 여부를 나타낸다.
module ?
Module은 Ansible에서 사용되는 명령어 혹은 작은 프로그램 정도로 이해하면 된다.
https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html
대표적인 Ansible module로는 copy, file, yum, apt, user 모듈 등이 있다.
이름만 들어도 딱 유추가 가능하듯이 무언가를 복사하거나 yum 패키지매니저를 통해 무언가를 설치, 업데이트, 삭제하거나 user를 생성, 삭제, 업데이트 등을 수행할 수 있다.
몇 가지 예시를 통해 확인해보자.
(참고 : web-servers, db-servers 등은 inventory 파일 내 등록된 group을 의미하며 inventory에 대한 내용은 아래에 설명한다.)
1) copy
ansible web-servers -m copy -a "src=/etc/hosts dest=/tmp/hosts"
web-servers란 그룹 | 호스트에게 copy란 모듈을 사용하며 arguments(인자)로 src와 dest를 전달한다.
2) file
ansible db-servers -m file -a "dest=/path/to/c mode=755 owner=ec2-user group=admin state=directory"
db-servers란 그룹 | 호스트에게 file이란 모듈을 사용하여 인자로 dest, owner, group, state를 전달한다.
3) user 모듈
ansible all -m user -a "name=foo password=<crypted password here>"
ansible all -m user -a "name=foo state=absent"
all이란 그룹 | 호스트에게 user 모듈을 사용하여 name, password 혹은 name, state를 인자로 전달한다.
ansible의 개념을 여기서 다시 한번 집어보자.
1. controller 노드가
2. remote 노드에게
3. ssh protocol을 통해
4. module이란 프로그램을 실행한다.
5. module을 실행할 때 적절한 인자(arguments)를 전달해주면 된다.
이 5가지에서 조금씩 host_vars, group_vars, facts, if, for, block, playbook, vault, role, .. 등의 개념들을 실습과 동시에 이해한다면 ansible을 빠르게 익힐 수 있을 것이다.
inventory ?
인벤토리는 text file이며 controller node가 remote node들을 관리하는 파일이다.
remote node들을 어떻게 그룹화를 하며 각 그룹들이 어떤 변수를 가지고 있고 ssh key file 경로 등을 지정할 수 있다.
ip 기반으로도 inventory를 지정할 수도 있고 domain name 기반으로도 지정할 수 있다.
다음은 inventory 파일에 대한 예시이다.
[web-servers]
host1 http_port=80 maxRequestPerChild=888
host2 http_port=443 maxRequestPerChild=400
[web-servers:vars]
ntp_server=centos7.org
proxy=bastion.com
...
web-servers란 그룹에 host1, host2가 있다.
host1의 변수는 http_port, maxRequestPerChild가 각각 80, 888이고
host2의 변수는 http_port, maxRequestPerChild가 각각 443, 400이다.
이는 각 호스트에 대한 변수이며 web-servers:vars 라는 그룹 변수에는 ntp_server, proxy가 있다. 이는 host1, host2 모두 동일한 값을 가지게 된다.
인증 처리
인증 처리란 Controller Node가 Remote Node로 접속하여 Module을 수행하기 위해 필요한 인증을 의미한다.
이 때 인증은 SSH Protocol을 사용하여 수행하게 되는데 Key based와 ID, PW Based 2가지 방식이 있다.
일반적으로 SSH Key 기반으로 인증을 많이 수행하게 된다.
Controller 노드는 Remote 노드에게 SSH Key 기반으로 접속하고,
ec2-user를 통해 1차 접속하며 ROOT Privilege를 에스컬레이션 받기 위해 become 설정 또한 추가한다고 가정하자.
ansible.cfg에는 다음의 설정 파일들이 들어갈 수 있을 것이다.
[defaults]
host_key_checking = False
ask_pass = False
inventory=./inventory
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
inventory 파일이 어디 있는지, root escalation 방법 등을 명시해준다.
inventory 파일에는 다음의 설정들이 들어갈 수 있을 것이다.
[my-amz-linux2]
cc.cc.cc.cc
cc.cc.cc.cc
[my-ubuntu]
xx.xx.xx.xx
xx.xx.xx.xx
[all:vars]
ansible_user = ec2-user
ansible_ssh_private_key_file = ~/ssh-key.pem
[my-ubuntu:vars]
ansible_user = ubuntu
all:vars는 모든 호스트에게 적용하는 변수를 의미한다.
my-ubuntu:vars는 my-ubuntu 그룹에게만 적용하는 변수를 의미한다.
여기서는 어떤 user 혹은 어떤 ssh key file로 인증할것인지 등을 명시해준다.
이를 그림으로 그리면 다음과 같을 것이다.
ad-hoc , playbook
ansible로 원격 노드에 명령어를 날릴려면 ad-hoc 방법과 playbook 방법 크게 2가지가 있다. (ansible role은 여기서 논외)
ad-hoc은 linux 명령어 단 한줄로 간단하게 module을 수행할 때 사용하는 방법이다.
ansible {호스트|그룹} -m {모듈} -a "k1=v1 k2=v2 k3=v3"
ansible 명령을 ad-hoc으로 실행하지 않고 script화 한 것이 playbook이다.
일반적으로 2번 이상 실행해야 하는 경우 playbook을 작성한다.
아래 예시는 all이란 그룹을 대상으로 user 모듈을 사용하여 name, state 인자로 User를 생성하는 것을 스크립트화하였다.
---
- hosts: all
vars:
user: ansible2
tasks:
- name: Create User {{ user }}
ansible.builtin.user:
name: "{{ user }}"
state: present
ansible playbook을 실행할 때 변수 우선순위 또한 중요하다.
우선순위
1) ansible-playbook 명령어와 동시에 넣은 파라미터
2) 플레이 변수
3) 호스트 변수
4) 그룹 변수
다음 예시는 centos7_hosts 그룹에게 shell 모듈과 debug 모듈을 사용한 2개의 task를 실행한 것이다.
shell 모듈에서는 pwd란 쉘 명령을 수행하고 register를 선언하면 result라는 변수에 저장하겠다는 의미가 된다.
- name: Ansible Test
hosts: centos7_hosts
tasks:
- name: Test
shell: pwd
register: result
- name: Display pwd output
debug:
msg: "{{ result }}"
ansible-vault
앤서블에서 데이터 파일을 암호화하거나 해독할 수 있는 tool이 ansible-vault이다.
https://docs.ansible.com/ansible/2.9/user_guide/vault.html
ansible-vault 명령어를 통해 새로운 암호화된 파일을 만들수도 있고 이미 만들어진 파일에 암호화를 맥일수도 있다.
당연히 이 암호화된 내용을 해독한 뒤 조회할 수도 있고 암호화를 해제할 수도 있고 ansible-playbook을 수행할 때 암호화된 파일이 있다면 수행 시 적용된 암호를 통해 안전하게 ansible을 수행할 수도 있다.
Facts
Facts는 Controller 노드에서 자동으로 검색한 변수들이다.
Facts 변수들은 Playbook 내에서 다양하게 사용될 수 있다.
예를 들어 1) OS가 Ubuntu 22.04인 Remote 노드에만 Task를 실행한다던가 특정 Kernel 및 DIsk Partition 크기가 일정 이상일 경우 등 다양한 조건을 통해 Playbook을 사용할 수 있게 된다.
물론 이 Facts 변수는 Remote Host가 몇 대 없을 경우 부하에 대해 크게 걱정하지 않아도 되지만 수십, 수백대가 될 경우 Controller 노드가 매번 Playbook을 수행할 때마다 가져와야 하기 때문에 부하가 발생할 수 있다.
이럴 경우를 대비하여 Facts Caching을 적용할 수도 있으니 참고하자.
https://docs.ansible.com/ansible/latest/plugins/cache.html#enabling-fact-cache-plugins
여기까지 Ansible의 기본 개념에 대해 알아보았다.
다음 글에서는 Ansible 기본 개념을 확장하여 다양한 실습을 진행해 볼 예정이다.
'DevOps' 카테고리의 다른 글
[Ansible] 사용자 계정 생성 및 apache http 설치 실습 (0) | 2024.02.04 |
---|---|
[Ansible] 반복문, 조건문, 핸들러, 블록, Recsue 등 개념 정리 (0) | 2024.01.20 |
[AWS] 클라우드 와치 로그에서 특정 패턴일 경우 Slack 알람 보내는 방법 (0) | 2023.07.02 |
[Github Action] Self hosted runner에서 Gradle, Docker image cache #2 - EFS 활용 (8) | 2022.12.19 |
[Github Action] Self hosted runner에서 Gradle, Docker image cache #1 - EBS, PVC로 캐시하기 (2) | 2022.12.17 |