Ansible Study -4

LEE EUI JOO·2024년 2월 10일
0

Ansible & Vagrant

목록 보기
7/7

실습을 위한 사용자 생성

  • 사용자 : ansible, stack
  • 프로젝트 디렉터리 생성 및 ansible.cfg, inventory 파일 작성
#
mkdir ~/my-ansible/chapter_09.1
cd ~/my-ansible/chapter_09.1

# ansible.cfg, inventory 파일 작성
cat <<EOT > ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
EOT

cat <<EOT> inventory
tnode1
tnode2
tnode3
EOT
  • 사용자 계정 정보가 정의된 변수 파일을 생성
mkdir vars
cat <<EOT > vars/users.yml
user_info:
  - userid: "ansible"
    userpw: "ansiblePw1"
  - userid: "stack"
    userpw: "stackPw1"
EOT
  • 사용자 계정을 생성하는 플레이북을 작성 : 모든 호스트에 동일하게 생성하며 vault로 작성된 변수 파일을 읽어 사용합니다.
---

- hosts: all

  # vault로 사용자 계정 관련 변수가 정의된 파일을 임포트하여 사용
  vars_files:
    - vars/users.yml

  tasks:
  # loop 문을 사용하여 user_info의 userid와 userpw 사용
  - name: Create user
    ansible.builtin.user:
      name: "{{ item.userid }}"
      password: "{{ item.userpw | password_hash('sha512', 'mysecret') }}"
      state: present
      shell: /bin/bash
    loop: "{{ user_info }}"
  • 실행
ansible-playbook create_user.yml

PLAY [all] ***********************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************
ok: [tnode3]
ok: [tnode2]
ok: [tnode1]

TASK [Create user] ***************************************************************************************************************************
[DEPRECATION WARNING]: Encryption using the Python crypt module is deprecated. The Python crypt module is deprecated and will be removed from
 Python 3.13. Install the passlib library for continued encryption functionality. This feature will be removed in version 2.17. Deprecation 
warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: Encryption using the Python crypt module is deprecated. The Python crypt module is deprecated and will be removed from
 Python 3.13. Install the passlib library for continued encryption functionality. This feature will be removed in version 2.17. Deprecation 
warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: Encryption using the Python crypt module is deprecated. The Python crypt module is deprecated and will be removed from
 Python 3.13. Install the passlib library for continued encryption functionality. This feature will be removed in version 2.17. Deprecation 
warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
changed: [tnode3] => (item={'userid': 'ansible', 'userpw': 'ansiblePw1'})
changed: [tnode2] => (item={'userid': 'ansible', 'userpw': 'ansiblePw1'})
changed: [tnode1] => (item={'userid': 'ansible', 'userpw': 'ansiblePw1'})
changed: [tnode2] => (item={'userid': 'stack', 'userpw': 'stackPw1'})
changed: [tnode3] => (item={'userid': 'stack', 'userpw': 'stackPw1'})
changed: [tnode1] => (item={'userid': 'stack', 'userpw': 'stackPw1'})

PLAY RECAP ***********************************************************************************************************************************
tnode1                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

# 계정 생성 확인
ansible -m shell -a "tail -n 3 /etc/passwd" all
tnode3 | CHANGED | rc=0 >>
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
ansible:x:1001:1001::/home/ansible:/bin/bash
stack:x:1002:1002::/home/stack:/bin/bash
tnode1 | CHANGED | rc=0 >>
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
ansible:x:1001:1001::/home/ansible:/bin/bash
stack:x:1002:1002::/home/stack:/bin/bash
tnode2 | CHANGED | rc=0 >>
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
ansible:x:1001:1001::/home/ansible:/bin/bash
stack:x:1002:1002::/home/stack:/bin/bash
  • 정상적으로 두개의 User 가 생성이 완료

1. 보안 설정 자동화

1. 패스워드 주기 설정

분석

  • 패스워드 변경 주기를 설정할 대상 호스트는 인벤토리를 통해 설정하겠습니다.
  • 패스워드 변경 주기를 설정할 사용자 계정 정보와 최대 변경일은 변수를 통해 별도의 파일로 정의하겠습니다.
  • 패스워드 변경 주기 설정은 ansible.builtin.user 모듈을 이용할 것입니다.

플레이북 설계

  • 사용자 계정과 최대 변경일을 변수로 설정하기 위해 vars_maxdays.yml 파일 생성합니다.
  • 메인 플레이북 set_chage_password.yml 파일에는 변경 주기를 설정할 태스크가 포함됩니다.

플레이북 개발

  • 프로젝트 디렉터리 생성 및 ansible.cfg, inventory 파일 작성
mkdir ~/my-ansible/chapter_11.1
cd ~/my-ansible/chapter_11.1

# ansible.cfg, inventory 파일 작성
cat <<EOT> ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
EOT

cat <<EOT> inventory
[tnode]
tnode1
tnode2
tnode3
EOT
  • 사전형 변수 파일 작성
vi vars_maxdays.yml

---

Userinfo:
  - username: ansible
    maxdays: 90
  - username: stack
    maxdays: 90
  • 메인플레이북 작성
    • 패스워드 변경 주기는 user 모듈의 password_expire_max 파라미터로 설정합니다.
cat set_chage_password.yml 
---

- hosts: tnode
  vars_files: vars_maxdays.yml
  
  tasks:
    - name: Change Password Maxdays
      ansible.builtin.user:
        name: "{{ item.username }}"
        password_expire_max: "{{ item.maxdays }}"
      loop: "{{ Userinfo }}"
  • 플레이북 실행
### 문법 체크
ansible-playbook --syntax-check set_chage_password.yml

playbook: set_chage_password.yml

### 시뮬레이트
ansible-playbook --check set_chage_password.yml

PLAY [tnode] *********************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************
ok: [tnode3]
ok: [tnode1]
ok: [tnode2]

TASK [Change Password Maxdays] ***************************************************************************************************************
changed: [tnode1] => (item={'username': 'ansible', 'maxdays': 90})
changed: [tnode3] => (item={'username': 'ansible', 'maxdays': 90})
changed: [tnode2] => (item={'username': 'ansible', 'maxdays': 90})
changed: [tnode1] => (item={'username': 'stack', 'maxdays': 90})
changed: [tnode3] => (item={'username': 'stack', 'maxdays': 90})
changed: [tnode2] => (item={'username': 'stack', 'maxdays': 90})

PLAY RECAP ***********************************************************************************************************************************
tnode1                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

### 플레이북 실행

ansible-playbook set_chage_password.yml

PLAY [tnode] *********************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************
ok: [tnode3]
ok: [tnode2]
ok: [tnode1]

TASK [Change Password Maxdays] ***************************************************************************************************************
changed: [tnode3] => (item={'username': 'ansible', 'maxdays': 90})
changed: [tnode1] => (item={'username': 'ansible', 'maxdays': 90})
changed: [tnode2] => (item={'username': 'ansible', 'maxdays': 90})
changed: [tnode3] => (item={'username': 'stack', 'maxdays': 90})
changed: [tnode1] => (item={'username': 'stack', 'maxdays': 90})
changed: [tnode2] => (item={'username': 'stack', 'maxdays': 90})

PLAY RECAP ***********************************************************************************************************************************
tnode1                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  • 플레이북 실행 결과 확인
for i in {1..3}; do echo ">> tnode$i <<"; ssh tnode$i sudo chage -l ansible; echo; done
>> tnode1 <<
Last password change                                    : Feb 10, 2024
Password expires                                        : May 10, 2024
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 90
Number of days of warning before password expires       : 7

>> tnode2 <<
Last password change                                    : Feb 10, 2024
Password expires                                        : May 10, 2024
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 90
Number of days of warning before password expires       : 7

>> tnode3 <<
Last password change                                    : Feb 10, 2024
Password expires                                        : May 10, 2024
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 90
Number of days of warning before password expires       : 7

2. 패스워드 생성 법칙 적용

  • 패스워드 생성 법칙 적용을 위해서는 pwquality.conf 라는 pam 설정 파일을 이용해야 하며, 리눅스 서버에 libpam-pwquality 패키지가 있어야 합니다.
  • 패스워드 변경 주기는 /etc/securiy/pwquality.conf 파일로 설정할 수 있습니다.
  • /etc/securiy/pwquality.conf 파일을 설정하기 전에 원본 파일을 백업받습니다.
  • pwquality.conf 파일은 사용자가 커스텀으로 설정하는 파라미터들로 구성되어 있으며, Jinja2 템플릿 방식으로 구현할 것입니다.
  • 파라미터들은 별도의 변수 설정 파일에서 정의한 파라미터 값으로 사용하고, 파라미터 정의 여부를 체크하여 pwquality.conf 파일의 내용을 구성하겠습니다.

플레이북 설계

  • 변수 vars_pw_rule.yml 에 정의

    • 최소 패스워드 길이 설정 minlen
    • 최소 숫자 개수 설정 dcredit
    • 최소 대문자 개수 설정 ucredit
    • 최소 소문자 개수 설정 lcredit
    • 최소 특수문자 개수 설정 ocredit
    • root 계정에서도 해당 패스워드 룰을 설정할 수 있는 enforce_for_root
  • Jinja2 템플릿 파일 pwqulity.conf.j2 에 아래의 내용을 포함

    • minlen, dcredit, ucredit, lcredit, orcedit, enforce_for_root
    • minclass : 최소 문자클래스 개수
    • maxrepeat : 최대 연속 동일 문자 수
    • maxclassrepeat : 동일 글래스의 최대 연속 문자 수

