소개
이 종합적인 실습에서는 Ansible 을 사용하여 중요한 Linux 관리 작업을 자동화하는 방법을 마스터하게 됩니다. 파일 관리 기초를 바탕으로 소프트웨어 설치부터 사용자 관리, 서비스 구성, 스토리지 프로비저닝, 네트워크 설정에 이르기까지 시스템 관리의 전체 수명 주기를 관리하는 방법을 탐색합니다.
ansible.builtin.dnf, ansible.builtin.yum_repository, ansible.builtin.rpm_key와 같은 모듈을 사용하여 소프트웨어 패키지 관리 및 리포지토리 구성을 자동화하는 것부터 시작합니다. 다음으로 사용자 계정을 생성 및 관리하고, SSH 액세스를 구성하며, sudo 권한을 설정합니다. 실습은 LVM 및 파일 시스템 작업을 사용한 스토리지 관리로 진행하기 전에 cron 및 systemd 를 사용한 예약 작업, 서비스 관리로 진행됩니다. 마지막으로 네트워크 인터페이스를 구성하고 시스템 정보를 수집합니다.
이 실습은 엔터프라이즈 Linux 환경에서 일반적으로 발생하는 실제 시나리오를 강조하여 Infrastructure as Code(IaC) 관행을 효과적으로 구현할 수 있도록 준비시킵니다.
리포지토리 구성 및 소프트웨어 패키지 관리
이 단계에서는 Ansible 을 사용하여 RHEL 시스템에서 소프트웨어 패키지 관리를 자동화하는 방법을 배웁니다. Yum 리포지토리를 구성하고, RPM GPG 키를 관리하며, 관리 대상 호스트에서 패키지 정보를 수집합니다. 이는 인프라 전반에 걸쳐 일관된 소프트웨어 설치를 유지하는 데 필수적입니다.
리포지토리 관리를 위한 ansible.builtin.yum_repository, GPG 키 처리를 위한 ansible.builtin.rpm_key, 패키지 정보 수집을 위한 ansible.builtin.package_facts, 패키지 설치를 위한 ansible.builtin.dnf와 같은 몇 가지 주요 모듈을 사용합니다.
먼저 프로젝트 환경을 설정하고 Ansible 을 설치합니다.
ansible-core패키지를 설치하고 프로젝트 디렉토리로 이동합니다.sudo dnf install -y ansible-core cd ~/project mkdir system-software cd system-software관리 대상 호스트를 정의할 Ansible 인벤토리 파일을 생성합니다. 이 실습에서는 로컬 머신을 관리합니다.
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local [all:children] webservers EOF리포지토리 구성 및 패키지 설치를 관리할 메인 플레이북
repo_playbook.yml을 생성합니다. 이 플레이북은 완전한 소프트웨어 관리 워크플로우를 보여줍니다.nano repo_playbook.yml포괄적인 소프트웨어 관리 플레이북을 생성하기 위해 다음 내용을 추가합니다:
--- - name: Repository Configuration and Software Management hosts: all become: true vars: custom_pkg: httpd tasks: - name: Gather Package Facts ansible.builtin.package_facts: manager: auto - name: Show Package Facts for the custom package (initial check) ansible.builtin.debug: var: ansible_facts['packages'][custom_pkg] when: custom_pkg in ansible_facts['packages'] - name: Ensure EPEL repository is configured ansible.builtin.yum_repository: name: epel description: Extra Packages for Enterprise Linux 9 file: epel baseurl: https://download.fedoraproject.org/pub/epel/9/Everything/x86_64/ gpgcheck: yes gpgkey: https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9 enabled: yes state: present - name: Import EPEL GPG key ansible.builtin.rpm_key: state: present key: https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9 - name: Install the custom package ansible.builtin.dnf: name: "{{ custom_pkg }}" state: present - name: Gather Package Facts (after installation) ansible.builtin.package_facts: manager: auto - name: Show Package Facts for the custom package (post-installation) ansible.builtin.debug: var: ansible_facts['packages'][custom_pkg] when: custom_pkg in ansible_facts['packages'] - name: Display installed package version ansible.builtin.debug: msg: "{{ custom_pkg }} version {{ ansible_facts['packages'][custom_pkg][0]['version'] }} is installed" when: custom_pkg in ansible_facts['packages']참고: 이 실습의 구성 파일은 상당히 길기 때문에 문서의 간결성을 유지하기 위해 자세한 설명을 제공하지 않습니다. 특정 부분에 대한 설명이 필요한 경우 코드 블록의 왼쪽 하단에 있는 "Explain Code" 버튼을 클릭하여 Labby 의 자세한 설명을 확인할 수 있습니다.
이 플레이북은 다음과 같은 몇 가지 중요한 개념을 보여줍니다:
- 패키지 사실 수집: 설치된 패키지에 대한 정보를 수집하는 방법
- 리포지토리 관리: 올바른 GPG 검증으로 EPEL 리포지토리 구성
- GPG 키 관리: 보안을 위해 리포지토리의 GPG 키 가져오기
- 패키지 설치: dnf 모듈을 사용하여 지정된 패키지 설치
- 검증: 업데이트된 사실로 패키지 설치 확인
플레이북을 실행하여 완전한 소프트웨어 관리 워크플로우를 확인합니다.
ansible-playbook -i inventory.ini repo_playbook.yml다음과 같은 출력을 볼 수 있습니다:
- 초기 패키지 확인 (httpd 가 설치되지 않았으므로 건너뛸 가능성이 높음)
- 리포지토리 구성
- GPG 키 가져오기
- 패키지 설치
- 설치된 패키지를 보여주는 최종 확인
생성된 리포지토리 파일을 확인하여 리포지토리 구성을 검증합니다.
cat /etc/yum.repos.d/epel.repobaseurl, gpgcheck 및 gpgkey 설정이 포함된 EPEL 리포지토리 구성을 볼 수 있습니다.
플레이북을 다시 실행하여 패키지 관리의 멱등성 (idempotency) 을 테스트합니다.
ansible-playbook -i inventory.ini repo_playbook.ymlAnsible 이 변경이 필요하지 않은 작업에 대해 "ok"를 보고하는 것을 확인하여 멱등성을 보여줍니다.
Ansible 을 사용하여 리포지토리 구성, GPG 키 관리 및 패키지 설치 확인을 포함한 소프트웨어 패키지 관리를 성공적으로 자동화했습니다.
사용자 관리 및 SSH 구성 자동화
이 단계에서는 Ansible 을 사용하여 사용자 계정 관리, SSH 구성 및 sudo 권한을 자동화하는 방법을 배웁니다. 이는 인프라 전반에 걸쳐 일관된 사용자 액세스 및 보안 정책을 유지하는 데 중요합니다.
사용자 관리를 위한 ansible.builtin.user, 그룹 생성을 위한 ansible.builtin.group, SSH 키 관리를 위한 ansible.posix.authorized_key, 구성 파일 수정을 위한 ansible.builtin.lineinfile과 같은 모듈을 사용합니다.
사용자 관리 작업을 위한 새 프로젝트 디렉토리로 이동합니다.
cd ~/project mkdir system-users cd system-usersansible.posix컬렉션을 설치합니다.ansible-galaxy collection install ansible.posix이 연습을 위한 인벤토리 파일을 생성합니다.
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local EOF관리하려는 사용자 및 그룹을 정의할 변수 파일을 생성합니다.
mkdir vars nano vars/users_vars.yml사용자 계정 및 해당 그룹 멤버십을 정의하기 위해 다음 내용을 추가합니다:
--- users: - username: webuser1 groups: webadmin - username: webuser2 groups: webadmin - username: devuser1 groups: webadmin사용자를 위한 SSH 키 쌍을 생성합니다. 실제 환경에서는 사용자가 공개 키를 제공합니다.
mkdir files ## Generate SSH keys for each user ssh-keygen -t rsa -b 2048 -f files/webuser1.key -N "" -C "webuser1@example.com" ssh-keygen -t rsa -b 2048 -f files/webuser2.key -N "" -C "webuser2@example.com" ssh-keygen -t rsa -b 2048 -f files/devuser1.key -N "" -C "devuser1@example.com"주요 사용자 관리 플레이북
users.yml을 생성합니다. 이 플레이북은 그룹, 사용자를 생성하고, SSH 키를 배포하며, sudo 액세스를 구성합니다.nano users.yml다음의 포괄적인 사용자 관리 플레이북을 추가합니다:
--- - name: Create and manage user accounts hosts: webservers become: true vars_files: - vars/users_vars.yml tasks: - name: Create webadmin group ansible.builtin.group: name: webadmin state: present - name: Create user accounts ansible.builtin.user: name: "{{ item['username'] }}" groups: "{{ item['groups'] }}" shell: /bin/bash create_home: yes state: present loop: "{{ users }}" - name: Set up SSH authorized keys ansible.posix.authorized_key: user: "{{ item['username'] }}" key: "{{ lookup('file', 'files/' + item['username'] + '.key.pub') }}" state: present loop: "{{ users }}" - name: Configure sudo access for webadmin group ansible.builtin.lineinfile: path: /etc/sudoers.d/webadmin state: present create: yes mode: "0440" line: "%webadmin ALL=(ALL) NOPASSWD: ALL" validate: /usr/sbin/visudo -cf %s - name: Configure SSH to disable root login ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config regexp: "^PermitRootLogin" line: "PermitRootLogin no" backup: yes notify: restart sshd - name: Configure SSH to disable password authentication ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config regexp: "^PasswordAuthentication" line: "PasswordAuthentication no" backup: yes notify: restart sshd handlers: - name: restart sshd ansible.builtin.service: name: sshd state: restarted이 플레이북은 몇 가지 사용자 관리 모범 사례를 보여줍니다:
- 그룹 관리: 관리 그룹 생성
- 사용자 생성: 올바른 홈 디렉토리로 사용자 계정 설정
- SSH 키 관리: 키 기반 인증을 위한 공개 키 배포
- Sudo 구성: 관리자 권한을 안전하게 부여
- SSH 강화: 루트 로그인 및 비밀번호 인증 비활성화
- 서비스 관리: 구성 변경 시 SSH 서비스 재시작
사용자 관리 플레이북을 실행합니다.
ansible-playbook -i inventory.ini users.yml플레이북은 사용자를 생성하고, SSH 키를 설정하며, sudo 액세스를 구성하고, SSH 구성을 강화합니다.
사용자 생성 및 그룹 멤버십을 확인합니다.
## Check if users were created getent passwd webuser1 webuser2 devuser1 ## Check group membership groups webuser1 groups webuser2 groups devuser1 ## Verify webadmin group exists getent group webadmin생성된 사용자 중 한 명에 대해 SSH 키 인증을 테스트합니다.
## Test SSH key authentication (this will connect to localhost) ssh -i files/webuser1.key webuser1@localhost "whoami"비밀번호 없는 sudo 액세스를 테스트하여 sudo 구성을 확인합니다.
## Test sudo access for webuser1 ssh -i files/webuser1.key webuser1@localhost "sudo whoami"SSH 구성 변경 사항을 확인합니다.
## Verify SSH configuration sudo grep "PermitRootLogin\|PasswordAuthentication" /etc/ssh/sshd_config ## Check sudo configuration sudo cat /etc/sudoers.d/webadmin
Ansible 을 사용하여 사용자 계정 생성, SSH 키 배포 및 보안 구성을 성공적으로 자동화하여 인프라 전반에 걸쳐 안전한 사용자 관리를 위한 기반을 마련했습니다.
서비스 관리 및 작업 스케줄링 자동화
이 단계에서는 Ansible 을 사용하여 systemd 서비스를 관리하고, cron 작업을 스케줄링하며, 시스템 부팅 타겟을 구성하는 방법을 배웁니다. 이는 서비스 가용성을 유지하고 인프라 전반에 걸쳐 일상적인 작업을 자동화하는 데 필수적입니다.
서비스 관리를 위한 ansible.builtin.service, 작업 스케줄링을 위한 ansible.builtin.cron, 일회성 작업을 위한 ansible.posix.at, 시스템 타겟 관리를 위한 ansible.builtin.systemd와 같은 모듈을 사용합니다.
서비스 및 프로세스 관리를 위한 새 프로젝트 디렉토리로 이동합니다.
cd ~/project mkdir system-process cd system-process이 연습을 위한 인벤토리 파일을 생성합니다.
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local EOFApache HTTP 서버 서비스를 관리하는 플레이북을 생성합니다. 이는 기본적인 서비스 관리를 시연합니다.
nano service_management.yml다음 내용을 추가합니다:
--- - name: Manage Apache HTTP Server Service hosts: webservers become: true tasks: - name: Start and enable httpd service ansible.builtin.service: name: httpd state: started enabled: yes - name: Create a simple index.html ansible.builtin.copy: content: | <html> <head><title>Ansible Managed Server</title></head> <body> <h1>Welcome to Ansible Managed Apache Server</h1> <p>This server is configured and managed by Ansible.</p> <p>Service started at: $(date)</p> </body> </html> dest: /var/www/html/index.html owner: apache group: apache mode: "0644" - name: Verify httpd service is running ansible.builtin.service_facts: - name: Display httpd service status ansible.builtin.debug: var: ansible_facts.services['httpd.service']cron 작업을 스케줄링하는 플레이북을 생성합니다. 이는 자동화된 작업 스케줄링을 시연합니다.
nano create_crontab_file.yml다음 내용을 추가합니다:
--- - name: Schedule recurring cron jobs hosts: webservers become: true tasks: - name: Create labex user for cron jobs ansible.builtin.user: name: labex state: present create_home: yes - name: Schedule system monitoring cron job ansible.builtin.cron: name: System monitoring log job: "date >> /home/labex/system_monitor.log && df -h >> /home/labex/system_monitor.log" minute: "*/5" hour: "*" user: labex cron_file: system-monitoring state: present - name: Schedule daily log rotation ansible.builtin.cron: name: Daily log cleanup job: "find /home/labex -name '*.log' -mtime +7 -delete" minute: "0" hour: "2" weekday: "*" user: labex cron_file: log-cleanup state: present - name: Schedule weekly system update check ansible.builtin.cron: name: Weekly update check job: "dnf check-update > /home/labex/update_check.log 2>&1" minute: "0" hour: "3" weekday: "0" user: labex cron_file: update-check state: presentat을 사용하여 일회성 작업 스케줄링을 위한 플레이북을 생성합니다.nano schedule_at_task.yml다음 내용을 추가합니다:
--- - name: Schedule one-time tasks with at hosts: webservers become: true become_user: labex tasks: - name: Schedule immediate system info collection ansible.posix.at: command: "uname -a > ~/system_info_$(date +%Y%m%d_%H%M%S).txt" count: 2 units: minutes unique: yes state: present - name: Schedule delayed service status check ansible.posix.at: command: "systemctl status httpd > ~/httpd_status_$(date +%Y%m%d_%H%M%S).txt" count: 5 units: minutes unique: yes state: present시스템 부팅 타겟을 관리하는 플레이북을 생성합니다.
nano boot_target_management.yml다음 내용을 추가합니다:
--- - name: Manage system boot targets hosts: webservers become: true tasks: - name: Check current default target ansible.builtin.command: cmd: systemctl get-default register: current_target changed_when: false - name: Display current boot target ansible.builtin.debug: msg: "Current default boot target: {{ current_target.stdout }}" - name: Set default boot target to multi-user ansible.builtin.systemd: name: multi-user.target enabled: yes when: current_target.stdout != "multi-user.target" - name: Verify the boot target change ansible.builtin.command: cmd: systemctl get-default register: new_target changed_when: false - name: Display new boot target ansible.builtin.debug: msg: "New default boot target: {{ new_target.stdout }}"서비스 관리 플레이북을 실행합니다.
ansible-playbook -i inventory.ini service_management.yml이것은 httpd 서비스를 시작하고 환영 페이지를 생성합니다.
cron 작업 스케줄링 플레이북을 실행합니다.
ansible-playbook -i inventory.ini create_crontab_file.yml이것은 시스템 모니터링 및 유지보수를 위한 여러 예약된 작업을 생성합니다.
일회성 작업 스케줄링 플레이북을 실행합니다.
ansible-playbook -i inventory.ini schedule_at_task.yml이것은
at명령을 사용하여 즉시 작업을 예약합니다.부팅 타겟 관리 플레이북을 실행합니다.
ansible-playbook -i inventory.ini boot_target_management.yml이것은 시스템의 기본 부팅 타겟을 확인하고 잠재적으로 수정합니다.
예약된 작업 및 서비스를 확인합니다.
## Check cron jobs sudo cat /etc/cron.d/system-monitoring sudo cat /etc/cron.d/log-cleanup sudo cat /etc/cron.d/update-check ## Check at jobs sudo atq ## Check httpd service status sudo systemctl status httpd ## Test the web server curl localhost ## Check system monitoring log (wait a few minutes for cron to run) sudo cat /home/labex/system_monitor.log필요할 때 예약된 작업을 제거하는 정리 플레이북을 생성합니다.
nano remove_scheduled_tasks.yml다음 내용을 추가합니다:
--- - name: Remove scheduled tasks hosts: webservers become: true tasks: - name: Remove system monitoring cron job ansible.builtin.cron: name: System monitoring log user: labex cron_file: system-monitoring state: absent - name: Remove log cleanup cron job ansible.builtin.cron: name: Daily log cleanup user: labex cron_file: log-cleanup state: absent - name: Remove update check cron job ansible.builtin.cron: name: Weekly update check user: labex cron_file: update-check state: absent
Ansible 을 사용하여 서비스 관리, 작업 스케줄링 및 시스템 구성을 성공적으로 자동화하여 인프라를 자동으로 유지 관리하고 모니터링하기 위한 기반을 제공했습니다.
LVM 및 파일 시스템을 사용한 스토리지 관리 자동화
이 단계에서는 Ansible 을 사용하여 LVM 물리 볼륨 (physical volumes), 볼륨 그룹 (volume groups), 논리 볼륨 (logical volumes), 파일 시스템을 생성하여 스토리지 관리를 자동화하는 방법을 배웁니다. 이는 인프라 전반에 걸쳐 스토리지 리소스를 일관되고 확장 가능한 방식으로 관리하는 데 중요합니다.
볼륨 그룹 관리를 위한 ansible.builtin.lvg, 논리 볼륨 생성을 위한 ansible.builtin.lvol, 파일 시스템 생성을 위한 ansible.builtin.filesystem, 마운트 포인트 관리를 위한 ansible.posix.mount와 같은 모듈을 사용합니다.
스토리지 관리를 위한 새 프로젝트 디렉토리로 이동합니다.
cd ~/project mkdir system-storage cd system-storage이 연습을 위한 인벤토리 파일을 생성합니다.
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local EOF가상 환경에서 작업하므로 추가 스토리지를 시뮬레이션하기 위해 루프 장치 (loop device) 를 생성합니다.
## Create a 1GB file to use as a virtual disk sudo dd if=/dev/zero of=/tmp/virtual_disk bs=1M count=1024 ## Set up loop device sudo losetup /dev/loop0 /tmp/virtual_disk ## Verify the loop device lsblk | grep loop0포괄적인 스토리지 관리 플레이북을 생성합니다. 이는 LVM 작업 및 파일 시스템 관리를 시연합니다.
nano storage.yml다음 내용을 추가합니다:
--- - name: Configure LVM storage and filesystems hosts: webservers become: true vars: storage_device: /dev/loop0 volume_group: apache-vg content_lv: content-lv logs_lv: logs-lv backup_lv: backup-lv tasks: - name: Install LVM utilities ansible.builtin.dnf: name: lvm2 state: present - name: Create physical volume community.general.lvg: vg: "{{ volume_group }}" pvs: "{{ storage_device }}" state: present - name: Create logical volume for web content community.general.lvol: vg: "{{ volume_group }}" lv: "{{ content_lv }}" size: 256m state: present - name: Create logical volume for logs community.general.lvol: vg: "{{ volume_group }}" lv: "{{ logs_lv }}" size: 256m state: present - name: Create logical volume for backup community.general.lvol: vg: "{{ volume_group }}" lv: "{{ backup_lv }}" size: 256m state: present - name: Create XFS filesystem on content volume community.general.filesystem: fstype: xfs dev: "/dev/{{ volume_group }}/{{ content_lv }}" force: no - name: Create XFS filesystem on logs volume community.general.filesystem: fstype: xfs dev: "/dev/{{ volume_group }}/{{ logs_lv }}" force: no - name: Create ext4 filesystem on backup volume community.general.filesystem: fstype: ext4 dev: "/dev/{{ volume_group }}/{{ backup_lv }}" force: no - name: Create mount points ansible.builtin.file: path: "{{ item }}" state: directory mode: "0755" loop: - /var/www - /var/log/httpd - /backup - name: Mount web content volume ansible.posix.mount: path: /var/www src: "/dev/{{ volume_group }}/{{ content_lv }}" fstype: xfs opts: defaults state: mounted - name: Mount logs volume ansible.posix.mount: path: /var/log/httpd src: "/dev/{{ volume_group }}/{{ logs_lv }}" fstype: xfs opts: defaults state: mounted - name: Mount backup volume ansible.posix.mount: path: /backup src: "/dev/{{ volume_group }}/{{ backup_lv }}" fstype: ext4 opts: defaults state: mounted - name: Set appropriate ownership for web content ansible.builtin.file: path: /var/www owner: apache group: apache recurse: yes - name: Set appropriate ownership for httpd logs ansible.builtin.file: path: /var/log/httpd owner: apache group: apache recurse: yes - name: Create html directory for web content ansible.builtin.file: path: /var/www/html state: directory owner: apache group: apache mode: "0755" - name: Create sample web content ansible.builtin.copy: content: | <html> <head><title>Storage Management Demo</title></head> <body> <h1>LVM Storage Configuration</h1> <p>This content is served from an LVM logical volume managed by Ansible.</p> <p>Volume Group: {{ volume_group }}</p> <p>Logical Volume: {{ content_lv }}</p> <p>Filesystem: XFS</p> </body> </html> dest: /var/www/html/storage.html owner: apache group: apache mode: "0644"LVM 관리에 필요한 Ansible 컬렉션을 설치합니다.
ansible-galaxy collection install community.general스토리지 관리 플레이북을 실행합니다.
ansible-playbook -i inventory.ini storage.yml이것은 LVM 구조, 파일 시스템 및 마운트 포인트를 생성합니다.
스토리지 정보를 수집하고 표시하는 플레이북을 생성합니다.
nano get-storage.yml다음 내용을 추가합니다:
--- - name: Gather storage information hosts: webservers become: true tasks: - name: Gather disk facts ansible.builtin.setup: gather_subset: - hardware - name: Display volume group information ansible.builtin.command: cmd: vgdisplay apache-vg register: vg_info changed_when: false - name: Display logical volume information ansible.builtin.command: cmd: lvdisplay apache-vg register: lv_info changed_when: false - name: Display filesystem information ansible.builtin.command: cmd: df -h /var/www /var/log/httpd /backup register: fs_info changed_when: false - name: Display mount information ansible.builtin.command: cmd: cat /proc/mounts register: mount_info changed_when: false - name: Show volume group details ansible.builtin.debug: var: vg_info.stdout_lines - name: Show logical volume details ansible.builtin.debug: var: lv_info.stdout_lines - name: Show filesystem usage ansible.builtin.debug: var: fs_info.stdout_lines - name: Show fstab entries ansible.builtin.command: cmd: grep apache-vg /etc/fstab register: fstab_entries changed_when: false failed_when: false - name: Display fstab entries ansible.builtin.debug: var: fstab_entries.stdout_lines스토리지 정보 수집 플레이북을 실행합니다.
ansible-playbook -i inventory.ini get-storage.yml이것은 생성된 스토리지 구조에 대한 자세한 정보를 표시합니다.
스토리지 구성을 수동으로 확인합니다.
## Check LVM structure sudo vgs apache-vg sudo lvs apache-vg sudo pvs /dev/loop0 ## Check filesystems df -h /var/www /var/log/httpd /backup ## Check mount points mount | grep apache-vg ## Check fstab entries grep apache-vg /etc/fstab ## Test the web content cat /var/www/html/storage.html확장 작업을 시연하기 위해 스토리지 확장 플레이북을 생성합니다.
nano expand_storage.yml다음 내용을 추가합니다:
--- - name: Expand storage volumes hosts: webservers become: true vars: volume_group: apache-vg content_lv: content-lv tasks: - name: Extend content logical volume community.general.lvol: vg: "{{ volume_group }}" lv: "{{ content_lv }}" size: 400m state: present - name: Extend XFS filesystem community.general.filesystem: fstype: xfs dev: "/dev/{{ volume_group }}/{{ content_lv }}" resizefs: yes - name: Display updated filesystem size ansible.builtin.command: cmd: df -h /var/www register: new_size changed_when: false - name: Show new filesystem size ansible.builtin.debug: var: new_size.stdout_lines스토리지 확장을 테스트합니다.
## Check current size before expansion df -h /var/www ## Run the expansion playbook ansible-playbook -i inventory.ini expand_storage.yml ## Verify the expansion df -h /var/www sudo lvs apache-vg/content-lv
Ansible 을 사용하여 물리 볼륨 생성, 논리 볼륨 관리, 파일 시스템 생성 및 마운트 포인트 구성을 포함한 LVM 스토리지 관리 자동화를 성공적으로 수행했습니다.
네트워크 구성 및 정보 수집 자동화
이 마지막 단계에서는 Ansible 을 사용하여 네트워크 인터페이스 구성을 자동화하고 포괄적인 시스템 정보를 수집하는 방법을 배웁니다. 이를 통해 소프트웨어부터 스토리지, 네트워킹까지 시스템 관리 자동화의 전체 범위를 완료합니다.
네트워크 구성 파일을 위한 ansible.builtin.template 모듈을 사용하고, 네트워크 사실 (facts) 을 수집하며, 포괄적인 시스템 보고서를 생성합니다.
네트워크 관리를 위한 새 프로젝트 디렉토리로 이동합니다.
cd ~/project mkdir system-network cd system-network이 연습을 위한 인벤토리 파일을 생성합니다.
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local EOF포괄적인 네트워크 및 시스템 정보 수집 플레이북을 생성합니다.
nano network_info.yml다음 내용을 추가합니다:
--- - name: Gather comprehensive system information hosts: webservers become: true tasks: - name: Gather all system facts ansible.builtin.setup: - name: Create system report directory ansible.builtin.file: path: /tmp/system_reports state: directory mode: "0755" - name: Generate system information report ansible.builtin.template: src: system_report.j2 dest: /tmp/system_reports/system_info_{{ ansible_facts['hostname'] }}.html mode: "0644" - name: Generate network configuration report ansible.builtin.template: src: network_report.j2 dest: /tmp/system_reports/network_info_{{ ansible_facts['hostname'] }}.html mode: "0644" - name: Collect network interface information ansible.builtin.command: cmd: ip addr show register: ip_info changed_when: false - name: Collect routing information ansible.builtin.command: cmd: ip route show register: route_info changed_when: false - name: Collect DNS configuration ansible.builtin.command: cmd: cat /etc/resolv.conf register: dns_info changed_when: false - name: Display network summary ansible.builtin.debug: msg: | System: {{ ansible_facts['hostname'] }} OS: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }} Kernel: {{ ansible_facts['kernel'] }} Default IPv4: {{ ansible_facts['default_ipv4']['address'] | default('N/A') }} Default Interface: {{ ansible_facts['default_ipv4']['interface'] | default('N/A') }} Total Memory: {{ ansible_facts['memtotal_mb'] }}MB CPU Cores: {{ ansible_facts['processor_vcpus'] }}템플릿 디렉토리 및 보고서 파일을 생성합니다.
mkdir templates nano templates/system_report.j2시스템 보고서 템플릿에 다음 내용을 추가합니다:
<!doctype html> <html> <head> <title>System Report - {{ ansible_facts['hostname'] }}</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .section { margin-bottom: 20px; padding: 10px; border: 1px solid #ccc; } .header { background-color: #f5f5f5; padding: 10px; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } </style> </head> <body> <div class="header"> <h1>System Report for {{ ansible_facts['hostname'] }}</h1> <p> Generated on: {{ ansible_date_time.date }} {{ ansible_date_time.time }} </p> </div> <div class="section"> <h2>System Information</h2> <table> <tr> <th>Property</th> <th>Value</th> </tr> <tr> <td>Hostname</td> <td>{{ ansible_facts['hostname'] }}</td> </tr> <tr> <td>FQDN</td> <td>{{ ansible_facts['fqdn'] }}</td> </tr> <tr> <td>Operating System</td> <td> {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }} </td> </tr> <tr> <td>Kernel</td> <td>{{ ansible_facts['kernel'] }}</td> </tr> <tr> <td>Architecture</td> <td>{{ ansible_facts['architecture'] }}</td> </tr> <tr> <td>CPU Cores</td> <td>{{ ansible_facts['processor_vcpus'] }}</td> </tr> <tr> <td>Total Memory</td> <td>{{ ansible_facts['memtotal_mb'] }}MB</td> </tr> <tr> <td>Uptime</td> <td>{{ ansible_facts['uptime_seconds'] }} seconds</td> </tr> </table> </div> <div class="section"> <h2>Storage Information</h2> <table> <tr> <th>Mount Point</th> <th>Filesystem</th> <th>Size</th> <th>Used</th> <th>Available</th> </tr> {% for mount in ansible_facts['mounts'] %} <tr> <td>{{ mount.mount }}</td> <td>{{ mount.fstype }}</td> <td> {{ (mount.size_total / 1024 / 1024 / 1024) | round(2) }}GB </td> <td> {{ ((mount.size_total - mount.size_available) / 1024 / 1024 / 1024) | round(2) }}GB </td> <td> {{ (mount.size_available / 1024 / 1024 / 1024) | round(2) }}GB </td> </tr> {% endfor %} </table> </div> <div class="section"> <h2>Services Status</h2> <table> <tr> <th>Service</th> <th>Status</th> </tr> <tr> <td>httpd</td> <td> {{ ansible_facts.services['httpd.service']['state'] | default('not installed') }} </td> </tr> <tr> <td>sshd</td> <td> {{ ansible_facts.services['sshd.service']['state'] | default('unknown') }} </td> </tr> <tr> <td>NetworkManager</td> <td> {{ ansible_facts.services['NetworkManager.service']['state'] | default('unknown') }} </td> </tr> </table> </div> </body> </html>네트워크 보고서 템플릿을 생성합니다.
nano templates/network_report.j2다음 내용을 추가합니다:
<!doctype html> <html> <head> <title>Network Report - {{ ansible_facts['hostname'] }}</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .section { margin-bottom: 20px; padding: 10px; border: 1px solid #ccc; } .header { background-color: #f5f5f5; padding: 10px; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } pre { background-color: #f9f9f9; padding: 10px; overflow-x: auto; } </style> </head> <body> <div class="header"> <h1>Network Configuration Report</h1> <p>Host: {{ ansible_facts['hostname'] }}</p> <p> Generated on: {{ ansible_date_time.date }} {{ ansible_date_time.time }} </p> </div> <div class="section"> <h2>Network Interfaces</h2> <table> <tr> <th>Interface</th> <th>IPv4 Address</th> <th>IPv6 Address</th> <th>MAC Address</th> <th>Status</th> </tr> {% for interface_name in ansible_facts['interfaces'] %} {% if interface_name != 'lo' %} {% set interface_facts = ansible_facts[interface_name] %} <tr> <td>{{ interface_name }}</td> <td> {{ interface_facts.get('ipv4', {}).get('address', 'N/A') }} </td> <td> {{ interface_facts.get('ipv6', [{}])[0].get('address', 'N/A') if interface_facts.get('ipv6') else 'N/A' }} </td> <td>{{ interface_facts.get('macaddress', 'N/A') }}</td> <td> {{ interface_facts.get('active', false) | ternary('Active', 'Inactive') }} </td> </tr> {% endif %} {% endfor %} </table> </div> <div class="section"> <h2>Default Gateway</h2> <table> <tr> <th>Property</th> <th>Value</th> </tr> <tr> <td>Default IPv4 Address</td> <td> {{ ansible_facts['default_ipv4']['address'] | default('N/A') }} </td> </tr> <tr> <td>Default Interface</td> <td> {{ ansible_facts['default_ipv4']['interface'] | default('N/A') }} </td> </tr> <tr> <td>Default Gateway</td> <td> {{ ansible_facts['default_ipv4']['gateway'] | default('N/A') }} </td> </tr> </table> </div> <div class="section"> <h2>DNS Configuration</h2> <table> <tr> <th>DNS Servers</th> </tr> {% for dns in ansible_facts['dns']['nameservers'] %} <tr> <td>{{ dns }}</td> </tr> {% endfor %} </table> </div> </body> </html>네트워크 인터페이스 구성 플레이북을 생성합니다.
nano configure_network.yml다음 내용을 추가합니다:
--- - name: Configure network settings hosts: webservers become: true tasks: - name: Install NetworkManager if not present ansible.builtin.dnf: name: NetworkManager state: present - name: Ensure NetworkManager is running ansible.builtin.service: name: NetworkManager state: started enabled: yes - name: Configure hosts file with system information ansible.builtin.lineinfile: path: /etc/hosts line: "{{ ansible_facts['default_ipv4']['address'] }} {{ ansible_facts['hostname'] }}.lab.example.com {{ ansible_facts['hostname'] }}" regexp: ".*{{ ansible_facts['hostname'] }}.*" backup: yes - name: Create network monitoring script ansible.builtin.copy: content: | #!/bin/bash ## Network monitoring script generated by Ansible echo "=== Network Status Report ===" echo "Generated at: $(date)" echo echo "=== Interface Status ===" ip addr show echo echo "=== Routing Table ===" ip route show echo echo "=== DNS Configuration ===" cat /etc/resolv.conf echo echo "=== Network Connectivity Test ===" ping -c 3 8.8.8.8 dest: /usr/local/bin/network-status.sh mode: "0755" - name: Create network information gathering cron job ansible.builtin.cron: name: Network status monitoring job: "/usr/local/bin/network-status.sh >> /var/log/network-status.log 2>&1" minute: "*/15" user: root cron_file: network-monitoring state: present네트워크 정보 수집 플레이북을 실행합니다.
ansible-playbook -i inventory.ini network_info.yml이것은 포괄적인 시스템 및 네트워크 보고서를 생성합니다.
네트워크 구성 플레이북을 실행합니다.
ansible-playbook -i inventory.ini configure_network.yml이것은 네트워크 설정 및 모니터링을 구성합니다.
생성된 보고서를 확인합니다.
## List generated reports ls -la /tmp/system_reports/ ## View the system report (you can also open in a browser) cat /tmp/system_reports/system_info_*.html ## Check the network monitoring script cat /usr/local/bin/network-status.sh ## Test the network monitoring script sudo /usr/local/bin/network-status.sh ## Check the network monitoring cron job sudo cat /etc/cron.d/network-monitoring학습한 모든 개념을 결합하는 최종 포괄 플레이북을 생성합니다.
nano complete_system_setup.yml다음 내용을 추가합니다:
--- - name: Complete system setup and configuration hosts: webservers become: true vars: admin_users: - webuser1 - webuser2 tasks: - name: Ensure all required packages are installed ansible.builtin.dnf: name: - httpd - lvm2 - NetworkManager - cronie state: present - name: Ensure all services are running ansible.builtin.service: name: "{{ item }}" state: started enabled: yes loop: - httpd - NetworkManager - crond - name: Generate final system status report ansible.builtin.template: src: system_report.j2 dest: /tmp/final_system_report.html mode: "0644" - name: Display completion message ansible.builtin.debug: msg: | ============================================ RHEL System Administration Automation Complete! ============================================ Summary of configured components: - Software: EPEL repository and packages installed - Users: {{ admin_users | length }} administrative users created - Services: httpd, NetworkManager, and crond configured - Storage: LVM volumes and filesystems configured - Network: Interface configuration and monitoring set up - Scheduling: Cron jobs and at tasks configured Reports available at: - /tmp/system_reports/ - /tmp/final_system_report.html Your RHEL system is now fully automated with Ansible!최종 포괄 설정 플레이북을 실행합니다.
ansible-playbook -i inventory.ini complete_system_setup.yml
Ansible 을 사용하여 소프트웨어 관리, 사용자 관리, 서비스 관리, 스토리지 구성 및 네트워크 설정을 포함하는 RHEL 시스템 관리 작업의 포괄적인 자동화를 성공적으로 완료했습니다.
웹 브라우저에서 생성된 보고서를 미리 봅니다.
보고서 디렉토리로 이동합니다:
cd /tmp/system_reportsPython을 사용하여 임시 웹 서버를 시작합니다:
python -m http.server 8000브라우저에서 보고서를 미리 보려면 다음 단계를 따르세요:
- 상단 메뉴 표시줄에서 + 버튼을 클릭합니다.
- Web Service를 선택합니다.
- 포트 번호 8000을 입력합니다.
- 이제 생성된 HTML 보고서를 온라인으로 볼 수 있습니다.

웹 서버는 디렉토리 목록을 표시하며, 여기서 HTML 파일을 클릭하여 Ansible 플레이북에서 생성된 포괄적인 시스템 및 네트워크 보고서를 볼 수 있습니다.
참고: 보고서 보기가 끝나면
Ctrl+C를 눌러 웹 서버를 중지하십시오.
요약
이 종합 실습을 통해 Ansible 을 사용하여 필수적인 Red Hat Enterprise Linux (RHEL) 관리 작업을 자동화하는 방법을 익혔습니다. 저장소 구성, GPG 키 관리, 패키지 설치 및 패키지 사실 (facts) 을 통한 시스템 정보 수집 방법을 배우면서 소프트웨어 패키지 관리부터 시작했습니다. 이를 통해 인프라 전반에 걸쳐 일관된 소프트웨어 배포의 기반을 마련했습니다.
이후 사용자 관리 및 인증으로 진행하여 사용자 계정 생성 자동화, SSH 키 기반 인증 구성, sudo 권한 설정, SSH 구성 강화 방법을 배웠습니다. 이를 통해 엔터프라이즈 환경에 필수적인 안전하고 표준화된 사용자 액세스 정책을 수립했습니다.
실습은 서비스 관리 및 작업 스케줄링으로 이어져, systemd 서비스 관리, 주기적인 cron 작업 생성, at을 사용한 일회성 작업 예약, 시스템 부팅 대상 구성 방법을 배웠습니다. 이러한 기술은 서비스 가용성을 유지하고 일상적인 유지보수 작업을 자동화하는 데 필수적입니다.
스토리지 관리는 물리 볼륨 생성, 볼륨 그룹 관리, 논리 볼륨 프로비저닝, 파일 시스템 생성 및 마운트 포인트 구성을 포함한 포괄적인 LVM 자동화를 통해 다루었습니다. 또한 확장 가능한 인프라 관리에 중요한 스토리지 볼륨을 동적으로 확장하는 방법도 배웠습니다.
마지막으로 네트워크 구성 자동화 및 포괄적인 시스템 모니터링을 완료했습니다. 네트워크 사실 수집, 인터페이스 구성, Jinja2 템플릿을 사용한 상세 시스템 보고서 생성, 자동화된 모니터링 스크립트 설정 방법을 배웠습니다. 이를 통해 시스템 상태 관리 및 보고의 전체적인 그림을 파악할 수 있었습니다.
이 실습 전반에 걸쳐 인프라스트럭처 코드 (IaC) 원칙을 적용하여 모든 시스템 구성이 재현 가능하고, 버전 관리되며, 일관되게 배포될 수 있도록 했습니다. 이제 초기 배포부터 지속적인 유지보수 및 모니터링까지 RHEL 시스템 관리의 전체 수명 주기를 자동화할 수 있는 기술을 갖추게 되었습니다.


