본문으로 건너뛰기

RHCE 9 연습/기출문제 (EX294)

· 약 29분

Lab환경구성

FQDNDescriptionIP AddressesRoles
control.lab.example.comcontrol172.25.250.254ansible control node
classroom.lab.example.comclassroom172.25.250.254materials
content.lab.example.comcontent172.25.250.254YUM repo
node1.lab.example.comnode1172.25.250.9ansible managed node
node2.lab.example.comnode2172.25.250.10ansible managed node
node3.lab.example.comnode3172.25.250.11ansible managed node
node4.lab.example.comnode4172.25.250.12ansible managed node
node5.lab.example.comnode5172.25.250.13ansible managed node
utility.lab.example.comutilit172.25.250.220utility

1. Ansible 설치 및 구성

제어 노드 control에서 에 Ansible을 다음과 같이 구성하시오.

  • 필요한 패키지 설치.
  • /home/greg/ansible/inventory라는 정적 인벤토리 파일을 생성하고 다음과 같이 구성합니다:
    • node1dev 호스트 그룹의 구성원입니다.
    • node2test 호스트 그룹의 구성원입니다.
    • node3node4prod 호스트 그룹의 구성원입니다.
    • node5balancers 호스트 그룹의 구성원입니다.
    • prod 그룹은 webservers 호스트 그룹의 구성원입니다.
  • 구성 파일 /home/greg/ansible/ansible.cfg 을 생성하고 다음과 같이 구성합니다:
    • 호스트 인벤토리 파일은 /home/greg/ansible/inventory입니다.
    • 본 컨텐츠 컬렉션 디렉토리는 /home/greg/ansible/roles입니다.
    • 기본 컨텐츠 컬렉션 디렉토리는 /home/greg/ansible/mycollection입니다.
# control노드 접속
ssh greg@control
# ansible 패키지 설치
sudo dnf -y install ansible-automation-platform-common.noarch ansible-navigator

# 디렉토리 생성
mkdir -p /home/greg/ansible/roles
mkdir /home/greg/ansible/mycollection
cd ansible/

# 구성파일 생성
ansible-config init --disabled > /home/greg/ansible/ansible.cfg
vim ansible.cfg

[defaults]
inventory = /home/greg/ansible/inventory
remote_user = greg
host_key_checking = False
roles_path = /home/greg/ansible/roles:/usr/share/ansible/roles
collections_path = ./mycollection/:.ansible/collections:/usr/share/ansible/collections
[privilege_escalation]
become=True

# 구성파일 확인
ansible --version
ansible-galaxy list

# inventory파일 생성
vim /home/greg/ansible/inventory

[dev]
node1
[test]
node2
[prod]
node3
node4
[balancers]
node5
[webservers:children]
prod

# inventory 확인
ansible-inventory --graph
# ping테스트
ansible all -m ping

시험과정에 ansible-navigator 사용가능,ansible-navigator사용시 podman 미리 로그인해보도록

podman login utility.lab.example.com -u admin -p redhat
ansible-navigator images
ansible-navigator collections

2. YUM저장소 생성

시스템 관리자로서 관리 대상 노드에 소프트웨어를 설치해야 합니다.

다음 작업을 수행하는 /home/greg/ansible/yum_repo.yml 플레이북을 생성하세요. 각 관리되는 노드에 다음 yum 저장소를 만듭니다.

# 모듈명 검색
ansible-doc -l | grep yum
# doc
ansible-doc yum_repository

# playbook
vim /home/greg/ansible/yum_repo.yml

---
- name: Configure YUM repositories
hosts: all
tasks:
- name: Configure EX294_BASE repository
yum_repository:
file: EX294_BASE
name: EX294_BASE
description: "EX294 base software"
baseurl: http://content/rhel9.0/x86_64/dvd/BaseOS
gpgcheck: yes
gpgkey: http://content/rhel9.0/x86_64/dvd/RPM-GPG-KEY-redhat-release
enabled: yes

- name: Configure EX294_STREAM repository
yum_repository:
file: EX294_STREAM
name: EX294_STREAM
description: "EX294 stream software"
baseurl: http://content/rhel9.0/x86_64/dvd/AppStream
gpgcheck: yes
gpgkey: http://content/rhel9.0/x86_64/dvd/RPM-GPG-KEY-redhat-release
enabled: yes
# playbook실행
ansible-navigator run yum_repo.yml -m stdout

# 검증
ansible all -a 'yum repoinfo'
ansible all -a 'yum -y install ftp'
ansible all -a 'rpm -q ftp'