플레이북 개발 및 실행

  • 프로젝트 디렉터리 생성 및 ansible.cfg, inventory 파일 작성
mkdir ~/my-ansible/chapter_11.2
cd ~/my-ansible/chapter_11.2

# ansible.cfg, inventory 파일 작성
cat <<EOT> ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
EOT

cat <<EOT> inventory
[tnode]
tnode1
tnode2
tnode3
EOT
  • 변수 값 설정
    • vars_pw_rule.yml
cat vars_pw_rule.yml 
---

minlen: 8
dcredit: -1
ucredit: -1
lcredit: -1
ocredit: -1
enforce_for_root: false
  • Jinja2 템플릿 파일 pwquality.conf.j2 작성
  • {% ~ %} 사이에 제어문 구문 위치
  • {% if minlen is defined %} 구문 : minlen 이라는 변수가 정의되면 아래 문장을 삽입하라’ 는 의미
  • 아래 템플릿에는 {% if 변수 is defined %} ~ {% endif %} 구문을 사용하여 파라미터와 관련된 변수가 선언되면 해당 파라미터를 삽입
cat pwquality.conf.j2 
# Created by ansible

{% if minlen is defined %}
# Minimum acceptable size for the new password
minlen = {{ minlen }}
{% endif %}

{% if dcredit is defined %}
# The maximum credit for having digits in the new password
dcredit = {{ dcredit }}
{% endif %}

{% if ucredit is defined %}
# The maximum credit for having uppercase characters in the new password
ucredit = {{ ucredit }}
{% endif %}

{% if lcredit is defined %}
# The maximum credit for having lowercase characters in the new password
lcredit = {{ lcredit }}
{% endif %}

{% if ocredit is defined %}
# The maximum credit for having other characters in the new password
ocredit = {{ ocredit }}
{% endif %}

{% if minclass is defined %}
# The minimum number of required classes of characters for the new password
minclass = {{ minclass }}
{% endif %}

{% if maxrepeat is defined %}
# The maximum number of allowed consecutive same characters in the new password
maxrepeat = {{ maxrepeat}}
{% endif %}

{% if maxclassrepeat is defined %}
# The maximum number of allowed consecutive characters of the same class in the new password
maxclassrepeat = {{ maxclassreapt }}
{% endif %}

{% if retry is defined %}
# Prompt user at most N times before returning with error
retry = {{ retry }}
{% endif %}

{% if enforce_for_root is defined %}
# Enforces pwquality checks on the root user password.
enforce_for_root
{% endif %}
  • 메인 플레이북 작성
    • when 구문으로 데비안/우분투 경우 apt설치. 이후 copy로 백업 후 template 로 템플릿 파일 복사하는 플레이북
cat set_password_rule.yml 
---

- hosts: tnode
  vars_files: vars_pw_rule.yml

  tasks:
    - name: Install libpam-pwquality
      ansible.builtin.apt:
        name: libpam-pwquality
        state: present
      when: ansible_facts.os_family == "Debian"

    - name: Backup pwquality.conf
      ansible.builtin.copy:
        src: /etc/security/pwquality.conf
        dest: /etc/security/pwquality.conf.bak
        remote_src: yes

    - name: Copy pwquality.conf.j2 at /etc/security
      ansible.builtin.template:
        src: pwquality.conf.j2
        dest: /etc/security/pwquality.conf
        mode: '0644'
  • 플레이북 실행 및 확인
    • 실행 전
for i in {1..3}; do echo ">> tnode$i <<"; ssh tnode$i sudo cat /etc/security/pwquality.conf; echo; done
>> tnode1 <<
cat: /etc/security/pwquality.conf: No such file or directory

>> tnode2 <<
cat: /etc/security/pwquality.conf: No such file or directory

>> tnode3 <<
cat: /etc/security/pwquality.conf: No such file or directory
  • 실행 후
ansible-playbook set_password_rule.yml

PLAY [tnode] *********************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************
ok: [tnode3]
ok: [tnode1]
ok: [tnode2]

TASK [Install libpam-pwquality] **************************************************************************************************************
changed: [tnode2]
changed: [tnode3]
changed: [tnode1]

TASK [Backup pwquality.conf] *****************************************************************************************************************
changed: [tnode2]
changed: [tnode1]
changed: [tnode3]

TASK [Copy pwquality.conf.j2 at /etc/security] ***********************************************************************************************
changed: [tnode2]
changed: [tnode1]
changed: [tnode3]

PLAY RECAP ***********************************************************************************************************************************
tnode1                     : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
  • 확인
for i in {1..3}; do echo ">> tnode$i <<"; ssh tnode$i sudo cat /etc/security/pwquality.conf; echo; done
>> tnode1 <<
# Created by ansible

# Minimum acceptable size for the new password
minlen = 8

# The maximum credit for having digits in the new password
dcredit = -1

# The maximum credit for having uppercase characters in the new password
ucredit = -1

# The maximum credit for having lowercase characters in the new password
lcredit = -1

# The maximum credit for having other characters in the new password
ocredit = -1





# Enforces pwquality checks on the root user password.
enforce_for_root

>> tnode2 <<
# Created by ansible

# Minimum acceptable size for the new password
minlen = 8

# The maximum credit for having digits in the new password
dcredit = -1

# The maximum credit for having uppercase characters in the new password
ucredit = -1

# The maximum credit for having lowercase characters in the new password
lcredit = -1

# The maximum credit for having other characters in the new password
ocredit = -1





# Enforces pwquality checks on the root user password.
enforce_for_root

>> tnode3 <<
# Created by ansible

# Minimum acceptable size for the new password
minlen = 8

# The maximum credit for having digits in the new password
dcredit = -1

# The maximum credit for having uppercase characters in the new password
ucredit = -1

# The maximum credit for having lowercase characters in the new password
lcredit = -1

# The maximum credit for having other characters in the new password
ocredit = -1





# Enforces pwquality checks on the root user password.
enforce_for_root
  • 패스워드 TEST
ssh tnode2
sudo su - ansible
ansible@tnode2:~$ 

## 현재 passwd : ansiblePw1
New password: qwer
BAD PASSWORD: The password contains less than 1 digits
New password: qwer1234
BAD PASSWORD: The password contains less than 1 uppercase letters
New password: Qwer1234
BAD PASSWORD: The password contains less than 1 non-alphanumeric characters
passwd: Have exhausted maximum number of retries for service
passwd: password unchanged

exit X2

3. 디렉터리 및 파일 접근 권한 변경

  • 리눅스 보안 중에 꼭 확인해야 하는 항목이 바로 Sticky bit 설정 파일World Writable 설정 파일입니다.
  • Sticky bit 설정 파일은 리눅스에서 파일 소유자그룹 소유자만 해당 파일을 읽고 쓰고 삭제할 수 있도록 권한을 부여한 것을 의미합니다.
  • 파일 소유자에게 권한을 부여하면 SUID, 파일 그룹에게 권한을 부여하면 SGID, 다른 사람에게 권한을 부여하면 Sticky bit 라고 합니다.
  • Sticky bit가 적용된 파일 목록 중 보안을 위해 이를 적용하면 안 되는 파일 목록들이 있습니다.
  • Sticky bit가 적용된 파일의 권한을 수정할 때는 적용되면 안 되는 파일인지 반드시 먼저 확인합니다
  • World Writable 파일모든 사용자에게 파일을 읽고 쓸 수 있는 권한이 부여된 파일을 의미합니다.

분석

  • Sticky bit 파일 검색 명령어: find / -xdev -perm -04000 -o -perm -02000 -o -perm -01000
  • World Writable 파일 검색 명령어: find / -xdev -type f -perm -2
  • ansible.builtin.**shell** 모듈을 이용하여 Sticky bit 파일과 World Writable 파일을 찾습니다.
  • 찾은 파일 목록은 ansible.builtin.file 모듈을 이용하여 파일의 접속 권한을 설정하겠습니다. 예) 0644
  • Sticky bit 파일은 u-s, g-s, o-s 로 설정하고, World Writable 파일은 o-w 로 설정합니다.

플레이북 설계

플레이북 개발 및 실행

  • 프로젝트 디렉터리 생성 및 ansible.cfg, inventory 파일 작성
mkdir ~/my-ansible/chapter_11.3
cd ~/my-ansible/chapter_11.3

# ansible.cfg, inventory 파일 작성
cat <<EOT> ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
EOT

cat <<EOT> inventory
[tnode]
tnode1
tnode2
tnode3
EOT
  • 태스크 파일 작성 : 검색 시 grep 으로 필터링(-e 정규식 패턴, -v 매칭되지 않는 경우)
cat set_sticky_writable_files.yml 
---

