Ossian Story
article thumbnail

[Ansible] Install - CentOS 7.x



Ansible이란?


Ansible은 서버의 설정 및 관리, 소프트웨어 배포 등 다수의 서버에 대해 자동화를 구성하여 관리할 수 있는 도구입니다.




Ansible 특징


1. Agent less
  - SSH 접속이 가능한 Host라면 대부분 Ansible 작업을 실행할 수 있습니다.

2. 비교적 이해하기 쉬운 YAML 문법으로 작업을 실행 할 수 있습니다.


3. 같은 조작을 반복해서 수행하더라도 같은 결과가 달라지지 않는 멱등성을 제공합니다.


4. Play book을 사용하여 여러 Host에 정의된 'Role'과 'Task'를 맵핑하여 실행합니다.


5. Play book을 사용하지 않더라도 Ansible 명령을 통해 Host에서 작업 실행을 가능하게 합니다.



Ansible 구성


Ansible 운영할 서버 1대, Ansible Task를 수행할 Client 서버 2대로 구성하였습니다.

 - Client 서버는 Agent를 설치하는 것이 아닌 SSH 접속이 가능한 순수한 CentOS로 구성





Ansible 설치


Ansible 운영할 Ansible Controller 서버에서 SSH-KEY를 생성합니다.


[root@ansible-controller ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:owC+XZfEA1B4231AHhZK4gB2TLiO6qqLVOm2u3HaaVQ root@ansible-controller
The key's randomart image is:
+---[RSA 2048]----+
|  o==++ ..=.     |
| ...oo.= +..     |
|  .. ..o=...     |
| .... .E.o. .    |
| o.o. o S  .     |
|. +o + o .       |
|...+o..          |
|+ . *..          |
|Oo =+o           |
+----[SHA256]-----+
[root@ansible-controller ~]#




생성된 SSH Public Key를 Client로 사용할 서버 2대에 전송합니다.


[root@ansible-controller ~]# ssh-copy-id root@10.146.0.3
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '10.146.0.3 (10.146.0.3)' can't be established.
ECDSA key fingerprint is SHA256:lRWhJ4nIxKN+LPoY2SXKe5RwVD2LGq5R6kYlJdc7moA.
ECDSA key fingerprint is MD5:29:28:b8:85:58:c7:08:f4:13:a5:5b:99:01:92:f4:51.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@10.146.0.3's password:
 
Number of key(s) added: 1
 
Now try logging into the machine, with:   "ssh 'root@10.146.0.3'"
and check to make sure that only the key(s) you wanted were added.
 
 
[root@ansible-controller ~]# ssh-copy-id root@10.146.0.4
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '10.146.0.4 (10.146.0.4)' can't be established.
ECDSA key fingerprint is SHA256:UcQz7yKEiVkTsFDaadVtXE5rJ9g9qQvFD6+HiLmIocM.
ECDSA key fingerprint is MD5:bd:b6:5a:b1:60:c2:8d:14:8a:75:8e:e8:9e:bf:1e:b0.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@10.146.0.4's password:
 
Number of key(s) added: 1
 
Now try logging into the machine, with:   "ssh 'root@10.146.0.4'"
and check to make sure that only the key(s) you wanted were added.
 
[root@ansible-controller ~]#




Ansible을 설치하기 위해 EPEL Repository를 추가합니다.


[root@ansible-controller ~]# yum install -y epel-release
Loaded plugins: fastestmirror
Determining fastest mirrors
epel/x86_64/metalink                                                    |  19 kB  00:00:00
 * base: ftp.jaist.ac.jp
 * epel: mirrors.cat.pdx.edu
 * extras: ftp.jaist.ac.jp
 * updates: ftp.jaist.ac.jp
base                                                                    | 3.6 kB  00:00:00
epel                                                                    | 3.2 kB  00:00:00
extras                                                                  | 3.4 kB  00:00:00
google-cloud-compute/signature                                          |  454 B  00:00:00
google-cloud-compute/signature                                          | 1.8 kB  00:00:00 !!!
google-cloud-sdk/signature                                              |  454 B  00:00:00
google-cloud-sdk/signature                                              | 1.4 kB  00:00:00 !!!
updates                                                                 | 3.4 kB  00:00:00
(1/10): base/7/x86_64/group_gz                                          | 166 kB  00:00:00
(2/10): epel/x86_64/group_gz                                            |  88 kB  00:00:00
(3/10): base/7/x86_64/primary_db                                        | 5.9 MB  00:00:01
(4/10): epel/x86_64/updateinfo                                          | 930 kB  00:00:01
(5/10): extras/7/x86_64/primary_db                                      | 149 kB  00:00:00
(6/10): google-cloud-sdk/primary                                        |  22 kB  00:00:00
(7/10): google-cloud-compute/updateinfo                                 | 1.1 kB  00:00:00
(8/10): google-cloud-compute/primary                                    | 3.6 kB  00:00:00
(9/10): updates/7/x86_64/primary_db                                     | 2.0 MB  00:00:00
(10/10): epel/x86_64/primary                                            | 3.5 MB  00:00:01
epel                                                                               12583/12583
google-cloud-compute                                                                     10/10
google-cloud-sdk                                                                       128/128
Package epel-release-7-11.noarch already installed and latest version
Nothing to do
 
[root@ansible-controller ~]#




EPEL Repository 설치 완료 후 Ansible을 설치합니다.


[root@ansible-controller ~]# yum install -y ansible
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.jaist.ac.jp
 * epel: mirrors.cat.pdx.edu
 * extras: ftp.jaist.ac.jp
 
......
 
Dependency Installed:
  PyYAML.x86_64 0:3.10-11.el7                     libtomcrypt.x86_64 0:1.17-26.el7
  libtommath.x86_64 0:0.42.0-6.el7                libyaml.x86_64 0:0.1.4-11.el7_0
  python-babel.noarch 0:0.9.6-8.el7               python-cffi.x86_64 0:1.6.0-5.el7
  python-enum34.noarch 0:1.0.4-1.el7              python-httplib2.noarch 0:0.9.2-1.el7
  python-idna.noarch 0:2.4-1.el7                  python-jinja2.noarch 0:2.7.2-2.el7
  python-keyczar.noarch 0:0.71c-2.el7             python-markupsafe.x86_64 0:0.11-10.el7
  python-paramiko.noarch 0:2.1.1-4.el7            python-ply.noarch 0:3.4-11.el7
  python-pycparser.noarch 0:2.14-1.el7            python2-crypto.x86_64 0:2.6.1-15.el7
  python2-cryptography.x86_64 0:1.7.2-2.el7       python2-jmespath.noarch 0:0.9.0-3.el7
  sshpass.x86_64 0:1.06-2.el7
 
Complete!
 
[root@ansible-controller ~]#




Ansible 설치가 완료되었다면 " /etc/ansible/hosts " 파일에 Client IP를 등록합니다.
 - hosts 파일은 앞서 설명한 Ansible의 Inventory입니다.


[root@ansible-controller ~]# cd /etc/ansible/
ansible.cfg  hosts        roles/
 
[root@ansible-controller ~]# vi /etc/ansible/hosts




hosts 파일에 " [test] "라는 그룹을 만들고 Client IP를 입력합니다.
 - hosts 파일을 사용하여 다양한 그룹 및 Client 맵핑을 할 수 있습니다.


# Here's another example of host ranges, this time there are no
# leading 0s:
 
## db-[99:101]-node.example.com
 
[test]
10.146.0.3
10.146.0.4




"ansible all -m ping" 명령어를 입력하여 Client와 연결이 잘되었는지 확인합니다.

아래와 같이 Client에서 "pong"라는 작업이 반환 된다면 정상적으로 잘 연결된 부분입니다.


[root@ansible-controller ~]# ansible all -m ping
 
10.146.0.3 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.146.0.4 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
[root@ansible-controller ~]#




ansible [host] or [host group] or [all] 명령을 통해 지정한 Host에 작업을 실행합니다.


[root@ansible-controller ~]# ansible 10.146.0.4 -m ping
10.146.0.4 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
 
 
[root@ansible-controller ~]# ansible test -m ping
10.146.0.4 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.146.0.3 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}