3.패키지 설치

다음 요구 사항에 따라 /home/greg/ansible/packages.yml 플레이북을 생성하고 관리 대상 노드에 소프트웨어 패키지를 설치하세요.

  • phpmariadb 패키지를 dev, test, prod 호스트 그룹의 노드에 설치합니다.
  • RPM Development Tools 패키지 그룹을 dev 호스트 그룹의 노드에 설치합니다.
  • dev 호스트 그룹의 모든 패키지를 최신 버전으로 업데이트합니다.
# doc
ansible-doc yum
# playbook작성
vim /home/greg/ansible/packages.yml
---
- name: Install php and mariadb
hosts: dev,test,prod
tasks:
- name: Install required packages
yum:
name:
- php
- mariadb
state: present

- name: Install RPM Development Tools and upgrade packages
hosts: dev
tasks:
- name: Install RPM Development Tools group
yum:
name: "@RPM Development Tools"
state: present

- name: Upgrade all packages to the latest version
yum:
name: "*"
state: latest
# playbook실행
ansible-navigator run packages.yml -m stdout

# 검증
ansible dev,test,prod -a 'rpm -q php mariadb'
ansible dev -a 'yum grouplist'
ansible dev -a 'yum update'

4.RHEL 시스템 역할(ROLE) 사용하기

다음 요구 사항을 충족하는 /home/greg/ansible/selinux.yml 플레이북을 작성하세요:

  • 모든 관리 대상 노드에서 실행됩니다.
  • selinux role을 사용합니다.
  • SElinux 정책을 targeted으로 구성합니다.
  • SElinux 상태를 enforcing으로 설정합니다.
# 패키지 검색
yum search role
# 설치
sudo yum -y install rhel-system-roles
# 사용 가능한 system roles 확인
ansible-galaxy list
# 예제 playbook 가져다 편집하여 사용하는게 편함
cp /usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml /home/greg/ansible/selinux.yml
vim selinux.yml
# 행 번호 표시 및 필요 없는 내용 삭제 (버전에 따라 행 번호가 다를 수 있으므로 직접 확인 후 삭제하도록)
:set nu
:43,51d
:11,39d

최종 내용:

---
- hosts: all
become: true
become_method: sudo
become_user: root
vars:
# Use "targeted" SELinux policy type
selinux_policy: targeted
# Set "enforcing" mode
selinux_state: enforcing

# Prepare the prerequisites required for this playbook
tasks:
- name: execute the role and catch errors
block:
- name: Include selinux role
include_role:
name: rhel-system-roles.selinux
rescue:
# Fail if failed for a different reason than selinux_reboot_required.
- name: handle errors
fail:
msg: "role failed"
when: not selinux_reboot_required

- name: restart managed host
reboot:

- name: wait for managed host to come back
wait_for_connection:
delay: 10
timeout: 300

- name: reapply the role
include_role:
name: rhel-system-roles.selinux
# playbook실행
# rpm 패키지로 설치된 역할은 ansible-playbook으로 실행, collection으로 설치된 역할은 ansible-navigator로 실행
ansible-playbook selinux.yml
# 검증
ansible all -m shell -a 'grep ^SELINUX= /etc/selinux/config; getenforce'

node3 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing
node2 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing
node5 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing
node1 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing
node4 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing

5.Collection 설치

  • 다음 컬렉션 아티팩트를 http://classroom/materials/ 에서 가져와 control노드에 설치하십시오.
    • redhat-insights-1.0.7.tar.gz
    • community-general-5.5.0.tar.gz
    • redhat-rhel_system_roles-1.19.3.tar.gz
  • 컬렉션은 기본 컬렉션 디렉토리인 /home/greg/ansible/mycollection에 설치해야 합니다.
vim requirements.yml
---
collections:
- name: http://classroom/materials/redhat-insights-1.0.7.tar.gz
- name: http://classroom/materials/community-general-5.5.0.tar.gz
- name: http://classroom/materials/redhat-rhel_system_roles-1.19.3.tar.gz
# 설치
ansible-galaxy collection install -r requirements.yml -p /home/greg/ansible/mycollection

# 검증
ansible-navigator collections
ansible-navigator doc community.general.filesystem -m stdout

6. Ansible Galaxy를 사용하여 역할 설치하기

Ansible Galaxy와 요구사항 파일 (/home/greg/ansible/roles/requirements.yml)을 사용하여 다음 URL에서 역할을 다운로드하고 /home/greg/ansible/roles 디렉토리에 설치하세요:

