앤서블 간단 안내서
Ansible 이란:
- 파이썬으로 만들어 졌다.
- 그래서, 느리다는 하소연이 있다.
- 원격의 컴퓨터를 구성-관리 한다.
- 원격 컴퓨터에 에이전트를 설치할 필요가 없다.
- ssh를 통해 원격 컴퓨터에 명령한다.
- 원격 컴퓨터에 앤서블 명령을 내리는 컴퓨터는 앤서블 코어가 설치 되어야 한다.
- 다수의 컴퓨터를 동시에, 동일한 환경을 배포한다.
앤서블 3요소
- 인벤터리: 어디서 수행할 것인지 기술한다.
- 플레이북: 무엇을 수행할 것인지 기술한다.
- 모듈: 어떻게 수행할 것인지 기술한다.
앤서블 서버
앤서블 코어가 설치된 컴퓨터를 말한다.
우분투에 앤서블 코어 설치:
sudo apt install ansible -y
앤서블 명령어 목록 확인:
ls /usr/bin/ansible*
/usr/bin/ansible
/usr/bin/ansible-config
/usr/bin/ansible-connection
/usr/bin/ansible-console
/usr/bin/ansible-doc
/usr/bin/ansible-galaxy
/usr/bin/ansible-inventory
/usr/bin/ansible-pull
/usr/bin/ansible-playbook
/usr/bin/ansible-vaul
앤서블 인벤터리 (inventory)
엔서블에 의해 제어될 컴퓨터들을 정의한다. 일반적으로 hosts.ini 파일에 정의한다. 여러 컴퓨터들의 ssh 접근을 위한 IP주소, 포트, 리눅스 사용자 권한과 같은 접속 정보를 기술한다.
[webserver]
web1 ansible_host = 192.168.112.101
web2 ansible_host = 192.168.112.102
[db]
db1 ansible_host = 192.168.112.103
db2 ansible_host = 192.168.112.104
앤서블 플레이북 (playbook)
무엇을 수행할 것인지 yaml 으로 정의한다. 앤서블을 다룬다는 것은 플레이북을 다룬다는 것을 말할정도로 중요하다. 대상을 정의해야 하기때문에 단독으로 사용하지는 않고 플레이북과 함께 사용된다.
- name: install nginx
hosts: all
become: true
tasks:
- name: ngix package install
apt:
name: nginx
state: installed
앤서블 애드혹 (ad-hoc)
shell에서 명령줄로 주는 1회성 명령이다. 반복 사용할 수 있게 yaml로 작성하는 것을 플레이북이라고 한다.
앤서블 모듈 (module)
플레이북이 task들이 어떻게 수행될지 정의한다.
타겟 호스트로 실제 작업을 처리하는 단위로 이 모듈의 개념을 사용한다. 앤서블 모듈은 파이썬 코드로 작성 된다. 위 플레이북 예시에서 apt가 우분투에서 사용되는 모듈이다.
구글에서 ansible all modules
를 검색해보면 모듈 목록과 사용법을 확인 할 수 있다.
멱등성 (idempotency)
앤서블은 선언형으로 멱등성을 가진다. 여러번 코드를 실행하여도 결과가 동일하다. 컴퓨터의 상태가 코드와 다른 부분이 있다면 선언한 코드 내용에 맞게 변경될 뿐이다.
앤서블 노드:
앤서블 서버의 명령을 받아서 실행될 컴퓨터들로 앤서블 서버의 `/etc/ans## 앤서블 애드혹
shell에서 명령줄로 주는 1회성 명령. 반복 사용할 수 있게 YAML로 작성하는 것을 플레이북이라고 함.ible/hosts` 파일에 앤서블 노드를 나열한다.
192.168.0.xxx ansible_connection=ssh ansible_user=<username> ansible_password=<passwd> ansible_become=yes ansible_become_method=su ansible_become_user=root ansible_become_password=<passwd>
<앤서블 노드 2>
...
<앤서블 노드 n-1>
<앤서블 노드 n>
앤서블 노드 연결 확인:
ansible all -m ping
앤서블 애드혹
ssh키값을 입력 받기 위해 yes
를 입력
앤서블 명령 전달 확인:
ansible all -m ping -k
이때 암호를 물으면 암호를 입력 한다.
앤서블 구성 파일:
/etc/ansible/ansible.cfg
파일:
앤서블 노드 그룹:
/etc/ansible/hosts
에 그룹 지정.
[그룹이름]
<앤서블 노드 1>
<앤서블 노드 2>
...
<앤서블 노드 n-1>
<앤서블 노드 n>
all 대신 노드 그룹을 지정하여 노드 그룹에 앤서블 명령 전달 확인:
ansible <그룹이름> -m ping -k
앤서블 노드 상세:
형식 | 설명 | 예제 |
---|---|---|
<타겟>타겟> | 타겟 호스트 이름 | taget1 |
ansible_host=<앤서블 노드 주소> |
앤서블 노드 주소 지정 (필수) | 192.168.0.21 |
ansible_user=<유저이름> |
앤서블 SSH 유저 이름 지정 | booil |
ansible_connection= |
||
ansible_network_os=<운영체제 이름> |
노드의 운영체제 종류 |
인벤터리 파일 지정:
/etc/ansible/hosts
파일을 사용하지 않고 특정한 노드 목록 파일을 지정한다. -i <인벤터리 파일 경로>
또는 ---inventory-file <인벤터리 파일 경로>
로 지정한다:
ansible -i <인벤터리 파일 경로> ...
인벤터리 파일내의 모든 호스트에 대해 지정:
ansible -i <인벤터리 파일 경로> all ...
인벤터리 파일내의 특정 호스트에 대해 지정:
ansible -i <인벤터리 파일 경로> <호스트 주소> ...
노드에 대한 패스워드를 물어 보도록 지정:
ansible -k
또는
ansible --ask-pass
적용되는 노드들 확인:
실제로 앤서블 명령이 실행 되는 것이 아니라 명령 라인에 대해 적용되는 노드 목록만을 확인 한다. -k
같은 파라미터는 무시되며 지정하지 않아도 된다.
ansible --list-hosts
앤서블 애드혹
shell에서 명령줄로 주는 1회성 명령. 반복 사용할 수 있게 YAML로 작성하는 것을 플레이북이라고 함.
사용할 모듈 지정:
-m
또는 --module-name
으로 사용할 모듈 이름을 지정
앞에서 사용하였던 -m ping
은 ping
모듈을 사용 한 것
shell 모듈:
sh나 bash 같은 명령을 노드에서 직접 실행
ansible ... -m shell -a "<셸 명령줄>" ...
예를 들어 가동 시간을 확인:
ansible ... -m shell -a "uptime"
모듈 지정을 생략:
모듈을 지정하지 않으면 기본적으로 shell 모듈이기 때문에 -m shell
은 생략하고 -a "<셸 명령줄>"
만을 지정 가능.
ansible ... -a "uptime"
명령줄에 따옴표 생략:
-a
뒤의 셸 명령줄이 한개의 단어라면 따옴표에 넣지 않아도 된다.
ansible ... -a uptime
사용자 모듈:
사용자 추가:
ansible ... -m user -"name=<사용자 이름>" -k
마지막 추가된 사용자 확인:
ansible ... -a "tail -n 1 /etc/passwd" -k
사용자 제거:
ansible ... -m user - "name=<사용자 이름> state=absent" -k
패키지 모듈:
패키지 설치:
ansible ... -m <yum> -a "name=httpd state=present" -k
ansible ... -m <apt> -a "pkg=httpd update_cache=yes state=present" -k
패키지 제거:
ansible ... -m <yum> -a "name=httpd state=absent" -k
ansible ... -m <apt> -a "name=httpd autoremove=yes state=absent" -k
파일 복사 모듈:
앤서블 서버에서 앤서블 노드로 파일 복사.
ansible ... -m copy -a "src=<앤서블 서버 내의 원본 경로> dest=<앤서블 노드 내의 대상 경로>"
서비스 모듈:
서비스 시작, 중지, 재시작.
ansible ... -m service -a "name=<서비스 이름> state=<상태>"
서비스 상태:
- started: 시작
- stop: 중지
- restarted: 재시작
facts 확인
ansible <노드> -m setup
노드별로 facts 따로 저장
ansible <노드> -m setup --tree
앤서블 플레이북
- 앤서블 애드혹은 1회성이다.
- 앤서블 플레이북은 YAML로 작성한다.
- 반복적으로 사용가능하다.
- 플레이북 자체가 문서다.
명령줄에서 실행:
ansible-playbook <앤서플 플레이북 파일.yml> -k
--- # 첫줄은 반드시 ---로 시작해야 한다.
- name: <이 플레이북에 대한 설명>
hosts: <호스트 지정>
gather_facts: <yes 또는 no>
become: <아래 작업들에 대해 수퍼 유저 권한을 사용하려면 yes 아니면 no>
tasks:
<이하 작업 내용들 기술>
facts를 수집하여 json으로 저장
---
- name: <이름>
hosts: <노드>
tasks:
- name: <이름>
setup:
register: facts
- name: save facts
local_action:
module: copy
content: ""
dest: ./_facts_by_collector.txt
facts를 출력
- name: debug by msg
debug:
msg:
- "eth0's ip "
- "eth1's ip "
작업 include
---
- name: <이름>
hosts: <노드들>
become: yes
taks:
- include_taks: <서브 작업 파일>
서브 작업 파일:
- name: <이름>
<do something>
...
조건에 의한 작업 수행:
구문을 모두 해석하므로 느리다.
tasks:
- name: <이름>
<뭔가 함>
when: ansible_distribution == 'CentOS'
또는
when: ansible_distribution == 'Ubuntu'
배포판 조건에 의한 작업 include
필요 구문만 해석하므로 빠름
---
- name: <이름>
hosts: <노드>
vars:
linux_distribution: "centos
else 'ubuntu' if ansible_distribution == 'Ubuntu'
else 'unknown' }}"
tasks:
- name: <이름>
include_tasks: ".yml"
Magic Variables
기본 변수
타입 | 매직변수 | ||
---|---|---|---|
base | connection | ansible_connection | |
module_compression | ansible_module_compression | ||
shell | ansible_shell_type | ||
executable | ansible_shell_executable | ||
connection common | remote_addr | ansible_ssh_host | ansible_host |
remote_user | ansible_ssh_user | ansible_user | |
password | ansible_ssh_pass | ansible_password | |
port | ansible_ssh_port | ansible_port | |
pipelining | ansible_ssh_pipelining | ansible_pipelining | |
timeout | ansible_ssha_timeout | ansible_timeout | |
private_key_file | ansible_ssh_private_key_file | ansible_private_key_file | |
networking modules | netwok_os | ansible_network_os | |
connection_user | ansible_connection_user | ||
become | become | ansible_become | |
become_method | ansible_become_method | ||
become_user | ansible_become_user | ||
become_pass | ansible_become_password | ansible_become_pass | |
become_exe | ansible_exe | ||
become_flags | ansible_become_flags |
hosts:
플레이북 파일을 실행할 호스트를 지정한다.
all
: /etc/ansible/hosts의 모든 노드들을 지정.<노드 그룹 이름>
: /etc/ansible/hosts에서 특정 그룹의 노드들을 지정.localhost
: 앤서블 플레이북이 실행되고 있는 컴퓨터를 지정.
유저 전환:
수퍼 유저로 전환:
tasks:
- name: <이름>
become: <수퍼 유저 권한을 사용하려면 yes 아니면 no>
지정한 유저로 전환:
tasks:
- name: <이름>
become: <유저 권한을 사용하려면 yes 아니면 no>
become_user: <유저 이름>
앤서블 모듈:
플레이북에서 작업을 수행하는 수단. 파일 복사, 다운로드, 패키지 설치 등 각 작업을 수행하는 기능을 제공.
패스워드 없이 수행하기 위해 앤서블 서버와 노드사이의 인증 생성:
---
- name: Create known_hosts between server and hosts
host: nodes
connection: local
serial: 1
tasks:
- name: ssh-keyscan for known_hosts file
command: /usr/bin/ssh-keyscan -t ecdsa
register: keyscan
- name: input key
lineinfile:
path: ~/.ssh/known_hosts
line: ""
create: yes
with_item:
- ""
- name: Create authority_key between server and hosts
host: nodes
connection: local
gather_facts: no
vars:
ansible_password: <비밀번호>
- name: ssh-keygen for authorized_key file
command: "ssh-keygen -b 2048 -t rsa -f ~/ssh/id_rsa -q -N ''"
ignore_errors: yes
run_once: true
- name: input key for each node
connection: ssh
authorized_key:
user: <유저이름>
state: present
key: ""
셸명령 실행:
tasks:
- name: <이름>
shell: ""
with_items:
- "<명령줄 1>"
- "<명령줄 2>"
- ...
텍스트 파일 멱등성 라인 추가:
tasks:
- name: <이름>
lineinfile:
path: <파일경로>
line: ""
with_items:
- "<라인 1>"
- "<라인 2>"
- ...
파일 내에서 검색하여 치환:
tasks:
- name: <이름>
replace:
path: <파일경로>
regexp: <검색할 정규식>
replace: <치환할 텍스트>
다수의 검색어 치환:
tasks:
- name: <이름>
replace:
path: ""
regexp: ""
replace: ""
with_items:
- { path: "<경로1>", regexp: "<검색 정규식1>", replace: "치환문자열1" }
- { path: "<경로2>", regexp: "<검색 정규식2>", replace: "치환문자열2" }
호스트 추가:
tasks:
- name: <이름>
blockinfile:
path: /etc/ansible/hosts
block: |
[<그룹 이름>]
<호스트1>
<호스트2>
...
<호스트n-1>
<호스트n>
SSH 키 생성:
tasks:
- name: <이름>
become: yes
become_user: <유저이름>
shell: ""
with_items:
- "ssh-keyscan <IP주소> >> ~/.ssh/known_hosts"
- "ssh-keyscan <IP주소> >> ~/.ssh/known_hosts"
...
- "ssh-keyscan <IP주소> >> ~/.ssh/known_hosts"
- "ssh-keyscan <IP주소> >> ~/.ssh/known_hosts"
패키지 설치:
레드헷:
tasks:
- name: <이름>
yum:
name: <패키지 이름>
status: <present 또는 latest>
레드헷 다수의 패키지 설치:
tasks:
- name: <이름>
yum:
name: " "
status: <present 또는 latest>
update_cache: true
with_items:
- "<패키지 이름 1>"
- "<패키지 이름 2>"
- ...
- "<패키지 이름 n-1>"
- "<패키지 이름 n>"
우분투:
tasks:
- name: <이름>
apt:
pkg: ""
state: <present 또는 latest>
update_cache: true
with_items:
- "<패키지 이름 1>"
- "<패키지 이름 2>"
- ...
- "<패키지 이름 n-1>"
- "<패키지 이름 n>"
윈도우:
tasks:
- name: <이름>
win_chocolatey:
name: <패키지 이름>
공통:
tasks:
- name: <이름>
action: " name=<패키지이름> state=<present 또는 latest>"
진행 상태 표시 패키지 설치:
tasks
- name: Install ...
become: yes
apt:
name: <package-name>
async: 1000
poll: 0
register: apt_sleeper
- name: 'apt - check on async task'
async_status:
jid: ""
register: job_result
until: job_result.finished
retries: 1000
패키지 제거:
레드햇:
tasks:
- name: <이름>
yum:
name: <패키지 이름>
status: absent
우분투:
tasks:
- name: <이름>
apt:
pkg: <패키지 이름>
status: absent
autoremove: yes
공통:
tasks:
- name: <이름>
action: " name=<패키지이름> state=absent"
Docker 우분투 gpg 키 등록:
tasks:
- name: Add docker apt signing key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
git 저장소 클론:
tasks:
- name: <이름>
git:
repo: <git 저장소 URL>
dest: <로컬 컴퓨터의 경로>
tasks:
- name: <이름>
cmake:
binary_dir: <빌드 디렉토리, 필수>
source_dir: <소스 디렉토리>
build_type: <빌드 타입, 기본 Debug>
target: <빌드 타겟>
cache_vars: <캐시 변수>
.bashrc 구성:
tasks:
- name: <이름>
lineinfile:
path: /home/.../.bashrc
line: "
with_items:
- "..."
- "..."
앤서블 서버에서 노드로 파일 복사하기:
tasks:
- name: <이름>
copy:
src: "<앤서블 서버에서 원본 파일 경로>"
dest: "<앤서블 노드에서 대상 파일 경로>"
owner: <파일 소유 유저 지정>
group: <파일 그룹 지정>
mode: <파일 권한 지정>
앤서블 노드에서 앤서블 서버로 파일 복사해오기:
tasks:
- name: <이름>
fetch:
src: "<앤서블 노드에서 원본 파일 경로>"
dest: "<앤서블 서버에서 대상 파일 경로>"
이때 앤서블 서버은 다수의 앤서블 노드에서 파일을 복사해 오므로 <dest 경로>/<앤서블 노드 이름>/<src 경로>
폴더에 저장 된다. 경로가 복잡하여 불편하면 다음과 같이 할 수 있다.
tasks:
- name: <이름>
fetch:
src: "<앤서블 노드에서 원본 파일 경로>"
dest: "<앤서블 서버에서 대상 디렉토리>/-파일명.확장자"
flat: true
flat
을 true
로 지정하여 앤서블 노드의 경로를 제거 한다.
파일 내용 표시:
tasks:
- name: <이름>
debug:
var: item
with_file:
- "<앤서블 노드에서 파일 경로 1>"
- "<앤서블 노드에서 파일 경로 2>"
...
디렉토리 만들기:
리눅스:
tasks:
- name: <이름>
file:
state: directory
path: <만들 디렉토리 경로>
recurse: <기본값은 no이며 깊은 디렉토리를 만드러면 yes를 지정>
윈도우:
tasks:
- name: <이름>
win_file:
state: directory
path: <만들 디렉토리 경로>
recurse: <기본값은 no이며 깊은 디렉토리를 만드러면 yes를 지정>
다수의 디렉토리 만들기:
아래는 /tmp
폴더에 test-00
부터 test-99
까지 100개의 하위 디렉토리를 만든다.
tasks:
- name: <이름>
file:
state: directory
path: "/tmp/test-"
recurse: <기본값은 no이며 깊은 디렉토리를 만드러면 yes를 지정>
with_sequence:
start: 0
end: 99
format: %02d
아래는 /tmp
폴더에 지정한 다수의 디렉토리를 만든다.
tasks:
- name: <이름>
file:
state: directory
path: "/tmp/test-"
recurse: <기본값은 no이며 깊은 디렉토리를 만드러면 yes를 지정>
with_items:
- foo
- bar
- baz
심볼릭 링크 만들기:
tasks:
- name: <이름>
file:
state: link다
src: <원본 경로>
path: <심볼링 링크 경로>
셸에서 디렉토리 만들기:
tasks:
- name: <이름>
shell: ""
with_items:
- "mkdir -p <생성할 디렉토리 이름>"
파일 삭제:
tasks:
- name: <이름>
file:
state: absent
path: <앤서블 노드에서 파일 경로>
디렉토리 보기:
tasks:
- name: <이름>
command: ls -lht <경로>
register: <결과를 저장할 변수명>
- name: <이름>
debug:
msg: ""
URL을 통해 파일 가져오기:
리눅스:
tasks:
- name: <이름>
get_url:
url: "<원본 URL>"
dest: "<대상 로컬 경로>"
mode: <파일 권한 지정>
리눅스 파일 권한:
0<owner><group><other>
순서로 지정.r: 4, w: 2, x: 1
- 읽고 쓰고 실행 가능:
7
- 읽기만 가능:
4
- 읽고 쓰기만 가능:
6
- 읽고 실행만 가능:
5
윈도우:
tasks:
- name: <이름>
win_get_url:
url: "<원본 URL>"
dest: "<대상 로컬 경로>"
윈도우 서비스 등록:
- 먼저 nssm이 설치되어 있어야 한다.
tasks:https://kim-dragon.tistory.com/53
- name: <이름>
win_nssm:
name: <애플리케이션 이름>
application: <애플리케이션 실행파일 경로>
state: present
타임존 변경:
리눅스:
https://kim-dragon.tistory.com/53https://kim-dragon.tistory.com/53 tasks:
- name: <이름>
timezone:
name: Aisa/Seoul
리눅스 타임존 목록:
timedatectl list-timezones
윈도우:
https://kim-dragon.tistory.com/53 tasks:
- name: <이름>
win_timezone:
timezone: 'Korea Standard Time'
마운트:
리눅스:
tasks:
- name: <이름>
become: yes
mount:
path: <마운트 할 대상 경로>
src: <마운트 할 소스 경로>
fstype: <파일 시스템 타입>
opts: <파일 시스템 옵션>
state: mounted
윈도우 NFS 마운트:
tasks:
- name: <설명 1>
win_feature:
name: NFS-Client
state: present
- name: <설명 2>
win_command: net use "드라이브 문자:" "NFS 경로"
파일 압축 풀기:
윈도우:
tasks:https://kim-dragon.tistory.com/https://kim-dragon.tistory.com/53https://kim-dragon.tistory.com/53https://kim-dragon.tistory.com/5353
- name: <이름>
win_unzip:
src: <압축된 파일 소스 경로>
dst: <풀어진 파일 저장 경로>
delete_archive: <압축 파일을 삭제하려면 yes 아니면 no>
서비스 시작:
리눅스:
tasks:
- name: <이름>
service:
name: <서비스 이름>
state: started
https://kim-dragon.tistory.com/53윈도우:https://kim-dragon.tistory.com/53
tasks:
- name: <이름>
win_service:
name: <서비스 이름>
state: started
서비스 중지:
리눅스:https://kim-dragon.tistory.com/53https://kim-dragon.tistory.com/53
tasks:
- name: <이름>
service:
name: <서비스 이름>
state: stop
윈도우:
tasks:
- name: <이름>
win_service:
name: <서비스 이름>
state: stop
https://kim-dragon.tistory.com/53서비스 재시작https://kim-dragon.tistory.com/53
리눅스:
tasks:
- name: <이름>
service:
name: <서비스 이름>
state: restarted
윈도우:
https://kim-dragon.tistory.com/53 tasks:
- name: <이름>
win_service:
name: <서비스 이름>
state: restarted
리부팅:
윈도우:
tasks:
- name: <이름>
win_reboot:https://kim-dragon.tistory.com/53
서비스 데몬 재시작:
tasks:
- name: <이름>
systemd:
state: restarted
daemon_reload: yes
name: tftp
핸들러
- 전 단계가 정상적으로 이루어진 경우에 동작
- 변경 사항이 발생한 경우에만 동작
핸들러:
handlers:
- name: <핸들러 이름>
<Do something>
핸들러 실행을 요청:
- name: <이름>
<Do something>
notify: <핸들러 이름>
참조
- https://www.ansible.com
- https://nirsa.tistory.com/281
- 우아하게 앤서블, 조훈, 김정민, 비제이퍼블릭