- hosts: tnode

  tasks:
  - name: Find Sticky bit files
    ansible.builtin.shell: |
      find / -xdev -perm -04000 -o -perm -02000 -o -perm 01000 \
      | grep -e 'dump$' \
             -e 'lp*-lpd$' \ 
             -e 'newgrp$' \
             -e 'restore$' \
             -e 'at$' \
             -e 'traceroute$' | xargs ls
    register: sfile_list

  - name: Find World Writable files
    ansible.builtin.shell: |
      find / -xdev -perm -2 -ls \
      | grep -v 'l..........' | awk '{print $NF}'
    register: wfile_list

  - name: Print Sticky bit files
    ansible.builtin.debug:
      msg: "{{ sfile_list.stdout_lines }}"

  - name: Print World Writable files
    ansible.builtin.debug:
      msg: "{{ wfile_list.stdout_lines }}"

  - name: Set Sticky bit files
    ansible.builtin.file:
      path: "{{ item }}"
      mode: "u-s,g-s,o-s"
    loop: "{{ sfile_list.stdout_lines }}"

  - name: Set World Writable files
    ansible.builtin.file:
      path: "{{ item }}"
      mode: "o-w"
    loop: "{{ wfile_list.stdout_lines }}"
    
  • 플레이북 실행
    • 변경 전
for i in {1..3}; do echo ">> tnode$i <<"; ssh tnode$i sudo ls -al /usr/bin/newgrp; echo; done
>> tnode1 <<
-rwsr-xr-x 1 root root 40496 Nov 24  2022 /usr/bin/newgrp

>> tnode2 <<
-rwsr-xr-x 1 root root 40496 Nov 24  2022 /usr/bin/newgrp

>> tnode3 <<
-rwsr-xr-x 1 root root 40496 Nov 24  2022 /usr/bin/newgrp
  • 변경 후
ansible-playbook set_sticky_writable_files.yml

PLAY [tnode] *********************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************
ok: [tnode3]
ok: [tnode2]
ok: [tnode1]

TASK [Find Sticky bit files] *****************************************************************************************************************
changed: [tnode2]
changed: [tnode1]
changed: [tnode3]

TASK [Find World Writable files] *************************************************************************************************************
changed: [tnode1]
changed: [tnode2]
changed: [tnode3]

TASK [Print Sticky bit files] ****************************************************************************************************************
ok: [tnode1] => {
    "msg": [
        "/usr/bin/newgrp"
    ]
}
ok: [tnode2] => {
    "msg": [
        "/usr/bin/newgrp"
    ]
}
ok: [tnode3] => {
    "msg": [
        "/usr/bin/newgrp"
    ]
}

TASK [Print World Writable files] ************************************************************************************************************
ok: [tnode1] => {
    "msg": [
        "/var/crash",
        "/var/tmp",
        "/var/tmp/cloud-init",
        "/var/tmp/systemd-private-2bd71de739314feb944ad886ac37bd0f-chrony.service-3OyAEm/tmp",
        "/tmp",
        "/tmp/systemd-private-2bd71de739314feb944ad886ac37bd0f-chrony.service-8M0WvF/tmp",
        "/tmp/.X11-unix",
        "/tmp/snap-private-tmp/snap.lxd/tmp",
        "/tmp/.font-unix",
        "/tmp/.ICE-unix",
        "/tmp/.Test-unix",
        "/tmp/.XIM-unix"
    ]
}
ok: [tnode2] => {
    "msg": [
        "/var/crash",
        "/var/tmp",
        "/var/tmp/cloud-init",
        "/var/tmp/systemd-private-b248997e37244b3299e485806660eb60-chrony.service-ovCkqf/tmp",
        "/tmp",
        "/tmp/.X11-unix",
        "/tmp/snap-private-tmp/snap.lxd/tmp",
        "/tmp/.font-unix",
        "/tmp/.ICE-unix",
        "/tmp/.Test-unix",
        "/tmp/systemd-private-b248997e37244b3299e485806660eb60-chrony.service-bL1m5f/tmp",
        "/tmp/.XIM-unix"
    ]
}
ok: [tnode3] => {
    "msg": [
        "/var/crash",
        "/var/tmp",
        "/var/tmp/systemd-private-a63449ea80e2469aa217bf69316a61bc-chrony.service-tO7O2t/tmp",
        "/var/tmp/cloud-init",
        "/tmp",
        "/tmp/systemd-private-a63449ea80e2469aa217bf69316a61bc-chrony.service-j0evlU/tmp",
        "/tmp/.X11-unix",
        "/tmp/snap-private-tmp/snap.lxd/tmp",
        "/tmp/.font-unix",
        "/tmp/.ICE-unix",
        "/tmp/.Test-unix",
        "/tmp/.XIM-unix"
    ]
}

TASK [Set Sticky bit files] ******************************************************************************************************************
changed: [tnode2] => (item=/usr/bin/newgrp)
changed: [tnode1] => (item=/usr/bin/newgrp)
changed: [tnode3] => (item=/usr/bin/newgrp)

TASK [Set World Writable files] **************************************************************************************************************
changed: [tnode2] => (item=/var/crash)
changed: [tnode1] => (item=/var/crash)
changed: [tnode3] => (item=/var/crash)
changed: [tnode2] => (item=/var/tmp)
changed: [tnode1] => (item=/var/tmp)
changed: [tnode3] => (item=/var/tmp)
changed: [tnode2] => (item=/var/tmp/cloud-init)
changed: [tnode1] => (item=/var/tmp/cloud-init)
changed: [tnode3] => (item=/var/tmp/systemd-private-a63449ea80e2469aa217bf69316a61bc-chrony.service-tO7O2t/tmp)
changed: [tnode2] => (item=/var/tmp/systemd-private-b248997e37244b3299e485806660eb60-chrony.service-ovCkqf/tmp)
changed: [tnode1] => (item=/var/tmp/systemd-private-2bd71de739314feb944ad886ac37bd0f-chrony.service-3OyAEm/tmp)
changed: [tnode3] => (item=/var/tmp/cloud-init)
changed: [tnode2] => (item=/tmp)
changed: [tnode1] => (item=/tmp)
changed: [tnode2] => (item=/tmp/.X11-unix)
changed: [tnode3] => (item=/tmp)
changed: [tnode1] => (item=/tmp/systemd-private-2bd71de739314feb944ad886ac37bd0f-chrony.service-8M0WvF/tmp)
changed: [tnode2] => (item=/tmp/snap-private-tmp/snap.lxd/tmp)
changed: [tnode3] => (item=/tmp/systemd-private-a63449ea80e2469aa217bf69316a61bc-chrony.service-j0evlU/tmp)
changed: [tnode1] => (item=/tmp/.X11-unix)
changed: [tnode2] => (item=/tmp/.font-unix)
changed: [tnode3] => (item=/tmp/.X11-unix)
changed: [tnode3] => (item=/tmp/snap-private-tmp/snap.lxd/tmp)
changed: [tnode1] => (item=/tmp/snap-private-tmp/snap.lxd/tmp)
changed: [tnode2] => (item=/tmp/.ICE-unix)
changed: [tnode3] => (item=/tmp/.font-unix)
changed: [tnode2] => (item=/tmp/.Test-unix)
changed: [tnode1] => (item=/tmp/.font-unix)
changed: [tnode3] => (item=/tmp/.ICE-unix)
changed: [tnode1] => (item=/tmp/.ICE-unix)
changed: [tnode2] => (item=/tmp/systemd-private-b248997e37244b3299e485806660eb60-chrony.service-bL1m5f/tmp)
changed: [tnode3] => (item=/tmp/.Test-unix)
changed: [tnode2] => (item=/tmp/.XIM-unix)
changed: [tnode1] => (item=/tmp/.Test-unix)
changed: [tnode1] => (item=/tmp/.XIM-unix)
changed: [tnode3] => (item=/tmp/.XIM-unix)

PLAY RECAP ***********************************************************************************************************************************
tnode1                     : ok=7    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=7    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=7    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
  • 확인
    • -rwsr-xr-x -> -rwxr-xr-x 로 변경
for i in {1..3}; do echo ">> tnode$i <<"; ssh tnode$i sudo ls -al /usr/bin/newgrp; echo; done
>> tnode1 <<
-rwxr-xr-x 1 root root 40496 Nov 24  2022 /usr/bin/newgrp

>> tnode2 <<
-rwxr-xr-x 1 root root 40496 Nov 24  2022 /usr/bin/newgrp

>> tnode3 <<
-rwxr-xr-x 1 root root 40496 Nov 24  2022 /usr/bin/newgrp

2. 모니터링 자동화

팩트를 이용한 시스템 모니터링

사전 분석

  • 팩트는 관리 노드에서 시스템과 관련된 정보(아래 예시)들을 찾아 변수로 제공 → 인프라 정보 파악 및 로그로 저장
    • 호스트 이름
    • 커널 버전
    • 네트워크 인터페이스 이름
    • 네트워크 인터페이스 IP 주소
    • 운영체제 버전
    • CPU 개수
    • 사용 가능한 메모리
    • 스토리지 장치의 크기 및 여유 공간
  • 추출한 내용은 ansible.builtin.shell 모듈을 이용하여 /var/log/daily_check 디렉터리에 저장합니다.

플레이북 설계

플레이북 개발 및 실행

  • 프로젝트 디렉터리 생성 및 ansible.cfg, inventory 파일 작성