Ansible 주요 명령어 및 옵션


Ansible 실행은 여러가지의 명령어와 옵션을 사용할 수 있으며 주요 옵션은 및 명령어 작성방법은 아래와 같습니다. 


" ansible [Host or Host Group or 옵션] [module] [Etc Option] "


[ -i 옵션 ]

ansible -i [ Host File Name ] -m ping -k

기본적으로 ansible 실행 시 적용할 대상의 Host or Host Group을 선택 시 " /etc/ansible/hosts/ " 파일을 사용하게 됩니다. 
" -i " 옵션을 적용한 후 사용자가 임의로 작성한 Host File을 선택할 경우 해당 파일에 작성된 Host에 Ansible 명령이 적용되게 됩니다. 


[ -m 옵션 ]

ansible all -m [ Module Name ] -k


ansible에서 실행할 모듈을 불러오게 됩니다. 예를 들어 Ansible Host에 " Ping " 명령어를 사용하고자 할 경우 " Ping " 모듈을 불러온 후 사용할 수 있습니다.

주요 예제로 본다면 아래와 같습니다.


ansible all -m ping -k

- ansible의 모든 호스트에 ping 명령어를 실행


ansible all -m copy -a "src=/etc/copy.txt dest=/etc/copy.txt" -k

- ansible의 모든 호스트에 copy 명령어를 실행하여 Ansible Server에 있는 " /etc/copy.txt " 파일을 Ansible Host의 " /etc/copy.txt "에 복사