vim /home/greg/ansible/roles/requirements.yml
---
- src: http://classroom/materials/haproxy.tar
name: balancer
- src: http://classroom/materials/phpinfo.tar
name: phpinfo
# install
ansible-galaxy install -r /home/greg/ansible/roles/requirements.yml
# 검증
ansible-galaxy list

7.ROLE 생성 및 사용하기

다음 요구 사항에 맞춰 /home/greg/ansible/roles 디렉토리에 apache라는 역할을 생성하고 아래 조건을 만족해야 합니다:

  • httpd 소프트웨어 패키지가 설치되고, 시스템 시작 시 활성화시작 상태여야 합니다.
  • 방화벽이 활성화되어 실행 중이어야 하며, 웹 서버 접근을 허용하는 규칙을 사용해야 합니다.
  • index.html.j2 템플릿 파일이 존재하며, 이 파일을 사용해 다음과 같은 출력 파일을 생성해야 합니다:
    • /var/www/html/index.html :
      Welcome to HOSTNAME on IPADDRESS
      여기서, HOSTNAME은 관리 대상 노드의 완전한 도메인 이름(FQDN)이고, IPADDRESS는 관리 대상 노드의 IP 주소입니다.

/home/greg/ansible/apache.yml라는 이름의 플레이북을 생성합니다:

  • 이 플레이북은 webservers 호스트 그룹의 노드에서 실행되며, apache 역할을 사용합니다.
# apache role 생성
ansible-galaxy role init --init-path /home/greg/ansible/roles apache
# task작성
vim /home/greg/ansible/roles/apache/tasks/main.yml
---
- name: Install Apache
yum:
name: httpd
state: latest

- name: Start and enable Apache service
systemd:
name: httpd
state: started
enabled: yes

- name: Start and enable firewalld
systemd:
name: firewalld
state: started
enabled: yes

- name: Configure firewalld to allow HTTP
firewalld:
service: http
permanent: yes
state: enabled
immediate: yes

- name: Deploy index.html template
template:
src: index.html.j2
dest: /var/www/html/index.html
vim /home/greg/ansible/roles/apache/templates/index.html.j2

Welcome to {{ ansible_fqdn }} on {{ ansible_default_ipv4.address }}

# playbook작성
vim /home/greg/ansible/apache.yml
---
- name: Deploy Apache role
hosts: webservers
roles:
- apache
# playbook실행
ansible-navigator run apache.yml -m stdout

# 검증
ansible webservers -a 'systemctl status httpd'
ansible webservers -a 'firewall-cmd --list-all'
ansible webservers --list-hosts
curl http://node3
curl http://node4

8.Ansible Galaxy에서 ROLE 사용하기

