Actually Change RHEL With Ansible
한국어 원문으로 표시합니다.
이 실습은 진짜 RHEL 계열에서 돕니다
VM 안에 AlmaLinux 9 가 떠 있습니다. systemd 가 PID 1 로 돌고, SELinux 가 Enforcing 이며, firewalld 가 살아 있습니다. 플레이북이 시스템을 진짜로 바꾸고, 채점기는 그 결과를 시스템에서 직접 읽습니다.
기존 Ansible 코스는 파드에서 돌아 문법 확인까지가 전부였습니다. 여기서는 설정하지 않으면 실제로 막힙니다.
처음 뜨는 데 2분쯤 걸립니다.
목표
RHCE 시험이 실제로 묻는 것들을 한 바퀴 돕니다. 사용자, 서비스, SELinux, 방화벽, 템플릿, 그리고 멱등성입니다.
왜 중요한가
RHCE(EX294)는 "Ansible 문법을 아는가" 를 묻지 않습니다. 시스템을 원하는 상태로 만들 수 있는가를 묻습니다. 그래서 감점의 대부분이 문법이 아니라 이런 데서 나옵니다.
state: started만 쓰고enabled: true를 빠뜨려 재부팅 후 서비스가 안 뜸- firewalld 를
permanent로만 열어 지금은 안 열리거나,immediate로만 열어 재시작 후 사라짐 - SELinux 불리언을 켰지만
persistent가 없어 재부팅 때 되돌아감 command/shell을 조건 없이 써서 매번 changed 가 나옴
마지막 것이 특히 중요합니다. 멱등하지 않은 플레이북은 돌릴 때마다 무언가를 바꾸는 플레이북입니다. 그러면 "이번 실행이 무엇을 바꿨는가" 를 알 수 없고, 핸들러가 매번 서비스를 재시작해 불필요한 중단이 생깁니다.
단계
/root/rhce/inventory.ini에[webservers]그룹으로 이 호스트를 넣고,/root/rhce/ansible.cfg도 만드세요.ansible webservers -m ping이 성공해야 합니다./root/rhce/users.yml로webadmin그룹과alice·bob사용자(셸/bin/bash, 보조 그룹webadmin)를 만드세요. 반복(loop) 을 쓰세요./root/rhce/service.yml로httpd를 설치하고 started 와 enabled 를 모두 만족시키세요.curl http://127.0.0.1/이 200 이어야 합니다./root/rhce/selinux.yml로httpd_can_network_connect불리언을 영구히 켜고,/srv/web에httpd_sys_content_t컨텍스트를 붙이세요./root/rhce/firewall.yml로http서비스를 방화벽에 여세요. runtime 과 permanent 를 모두 만족시켜야 합니다./root/rhce/templates/index.html.j2로 호스트명이 들어간 페이지를 만들고/root/rhce/template.yml로 배포하세요. 바뀔 때만 httpd 를 재시작하는 핸들러를 쓰세요.- 위 전부를 부르는
/root/rhce/site.yml을 만드세요. 그리고 상태를 일부러 흔들어 놓은 뒤(서비스 중지·파일 삭제·계정 삭제) 두 번 돌려changed수를/root/rhce/idempotent.txt에changed_first=·changed_second=로 적으세요. 첫 번째는 0보다 커야 하고 두 번째는 0 이어야 합니다. 흔들지 않고 재면 첫 실행부터 0 이라 "고쳐서 0 이 됐다" 와 "원래 아무것도 안 했다" 를 구분할 수 없습니다. /root/rhce/report.md에selinux=Enforcing,idempotent=yes,playbooks=<개수>세 줄과 설명을 쓰세요.
참고
- SELinux 모듈은
ansible.posix.seboolean과community.general.sefcontext입니다. 두 컬렉션이 모두 필요하고, ansible-core 버전과 맞는 판이어야 합니다 — 안 맞으면 경고만 내고couldn't resolve module/action으로 죽는데, 그 문구가 오타를 의심하게 만듭니다. 컨텍스트를 정의한 뒤에는ansible.builtin.command: restorecon -R /srv/web을changed_when과 함께 써야 멱등이 깨지지 않습니다. - firewalld 모듈에는
permanent와immediate가 따로 있습니다. 둘 다 참이어야 "지금도 열리고 재시작 후에도 열린" 상태가 됩니다. - 팩트는
ansible_facts['hostname']또는{{ ansible_hostname }}으로 씁니다. changed수는ansible-playbook site.yml | grep -oE 'changed=[0-9]+'로 셉니다.- 흔한 실수 1:
command/shell을 조건 없이 쓰는 것. 그 태스크는 언제나 changed 입니다.creates:·changed_when:으로 조건을 주세요. - 흔한 실수 2:
state: started만 쓰고enabled: true를 빠뜨리는 것. 지금은 돌지만 재부팅하면 안 뜹니다. - 흔한 실수 3: SELinux 불리언에
persistent: true를 빠뜨리는 것. 지금은 켜지지만 재부팅 때 되돌아갑니다. - 흔한 실수 4: 두 태스크가 같은 파일을 서로 다른 내용으로 관리하는 것. 서로를 되돌리며 둘 다 영원히 changed 이고, 각 태스크는 따로 보면 멀쩡해서 가장 찾기 어렵습니다. 파일 하나에는 주인이 하나여야 하고, 부트스트랩용이라면
force: false로 "없을 때만" 을 명시하세요.
인벤토리와 설정 파일
/root/rhce/inventory.ini 에 [webservers] 그룹으로 이 호스트를 넣고, /root/rhce/ansible.cfg 도 만드세요. ansible webservers -m ping 이 성공해야 합니다.
이 VM 자신을 대상으로 삼습니다. ansible_connection=local 을 쓰면 SSH 없이 바로 됩니다. ansible.cfg 에 인벤토리 경로를 적어 두면 매번 -i 를 주지 않아도 됩니다.
사용자와 그룹을 만든다
/root/rhce/users.yml 로 webadmin 그룹과 alice·bob 사용자(셸 /bin/bash, 보조 그룹 webadmin)를 만드세요. 반복(loop) 을 쓰세요.
ansible.builtin.group 을 먼저, 그 다음 ansible.builtin.user 를 loop 로 돌립니다. 그룹이 없는 상태에서 사용자를 만들면 실패합니다.
서비스는 두 가지를 만족해야 한다
/root/rhce/service.yml 로 httpd 를 설치하고 started 와 enabled 를 모두 만족시키세요. curl http://127.0.0.1/ 이 200 이어야 합니다.
state: started 는 지금, enabled: true 는 재부팅 후입니다. 둘은 다른 이야기이고 시험에서 가장 자주 빠뜨리는 것입니다.
SELinux 는 켜져 있고 실제로 막는다
/root/rhce/selinux.yml 로 httpd_can_network_connect 불리언을 영구히 켜고, /srv/web 에 httpd_sys_content_t 컨텍스트를 붙이세요.
불리언은 ansible.posix.seboolean 에 persistent: true 를, 파일 컨텍스트는 community.general.sefcontext 뒤에 restorecon 을 씁니다.
runtime 과 permanent 는 다르다
/root/rhce/firewall.yml 로 http 서비스를 방화벽에 여세요. runtime 과 permanent 를 모두 만족시켜야 합니다.
permanent: true 는 설정 파일에, immediate: true 는 지금 도는 방화벽에 적용합니다. 둘 다 주어야 완성입니다.
바뀔 때만 재시작한다
/root/rhce/templates/index.html.j2 로 호스트명이 들어간 페이지를 만들고 /root/rhce/template.yml 로 배포하세요. 바뀔 때만 httpd 를 재시작하는 핸들러를 쓰세요.
template 태스크에 notify 를 달고 handlers 절에 재시작을 둡니다. 핸들러는 그 태스크가 changed 일 때만 돕니다.
두 번째 실행은 조용해야 한다
위 전부를 부르는 /root/rhce/site.yml 을 만드세요. 그리고 상태를 일부러 흔들어 놓은 뒤(서비스 중지·파일 삭제·계정 삭제) 두 번 돌려 changed 수를 /root/rhce/idempotent.txt 에 changed_first=·changed_second= 로 적으세요.
첫 번째는 0보다 커야 하고 두 번째는 0 이어야 합니다. 흔들지 않고 재면 첫 실행부터 0 이라 "고쳐서 0 이 됐다" 와 "원래 아무것도 안 했다" 를 구분할 수 없습니다.
site.yml 에서 앞의 플레이북들을 import_playbook 으로 부르고 두 번 돌립니다. 두 번째의 changed 가 0 이 아니면 그 태스크를 찾으세요.
무엇을 배웠나
/root/rhce/report.md 에 selinux=Enforcing, idempotent=yes, playbooks=<개수> 세 줄과 설명을 쓰세요.
selinux=, idempotent=, playbooks= 세 줄과 함께, 시험에서 감점이 나는 자리들을 정리하세요.