[ -a  옵션 ]


ansible all -m copy -a [ Ansible Host에서 실행할 명령어 ] -k


ansible 모듈에서 Copy or Shell or Etc 등의 명령어 사용 시 명령어 값을 전달하는 아규먼트 옵션입니다.


ansible all -m copy -a "src=/etc/copy.txt dest=/etc/copy.txt" -k

- ansible의 모든 호스트에 copy 명령어를 실행하여 Ansible Server에 있는 " /etc/copy.txt " 파일을 Ansible Host의 " /etc/copy.txt "에 복사


ansible 모듈에서 " Copy " 라는 모듈을 사용했고 해당 모듈을 통해 실행할 명령어 " "src=/etc/copy.txt dest=/etc/copy.txt" ] "를 아규먼트로 전달하는 옵션입니다.



[ -k 옵션 ]


ansible all -m ping -k


ansible 실행 시 ansible host의 패스워드를 물어볼 수 있도록 하는 옵션입니다. 일반적으로 Linux System에 SSH 접속 시 암호를 입력하여 접속하는 과정과 동일합니다.



[ -K 옵션 ]


ansible all -m ping -k -K


ansible 실행 시 ansible host의 root 권한으로 상승하기 위한 옵션입니다. 일반적으로 root 계정을 사용할 시에는 큰 의미가 없지만 root 계정이 아닌 User 계정을 사용할 경우 " -K " 옵션을 사용하여 명령어를 root 권한으로 작동시킬 수 있습니다.



[ --list-hosts 옵션 ]


ansible all -m ping --list-hosts -k


ansible 실행 시 어떠한 host들이 명령어를 적용받는지 확인할 수 있는 옵션입니다.




Ansible Playbook을 통한 Nginx 설치 및 삭제


2대의 Client에 Nginx을 설치하기 위하여 YAML 문법을 통해 Playbook을 작성합니다.

 - 꼭 아래의 경로에 Playbook을 설치할 필요는 없습니다.


[root@ansible-controller ansible]# pwd
/etc/ansible
 
[root@ansible-controller ansible]# vi install_nginx.yml




install_nginx.yml 파일에 아래의 YAML 문법으로 Task 및 Handlers를 작성합니다.

Playbook을 사용하는 가장 기초적인 샘플이며 다양한 방법으로 서버에 대한 설정, 어플리케이션 배포 등 다양하게 활용할 수 있습니다.


---
- hosts: test                                   # Task를 실행할 [Host] or [Host Group] or [All]을 지정합니다.
  remote_user: root                             # Client Server에서 Task를 실행할 User를 지정합니다.
  tasks:                                        # Task를 정의합니다.
      - name: Install nginx web server          # Task의 이름을 정의합니다.
        yum: name=nginx state=latest            # Task를 통해 작업할 내용을 정의합니다.
        notify:                                 # Task 작업이 완료 된 후 수행할 액션을 handlers를 참조하여 수행합니다. 주로 Service 시작, 재시작, 정지등에 사용합니다.
          - restart nginx                       # name에 정의된 "restart nginx"는 handlers의 name으로 설정된 액션과 맵핑합니다.
  handlers:
      - name: restart nginx                     # Task의 notify에 작성된 name과 맵핑됩니다.
        service: name=nginx state=restarted     # task의 notify에 name과 동일한 "restart nginx"가 있을 경우 작동하며 Task 작업이 완료된 후 nginx service를 재시작 합니다.




Playbook 파일 작성이 완료되었다면 "ansible-playbook [Playbook YAML File] -f 10" 명령어를 통해 작성된 Playbook을 실행합니다.