다음 요구 사항에 맞춰 /home/greg/ansible/roles.yml 플레이북을 생성하세요:

  • playbook에 하나의 플레이가 포함되어야 하며, 이 플레이는 balancers 호스트 그룹의 노드에서 실행되며 balancer 역할을 사용합니다.

    • 이 역할은 webservers 호스트 그룹의 노드 간에 웹 서버 요청의 부하를 균형 맞추는 서비스를 구성합니다.
    • balancers 호스트 그룹의 노드(예: ***http://172.25.250.13***)에 접속하면 아래와 같은 출력이 생성됩니다:
      Welcome to node3.lab.example.com on 172.25.250.11
    • 브라우저를 새로 고침하면 다른 웹 서버에서 아래와 같은 출력이 생성됩니다:
      Welcome to node4.lab.example.com on 172.25.250.12
  • playbook에 또 다른 플레이가 포함되어야 하며, 이 플레이는 webservers 호스트 그룹의 노드에서 실행되며 phpinfo 역할을 사용합니다.

    • webservers 호스트 그룹의 노드에서 /hello.php URL로 접속하면 아래와 같은 출력이 생성됩니다:
      Hello PHP World from FQDN
      • 여기서 FQDN은 해당 노드의 완전한 도메인 이름입니다.
      • 예시 출력:
        Hello PHP World from node3.lab.example.com
        또한 설치된 PHP 버전 등 PHP 구성의 다양한 세부 정보도 표시됩니다.
  • ***http://172.25.250.12/hello.php***로 접속하면 아래와 같은 출력이 생성됩니다:
    Hello PHP World from node4.lab.example.com
    또한 PHP 구성의 다양한 세부 정보도 표시됩니다.

vim /home/greg/ansible/roles.yml
---
- name: Use phpinfo role
hosts: webservers
roles:
- phpinfo

- name: Use balancer role
hosts: balancers
roles:
- balancer
ansible-navigator run /home/greg/ansible/roles.yml -m stdout

# 검증
curl http://172.25.250.13
curl http://node3/hello.php
curl http://node4/hello.php

9. Logical Volume 생성 및 사용

다음 작업을 실행하는 /home/greg/ansible/lv.yml라는 playbook을 생성하세요. 이 플레이북은 모든 관리 대상 노드에서 실행됩니다:

  • 다음 요구 사항을 충족하는 논리 볼륨을 생성합니다:
    • 논리 볼륨은 research 볼륨 그룹에 생성됩니다.
    • 논리 볼륨 이름은 data입니다.
    • 논리 볼륨 크기는 1500 MiB입니다.
  • ext4 파일 시스템으로 논리 볼륨을 포맷합니다.
  • 요청한 논리 볼륨 크기를 생성할 수 없을 경우, 오류 메시지를 표시하고 대신 크기를 800 MiB로 사용합니다.
    Could not create logical volume of that size
  • 만약 볼륨 그룹 research가 존재하지 않으면 오류 메시지를 표시합니다:
    Volume group does not exist
  • 논리 볼륨은 어떤 방법으로도 마운트하지 않습니다.
# doc
ansible-doc community.general.lvol
ansible-doc community.general.filesystem
ansible-doc debug
ansible-doc stat
# playbook작성
vim /home/greg/ansible/lv.yml
---
- name: Create LVM
hosts: all
tasks:
- block:
- name: lv 1500M
community.general.lvol:
vg: research
lv: data
size: 1500
- name: Create ext4
community.general.filesystem:
fstype: ext4
dev: /dev/research/data
rescue:
- name: Could not create lvm
ansible.builtin.debug:
msg: Could not create logical volume of that size
- name: lv 800M
community.general.lvol:
vg: research
lv: data
size: 800
- name: Create ext4
community.general.filesystem:
fstype: ext4
dev: /dev/research/data
when: ansible_lvm.vgs.research is defined
- debug:
msg: Volume group done not exist
when: ansible_lvm.vgs.research is not defined
# playbook실행
ansible-navigator run /home/greg/ansible/lv.yml -m stdout

# 예상대로 흘러가는지 실행과정 확인하도록
PLAY [Create LVM] ***************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************************************
ok: [node3]
ok: [node5]
ok: [node4]
ok: [node2]
ok: [node1]

TASK [lv 1500M] *****************************************************************************************************************************************************************************************************************************************************************
skipping: [node1]
fatal: [node3]: FAILED! => {"changed": false, "err": " Volume group \"research\" has insufficient free space (31 extents): 47 required.\n", "msg": "Creating logical volume 'data' failed", "rc": 5}
changed: [node2]
changed: [node5]
changed: [node4]

TASK [Create ext4] **************************************************************************************************************************************************************************************************************************************************************
skipping: [node1]
changed: [node5]
changed: [node4]
changed: [node2]

TASK [Could not create lvm] *****************************************************************************************************************************************************************************************************************************************************
ok: [node3] => {
"msg": "Could not create logical volume of that size"
}

TASK [lv 800M] ******************************************************************************************************************************************************************************************************************************************************************
changed: [node3]

TASK [Create ext4] **************************************************************************************************************************************************************************************************************************************************************
changed: [node3]

TASK [debug] ********************************************************************************************************************************************************************************************************************************************************************
skipping: [node2]
skipping: [node5]
ok: [node1] => {
"msg": "Volume group done not exist"
}
skipping: [node3]
skipping: [node4]

PLAY RECAP **********************************************************************************************************************************************************************************************************************************************************************
node1 : ok=2 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
node2 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node3 : ok=4 changed=2 unreachable=0 failed=0 skipped=1 rescued=1 ignored=0
node4 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node5 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

# LVS확인
# - node3, VG가용공간 부족으로 800M LV생성
# - node1, VG찾을수 없어 LV생성 실패
ansible all -m shell -a 'lvs'

node3 | CHANGED | rc=0 >>
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
data research -wi-a----- 800.00m
node5 | CHANGED | rc=0 >>
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
data research -wi-a----- <1.47g
node2 | CHANGED | rc=0 >>
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
data research -wi-a----- <1.47g
node4 | CHANGED | rc=0 >>
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
data research -wi-a----- <1.47g
node1 | CHANGED | rc=0 >>

# 파일시스템 확인
ansible all -m shell -a 'blkid /dev/research/data'

node2 | CHANGED | rc=0 >>
/dev/research/data: UUID="83229b4c-dcba-4dcb-aab3-fe8601d3c75a" BLOCK_SIZE="4096" TYPE="ext4"
node3 | CHANGED | rc=0 >>
/dev/research/data: UUID="cdd60647-19a7-48e7-969f-9bd685fcc718" BLOCK_SIZE="4096" TYPE="ext4"
node5 | CHANGED | rc=0 >>
/dev/research/data: UUID="1ee8f698-7b79-410f-bc48-0a1ab781a542" BLOCK_SIZE="4096" TYPE="ext4"
node4 | CHANGED | rc=0 >>
/dev/research/data: UUID="71b9cf21-efae-4926-aef2-80ef3c74b8d2" BLOCK_SIZE="4096" TYPE="ext4"
node1 | FAILED | rc=2 >>
non-zero return code

10.hosts 파일 생성

  • 초기 템플릿 파일을 ***http://classroom/materials/hosts.j2***에서 다운로드하여 /home/greg/ansible에 저장합니다.
  • 이 템플릿을 완성하여 각 호스트에 대해 /etc/hosts와 동일한 형식의 파일을 생성합니다.
  • ***http://classroom/materials/hosts.yml***에서 플레이북을 다운로드하여 /home/greg/ansible에 저장합니다. 이 플레이북은 이 템플릿을 사용하여 dev 호스트 그룹의 호스트에서 /etc/myhosts 파일을 생성합니다.

이 플레이북이 실행된 후, dev 호스트 그룹에 있는 호스트의 /etc/myhosts 파일은 각 관리 대상 호스트에 대해 라인을 포함해야 합니다:

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.250.9 node1.lab.example.com node1
172.25.250.10 node2.lab.example.com node2
172.25.250.11 node3.lab.example.com node3
172.25.250.12 node4.lab.example.com node4
172.25.250.13 node5.lab.example.com node5

참고:인벤토리 호스트명이 나타는는 순서는 중요하지 않습니다.

# 템플릿 다운로드
wget http://classroom/materials/hosts.j2
# 템플릿 편집
vim hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for i in groups.all %}
{{ hostvars[i].ansible_facts.default_ipv4.address }} {{ hostvars[i].ansible_facts.fqdn }} {{ i }}
{% endfor %}
# playbook실행
ansible-navigator run hosts.yml -m stdout
# 검증
ansible dev -m shell -a 'cat /etc/myhosts'