mkdir ~/my-ansible/chapter_12.1
cd ~/my-ansible/chapter_12.1

# ansible.cfg, inventory 파일 작성
cat <<EOT> ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
EOT

cat <<EOT> inventory
[tnode]
tnode1
tnode2
tnode3
EOT
  • 플레이북 파일 작성 : debug과 facts 수집 후 file 에 저장
cat monitoring_facts.yml 
---

- hosts: tnode
  vars:
    log_directory: /var/log/daily_check

  tasks:
    - name: Print system info
      ansible.builtin.debug:
        msg:
        - "################ Start #####################"
        - "Date: {{ ansible_facts.date_time.date }} {{ ansible_facts.date_time.time }}" 
        - "HostName: {{ ansible_facts.hostname }}"
        - "OS: {{ ansible_facts.distribution }}"
        - "OS Version: {{ ansible_facts.distribution_version }}"
        - "OS Kernel: {{ ansible_facts.kernel }}"
        - "CPU Cores: {{ ansible_facts.processor_vcpus }}"
        - "Memory: {{ ansible_facts.memory_mb.real }}"
        - "Interfaces: {{ ansible_facts.interfaces }}"
        - "IPv4: {{ ansible_facts.all_ipv4_addresses }}"
        - "Devices: {{ ansible_facts.mounts }}"
        - "################# End #######################" 
      register: result

    - name: Create log directory
      ansible.builtin.file:
        path: "{{ log_directory }}"
        state: directory

    - name: Print logs to log file
      ansible.builtin.shell: |
        echo "{{ item }}" >> "{{ log_directory }}"/system_info.logs
      loop: "{{ result.msg }}"
  • 플레이북 실행
ansible-playbook monitoring_facts.yml

PLAY [tnode] *********************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************
ok: [tnode3]
ok: [tnode1]
ok: [tnode2]

TASK [Print system info] *********************************************************************************************************************
ok: [tnode1] => {
    "msg": [
        "################ Start #####################",
        "Date: 2024-02-10 17:36:48",
        "HostName: tnode1",
        "OS: Ubuntu",
        "OS Version: 22.04",
        "OS Kernel: 6.2.0-1018-aws",
        "CPU Cores: 2",
        "Memory: {'total': 3847, 'used': 1000, 'free': 2847}",
        "Interfaces: ['ens5', 'lo']",
        "IPv4: ['10.10.1.11']",
        "Devices: [{'mount': '/', 'device': '/dev/root', 'fstype': 'ext4', 'options': 'rw,relatime,discard,errors=remount-ro', 'size_total': 31024283648, 'size_available': 29134749696, 'block_size': 4096, 'block_total': 7574288, 'block_available': 7112976, 'block_used': 461312, 'inode_total': 3870720, 'inode_available': 3796001, 'inode_used': 74719, 'uuid': '1127d3f4-3de6-4e02-8705-713269caf74d'}, {'mount': '/snap/amazon-ssm-agent/7628', 'device': '/dev/loop0', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 26214400, 'size_available': 0, 'block_size': 131072, 'block_total': 200, 'block_available': 0, 'block_used': 200, 'inode_total': 16, 'inode_available': 0, 'inode_used': 16, 'uuid': 'N/A'}, {'mount': '/snap/core18/2812', 'device': '/dev/loop1', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 58458112, 'size_available': 0, 'block_size': 131072, 'block_total': 446, 'block_available': 0, 'block_used': 446, 'inode_total': 10944, 'inode_available': 0, 'inode_used': 10944, 'uuid': 'N/A'}, {'mount': '/snap/core20/2105', 'device': '/dev/loop2', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 67108864, 'size_available': 0, 'block_size': 131072, 'block_total': 512, 'block_available': 0, 'block_used': 512, 'inode_total': 12041, 'inode_available': 0, 'inode_used': 12041, 'uuid': 'N/A'}, {'mount': '/snap/lxd/26881', 'device': '/dev/loop3', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 91226112, 'size_available': 0, 'block_size': 131072, 'block_total': 696, 'block_available': 0, 'block_used': 696, 'inode_total': 959, 'inode_available': 0, 'inode_used': 959, 'uuid': 'N/A'}, {'mount': '/snap/snapd/20671', 'device': '/dev/loop4', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 42467328, 'size_available': 0, 'block_size': 131072, 'block_total': 324, 'block_available': 0, 'block_used': 324, 'inode_total': 658, 'inode_available': 0, 'inode_used': 658, 'uuid': 'N/A'}, {'mount': '/boot/efi', 'device': '/dev/nvme0n1p15', 'fstype': 'vfat', 'options': 'rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro', 'size_total': 109395456, 'size_available': 103061504, 'block_size': 512, 'block_total': 213663, 'block_available': 201292, 'block_used': 12371, 'inode_total': 0, 'inode_available': 0, 'inode_used': 0, 'uuid': '2D7D-66A4'}]",
        "################# End #######################"
    ]
}
ok: [tnode2] => {
    "msg": [
        "################ Start #####################",
        "Date: 2024-02-10 17:36:48",
        "HostName: tnode2",
        "OS: Ubuntu",
        "OS Version: 22.04",
        "OS Kernel: 6.2.0-1018-aws",
        "CPU Cores: 2",
        "Memory: {'total': 3847, 'used': 996, 'free': 2851}",
        "Interfaces: ['lo', 'ens5']",
        "IPv4: ['10.10.1.12']",
        "Devices: [{'mount': '/', 'device': '/dev/root', 'fstype': 'ext4', 'options': 'rw,relatime,discard,errors=remount-ro', 'size_total': 31024283648, 'size_available': 29134733312, 'block_size': 4096, 'block_total': 7574288, 'block_available': 7112972, 'block_used': 461316, 'inode_total': 3870720, 'inode_available': 3795999, 'inode_used': 74721, 'uuid': '1127d3f4-3de6-4e02-8705-713269caf74d'}, {'mount': '/snap/amazon-ssm-agent/7628', 'device': '/dev/loop0', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 26214400, 'size_available': 0, 'block_size': 131072, 'block_total': 200, 'block_available': 0, 'block_used': 200, 'inode_total': 16, 'inode_available': 0, 'inode_used': 16, 'uuid': 'N/A'}, {'mount': '/snap/lxd/26881', 'device': '/dev/loop3', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 91226112, 'size_available': 0, 'block_size': 131072, 'block_total': 696, 'block_available': 0, 'block_used': 696, 'inode_total': 959, 'inode_available': 0, 'inode_used': 959, 'uuid': 'N/A'}, {'mount': '/snap/core20/2105', 'device': '/dev/loop1', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 67108864, 'size_available': 0, 'block_size': 131072, 'block_total': 512, 'block_available': 0, 'block_used': 512, 'inode_total': 12041, 'inode_available': 0, 'inode_used': 12041, 'uuid': 'N/A'}, {'mount': '/snap/core18/2812', 'device': '/dev/loop2', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 58458112, 'size_available': 0, 'block_size': 131072, 'block_total': 446, 'block_available': 0, 'block_used': 446, 'inode_total': 10944, 'inode_available': 0, 'inode_used': 10944, 'uuid': 'N/A'}, {'mount': '/snap/snapd/20671', 'device': '/dev/loop4', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 42467328, 'size_available': 0, 'block_size': 131072, 'block_total': 324, 'block_available': 0, 'block_used': 324, 'inode_total': 658, 'inode_available': 0, 'inode_used': 658, 'uuid': 'N/A'}, {'mount': '/boot/efi', 'device': '/dev/nvme0n1p15', 'fstype': 'vfat', 'options': 'rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro', 'size_total': 109395456, 'size_available': 103061504, 'block_size': 512, 'block_total': 213663, 'block_available': 201292, 'block_used': 12371, 'inode_total': 0, 'inode_available': 0, 'inode_used': 0, 'uuid': '2D7D-66A4'}]",
        "################# End #######################"
    ]
}
ok: [tnode3] => {
    "msg": [
        "################ Start #####################",
        "Date: 2024-02-10 17:36:48",
        "HostName: tnode3",
        "OS: Ubuntu",
        "OS Version: 22.04",
        "OS Kernel: 6.2.0-1018-aws",
        "CPU Cores: 2",
        "Memory: {'total': 3847, 'used': 992, 'free': 2855}",
        "Interfaces: ['ens5', 'lo']",
        "IPv4: ['10.10.1.13']",
        "Devices: [{'mount': '/', 'device': '/dev/root', 'fstype': 'ext4', 'options': 'rw,relatime,discard,errors=remount-ro', 'size_total': 31024283648, 'size_available': 29134749696, 'block_size': 4096, 'block_total': 7574288, 'block_available': 7112976, 'block_used': 461312, 'inode_total': 3870720, 'inode_available': 3796001, 'inode_used': 74719, 'uuid': '1127d3f4-3de6-4e02-8705-713269caf74d'}, {'mount': '/snap/core18/2812', 'device': '/dev/loop1', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 58458112, 'size_available': 0, 'block_size': 131072, 'block_total': 446, 'block_available': 0, 'block_used': 446, 'inode_total': 10944, 'inode_available': 0, 'inode_used': 10944, 'uuid': 'N/A'}, {'mount': '/snap/core20/2105', 'device': '/dev/loop2', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 67108864, 'size_available': 0, 'block_size': 131072, 'block_total': 512, 'block_available': 0, 'block_used': 512, 'inode_total': 12041, 'inode_available': 0, 'inode_used': 12041, 'uuid': 'N/A'}, {'mount': '/snap/amazon-ssm-agent/7628', 'device': '/dev/loop0', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 26214400, 'size_available': 0, 'block_size': 131072, 'block_total': 200, 'block_available': 0, 'block_used': 200, 'inode_total': 16, 'inode_available': 0, 'inode_used': 16, 'uuid': 'N/A'}, {'mount': '/snap/lxd/26881', 'device': '/dev/loop3', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 91226112, 'size_available': 0, 'block_size': 131072, 'block_total': 696, 'block_available': 0, 'block_used': 696, 'inode_total': 959, 'inode_available': 0, 'inode_used': 959, 'uuid': 'N/A'}, {'mount': '/snap/snapd/20671', 'device': '/dev/loop4', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 42467328, 'size_available': 0, 'block_size': 131072, 'block_total': 324, 'block_available': 0, 'block_used': 324, 'inode_total': 658, 'inode_available': 0, 'inode_used': 658, 'uuid': 'N/A'}, {'mount': '/boot/efi', 'device': '/dev/nvme0n1p15', 'fstype': 'vfat', 'options': 'rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro', 'size_total': 109395456, 'size_available': 103061504, 'block_size': 512, 'block_total': 213663, 'block_available': 201292, 'block_used': 12371, 'inode_total': 0, 'inode_available': 0, 'inode_used': 0, 'uuid': '2D7D-66A4'}]",
        "################# End #######################"
    ]
}

