설치 환경 : Centos7
yum install ansible 할 때 no package ansible available 이라고 나오면
-> 기본적으로 갖고 있는 공간 내에선 ansible 설치 패키지가 들어있지 않음.
extra packages for enterprise linux
yum -y install epel-release
yum repolist
설치 다 하면 다시
yum -y install ansible
다른 node와 통신하기 위해 hosts 파일에 node의 ip 추가
[root@Ansible-Server ~]# tail -3 /etc/ansible/hosts
172.20.10.11
172.20.10.12
172.20.10.13
아래 명령어를 통해 public key 키 교환을 위해 yes를 입력
[root@Ansible-Server ~]# ansible all -m ping
Ansible 옵션
-i(--inventory-file) : 적용될 호스트에 대한 파일 지정
-m(--module-name) : 모듈 선택
-k(--ask-pass) : 패스워드를 물어보도록 설정
-K(--ask-become-pass) : 관리자로 권한 상승
--list-hosts : 적용되는 호스트 확인
[root@Ansible-Server ~]# ansible nginx -m ping --list-hosts
hosts (3):
172.20.10.11
172.20.10.12
172.20.10.13
#아래에서 사용하는 ping은 ICMP의 ping이 아닌 Python으로 짜여진 Module이다.(내부에서 호출)
그 다음부턴 -k 옵션을 통해 public key 교환을 skip하고 해당 node들과 통신이 가능
[root@Ansible-Server ~]# ansible all -m ping -k
SSH password:
172.20.10.13 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
172.20.10.12 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
172.20.10.11 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
별칭 사용
[]로 묶으면 아래 세 IP가 nginx라는 그룹으로 묶이게 된다.
[root@Ansible-Server ~]# tail -4 /etc/ansible/hosts
[nginx]
172.20.10.11
172.20.10.12
172.20.10.13
기존 all을 통해 노드와의 통신을 확인하기 위한 방법 대신
[root@Ansible-Server ~]# ansible all -m ping -k
SSH password:
172.20.10.13 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
172.20.10.12 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
172.20.10.11 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
nginx 별칭을 통한 통신 확인이 가능하다.
[root@Ansible-Server ~]# ansible nginx -m ping -k
SSH password:
172.20.10.12 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
172.20.10.13 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
172.20.10.11 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Ansible을 사용하면 각각의 계정에 접속하여 명령어를 입력하지 않아도 되는 편리함이 있고,
중앙에서 관리되어 빠른 일처리가 가능하다.
또한 명령어를 보게 되면 Readable 하기 때문에 어떤 작업인지 한 눈에 파악할 수 있다.수행하려는 작업에 맞는 Module을 설정하여 사용한다.
uptime
[root@Ansible-Server ~]# ansible all -i test -m shell -a "uptime" -k
SSH password:
172.20.10.11 | CHANGED | rc=0 >>
07:45:46 up 11 min, 2 users, load average: 0.03, 0.04, 0.05
디스크 용량 확인
[root@Ansible-Server ~]# ansible all -i test -m shell -a "df -k" -k
SSH password:
172.20.10.11 | CHANGED | rc=0 >>
Filesystem 1K-blocks Used Available Use% Mounted on
devtmpfs 237348 0 237348 0% /dev
tmpfs 249336 0 249336 0% /dev/shm
tmpfs 249336 4664 244672 2% /run
tmpfs 249336 0 249336 0% /sys/fs/cgroup
/dev/mapper/centos-root 52403200 1286600 51116600 3% /
/dev/mapper/centos-home 2090879492 33004 2090846488 1% /home
/dev/sda1 1038336 140288 898048 14% /boot
tmpfs 49868 0 49868 0% /run/user/0
메모리 상태 확인
[root@Ansible-Server ~]# ansible all -i test -m shell -a "free -h" -k
SSH password:
172.20.10.11 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 486M 143M 243M 4.6M 99M 325M
Swap: 2.0G 0B 2.0G
사용자 유저 만들기
[root@Ansible-Server ~]# ansible all -i test -m user -a "name=Ansi password=toor" -k
SSH password:
[WARNING]: The input password appears not to have been hashed. The 'password' argument must
be encrypted for this module to work properly.
172.20.10.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1001,
"home": "/home/Ansi",
"name": "Ansi",
"password": "NOT_LOGGING_PASSWORD",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1001
}
[root@node01 ~]# tail -1 /etc/passwd
Ansi:x:1001:1001::/home/Ansi:/bin/bash
파일 전송하기
- 특정 파일을 모든 서버에 빈번하게 전송해야 할 일이 생긴다.
[root@Ansible-Server ~]# ansible all -i test.file -m copy -a "src=./test.file dest=/tmp" -k
SSH password:
172.20.10.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "d036d694737d92a0c94c166b1f1a9f3dc82dec94",
"dest": "/tmp/test.file",
"gid": 0,
"group": "root",
"md5sum": "f1d0895613ff05cb7fb1af0aa7fe56e5",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 13,
"src": "/root/.ansible/tmp/ansible-tmp-1627041385.3-1810-235100174201201/source",
"state": "file",
"uid": 0
}
[root@Ansible-Server ~]# ssh root@172.20.10.11
root@172.20.10.11's password:
Last login: Fri Jul 23 07:56:27 2021 from 172.20.10.10
[root@node01 ~]# cd /tmp/
[root@node01 tmp]# ls | grep test.file
test.file
서비스 설치
[root@Ansible-Server ~]# ansible guest -m yum -a "name=httpd state=present" -k
[root@node01 ~]# systemctl status httpd
httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: man:httpd(8)
man:apachectl(8)
혹은
[root@Ansible-Server ~]# ansible guest -m shell -a "systemctl status httpd" -k
SSH password:
172.20.10.11 | FAILED | rc=3 >>
httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: man:httpd(8)
man:apachectl(8)non-zero return code
Ansible PlayBook
사용자가 원하는 내용을 미리 정의해둔 것
ex) 대량의 서버에 웹 서비스를 설치하고 구동해야 할 땐?
1. 웹 서버용 Virtual or Real 서버에 NginX를 설치
(Apache는 점유율이 꾸준히 하락, NginX는 상승중)
2. 메인페이지의 파일 전송
3. 서비스 재시작
이 과정을 Ansible PlayBook에 넣어놓고 한 번에 실행 가능
이 PlayBook은 멱등성(idempotent)의 특성을 가지고 있다.
멱등성
연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질
예를 들어, 아래와 같이 /etc/ansible/hosts 파일에 특정 내용을 추가하는 명령어가 있다.
(-e 옵션은 뒤에 추가될 내용의 \n과 같은 문자들을 엔터로 해석한다.)
[root@Ansible-Server ~]# echo -e "[test]\n192.168.219.13" >> /etc/ansible/hosts
사용자는 ip 주소 192.168.219.13을 hosts 파일에 추가할 예정이며 같은 명령어를 여러 번 수행해도
hosts에는 해당 내용이 한번만 추가돼야 한다.
그러나 결과는 아래와 같이 계속해서 추가된다.
[root@Ansible-Server ~]# echo -e "[test]\n192.168.219.13" >> /etc/ansible/hosts
[root@Ansible-Server ~]# echo -e "[test]\n192.168.219.13" >> /etc/ansible/hosts
[root@Ansible-Server ~]# tail -4 /etc/ansible/hosts
[test]
192.168.219.13
[test]
192.168.219.13
이러한 상황을 피하기 위해 Ansible PlayBook을 사용한다.
- host.yml
[root@Ansible-Server ~]# vi host.yml
---
- name: Ansible_vim
hosts: localhost
tasks:
- name: Add ansible hosts
blockinfile:
path: /etc/ansible/hosts
block: |
[host]
192.168.219.11
위와 같이 yaml 형식의 파일을 만들어준 후 아래 명령어를 실행한다.
[root@Ansible-Server ~]# ansible-playbook host.yml
PLAY [Ansible_vim] **************************************************************
TASK [Gathering Facts] **********************************************************
ok: [localhost]
TASK [Add ansible hosts] ********************************************************
changed: [localhost]
PLAY RECAP **********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
이렇게 PlayBook으로 실행하면 멱등성의 성질에 따라 여러 번 수행해도 결과가 변하지 않는다.
[root@Ansible-Server ~]# tail -4 /etc/ansible/hosts
# BEGIN ANSIBLE MANAGED BLOCK
[host]
192.168.219.11
# END ANSIBLE MANAGED BLOCK
PlayBook을 사용하여 3개의 노드에 nginx 설치 및 구동
먼저 yml 파일을 생성해준다.
- nginx.yml
[root@Ansible-Server ~]# cat nginx.yml
---
- hosts: nginx
remote_user: root
tasks:
- name: install epel-release
yum: name=epel-release state=latest
- name: install nginx web server
yum: name=nginx state=present
- name: Start nginx web server
service: name=nginx state=started
ansible-playbook 명령어를 통해 nginx.yml을 실행한다.
[root@Ansible-Server ~]# ansible-playbook nginx.yml -k
아래와 유사한 에러가 발생한다면 -k 옵션을 제거하여 public key 교환을 수행한다.
Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.
[root@Ansible-Server ~]# ansible-playbook nginx.yml
PLAY [nginx] ******************************************************************************
TASK [Gathering Facts] ********************************************************************
The authenticity of host '192.168.219.12 (192.168.219.12)' can't be established.
ECDSA key fingerprint is SHA256:35/2/xEm8yMJiry/It0SW4iqnjZL28aSA8Uie7OgSl8.
ECDSA key fingerprint is MD5:d7:c7:a4:8f:86:d6:6b:11:ec:09:d3:9d:7a:34:ff:3e.
Are you sure you want to continue connecting (yes/no)? The authenticity of host '192.168.219.11 (192.168.219.11)' can't be established.
ECDSA key fingerprint is SHA256:35/2/xEm8yMJiry/It0SW4iqnjZL28aSA8Uie7OgSl8.
ECDSA key fingerprint is MD5:d7:c7:a4:8f:86:d6:6b:11:ec:09:d3:9d:7a:34:ff:3e.
Are you sure you want to continue connecting (yes/no)? The authenticity of host '192.168.219.13 (192.168.219.13)' can't be established.
ECDSA key fingerprint is SHA256:35/2/xEm8yMJiry/It0SW4iqnjZL28aSA8Uie7OgSl8.
ECDSA key fingerprint is MD5:d7:c7:a4:8f:86:d6:6b:11:ec:09:d3:9d:7a:34:ff:3e.
Are you sure you want to continue connecting (yes/no)? yes
fatal: [192.168.219.12]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '192.168.219.12' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", "unreachable": true}
yes
fatal: [192.168.219.11]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '192.168.219.11' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", "unreachable": true}
yes
아래와 같이 실행된 결과를 확인한다.
(key 교환 이슈가 없었다면 changed=3이 표시되면 정상이다.)
PLAY RECAP ********************************************************************************
192.168.219.11 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.219.12 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.219.13 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
shell Module을 통해 세 개의 node 모두 nginx가 구동 중인 것을 확인할 수 있다.
[root@Ansible-Server ~]# ansible nginx -m shell -a "systemctl status nginx" -k
SSH password:
192.168.219.13 | CHANGED | rc=0 >>
â— nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: active (running) since Fri 2021-07-23 14:27:33 EDT; 6min ago
...
...
192.168.219.11 | CHANGED | rc=0 >>
â— nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: active (running) since Fri 2021-07-23 14:27:33 EDT; 6min ago
...
...
192.168.219.12 | CHANGED | rc=0 >>
â— nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: active (running) since Fri 2021-07-23 14:27:33 EDT; 6min ago
...
...
nginx의 default 페이지를 확인하려 했으나 정상적으로 접속이 되지 않는다.
이는 방화벽에서 http 포트를 허용해주지 않았기 때문이다.
[root@node01 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp0s3
sources:
services: dhcpv6-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
접속을 위해 80 포트를 방화벽에 추가시키도록 하자.
[root@node01 ~]# firewall-cmd --add-port=80/tcp
success
[root@node01 ~]# firewall-cmd --add-port=80/tcp --permanent
success
nginx 서버를 설치했는데 CentOS의 welcome page가 나온다.
초기화면의 경우 index.html의 값을 가져오니까 해당 디렉토리로 이동하여 확인해본다.
index.html은 아래 경로에 있으며 내용을 한번 확인해보자
[root@node01 html]# pwd
/usr/share/nginx/html
[root@node01 html]# ls -al | grep index.html
lrwxrwxrwx. 1 root root 25 Jul 23 14:25 index.html -> ../../doc/HTML/index.html
Welcome to nginx이 아닌 CentOS의 index.html이 들어있다.
우리가 보고 싶은 건 nginx의 default 페이지이기 때문에 nginx 홈페이지에서 indexl.html을 다운받는다.
먼저 기존 centos 내용이 담긴 index.html 파일은 과감히 지워버린다.
[root@node01 html]# rm -f index.html
[root@node01 html]# curl -o index.html https://www.nginx.com
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 125k 0 125k 0 0 82416 0 --:--:-- 0:00:01 --:--:-- 82486
다시 재접속 시 원하던 nginx 페이지가 표시된다.
나머지 두 노드는 PlayBook을 통해 index.html을 복사해준다.
192.168.219.11 ip를 제외한 나머지 노드의 기존 index.html 파일을 삭제하기 위해 별칭을 추가한다.
- /etc/ansible/hosts
[upload]
192.168.219.12
192.168.219.13
yml 파일에 아래 두 줄을 추가하여 index.html을 /usr/share/nginx/html/ 디렉토리에 복사해준다.
- nginx.yml
- name: Upload default index.html for web server
copy: src=~/index.html dest=/usr/share/nginx/html/ mode=0644
현재 nginx.yml 파일은 아래와 같다.
[root@Ansible-Server ~]# cat nginx.yml
---
- hosts: upload
remote_user: root
tasks:
- name: install epel-release
yum: name=epel-release state=latest
- name: install nginx web server
yum: name=nginx state=present
- name: Upload default index.html for web server
copy: src=~/index.html dest=/usr/share/nginx/html/ mode=0644
- name: Start nginx web server
service: name=nginx state=started
playbook 명령어를 통해 nginx.yml 파일을 적용시켜준다.
[root@Ansible-Server ~]# ansible-playbook nginx.yml -k
SSH password:
PLAY [upload] *****************************************************************************
TASK [Gathering Facts] ********************************************************************
ok: [192.168.219.13]
ok: [192.168.219.12]
...
...
PLAY RECAP ********************************************************************************
192.168.219.12 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.219.13 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
접속 화면
'IaC' 카테고리의 다른 글
Terraform이란? (0) | 2022.03.25 |
---|---|
Terraform vs Ansible (0) | 2021.09.20 |