애플리케이션을 원격 노드에 배포하고 반복적으로 서버를 배포하는데 사용되는 오픈 소스 도구
장점
단점
pip install ansible/etc/ansible/hosts : 기본 인벤토리 파일 ansible-inventory --list : 인벤토리 설정 확인ctrl-node
host1
host2
host3
host4
192.168.56.100
192.168.56.101
192.168.56.102
192.168.56.103
192.168.56.104192.168.56.101 # 그룹이 없는 경우 대괄호 의 그룹 세팅 위로 설정
[webservers]
host1
host2
[databaseserver]
host3
host4
192.168.56.100 # 대괄호 아래 정보는 대괄호 그룹에 포함ansible --list-hosts all -i {$PATH}ansible --list-hosts all -i inv02 : 전체 호스트 확인(그룹 표현X)ansible —list-hosts $(group OR host) -i $(INV_PATH) : 현재 인벤토리 파일에 특정 호스트가 있는지 확인ansible-inventory --list -i inv02 : 전체 등록 호스트 확인(그룹 표현 O)/etc/ansible/ansible.cfg~ > /etc# 실제 입력 시 주석 제거
[defaults]
inventory = inventory # 인벤토리 정보를 가진 파일명
remote_user = vagrant # 관리 노드에서 사용할 유저명
ask_pass = false # 원격 접속 시 password 요구 여부
host_key_checking = false
[privilige_escalation]
become = true # 접속자와 다르게 become_user로 작업
become_method = sudo
become_user = root # 접속 유저
become_ask_pass = false # sudo 사용 시 password 요구 여부ansible-config view : 현재 적용된 구성 파일 내용 확인ansible-config dumf : 현재 적용된 모든 구성 정보 확인ansible-config list : 설정 가능한 모든 설정 항목ansible-doc -l : ansible의 모든 모듈 및 플러그인 목록 확인ansible-doc $(module) : 특정 모듈의 매뉴얼 확인ansible [pattern] -m [module】 -a "[module options】"ansible all -m ping : 인벤토리 내 등록된 모든 노드에 ping 사용ansible group01 -a "/sbin/reboot" -u vagrant -b -k 들여쓰기는 공백 2칸으로 지정(탭은 구문 오류 발생)
시작은 —- 끝은 … 으로 표기가 권장되나 최근 생략하는 추세
여러 줄 값을 사용 시 | 나 > 기호를 사용한다
include_newlines: |
exactly as you see
will appear these three
lines of poetry
fold_nowlines: >
this is really a
single line of text
despite appearances
ansible-playbook playbook.yaml : 실행ansible-playbook playbook.yaml --syntax-check : 플레이북 문법 체크ansible-playbook playbook.yaml -C : 플레이북 간이 체크 (작업 X) ansible-playbook playbook.yaml -C -diff --limit host1 : 차이점 모드file + copy 모듈
---
- name: test file modules
hosts: host1
tasks:
- name: file create
file:
path: /tmp/fileA
state: touch
- name: file copy
copy:
src: /tmp/fileA
dest: /tmp/fileB
remote_src: true # remote_src가 true인 경우 대상 hosts의 경로에서 src를 찾는다.
- name: file remove
file:
path: /tmp/fileA
state: absent
- name: file link create
file:
src: /tmp/fileB
dest: /tmp/fileC
state: link
- name: directory create
file:
path: /tmp/test_dir
state: directory
...
user 모듈
---
- name: user test
hosts: host1
tasks:
- name: default user create
user:
name: ansible-user01
state: present
- name: uid and shell user create
user:
name: ansible-user02
state: present
uid: 2000
shell: /bin/sh
- name: group create
group:
name: ansible-group
gid: 3000
- name: primary group change
user:
name: ansible-user01
group: ansible-group
- name: secondary group change
user:
name: ansible-user02
groups: ansible-group
cron 모듈
---
- name: test cron
hosts: host1
tasks:
- name: cron job add
cron:
name: test cron
weekday: "2"
minute: "0"
hour: "12"
user: "root"
job: "ls -l /tmp"
cron_file: test_cron
...
parted 모듈
---
- name: parted test
hosts: host1
tasks:
- name: partitioning
parted:
# part_start 생략 시 fdisk 기본값과 같은 값이 입력
device: /dev/sdb
number: 1
part_end: 1GiB
state: present
fs_type: ext4
...
nmcli 모듈
- name : nmcli test
hosts: host1
tasks:
- name: Change IP
nmcli:
type: ethernet
conn_name: static
ip4: 192.168.56.200/24
state: present
gw4: 192.168.56.255
dns4: 8.8.8.8
ifname: eth1
method4: manual
- name: Change dns priority /etc/hosts
lineinfile:
path: /etc/hosts
line: "8.8.8.8 dns"
state: present
nfs 연결
- name: nfs-test
hosts: host1
tasks:
- name: Install nfs-utils package
dnf:
name: nfs-utils
state: latest
- name: nfs enable & start
become: true
command:
cmd: systemctl enable --now nfs-server
- name: mount setting
become: true
lineinfile:
path: /etc/fstab
line: "192.168.56.100:/home/vagrant/test /home/vagrant/nfs_test nfs defaults 0 1"
state: present
- name: final mount
become: true
command: mount -a
변수를 정의할 수 있는 위치는 아래와 같다.
기본 변수
variable: value 처럼 yaml 파일 형태의 Key:value로 지정# playbook.yaml
- name: This play is webserver config
hosts: host2
vars:
pkg_name: httpd
content_file: index.html
fw_rule: http
fw_st: enabled
tasks:
- name: "{{ pkg_name }} package install"
dnf:
name: "{{ pkg_name }}"
state: latest
목록 변수
# playbook.yaml
- name: test variables
hosts: localhost
vars:
pkg_name: httpd
region:
- northeast
- southeast
- midwest
foo:
field1: one
field2: two
tasks:
debug:
msg: "{{ region }}"
- name: list variable one print
debug:
msg: "{{ region[0] }}"
사전 변수
# playbook.yaml
- name: test variables
hosts: localhost
vars:
pkg_name: httpd
region:
- northeast
- southeast
- midwest
foo:
field1: one
field2: two
tasks:
- name: dictionary variable
debug:
msg: "{{ foo }}"
- name: dictionary variable
debug:
msg: "{{ foo['field1'] }}"
등록 변수
# playbook.yaml
- name: register test
hosts: host1
tasks:
- name: create user
user:
name: register_user01
state: present
register: debug_result
- name: print register uid only
debug:
msg: "{{ debug_result['uid'] }}"
호스트 변수
# inventory.ini
ctrl-node # var01=value01
host1 user_name=user01 user_st=absent
host2 user_name=user02 user_st=present
host3 user_name=user03 user_st=present
host4
[web]
host[1:2]
[db]
host[3:4]
그룹 변수 : 인벤토리의 그룹별로 변수를 저장
ctrl-node # var01=value01
host1
host2
host3
host4
[web]
host[1:2]
[web:vars]
var01=value02
[db:vars]
var01=value03
[db]
host[3:4]
플레이북에 변수 파일 포함
ansible 사용 디렉토리에서 vars/external_vars.yaml 파일을 생성(폴더, 파일이름 변경 가능)
생성된 변수 파일을 플레이북에 기재
# /var/external_var.yaml
somevar: somevalue
# playbook.yaml
- name: other vars file
hosts: localhost
vars_files:
- var/external_var.yaml
tasks:
- debug:
msg: "{{ somevar }}"
커맨드 런타임
ansible-playbook 사용 시 -e(extra-vars)에 변수를 정의
ansible-playbok playbook.yaml -e "version=1.0.0 other_var=foo"
ansible-playbok playbook.yaml -e '{"version":"1.0.0", "other_var"="foo"}'
ansible-playbok playbook.yaml -e "@/var/external_var.yaml"
프롬프트를 통한 변수 입력
- name: User Create with password_prompt
hosts: host1
vars_prompt:
- name: username
prompt: Enter username
private: false
default: admin
- name: hashed_password
prompt: Enter Password
private: true
encrypt: sha512_crypt
confirm: true
salt_size: 16
tasks:
- name: Create user
user:
name: "{{ username }}"
password: "{{ hashed_password }}"
변수에 기본값 제공 혹은 형식 변환하며 | 를이용해 필터 지정
기본값
- name: test filter
hosts: host1
tasks:
- debug:
msg: "{{ var01 | hash('sha256') }}"
ansible_ 로 시작하는 변수로 이루어진 운영체제, IP 주소, NIC 정보, 디스크 장치 등의 관리 노드와 관련된 정보를 가진 변수
ansible all -m setup특정 host의 hostname을 조건으로 작업 시 loop를 사용하면 안되고(=하나의 값) 단일 팩트로 조건 지정을 하면 host 작업 시 해당 host가 가진 fact로 변경된다.
name: fact test
hosts: all
gather_facts: false
tasks:
- name: print ifname
debug:
msg: "{{ ansible_eth1['ipv4']['address'] }}"
- name: custom fact print
debug:
msg: "{{ ansible_local }}"
# /etc/ansible/facts.d/reference.fact
[general]
foo=1
bar=2Python의 웹 템플릿 엔진인 Jinja2 를 사용할 수 있기 때문에 jinja 문법으로 파일을 작성하고 ansible로 작업을 한다면 반복적인 작업을 훨씬 편하게 사용할 수 있다.
{{ ansible_managed | comment }}
{# /etc/hosts line #}
{% for host in groups['all'] %}
{{ hostvars[host]['ansible_facts']['default_ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
{% endfor %}
변수로 지정된 리스트, 딕셔너리처럼 반복되는 요소를 이용해 for문을 사용하는 것처럼 ansible-playbook에 반영이 가능하다
item 으로 고정된다.- name: test loop
hosts: host1
vars:
user_list: [ "testuser5", "testuser6" ]
tasks:
- name: add user item_list
user:
name: "{{ item }}"
state: present
groups: wheel
loop: "{{ user_list }}"
- name: add several users dict
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
state: present
loop:
- {name: "testuser7", groups: 'wheel' }
- {name: "testuser8", groups: 'vagrant' }변수 값을 이용해 작업의 상태를 변경할 수 있는 기능
{{ }} 이중 중괄호를 사용하지 않는다.$(변수) is $(비교값) → 해당 변수가 비교값과 동일한지 확인- name: control fact
hosts: all
vars:
user_list: ["user01", "user02", "user03"]
tasks:
- user:
name: "{{ item }}"
state: absent
when: ansible_facts['hostname'] == "host2"
loop: "{{ user_list }}"작업 실행 후 시스템의 변경이 있을 때 별도의 작업을 호출 후 실행
작업 → 알림 전송 → 핸들러 실행
핸들러는 알림의 순서가 아닌 yaml 파일의 순서대로 진행
둘 이상의 핸들러 작업의 이름이 같은 경우 알림은 마지막 핸들러 작업을 실행
name: Verify apache installation
hosts: host1
vars:
http_port: 443
max_clients: 200
tasks:
- name: Ensure apache is at the latest version
dnf:
name: httpd
state: latest
- name: Write the apache config file
lineinfile:
line: Listen {{ http_port }}
regexp: ^Listen 80
path: /etc/httpd/conf/httpd.conf
notify:
- Restart apache
handlers:
- name: Restart apache
service:
name: httpd
state: restarted
delegate를 사용하면 플레이 또는 일부 작업을 제어 노드나 다른 관리 노드에서 실행 할 수 있도록 해준다.
delegate_to 키워드를 통해 호스트를 지정detegate_to: localhost 대신 local_action: 키워드를 사용- name: test delegate
hosts: host1
tasks:
- name: create file
file:
name: /tmp/test_delegate
state: touch
delegate_to: host2Rescue(=실패 처리)
always(=무조건 실행)
- 작업의 실패, 성공과 관계없이 무조건 실행되는 구문
- 파이썬의 finally와 유사
name: test block
hosts: all
tasks:
- name: package and service block
block:
- name: package install
dnf:
name: nfs-utils
state: latest
- name: service start
service:
name: nfs-server
state: started
enabled: true
when: ansible_hostname == "host1"
rescue:
- debug:
msg: This is rescue
always:
- debug:
msg: This is always
많은 작업을 가진 플레이북에서 작업이나 블록 별로 태그를 부여해 플레이북 실행 시 태그를 기준으로 작업에 대한 진행을 조절할 수 있다.
ansible-playbook --tags all $(playbook) : 모든 작업 실행(=default)
ansible-playbook --tags [tag1, tag2] $(playbook) : 특정 태그만 실행
ansible-playbook --skip-tags [tag1, tag2] $(playbook) : 특정 태그 작업 건너뛰기
ansible-playbook --tagged $(playbook): 태그가 설정된 작업만 실행
ansible-playbook --untagged $(playbook) : 태그가 없는 작업만 실행
ansible-playbook --list-tags : 사용 가능한 태그 목록 확인
ansible-playbook --list-tasks : --tags 및 --skip-tags 옵션과 함께 사용 시 관련 작업 목록 확인
--skip-tags 명령으로 명시되는 경우를 제외하고 항상 실행--tags never 명령으로 명시적으로 태그를 실행하는 경우를 제외하고 항상 실행되지 않음ignore_errors - Play 레벨ignore_unreachable - Play 레벨force_handlers - playbook 레벨failed_when - play 레벨changed_when - play 레벨any_errors_fatal- playbook 레벨max_fail_percentage - playbook 레벨Ansible은 기본적으로 5개의 포크(Fork)를 사용해 하나의 작업을 동시에 5개의 호스트에서 실행
ansible-playbook linear.yaml -f 2 : -f는 포크의 개수(=동시처리 수) 를 조절 가능
serial : 한번에 작업을 처리할 호스트의 수
fork : 플레이를 실행 할 때 한 호스트당 한번에 처리할 작업의 수
throttle : play 레벨, 블록 레벨
Ansible은 작업을 기본적으로 동기식으로 수행한다.
-B or --background : 비동기 실행 작업의 타임아웃 시간 설정-P or --pool : 비동기 작업을 실행 시 작업 사이의 시간 간격(=default 15초)ansible host1 -B 600 -P 0 -a "sleep 1M" : 실행 작업의 타임아웃 10분, 풀링 없음ansible host1 -m async_status -a jid=$(jobid Number)객체지향 프로그래밍처럼 ansible에서도 만들어둔 변수, 작업, 플레이북, 역할 파일을 참조해 작업을 작성할 수 있으며, 이를 통해 ansible 플레이북의 유지보수의 용이성과 재사용성을 높일 수 있다.
vars_files 키워드, include_vars 모듈을 이용해 외부 변수 파일 참조| 항목 | include | import |
|---|---|---|
| 재사용 형식 | 동적 | 정적 |
| 처리 시점 | 모듈 실행 시 | 플레이북 파싱 시 전처리 |
| 작업 옵션 | 작업 자체를 포함하는 경우만 | 모든 가져오기 모듈 적용 가능 |
| 반복문 호출 | O | X |
| 태그 및 작업 목록 확인 | X | O |
| 핸들러 호출 | 파일 내 작업 이름 호출 X | 파일 내 작업 이름 호출 O |
| 작업 시작 | X | O |
| 플레이북 전체 가져오기 | X | O |
| 변수 파일 가져오기 | O | X |
역할 - 표준화된 디렉토리 및 파일 구조를 기반으로 변수,작업, 핸들러, 템플릿 등을 구조화
ansible-galaxy init role $(role) : 롤 기반의 표준화된 디렉토리 및 파일 구조를 생성pre_tasks 의 작업pre_tasks 의 핸들러post_tasks 의 작업post_tasks 의 핸들러ansible-galaxy role search <ROLE> : 역할 검색 시 태그, 플랫폼, 작성자로 검색ansible-galaxy role search elasticsearch --author <SOMEONE> : 역할과 작성자로 검색--platform : 플랫폼--author : 작성자--galaxy-tags : 태그ansible-galaxy role info <ansible galaxy user>.role_name : 특정 유저의 역할 정보 확인ansible-galaxy role install <ansible galaxy user>.role_name : 역할 설치ansible-galaxy role remove <ansible galaxy user>.role_name : 설치된 역할 제거Ansible Vault는 플레이북 또는 변수 파일을 암호화 하거나 변수 값을 암호화하여 민감한 콘렌츠를 보호 할 수 있다
ansible-vault --vault-password-file <source>--vault-id label@sourceansible-vault encrypt --vault-id <label>@<source> <filename>ansible-vault decrypt --vault-id <label>@<source> <filename>ansible-vault create --vault-id <label>@<source> <filename>ansible-vault encrypt_string --vault-id <label>@prompt 'abcd'ansible-playbook --vault-id <label>@prompt playbook.yml 을 입력 후 패스워드를 입력하면 암호화된 변수의 값이 복호화 되어 화면에 출력된다.