TASK [Create log directory] ******************************************************************************************************************
changed: [tnode2]
changed: [tnode1]
changed: [tnode3]

TASK [Print logs to log file] ****************************************************************************************************************
changed: [tnode3] => (item=################ Start #####################)
changed: [tnode1] => (item=################ Start #####################)
changed: [tnode2] => (item=################ Start #####################)
changed: [tnode3] => (item=Date: 2024-02-10 17:36:48)
changed: [tnode1] => (item=Date: 2024-02-10 17:36:48)
changed: [tnode2] => (item=Date: 2024-02-10 17:36:48)
changed: [tnode3] => (item=HostName: tnode3)
changed: [tnode1] => (item=HostName: tnode1)
changed: [tnode2] => (item=HostName: tnode2)
changed: [tnode3] => (item=OS: Ubuntu)
changed: [tnode1] => (item=OS: Ubuntu)
changed: [tnode2] => (item=OS: Ubuntu)
changed: [tnode3] => (item=OS Version: 22.04)
changed: [tnode1] => (item=OS Version: 22.04)
changed: [tnode2] => (item=OS Version: 22.04)
changed: [tnode3] => (item=OS Kernel: 6.2.0-1018-aws)
changed: [tnode1] => (item=OS Kernel: 6.2.0-1018-aws)
changed: [tnode3] => (item=CPU Cores: 2)
changed: [tnode2] => (item=OS Kernel: 6.2.0-1018-aws)
changed: [tnode1] => (item=CPU Cores: 2)
changed: [tnode3] => (item=Memory: {'total': 3847, 'used': 992, 'free': 2855})
changed: [tnode2] => (item=CPU Cores: 2)
changed: [tnode1] => (item=Memory: {'total': 3847, 'used': 1000, 'free': 2847})
changed: [tnode2] => (item=Memory: {'total': 3847, 'used': 996, 'free': 2851})
changed: [tnode3] => (item=Interfaces: ['ens5', 'lo'])
changed: [tnode3] => (item=IPv4: ['10.10.1.13'])
changed: [tnode2] => (item=Interfaces: ['lo', 'ens5'])
changed: [tnode1] => (item=Interfaces: ['ens5', 'lo'])
changed: [tnode2] => (item=IPv4: ['10.10.1.12'])
changed: [tnode3] => (item=Devices: [{'mount': '/', 'device': '/dev/root', 'fstype': 'ext4', 'options': 'rw,relatime,discard,errors=remount-ro', 'size_total': 31024283648, 'size_available': 29134749696, 'block_size': 4096, 'block_total': 7574288, 'block_available': 7112976, 'block_used': 461312, 'inode_total': 3870720, 'inode_available': 3796001, 'inode_used': 74719, 'uuid': '1127d3f4-3de6-4e02-8705-713269caf74d'}, {'mount': '/snap/core18/2812', 'device': '/dev/loop1', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 58458112, 'size_available': 0, 'block_size': 131072, 'block_total': 446, 'block_available': 0, 'block_used': 446, 'inode_total': 10944, 'inode_available': 0, 'inode_used': 10944, 'uuid': 'N/A'}, {'mount': '/snap/core20/2105', 'device': '/dev/loop2', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 67108864, 'size_available': 0, 'block_size': 131072, 'block_total': 512, 'block_available': 0, 'block_used': 512, 'inode_total': 12041, 'inode_available': 0, 'inode_used': 12041, 'uuid': 'N/A'}, {'mount': '/snap/amazon-ssm-agent/7628', 'device': '/dev/loop0', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 26214400, 'size_available': 0, 'block_size': 131072, 'block_total': 200, 'block_available': 0, 'block_used': 200, 'inode_total': 16, 'inode_available': 0, 'inode_used': 16, 'uuid': 'N/A'}, {'mount': '/snap/lxd/26881', 'device': '/dev/loop3', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 91226112, 'size_available': 0, 'block_size': 131072, 'block_total': 696, 'block_available': 0, 'block_used': 696, 'inode_total': 959, 'inode_available': 0, 'inode_used': 959, 'uuid': 'N/A'}, {'mount': '/snap/snapd/20671', 'device': '/dev/loop4', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 42467328, 'size_available': 0, 'block_size': 131072, 'block_total': 324, 'block_available': 0, 'block_used': 324, 'inode_total': 658, 'inode_available': 0, 'inode_used': 658, 'uuid': 'N/A'}, {'mount': '/boot/efi', 'device': '/dev/nvme0n1p15', 'fstype': 'vfat', 'options': 'rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro', 'size_total': 109395456, 'size_available': 103061504, 'block_size': 512, 'block_total': 213663, 'block_available': 201292, 'block_used': 12371, 'inode_total': 0, 'inode_available': 0, 'inode_used': 0, 'uuid': '2D7D-66A4'}])
changed: [tnode1] => (item=IPv4: ['10.10.1.11'])
changed: [tnode2] => (item=Devices: [{'mount': '/', 'device': '/dev/root', 'fstype': 'ext4', 'options': 'rw,relatime,discard,errors=remount-ro', 'size_total': 31024283648, 'size_available': 29134733312, 'block_size': 4096, 'block_total': 7574288, 'block_available': 7112972, 'block_used': 461316, 'inode_total': 3870720, 'inode_available': 3795999, 'inode_used': 74721, 'uuid': '1127d3f4-3de6-4e02-8705-713269caf74d'}, {'mount': '/snap/amazon-ssm-agent/7628', 'device': '/dev/loop0', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 26214400, 'size_available': 0, 'block_size': 131072, 'block_total': 200, 'block_available': 0, 'block_used': 200, 'inode_total': 16, 'inode_available': 0, 'inode_used': 16, 'uuid': 'N/A'}, {'mount': '/snap/lxd/26881', 'device': '/dev/loop3', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 91226112, 'size_available': 0, 'block_size': 131072, 'block_total': 696, 'block_available': 0, 'block_used': 696, 'inode_total': 959, 'inode_available': 0, 'inode_used': 959, 'uuid': 'N/A'}, {'mount': '/snap/core20/2105', 'device': '/dev/loop1', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 67108864, 'size_available': 0, 'block_size': 131072, 'block_total': 512, 'block_available': 0, 'block_used': 512, 'inode_total': 12041, 'inode_available': 0, 'inode_used': 12041, 'uuid': 'N/A'}, {'mount': '/snap/core18/2812', 'device': '/dev/loop2', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 58458112, 'size_available': 0, 'block_size': 131072, 'block_total': 446, 'block_available': 0, 'block_used': 446, 'inode_total': 10944, 'inode_available': 0, 'inode_used': 10944, 'uuid': 'N/A'}, {'mount': '/snap/snapd/20671', 'device': '/dev/loop4', 'fstype': 'squashfs', 'options': 'ro,n
  • 플레이북 실행 결과 확인
for i in {1..3}; do echo ">> tnode$i <<"; ssh tnode$i ls -l /var/log/daily_check; echo; done
>> tnode1 <<
total 4
-rw-r--r-- 1 root root 2841 Feb 10 17:36 system_info.logs

>> tnode2 <<
total 4
-rw-r--r-- 1 root root 2840 Feb 10 17:36 system_info.logs

>> tnode3 <<
total 4
-rw-r--r-- 1 root root 2840 Feb 10 17:36 system_info.logs

ssh tnode1 sudo cat /var/log/daily_check/system_info.logs
################ Start #####################
Date: 2024-02-10 17:36:48
HostName: tnode1
OS: Ubuntu
OS Version: 22.04
OS Kernel: 6.2.0-1018-aws
CPU Cores: 2
Memory: {'total': 3847, 'used': 1000, 'free': 2847}
Interfaces: ['ens5', 'lo']
IPv4: ['10.10.1.11']
Devices: [{'mount': '/', 'device': '/dev/root', 'fstype': 'ext4', 'options': 'rw,relatime,discard,errors=remount-ro', 'size_total': 31024283648, 'size_available': 29134749696, 'block_size': 4096, 'block_total': 7574288, 'block_available': 7112976, 'block_used': 461312, 'inode_total': 3870720, 'inode_available': 3796001, 'inode_used': 74719, 'uuid': '1127d3f4-3de6-4e02-8705-713269caf74d'}, {'mount': '/snap/amazon-ssm-agent/7628', 'device': '/dev/loop0', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 26214400, 'size_available': 0, 'block_size': 131072, 'block_total': 200, 'block_available': 0, 'block_used': 200, 'inode_total': 16, 'inode_available': 0, 'inode_used': 16, 'uuid': 'N/A'}, {'mount': '/snap/core18/2812', 'device': '/dev/loop1', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 58458112, 'size_available': 0, 'block_size': 131072, 'block_total': 446, 'block_available': 0, 'block_used': 446, 'inode_total': 10944, 'inode_available': 0, 'inode_used': 10944, 'uuid': 'N/A'}, {'mount': '/snap/core20/2105', 'device': '/dev/loop2', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 67108864, 'size_available': 0, 'block_size': 131072, 'block_total': 512, 'block_available': 0, 'block_used': 512, 'inode_total': 12041, 'inode_available': 0, 'inode_used': 12041, 'uuid': 'N/A'}, {'mount': '/snap/lxd/26881', 'device': '/dev/loop3', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 91226112, 'size_available': 0, 'block_size': 131072, 'block_total': 696, 'block_available': 0, 'block_used': 696, 'inode_total': 959, 'inode_available': 0, 'inode_used': 959, 'uuid': 'N/A'}, {'mount': '/snap/snapd/20671', 'device': '/dev/loop4', 'fstype': 'squashfs', 'options': 'ro,nodev,relatime,errors=continue,threads=single', 'size_total': 42467328, 'size_available': 0, 'block_size': 131072, 'block_total': 324, 'block_available': 0, 'block_used': 324, 'inode_total': 658, 'inode_available': 0, 'inode_used': 658, 'uuid': 'N/A'}, {'mount': '/boot/efi', 'device': '/dev/nvme0n1p15', 'fstype': 'vfat', 'options': 'rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro', 'size_total': 109395456, 'size_available': 103061504, 'block_size': 512, 'block_total': 213663, 'block_available': 201292, 'block_used': 12371, 'inode_total': 0, 'inode_available': 0, 'inode_used': 0, 'uuid': '2D7D-66A4'}]

CPU, 메모리, 디스크 사용률 모니터링

  • 팩트에서 제공되지 않은 정보를 모니터링해야되는 상황을 가정
  • 자세한 CPU, 메모리, 디스크 사용률 모니터링을 위해 dstat, iostat, vmstat 명령어 사용 → 툴 설치 필요(dnf)
  • 각각의 명령어 실행은 ansible.builtin.shell 이용하여 실행하고, loop 키워드를 이용하여 모니터링 명령어별로 여러 옵션을 추가하여 명령 실행
  • 실행된 명령어 결과는 로그 디렉터리에 저장

플레이북 설계

플레이북 개발 및 실행

  • 프로젝트 디렉터리 생성 및 ansible.cfg, inventory 파일 작성
mkdir ~/my-ansible/chapter_12.2
cd ~/my-ansible/chapter_12.2

# ansible.cfg, inventory 파일 작성
cat <<EOT> ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
EOT

cat <<EOT> inventory
[tnode]
tnode1
tnode2
tnode3
EOT
  • 변수 파일 작성 : 로그 디렉터리와 설치할 패키지
cat vars_packages.yml 
---

log_directory: /home/ubuntu/logs
packages:
  - dstat
  - sysstat
  • 플레이북 작성
    • OS 가 Ubuntu 이기 떄문에 RedHat 은 Skipped 됩니다.
cat monitoring_system.yml 
---

- hosts: tnode
  vars_files: vars_packages.yml

  tasks:
    - name: Install packages on RedHat
      ansible.builtin.dnf:
        name: "{{ item }}"
        state: present
      loop: "{{ packages }}"
      when: ansible_facts.os_family == "RedHat"

    - name: Install packages on Ubuntu
      ansible.builtin.apt:
        name: "{{ item }}"
        state: present
      loop: "{{ packages }}"
      when: ansible_facts.os_family == "Debian"

    - name: Create log directory
      ansible.builtin.file:
        path: "{{ log_directory }}"
        state: directory

    - name: Monitoring dstat
      ansible.builtin.shell: |
        {{ item }} >> {{ log_directory }}/dstat.log
      loop:
        - dstat 2 10
        - dstat -cmdlt -D vda 2 10

    - name: Monitoring iostat
      ansible.builtin.shell: |
        {{ item }} >> {{ log_directory }}/iostat.log
      loop:
        - iostat
        - echo "==============="
        - iostat -t -c -dp vda
        - echo "==============="

    - name: Monitoring vmstat
      ansible.builtin.shell: |
        {{ item }} >> {{ log_directory }}/vmstat.log
      loop:
        - vmstat
        - echo "==============="
        - vmstat -dt
        - echo "==============="
        - vmstat -D
        - echo "==============="

    - name: Monitoring df
      ansible.builtin.shell: |
        df -h >> {{ log_directory }}/df.log
  • 플레이북 실행
### 툴이 설치되어 있는지 확인
ubuntu@server:~/my-ansible/chapter_12.2$ vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 1709684  93556 1765816    0    0    51   383  120  184  2  1 97  0  1
ubuntu@server:~/my-ansible/chapter_12.2$ dstat
Command 'dstat' not found, but can be installed with:
sudo apt install dstat  # version 0.7.4-6.1, or
sudo apt install pcp    # version 5.3.6-1build1
ubuntu@server:~/my-ansible/chapter_12.2$ iostat
Command 'iostat' not found, but can be installed with:
sudo apt install sysstat

### 실행
ansible-playbook monitoring_system.yml

PLAY [tnode] *********************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************
ok: [tnode3]
ok: [tnode1]
ok: [tnode2]

TASK [Install packages on RedHat] ************************************************************************************************************
skipping: [tnode1] => (item=dstat) 
skipping: [tnode1] => (item=sysstat) 
skipping: [tnode1]
skipping: [tnode2] => (item=dstat) 
skipping: [tnode2] => (item=sysstat) 
skipping: [tnode2]
skipping: [tnode3] => (item=dstat) 
skipping: [tnode3] => (item=sysstat) 
skipping: [tnode3]

TASK [Install packages on Ubuntu] ************************************************************************************************************
changed: [tnode2] => (item=dstat)
changed: [tnode3] => (item=dstat)
changed: [tnode1] => (item=dstat)
changed: [tnode2] => (item=sysstat)
changed: [tnode3] => (item=sysstat)
changed: [tnode1] => (item=sysstat)

TASK [Create log directory] ******************************************************************************************************************
changed: [tnode3]
changed: [tnode2]
changed: [tnode1]

TASK [Monitoring dstat] **********************************************************************************************************************
changed: [tnode2] => (item=dstat 2 10)
changed: [tnode1] => (item=dstat 2 10)
changed: [tnode3] => (item=dstat 2 10)
changed: [tnode2] => (item=dstat -cmdlt -D vda 2 10)
changed: [tnode3] => (item=dstat -cmdlt -D vda 2 10)
changed: [tnode1] => (item=dstat -cmdlt -D vda 2 10)

TASK [Monitoring iostat] *********************************************************************************************************************
changed: [tnode1] => (item=iostat)
changed: [tnode3] => (item=iostat)
changed: [tnode2] => (item=iostat)
changed: [tnode1] => (item=echo "===============")
changed: [tnode3] => (item=echo "===============")
changed: [tnode2] => (item=echo "===============")
changed: [tnode1] => (item=iostat -t -c -dp vda)
changed: [tnode3] => (item=iostat -t -c -dp vda)
changed: [tnode2] => (item=iostat -t -c -dp vda)
changed: [tnode1] => (item=echo "===============")
changed: [tnode3] => (item=echo "===============")
changed: [tnode2] => (item=echo "===============")

TASK [Monitoring vmstat] *********************************************************************************************************************
changed: [tnode1] => (item=vmstat)
changed: [tnode2] => (item=vmstat)
changed: [tnode3] => (item=vmstat)
changed: [tnode2] => (item=echo "===============")
changed: [tnode3] => (item=echo "===============")
changed: [tnode1] => (item=echo "===============")
changed: [tnode2] => (item=vmstat -dt)
changed: [tnode3] => (item=vmstat -dt)
changed: [tnode1] => (item=vmstat -dt)
changed: [tnode2] => (item=echo "===============")
changed: [tnode3] => (item=echo "===============")
changed: [tnode1] => (item=echo "===============")
changed: [tnode2] => (item=vmstat -D)
changed: [tnode2] => (item=echo "===============")
changed: [tnode3] => (item=vmstat -D)
changed: [tnode1] => (item=vmstat -D)
changed: [tnode3] => (item=echo "===============")
changed: [tnode1] => (item=echo "===============")

TASK [Monitoring df] *************************************************************************************************************************
changed: [tnode1]
changed: [tnode2]
changed: [tnode3]

PLAY RECAP ***********************************************************************************************************************************
tnode1                     : ok=7    changed=6    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
tnode2                     : ok=7    changed=6    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
tnode3                     : ok=7    changed=6    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
  • 플레이북 실행 후 확인
for i in {1..3}; do echo ">> tnode$i <<"; ssh tnode$i ls -l ~/logs; echo; done
>> tnode1 <<
total 16
-rw-r--r-- 1 root root  335 Feb 10 17:46 df.log
-rw-r--r-- 1 root root 1759 Feb 10 17:46 dstat.log
-rw-r--r-- 1 root root 2393 Feb 10 17:46 iostat.log
-rw-r--r-- 1 root root 1713 Feb 10 17:46 vmstat.log

>> tnode2 <<
total 16
-rw-r--r-- 1 root root  335 Feb 10 17:46 df.log
-rw-r--r-- 1 root root 1759 Feb 10 17:46 dstat.log
-rw-r--r-- 1 root root 2393 Feb 10 17:46 iostat.log
-rw-r--r-- 1 root root 1713 Feb 10 17:46 vmstat.log

>> tnode3 <<
total 16
-rw-r--r-- 1 root root  335 Feb 10 17:46 df.log
-rw-r--r-- 1 root root 1759 Feb 10 17:46 dstat.log
-rw-r--r-- 1 root root 2393 Feb 10 17:46 iostat.log
-rw-r--r-- 1 root root 1713 Feb 10 17:46 vmstat.log

3. 앤서블 Semaphore (OpenSource Ansible Mgmt UI)

설치

  • 패키지 매니저로 설치하겠습니다.
pwd
/home/ubuntu/playground

wget https://github.com/ansible-semaphore/semaphore/releases/download/v2.9.45/semaphore_2.9.45_linux_amd64.deb
sudo dpkg -i semaphore_2.9.45_linux_amd64.deb

Semaphore 셋업

  • DB : BoltDB (경량화 DB)
  • 슬랙 Alarm : Enabled
semaphore setup

Hello! You will now be guided through a setup to:

1. Set up configuration for a MySQL/MariaDB database
2. Set up a path for your playbooks (auto-created)
3. Run database Migrations
4. Set up initial semaphore user & password

What database to use:
   1 - MySQL
   2 - BoltDB
   3 - PostgreSQL
 (default 1): 2

db filename (default /home/ubuntu/playground/database.boltdb): 

Playbook path (default /tmp/semaphore): 

Public URL (optional, example: https://example.com/semaphore): 

Enable email alerts? (yes/no) (default no): 

Enable telegram alerts? (yes/no) (default no): 

Enable slack alerts? (yes/no) (default no): yes

Slack Webhook URL: 여러분의 Slack Web Hook URL

Enable LDAP authentication? (yes/no) (default no): 

Config output directory (default /home/ubuntu/playground): 

Running: mkdir -p /home/ubuntu/playground..
Configuration written to /home/ubuntu/playground/config.json..
 Pinging db..
Running db Migrations..
Executing migration v0.0.0 (at 2024-02-10 18:08:14.303712622 +0900 KST m=+24.275617958)...
Executing migration v1.0.0 (at 2024-02-10 18:08:14.307762641 +0900 KST m=+24.279668043)...
Executing migration v1.2.0 (at 2024-02-10 18:08:14.309079434 +0900 KST m=+24.280984753)...
Executing migration v1.3.0 (at 2024-02-10 18:08:14.310129793 +0900 KST m=+24.282035110)...
Executing migration v1.4.0 (at 2024-02-10 18:08:14.311354607 +0900 KST m=+24.283259927)...
Executing migration v1.5.0 (at 2024-02-10 18:08:14.312676297 +0900 KST m=+24.284581634)...
Executing migration v1.6.0 (at 2024-02-10 18:08:14.314260139 +0900 KST m=+24.286165476)...
Executing migration v1.7.0 (at 2024-02-10 18:08:14.315524547 +0900 KST m=+24.287429896)...
Executing migration v1.8.0 (at 2024-02-10 18:08:14.316869903 +0900 KST m=+24.288775259)...
Executing migration v1.9.0 (at 2024-02-10 18:08:14.318543667 +0900 KST m=+24.290449028)...
Executing migration v2.2.1 (at 2024-02-10 18:08:14.320042004 +0900 KST m=+24.291947369)...
Executing migration v2.3.0 (at 2024-02-10 18:08:14.321307588 +0900 KST m=+24.293212946)...
Executing migration v2.3.1 (at 2024-02-10 18:08:14.322697357 +0900 KST m=+24.294602689)...
Executing migration v2.3.2 (at 2024-02-10 18:08:14.324131571 +0900 KST m=+24.296036932)...
Executing migration v2.4.0 (at 2024-02-10 18:08:14.326988456 +0900 KST m=+24.298893783)...
Executing migration v2.5.0 (at 2024-02-10 18:08:14.330999201 +0900 KST m=+24.302904529)...
Executing migration v2.5.2 (at 2024-02-10 18:08:14.332692724 +0900 KST m=+24.304598045)...
Executing migration v2.7.1 (at 2024-02-10 18:08:14.334084896 +0900 KST m=+24.305990223)...
Executing migration v2.7.4 (at 2024-02-10 18:08:14.335212993 +0900 KST m=+24.307118321)...
Executing migration v2.7.6 (at 2024-02-10 18:08:14.336613093 +0900 KST m=+24.308518425)...
Executing migration v2.7.8 (at 2024-02-10 18:08:14.338017144 +0900 KST m=+24.309922462)...
Executing migration v2.7.9 (at 2024-02-10 18:08:14.339352273 +0900 KST m=+24.311257595)...
Executing migration v2.7.10 (at 2024-02-10 18:08:14.340720718 +0900 KST m=+24.312626042)...
Executing migration v2.7.12 (at 2024-02-10 18:08:14.34211445 +0900 KST m=+24.314019788)...
Executing migration v2.7.13 (at 2024-02-10 18:08:14.343787952 +0900 KST m=+24.315693287)...
Executing migration v2.8.0 (at 2024-02-10 18:08:14.344918696 +0900 KST m=+24.316824024)...
Executing migration v2.8.1 (at 2024-02-10 18:08:14.346165735 +0900 KST m=+24.318071063)...
Executing migration v2.8.7 (at 2024-02-10 18:08:14.347664047 +0900 KST m=+24.319569376)...
Executing migration v2.8.8 (at 2024-02-10 18:08:14.348973747 +0900 KST m=+24.320879082)...
Executing migration v2.8.20 (at 2024-02-10 18:08:14.356998926 +0900 KST m=+24.328904260)...
Executing migration v2.8.25 (at 2024-02-10 18:08:14.358488757 +0900 KST m=+24.330394084)...
Executing migration v2.8.26 (at 2024-02-10 18:08:14.360526683 +0900 KST m=+24.332432011)...
Executing migration v2.8.36 (at 2024-02-10 18:08:14.362038231 +0900 KST m=+24.333943577)...
Executing migration v2.8.38 (at 2024-02-10 18:08:14.363536023 +0900 KST m=+24.335441357)...
Executing migration v2.8.39 (at 2024-02-10 18:08:14.364901203 +0900 KST m=+24.336806534)...
Executing migration v2.8.40 (at 2024-02-10 18:08:14.36647003 +0900 KST m=+24.338375359)...
Executing migration v2.8.42 (at 2024-02-10 18:08:14.36789168 +0900 KST m=+24.339797014)...
Executing migration v2.8.51 (at 2024-02-10 18:08:14.36933462 +0900 KST m=+24.341239944)...
Executing migration v2.8.57 (at 2024-02-10 18:08:14.370579661 +0900 KST m=+24.342484995)...
Executing migration v2.8.58 (at 2024-02-10 18:08:14.371925538 +0900 KST m=+24.343830894)...
Executing migration v2.8.91 (at 2024-02-10 18:08:14.373462304 +0900 KST m=+24.345367632)...
Executing migration v2.9.6 (at 2024-02-10 18:08:14.375613734 +0900 KST m=+24.347519069)...
Migrations Finished


 > Username: euijoo
 > Email: euijoo@localhost
WARN[0045] no rows in result set                         level=Warn
 > Your name: euijoo
 > Password: qwe123

 You are all setup euijoo!
 Re-launch this program pointing to the configuration file

./semaphore server --config /home/ubuntu/playground/config.json

 To run as daemon:

nohup ./semaphore server --config /home/ubuntu/playground/config.json &

 You can login with euijoo@localhost or euijoo.
 
# config.json 파일 확인
cat ./config.json | jq 
{
  "mysql": {
    "host": "",
    "user": "",
    "pass": "",
    "name": "",
    "options": null
  },
  "bolt": {
    "host": "/home/ubuntu/playground/database.boltdb",
    "user": "",
    "pass": "",
    "name": "",
    "options": null
  },
  "postgres": {
    "host": "",
    "user": "",
    "pass": "",
    "name": "",
    "options": null
  },
  "dialect": "bolt",
  "port": "",
  "interface": "",
  "tmp_path": "/tmp/semaphore",
  "ssh_config_path": "",
  "git_client": "",
  "web_host": "",
  "cookie_hash": "lbEgsnDiMDXRrdUXHC5a//qRXvzOSNllm88hhAWPsa8=",
  "cookie_encryption": "7S9kLxGSq6Is3ola75ozmMqT/XTZ6u0F+7broYfwzUw=",
  "access_key_encryption": "GjWWCKckl9HU0MJYIljBGr3DfFnf8mqJD/3kAMVVYoI=",
  "email_alert": false,
  "email_sender": "",
  "email_host": "",
  "email_port": "",
  "email_username": "",
  "email_password": "",
  "email_secure": false,
  "ldap_enable": false,
  "ldap_binddn": "",
  "ldap_bindpassword": "",
  "ldap_server": "",
  "ldap_searchdn": "",
  "ldap_searchfilter": "",
  "ldap_mappings": {
    "dn": "",
    "mail": "",
    "uid": "",
    "cn": ""
  },
  "ldap_needtls": false,
  "telegram_alert": false,
  "telegram_chat": "",
  "telegram_token": "",
  "slack_alert": true,
  "slack_url": "https://hooks.slack.com/services/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",
  "oidc_providers": null,
  "max_task_duration_sec": 0,
  "max_parallel_tasks": 0,
  "runner_registration_token": "",
  "password_login_disable": false,
  "non_admin_can_create_project": false,
  "use_remote_runner": false,
  "runner": {
    "api_url": "",
    "registration_token": "",
    "config_file": "",
    "one_off": false,
    "webhook": "",
    "max_parallel_tasks": 0
  }
}

실행

semaphore service --config=./config.json
Loading config
Validating config
BoltDB /home/ubuntu/playground/database.boltdb
Tmp Path (projects home) /tmp/semaphore
Semaphore v2.9.45
Interface 
Port :3000
Server is running

### 서버 Web URL 제공
echo -e "Semaphore Web = http://$(curl -s ipinfo.io/ip):3000"

### CLI
semaphore user list
Loading config
Validating config
euijoo

# tmp project home
mkdir /tmp/semaphore
  • 접속 화면

  • Login 후 Project 생성 : ansible-pro
    • semaphore에서 Project 는 작업 간 분리 환경을 제공합니다.

4. semaphore 사용

  • 일단, 계정 별 로그인을 확인합니다.
ls /home/ubuntu/.ssh/
ssh tnode1
exit
ssh tnode2
exit
ssh tnode3
exit
### IP로도 접속 확인
ssh 10.10.1.11
exit
ssh 10.10.1.12
exit
ssh 10.10.1.13
exit
  • root 계정 암호 입력으로 로그인 확인
sudo su -

# 암호는 qwe123
ssh tnode1
ssh tnode2
ssh tnode3

Key Store : 암호 저장

  • 용도 : remote hosts, remote Repo, sudo credentials, Ansible vault passwords

  • 종류 : SSH, Login With Password, None, Personal Access Token(?)

    1. SSH : remote hosts, remote Repo에 SSH 접속 시 사용하는 SSH Keys
    2. Login With Password : 로그인 계정에 대한 암호 password 와 토큰 access Token
      • remote hosts 로그인 시 암호
      • remote hosts 에 sudo 사용 시 암호
      • remote Repo over HTTPS 로그인 시 암호
      • Ansible vaults 의 Unlock
    3. None : remote Repo 에 인증이 없는 경우

실습

  • 암호 생성
    • ansible-server 의 ubuntu 계정의 SSH 비밀키 복사
cat /home/ubuntu/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
  • Key Store - New Key 를 생성
    • Type : SSH Key

  • root 계정의 login password 생성

  • remote Repo 를 위한 None : none-Anonymous 생성

Repositories : playbooks 와 roles 위치한 곳

  • 3가지 저장소 지원
    1. 로컬 Git Repo : git://
    2. 로컬 파일시스템 : file://
    3. 리모트 Git Repo : accessed over HTTPS(https://) , or SSH(ssh://)
      • 인증 필요 : SSH 사용 시 SSH Key store , 인증 없을 경우 None type Key
  • [Repositories] - NEW REPOSITORY
  • local 파일시스템으로 repository 를 등록하겠습니다.
    • Path : /temp/semaphore

Environment : 인벤토리에 추가 변수 저장하는 곳으로 JSON 포맷으로 작성

  • [Environment] - NEW Environment

  • Empty : Extra variables에 아래 입력

{}
  • User-euijoo : Extra variables에 아래 입력
{
  "user" : "euijoo"
}

Inventory : playbook가 실행될 호스트 목록, 변수 사용 가능, YAML/JSON/TOML 포맷

  • [Inventory] - NEW Inventory
    • all : sshkey-ubuntu

  • env : login-ubuntu
[web]
tnode1
tnode2

[db]
tnode3

[all:children]
web
db

[all:vars]
user=study

  • task template 는 3가지 종류 지원 : Task, Build, Deploy
    • Task : Just runs specified playbooks with specified parameters
    • Build : This type of template should be used to create artifacts
      • The start version of the artifact can be specified in a template parameter. Each run increments the artifact version.

      • Semaphore doesn't support artifacts out-of-box, it only provides task versioning.

      • You should implement the artifact creation yourself. Read the article CI/CD to know how to do this.

        https://docs.semui.co/administration-guide/cicd

    • Deploy : This type of template should be used to deploy artifacts to the destination servers.
      • Each deploy template is associated with a build template.
      • This allows you to deploy a specific version of the artifact to the servers.

실습

  • 플레이북 생성
    • name : fact.yml, user.yml
    • 플레이북 위치 : tmp/semaphore
cat << EOT > /tmp/semaphore/fact.yml
---

- hosts: all

  tasks:
  - name: Print all facts
    ansible.builtin.debug:
      msg: >
        The default IPv4 address of {{ ansible_facts.fqdn }}
        is {{ ansible_facts.default_ipv4.address }}
EOT

cat << EOT > /tmp/semaphore/user.yml
---

- hosts: web
  tasks:
  - name: Create User {{ user }}
    ansible.builtin.user:
      name: "{{ user }}"
      state: present
EOT
  • [Task Templates] - NEW TEMPLATE

  • Task Template : facts

  • Task Template : users

  • facts 태스크 템플릿은 이미 cron에 의해서 태스트가 실행이 되고 있습니다.

  • 터미널에서도 계속해서 cron 작업이 돌고 있는 것을 확인

  • 5분 간격으로 task 가 진행

    1. fact.yml 파일 수정 후 실행 확인 : msg
cat fact.yml 
---

- hosts: all

  tasks:
  - name: Print all facts
    ansible.builtin.debug:
      msg: ->
        The default IPv4 address of {{ ansible_facts.fqdn }}
        is {{ ansible_facts.default_ipv4.address }}
  • 이후 실행 후 msg 출력 내용 비교

이전 task

방금 실행된 task

  • 실행될 때 마다 inventory 생성 확인
/tmp/semaphore$ ls -al
total 36
drwxrwxr-x  3 ubuntu ubuntu 4096 Feb 10 18:55  .
drwxrwxrwt 12 root   root   4096 Feb 10 18:55  ..
drwxrwxr-x  4 ubuntu ubuntu 4096 Feb 10 18:45  .ansible
-rw-rw-r--  1 ubuntu ubuntu  208 Feb 10 18:54 '\'
-rw-rw-r--  1 ubuntu ubuntu  208 Feb 10 18:54  fact.yml
-rw-rw-r--  1 ubuntu ubuntu   32 Feb 10 18:55  inventory_2147483644
-rw-rw-r--  1 ubuntu ubuntu   32 Feb 10 18:50  inventory_2147483645
-rw-rw-r--  1 ubuntu ubuntu   32 Feb 10 18:45  inventory_2147483646
-rw-rw-r--  1 ubuntu ubuntu  132 Feb 10 18:42  user.yml
  • user 플레이북 실행
    • ACTIONS 에 RUN 클릭

  • user 생성 확인
ssh tnode1 tail -n 3 /etc/passwd
ansible:x:1001:1001::/home/ansible:/bin/bash
stack:x:1002:1002::/home/stack:/bin/bash
euijoo:x:1003:1003::/home/euijoo:/bin/sh
  • 추가 변수 사용해보기 : 실행 시 파라미터로 변수 넘겨 주겠습니다.

    • -e user=ejl
  • 템플릿 수정

  • 실행

  • 생성 확인
ssh tnode1 tail -n 3 /etc/passwd
stack:x:1002:1002::/home/stack:/bin/bash
euijoo:x:1003:1003::/home/euijoo:/bin/sh
ejl:x:1004:1004::/home/ejl:/bin/sh

팀원 추가

  • admin 로그아웃 -> devteam 계정으로 접속


profile
무럭무럭 자라볼까

0개의 댓글