node1 | CHANGED | rc=0 >>
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.250.9 node1.lab.example.com node1
172.25.250.10 node2.lab.example.com node2
172.25.250.13 node5.lab.example.com node5
172.25.250.11 node3.lab.example.com node3
172.25.250.12 node4.lab.example.com node4

11. 파일 내용 수정하기

다음 요구 사항에 따라 /home/greg/ansible/issue.yml 플레이북을 생성하세요:

  • 이 플레이북은 인벤토리 호스트 전체에서 실행됩니다.
  • 이 플레이북은 /etc/issue 파일의 내용을 아래와 같은 텍스트로 교체합니다:
    • dev 호스트 그룹의 호스트에서는 텍스트가 Development로 표시됩니다.
    • test 호스트 그룹의 호스트에서는 텍스트가 Test로 표시됩니다.
    • prod 호스트 그룹의 호스트에서는 텍스트가 Production으로 표시됩니다.

이 플레이북은 인벤토리 호스트 전체에서 실행됩니다.

□ 이 플레이북은 /etc/issue 파일의 내용을 다음과 같이 변경합니다:

□ dev 호스트 그룹의 호스트에서는 다음과 같이 변경됩니다: Development

□ test 호스트 그룹의 호스트에서는 다음과 같이 변경됩니다: Test

□ prod 호스트 그룹의 호스트에서는 다음과 같이 변경됩니다: Production

# doc
ansible-doc copy
ansible-doc stat
# playbook작성
vim /home/greg/ansible/issue.yml
---
- name: Modify /etc/issue file content
hosts: all
tasks:
- name: Update content for dev
ansible.builtin.copy:
content: 'Development'
dest: /etc/issue
when: inventory_hostname in groups.dev

- name: Update content for test
ansible.builtin.copy:
content: 'Test'
dest: /etc/issue
when: inventory_hostname in groups.test

- name: Update content for prod
ansible.builtin.copy:
content: 'Production'
dest: /etc/issue
when: inventory_hostname in groups.prod
# playbook실행
ansible-navigator run issue.yml -m stdout