아래의 TASK 및 HANDLER 처럼 표시된다면 설치 및 서비스 실행이 정상적으로 완료된 부분입니다.


[root@ansible-controller ansible]# ansible-playbook install_nginx.yml -f 10
 
PLAY [test] *********************************************************************************************************
 
TASK [Gathering Facts] **********************************************************************************************
ok: [10.146.0.4]
ok: [10.146.0.3]
 
TASK [Install nginx web server] *************************************************************************************
changed: [10.146.0.3]
changed: [10.146.0.4]
 
RUNNING HANDLER [restart nginx] *************************************************************************************
changed: [10.146.0.4]
changed: [10.146.0.3]
 
PLAY RECAP **********************************************************************************************************
10.146.0.3                 : ok=3    changed=2    unreachable=0    failed=0
10.146.0.4                 : ok=3    changed=2    unreachable=0    failed=0
 
[root@ansible-controller ansible]#




Ansible-Client-1 Server와 Ansible-Client-2 Server에서 아래와 같이 nginx가 실행중인지 확인합니다.


[root@ansible-client-1 ~]# ps -ef | grep nginx
root      5230     1  0 16:19 ?        00:00:00 nginx: master process /usr/sbin/nginx
nginx     5231  5230  0 16:19 ?        00:00:00 nginx: worker process
root      5257  1228  0 16:21 pts/0    00:00:00 grep --color=auto nginx
[root@ansible-client-1 ~]#
 
 
 
 
 
[root@ansible-client-2 ~]# ps -ef | grep nginx
root      5290     1  0 16:19 ?        00:00:00 nginx: master process /usr/sbin/nginx
nginx     5291  5290  0 16:19 ?        00:00:00 nginx: worker process
root      5318  1236  0 16:21 pts/0    00:00:00 grep --color=auto nginx
[root@ansible-client-2 ~]#




Web Browser에서 접속하여 nginx가 정상적으로 실행중인지 확인합니다.




이제 Ansible Playbook을 통해 nginx를 종료하고 삭제해보겠습니다.

remove_nginx.yml 파일에 아래의 YAML 문법으로 Task 및 Handlers를 작성합니다.


[root@ansible-controller ansible]# vi remove_nginx.yml
 
 
---
- hosts: test
  remote_user: root
  tasks:
   - name: stop nginx
     service: name=nginx state=stopped
 
   - name: remove nginx
     yum: name=nginx state=removed




remove_nginx.yml Playbook 파일 작성이 완료되었다면 "ansible-playbook [Playbook YAML File] -f 10" 명령어를 통해 작성된 Playbook을 실행합니다. 아래의 TASK 및 HANDLER 처럼 표시된다면 서비스 종료 및 삭제가 정상적으로 완료된 부분입니다.


[root@ansible-controller ansible]# ansible-playbook remove_nginx.yml -f 10
 
PLAY [test] ********************************************************************
 
TASK [Gathering Facts] *********************************************************
ok: [10.146.0.3]
ok: [10.146.0.4]
 
TASK [stop nginx] **************************************************************
changed: [10.146.0.3]
changed: [10.146.0.4]
 
TASK [remove nginx] ************************************************************
changed: [10.146.0.3]
changed: [10.146.0.4]
 
PLAY RECAP *********************************************************************
10.146.0.3                 : ok=3    changed=2    unreachable=0    failed=0
10.146.0.4                 : ok=3    changed=2    unreachable=0    failed=0




Ansible-Client-1 Server와 Ansible-Client-2 Server에서 아래와 같이 nginx가 삭제된 것을 확인합니다.


[root@ansible-client-1 ~]# yum list installed |grep nginx
nginx-filesystem.noarch               1:1.12.2-2.el7                  @epel
 
 
 
[root@ansible-client-2 ~]# yum list installed |grep nginx
nginx-filesystem.noarch               1:1.12.2-2.el7                  @epel




마무리


Ansible은 테스트 해본 내용과 같이 간단한 YAML 문법을 통해 Playbook을 작성하고, 작성된 Playbook으로 다수의 Client Server에 작업명령을 내릴 수 있는 편리한 도구입니다.


본 포스팅은 Ansible의 가장 기초적이고 기본적인 작동방식에 대해 알아보았으며 추후 지속적인 포스팅을 통해 Ansible을 심층적으로 알아볼 수 있도록 하겠습니다.



profile

Ossian Story

@ossians