Ansible Playbook 심화 (vault, Facts, include_tasks, 조건문)
vagrantfile의 ansible server 부분에
cfg.vm.provision "shell", inline: "yum -y install epel-release" 추가
그리고 이제 window는 주석처리
=begin 부터 =end까지 한번에 주석 가능
# --- Ansible Server ---
Vagrant.configure("2") do |config|
config.vm.define "my-ansible-server" do |cfg|
cfg.vm.box = "centos/7"
cfg.vm.provider "virtualbox" do |vb|
vb.name = "my-ansible-server"
vb.cpus = 2
vb.memory = 4096
vb.gui = false
end
cfg.vm.host_name = "control.example.com"
cfg.vm.network "private_network", ip: "192.168.110.10"
cfg.vm.provision "shell", path: "ssh_conf.sh"
cfg.vm.synced_folder "../data", "/vagrant", disabled: true
############# 이부분 추가
cfg.vm.provision "shell", inline: "yum -y install epel-release"
#########################
cfg.vm.provision "shell", inline: "yum -y install centos-release-ansible-29.noarch"
cfg.vm.provision "shell", inline: "yum install ansible -y"
cfg.vm.provision "file", source: "ansible_env_ready.yml",
destination: "ansible_env_ready.yml"
cfg.vm.provision "shell", inline: "ansible-playbook ansible_env_ready.yml"
end
... 생략
ansible_env_ready.yaml 에서도 hosts파일에 있는 윈도우는 지우고(주석말고 지우기)
Generate sshkey 구문을 추가. (known_hosts를 직접 처리하기위해)
추가 안하면 ssh node1 이런식으로 접속하면서 fingerprint를 직접 등록해야 한다.
- name: setup for the ansible environment
hosts: localhost
gather_facts: no
tasks:
- name: add "/etc/hosts"
blockinfile:
path: /etc/hosts
block: |
192.168.110.20 node1.example.com node1
192.168.110.30 node2.example.com node2
192.168.110.40 node3.example.com node3
192.168.110.50 node4.example.com node4
192.168.110.60 node5.example.com node5
- name: add "/etc/ansible/hosts"
blockinfile:
path: /etc/ansible/hosts
block: |
[centos]
node1
node2
node3
[ubuntu]
node4
node5
# 추가된 곳 #################
- name: Generate sshkey
become: yes
become_user: vagrant
shell: "{{item}}"
with_items:
- "ssh-keyscan 192.168.110.20 >> ~/.ssh/known_hosts"
- "ssh-keyscan 192.168.110.30 >> ~/.ssh/known_hosts"
- "ssh-keyscan 192.168.110.40 >> ~/.ssh/known_hosts"
- "ssh-keyscan 192.168.110.50 >> ~/.ssh/known_hosts"
- "ssh-keyscan 192.168.110.60 >> ~/.ssh/known_hosts"
##############################
- name: create vim env directory & files
shell: "{{item}}"
loop:
- "touch /home/vagrant/.vimrc"
- "touch /home/vagrant/.bashrc"
... 생략
하지만 이렇게 known_hosts에 직접 등록하는건 많으면 효율적이지 못하다.
그러므로 자동화 하기 위해 아래와 같이 작성한다.
공개키 생성 및 fingerprint 저장
먼저 auto_pass.yml 파일을 만든다
- name: Create authority between server and nodes
hosts: all
connection: local
serial: 1
gather_facts: no
tasks:
- name: ssh-keyscan for known_hosts file
command: /usr/bin/ssh-keyscan -t ecdsa {{ ansible_host }}
register: keyscan
- name: input key
lineinfile:
path: ~/.ssh/known_hosts
line: "{{ item }}"
create: yes
with_items:
- "{{ keyscan.stdout_lines }}"
그후 vagrantfile을 수정한다. (server만)
# --- Ansible Server ---
Vagrant.configure("2") do |config|
config.vm.define "my-ansible-server" do |cfg|
cfg.vm.box = "centos/7"
cfg.vm.provider "virtualbox" do |vb|
vb.name = "my-ansible-server"
vb.cpus = 2
vb.memory = 4096
vb.gui = false
end
cfg.vm.host_name = "control.example.com"
cfg.vm.network "private_network", ip: "192.168.110.10"
cfg.vm.provision "shell", path: "ssh_conf.sh"
cfg.vm.synced_folder "../data", "/vagrant", disabled: true
cfg.vm.provision "shell", inline: "yum -y install epel-release"
cfg.vm.provision "shell", inline: "yum -y install centos-release-ansible-29.noarch"
cfg.vm.provision "shell", inline: "yum install ansible -y"
cfg.vm.provision "file", source: "ansible_env_ready.yml",
destination: "ansible_env_ready.yml"
cfg.vm.provision "shell", inline: "ansible-playbook ansible_env_ready.yml"
### 추가된 부분
cfg.vm.provision "file", source: "auto_pass.yml", destination: "auto_pass.yml"
cfg.vm.provision "shell", inline: "ansible-playbook auto_pass.yml",
privileged: false # vagrant 계정의 권한을 위해 (안쓰면 root 권한으로 만들어짐)
##############
ansible_env_ready.yml에 등록했던 Generate sshkey 부분을 삭제하고
vagrant provision으로 적용시킨다.
공개키 배포
fingerprint는 등록이 되어있지만,
아직까지는 비밀번호가 필요하다. (-k 사용해야함)
auto_pass.yml 파일을 수정
- name: Create authority between server and nodes
hosts: nodes
connection: local
serial: 1
gather_facts: no
### 추가된 부분 ###
vars:
ansible_password: vagrant
###################
tasks:
- name: ssh-keyscan for known_hosts file
command: /usr/bin/ssh-keyscan -t ecdsa {{ ansible_host }}
register: keyscan
- name: input key
lineinfile:
path: ~/.ssh/known_hosts
line: "{{ item }}"
create: yes
with_items:
- "{{ keyscan.stdout_lines }}"
### 추가된 부분 ###
- name: ssh-keygen for authorized_keys 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: vagrant
state: present
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
###################
우분투는 안될 수 있는데 fingerprint 받은 다음 (ssh 접속을 통해)
파이썬을 설치하고 ans ubuntu -m shell -a "sudo apt python" -k ( 설치 안해도 되는듯?)
ans ubuntu -m shell -a "sudo ln -s /usr/bin/python3 /usr/bin/python" -k
위의 명령을 통해 python3를 그냥 python으로 link를 걸어주면 된다.
(서버가 CentOS7(2.75)이고 node가 ubuntu(3.xx)라서 python 버전이 안맞아서 인듯)
대신 이런 경고문구가 뜨는데 무시해도 된다.
[DEPRECATION WARNING]: Distribution ubuntu 22.04 on host node5 should use
/usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior
Ansible releases. A future Ansible release will default to using the discovered platform
python for this host. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can
be disabled by setting deprecation_warnings=False in ansible.cfg.
하지만 경고를 없애고 싶다면, 다시 링크를 삭제 하면 됨
ans ubuntu -m shell -a "sudo unlink /usr/bin/python" -k
복잡하고 귀찮은 작업이지만 한번만 해두면 되는거니까...
물론 지금 하는 작업은 비밀번호가 다 같다는 전제하에 하는것임.
ansible vault
auto_pass.yml 같은 경우에는 비밀번호가 들어 있기 때문에 암호화 하는 것이 좋다.
ansible-vault encrypt auto_pass.yml # 암호화
ansible-vault decrypt auto_pass.yml # 암호화된 파일 복호화
ansible-vault create auto_pass.yml # 파일 작성시부터 암호화
ansible-vault edit auto_pass.yml # 암호화된 파일 수정
ansible-vault view auto_pass.yml # 암호화된 파일 보기
암호화된 파일은 ansible-playbook으로 실행할 수 없다. (복호화 후에 진행해야 함)
Facts 변수
facts.yaml
- name: print ipv4.address for nodes
hosts: nodes
#gather_facts: no ## fact변수를 사용할때 gather_facts: no가 있으면 안됨.
tasks:
- name: debug by msg
debug:
msg:
- "eth0s ip {{ ansible_eth0.ipv4.address }}"
- "eth1s ip {{ ansible_eth1.ipv4.address }}"
- name: debug by var
debug:
var: "{{ item }}"
with_items:
- hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']
- hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']
결과를 확인해보면 알겠지만, msg와 var를 둘다 쓸 수는 있지만
msg로 쓰는것이 보기 좋고 작성할때도 구분자를 적게 입력하기 때문에 편하다.
msg는 "." 마침표로 구분, var는 "[ ]" 대괄호로 구분한다.
결과
[vagrant@control work]$ anp facts.yaml
PLAY [print ipv4.address for nodes] ***************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [node2]
ok: [node1]
ok: [node3]
ok: [node4]
ok: [node5]
TASK [debug by msg] *******************************************************************************
ok: [node1] => {
"msg": [
"eth0s ip 10.0.2.15",
"eth1s ip 192.168.110.20"
]
}
ok: [node2] => {
"msg": [
"eth0s ip 10.0.2.15",
"eth1s ip 192.168.110.30"
]
}
ok: [node3] => {
"msg": [
"eth0s ip 10.0.2.15",
"eth1s ip 192.168.110.40"
]
}
ok: [node4] => {
"msg": [
"eth0s ip 10.0.2.15",
"eth1s ip 192.168.110.50"
]
}
ok: [node5] => {
"msg": [
"eth0s ip 10.0.2.15",
"eth1s ip 192.168.110.60"
]
}
TASK [debug by var] *******************************************************************************
ok: [node1] => (item=hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']": "10.0.2.15",
"item": "hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']"
}
ok: [node1] => (item=hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']": "192.168.110.20",
"item": "hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']"
}
ok: [node3] => (item=hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']": "10.0.2.15",
"item": "hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']"
}
ok: [node3] => (item=hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']": "192.168.110.40",
"item": "hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']"
}
ok: [node2] => (item=hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']": "10.0.2.15",
"item": "hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']"
}
ok: [node2] => (item=hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']": "192.168.110.30",
"item": "hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']"
}
ok: [node4] => (item=hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']": "10.0.2.15",
"item": "hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']"
}
ok: [node4] => (item=hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']": "192.168.110.50",
"item": "hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']"
}
ok: [node5] => (item=hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']": "10.0.2.15",
"item": "hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address']"
}
ok: [node5] => (item=hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']) => {
"ansible_loop_var": "item",
"hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']": "192.168.110.60",
"item": "hostvars[inventory_hostname]['ansible_eth1']['ipv4']['address']"
}
When 조건
조건에 맞을때 해당하는 play를 실행하라는것
nginx를 ubuntu와 centos에 설치하기
- name: install nginx
hosts: nodes
become: yes
tasks:
- name: install epel-release for CentOS
action: "{{ ansible_pkg_mgr }} name=epel-release state=latest" # action은 facts변수를 쓰기위해
when: ansible_distribution == 'CentOS' # CentOS일때 action을 실행해라
- name: install nginx web server for CentOS
action: "{{ ansible_pkg_mgr }} name=nginx state=present"
when: ansible_distribution == 'CentOS'
- name: upload default index.html
get_url:
url: https://www.nginx.com
dest: /usr/share/nginx/html/
mode: 0644
when: ansible_distribution == 'CentOS'
- name: start nginx
service:
name: nginx
state: started
when: ansible_distribution == 'CentOS'
- name: install nginx for ubuntu
action: "{{ ansible_pkg_mgr }} name=nginx state=present update_cache=yes"
when: ansible_distribution == 'Ubuntu'
- name: upload default index.html
get_url:
url: https://www.nginx.com
dest: /usr/share/nginx/html/
mode: 0644
validate_certs: no
when: ansible_distribution == 'Ubuntu'
include_tasks
playbook안에서 다른 yaml 파일을 참조하는것
(참조되는 yaml파일은 hosts, tasks를 빼고 그냥 모듈부터 적어야함)
ex) include_tasks.yaml
[vagrant@control work]$ cat include_tasks.yaml
- name: install nginx
hosts: nodes
become: yes
tasks:
- name: nginx for CentOS
include_tasks: CentOS.yaml
when: ansible_distribution == 'CentOS'
- name: nginx for Ubuntu
include_tasks: Ubuntu.yaml
when: ansible_distribution == 'Ubuntu'
CentOS.yaml
[vagrant@control work]$ cat CentOS.yaml
- name: install epel-release
action: "{{ ansible_pkg_mgr }} name=epel-release state=latest"
- name: install nginx web server
action: "{{ ansible_pkg_mgr }} name=nginx state=present"
- name: nginx start
service:
name: nginx
state: started
when: ansible_distribution == 'CentOS'
Ubuntu.yaml
[vagrant@control work]$ cat Ubuntu.yaml
- name: install nginx
action: "{{ ansible_pkg_mgr }} name=nginx state=present update_cache=yes"
- name: upload default index.html
get_url:
url: https://www.nginx.com
dest: /usr/share/nginx/html/
mode: 0644
validate_certs: no
if 조건
when말고도 if를 통해서 조건문을 작성 할 수 있다.
include_tasks.yaml 에서 when대신 vars를 이용한 if로 변경을 해본다면
if_nginx.yaml
[vagrant@control work]$ cat if_nginx.yaml
- name: install nginx on the nodes
hosts: nodes
become: yes
vars:
lnx_name: "{{ 'CentOS' if ansible_distribution == 'CentOS'
else 'Ubuntu' if ansible_distribution == 'Ubuntu'
else 'Just Linux' }}"
tasks:
- name: nginx for any linux
include_tasks: "{{ lnx_name }}.yaml"
** lnx_name ??
if 조건문을 사용하기 위한 변수라고 생각하면 될듯.
(lnx_name이 아닌 다른이름을 적고 playbook을 실행했더니 lnx_name이 없다고 나옴)
실행하면 skipped가 발생하지 않고 깔끔하게 된다.
대신 작성했을 때 가독성이 안좋음
[vagrant@control work]$ anp if_nginx.yaml
PLAY [install nginx on the nodes] *****************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [node3]
ok: [node2]
ok: [node1]
ok: [node5]
ok: [node4]
TASK [nginx for any linux] ************************************************************************
included: /home/vagrant/work/CentOS.yaml for node1, node2, node3
included: /home/vagrant/work/Ubuntu.yaml for node4, node5
TASK [install epel-release] ***********************************************************************
ok: [node1]
ok: [node2]
ok: [node3]
TASK [install nginx web server] *******************************************************************
ok: [node1]
ok: [node2]
ok: [node3]
TASK [nginx start] ********************************************************************************
ok: [node2]
ok: [node3]
ok: [node1]
TASK [install nginx] ******************************************************************************
ok: [node4]
ok: [node5]
TASK [upload default index.html] ******************************************************************
changed: [node4]
ok: [node5]
** 혹시나 ansible 모듈이 뭐가 있는지 궁금하다면 ansible-doc으로 찾아봐도 된다.
하지만 list로 보기 힘드므로 /usr/lib/python2.7/site-packages/ansible/modules 여기 안에 들어가서 찾는게 더 편함
물론 버전마다 python뒤에 있는 숫자가 바뀔수는 있음
'Ansible' 카테고리의 다른 글
ansible 미니 프로젝트 - wordpress 사이트 배포 (0) | 2024.02.22 |
---|---|
Handler, Template, Role (0) | 2024.02.20 |
centos, ubuntu, window node 생성 및 nfs (0) | 2024.02.15 |
실습 (0) | 2024.02.14 |
Playbook (0) | 2024.02.13 |