# 검증
ansible dev -a 'cat /etc/issue'
ansible test -a 'cat /etc/issue'
ansible prod -a 'cat /etc/issue'

12. 웹 콘텐츠 디렉토리 생성하기

다음 요구 사항에 맞춰 /home/greg/ansible/webcontent.yml 플레이북을 생성하세요:

  1. 이 플레이북은 dev 호스트 그룹의 관리 대상 노드에서 실행됩니다.
  2. 아래 요구 사항에 맞는 디렉토리 /webdev를 생성합니다:
    • 소유자는 webdev 그룹입니다.
    • 일반 권한은 다음과 같습니다:
      • owner=read+write+execute
      • group=read+write+execute
      • other=read+execute
    • 특수 권한: 그룹 ID 설정.
  3. /var/www/html/webdev/webdev로 심볼릭 링크를 만듭니다.
  4. /webdev/index.html 파일을 생성하고, 그 안에 다음과 같은 단일 행의 텍스트를 넣습니다:
    Development
  5. dev 호스트 그룹의 노드에서 이 디렉토리(예: http://172.25.250.9/webdev/)를 접속하면 ***"Development"***가 출력되어야 합니다:
# doc
ansible-doc file
ansible-doc copy
# file context확인
ansible dev -a 'ls -ldZ /var/www/html'
# playbook작성
vim /home/greg/ansible/webcontent.yml
---
- name: Create Web Content Directory
hosts: dev
tasks:
- name: Create /webdev directory
ansible.builtin.file:
path: /webdev
state: directory
group: webdev
mode: '2775'

- name: Create symbolic link for /webdev
ansible.builtin.file:
src: /webdev
dest: /var/www/html/webdev
state: link

- name: Create /webdev/index.html file
ansible.builtin.copy:
content: |
Development
dest: /webdev/index.html
setype: httpd_sys_content_t
# playbook실행
ansible-navigator run webcontent.yml -m stdout
# 검증
curl http://172.25.250.9/webdev/

13. 하드웨어 보고서 생성하기

/home/greg/ansible/hwreport.yml라는 이름의 플레이북을 생성하여, 모든 관리 대상 노드에서 다음 정보를 포함하는 출력 파일 /root/hwreport.txt를 생성하세요:

  • 인벤토리 호스트명;
  • 총 메모리 크기(MB);
  • BIOS 버전;
  • 디스크 장치 vda 크기;
  • 디스크 장치 vdb 크기;
  • 출력 파일의 각 행은 key=value 쌍을 포함해야 합니다.

플레이북은 다음과 같이 수행되어야 합니다:

  • ***http://classroom/materials/hwreport.empty***에서 파일을 다운로드하고 이를 /root/hwreport.txt에 저장합니다.
  • 정확한 값을 사용하여 /root/hwreport.txt를 업데이트합니다.
  • 하드웨어 항목이 없으면 해당 값은 NONE으로 설정해야 합니다.
# 리포트 생성에 필요한 옵션명 사전확인
ansible all -m setup | grep mem
ansible all -m setup | grep bios
ansible all -m setup -a 'filter=*device*'

# 리포트 파일내용 확인
curl http://materials/hwreport.empty
# playbook작성
vim /home/greg/ansible/hwreport.yml
---
- name: Generate hardware report
hosts: all
tasks:
- name: Download empty report template
ansible.builtin.get_url:
url: http://materials/hwreport.empty
dest: /root/hwreport.txt

- name: Add hostname to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^HOST='
line: "HOST={{ inventory_hostname }}"

- name: Add memory size to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^MEMORY='
line: "MEMORY={{ ansible_memtotal_mb | default('NONE', true) }}"

- name: Add BIOS version to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^BIOS='
line: "BIOS={{ ansible_bios_version | default('NONE', true) }}"

- name: Add vda disk size to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^DISK_SIZE_VDA='
line: "DISK_SIZE_VDA={{ ansible_devices.vda.size | default('NONE', true) }}"

- name: Add vdb disk size to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^DISK_SIZE_VDB='
line: "DISK_SIZE_VDB={{ ansible_devices.vdb.size | default('NONE', true) }}"
# playbook실행
ansible-navigator run hwreport.yml -m stdout
# 검증
ansible all -a 'cat /root/hwreport.txt'

node4 | CHANGED | rc=0 >>
# Hardware report
HOST=node4
MEMORY=960
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=1.00 GB
node2 | CHANGED | rc=0 >>
# Hardware report
HOST=node2
MEMORY=960
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=1.00 GB
node5 | CHANGED | rc=0 >>
# Hardware report
HOST=node5
MEMORY=960
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=1.00 GB
node3 | CHANGED | rc=0 >>
# Hardware report
HOST=node3
MEMORY=960
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=1.00 GB
node1 | CHANGED | rc=0 >>
# Hardware report
HOST=node1
MEMORY=5668
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=20.00 GB
DISK_SIZE_VDB=NONE

14. 비밀번호 저장소 생성하기

다음 요구 사항에 맞춰 Ansible 저장소를 생성하여 사용자 비밀번호를 저장하세요:

  • 저장소 이름은 /home/greg/ansible/locker.yml입니다.
  • 저장소에는 아래와 같이 두 개의 변수가 포함됨니다
    • pw_developer, 값은 Imadev
    • pw_manager, 값은 Imamgr
  • 이 저장소를 암호화하고 해독하는 비밀번호는 whenyouwishuponastar입니다.
  • 비밀번호는 /home/greg/ansible/secret.txt 파일에 저장됩니다.
# 비밀번호 저장파일 생성
echo "whenyouwishuponastar" > /home/greg/ansible/secret.txt

# 비밀번호 파일 지정
vim ansible.cfg
vault_password_file=/home/greg/ansible/secret.txt

# vault생성
ansible-vault create /home/greg/ansible/locker.yml
---
pw_developer: Imadev
pw_manager: Imamgr

# 검증
cat /home/greg/ansible/locker.yml

$ANSIBLE_VAULT;1.1;AES256
32316462663839316261653164376664376432313863333238383462396230663138323362363132
3361363734323065373531343431303234616232333135380a396530626436383566356337633966
64393365623237303333373037366461646638376164376130613637646434383537383636336265
3061666131656238320a303337366163633337313533376632646631316434323765326135396562
32393031383338386533643865653965366264653034633132396666666331663064626337333734
6136653065306631643466356531393031666339346165316637

15. 사용자 계정 생성하기

다음 요구 사항에 맞춰 사용자 계정을 생성하는 작업을 수행하세요:

  • ***http://classroom/materials/user_list.yml***에서 사용자 목록을 다운로드하고 이를 /home/greg/ansible에 저장합니다.

  • 이 실습에서는 다른 위치에서 생성된 비밀번호 저장소 /home/greg/ansible/locker.yml을 사용합니다. /home/greg/ansible/users.yml라는 이름의 플레이북을 생성하여, 아래 조건에 맞게 사용자 계정을 생성합니다:

    • 직무 설명이 developer인 사용자는:
      • devtest 호스트 그룹의 관리 대상 노드에서 생성됩니다.
      • pw_developer 변수에서 비밀번호를 할당받습니다.
      • 비밀번호 최대 유효 기간은 30일입니다.
      • 보조 그룹 devops의 멤버입니다.
    • 직무 설명이 manager인 사용자는:
      • prod 호스트 그룹의 관리 대상 노드에서 생성됩니다.
      • pw_manager 변수에서 비밀번호를 할당받습니다.
      • 비밀번호 최대 유효 기간은 30일입니다.
      • 보조 그룹 opsmgr의 멤버입니다.
  • 비밀번호는 SHA512 해시 형식으로 저장됩니다.

  • 이 플레이북은 다른 위치에서 생성된 비밀번호 파일 /home/greg/ansible/secret.txt을 사용하여 정상적으로 실행될 수 있어야 합니다.

# 파일 다운로드
wget http://classroom/materials/user_list.yml
# 파일내용 확인
cat user_list.yml
# playbook작성
vim /home/greg/ansible/users.yml
---
- name: Create User1
hosts: dev,test
vars_files:
- /home/greg/ansible/locker.yml
- /home/greg/ansible/user_list.yml
tasks:
- name: Add group1
group:
name: devops
state: present

- name: Add user1
user:
name: "{{ item.name }}"
groups: devops
password: "{{ pw_developer | password_hash('sha512') }}"
password_expire_max: "{{ item.password_expire_max }}"
loop: "{{ users }}"
when: item.job == 'developer'

- name: Create User2
hosts: prod
vars_files:
- /home/greg/ansible/locker.yml
- /home/greg/ansible/user_list.yml
tasks:
- name: Add group2
group:
name: opsmgr
state: present

- name: Add user2
user:
name: "{{ item.name }}"
groups: opsmgr
password: "{{ pw_manager | password_hash('sha512') }}"
password_expire_max: "{{ item.password_expire_max }}"
loop: "{{ users }}"
when: item.job == 'manager'
# playbook실행
ansible-navigator run users.yml -m stdout

PLAY [Create User1] *************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************************************
ok: [node2]
ok: [node1]

TASK [Add group1] ***************************************************************************************************************************************************************************************************************************************************************
ok: [node2]
ok: [node1]

TASK [Add user1] ****************************************************************************************************************************************************************************************************************************************************************
changed: [node2] => (item={'name': 'bob', 'job': 'developer', 'password_expire_max': 10, 'uid': 3000})
skipping: [node2] => (item={'name': 'sally', 'job': 'manager', 'password_expire_max': 20, 'uid': 3001})
changed: [node1] => (item={'name': 'bob', 'job': 'developer', 'password_expire_max': 10, 'uid': 3000})
skipping: [node1] => (item={'name': 'sally', 'job': 'manager', 'password_expire_max': 20, 'uid': 3001})
changed: [node2] => (item={'name': 'fred', 'job': 'developer', 'password_expire_max': 30, 'uid': 3002})
changed: [node1] => (item={'name': 'fred', 'job': 'developer', 'password_expire_max': 30, 'uid': 3002})

PLAY [Create User2] *************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************************************
ok: [node3]
ok: [node4]

TASK [Add group2] ***************************************************************************************************************************************************************************************************************************************************************
changed: [node3]
changed: [node4]

TASK [Add user2] ****************************************************************************************************************************************************************************************************************************************************************
skipping: [node3] => (item={'name': 'bob', 'job': 'developer', 'password_expire_max': 10, 'uid': 3000})
skipping: [node4] => (item={'name': 'bob', 'job': 'developer', 'password_expire_max': 10, 'uid': 3000})
changed: [node4] => (item={'name': 'sally', 'job': 'manager', 'password_expire_max': 20, 'uid': 3001})
skipping: [node4] => (item={'name': 'fred', 'job': 'developer', 'password_expire_max': 30, 'uid': 3002})
changed: [node3] => (item={'name': 'sally', 'job': 'manager', 'password_expire_max': 20, 'uid': 3001})
skipping: [node3] => (item={'name': 'fred', 'job': 'developer', 'password_expire_max': 30, 'uid': 3002})

PLAY RECAP **********************************************************************************************************************************************************************************************************************************************************************
node1 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node3 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node4 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 검증
ansible dev,test -m shell -a 'id bob; id fred'
ansible prod -m shell -a 'id sally'
ssh bob@node1
bob@node1\'s password: Imadev
ssh sally@node3
sally@node3\'s password: Imamgr

16. Ansible Vault 키 업데이트

다음 요구 사항에 맞춰 기존 Ansible Vault 키를 업데이트하세요:

  • ***http://classroom/materials/salaries.yml***에서 Ansible Vault을 다운로드하고 /home/greg/ansible에 저장합니다.
  • 현재 Vault 비밀번호는 insecure8sure입니다.
  • 새로운 Vault 비밀번호는 bbs2you9527입니다.
  • Vault은 새 비밀번호로 암호화된 상태를 유지해야 합니다.
# vault파일 다운
wget http://classroom/materials/salaries.yml
# 비밀번호 변경
ansible-vault rekey --ask-vault-pass /home/greg/ansible/salaries.yml

Vault password: insecure8sure
New Vault password: bbs2you9527
Confirm New Vault password: bbs2you9527
Rekey successful

# 검증
ansible-vault view --ask-vault-pass salaries.yml

Vault password: bbs2you9527
haha

17. cron 작업 설정하기

다음 요구 사항에 맞춰 /home/greg/ansible/cron.yml 플레이북을 생성하세요:

  • 이 플레이북은 test 호스트 그룹의 관리 대상 노드에서 실행됩니다.
  • cron 작업을 구성하여, 이 작업이 2분마다 실행되도록 설정하고, 다음 명령을 실행합니다: logger "EX200 in progress
  • 이 작업은 natasha 사용자 신분으로 실행됩니다.
# doc
ansible-doc cron
# playbook작성
vim /home/greg/ansible/cron.yml
---
- name: cron
hosts: test
tasks:
- name: cron job
cron:
name: "cron job1"
minute: "*/2"
job: 'logger "EX200 in progress"'
user: natasha
# playbook실행
ansible-navigator run cron.yml -m stdout
# 검증
ansible test -a 'crontab -l -u natasha'