Red Hat Certified Engineer (RHCE) #15 RHCSA 자동화 2: 서비스, chronyd, log
#14 RHCSA 자동화 1에서 사용자,그룹과 패키지,repository를 플레이북으로 잡았습니다. 이번 #15에서는 RHCSA 손작업의 두 번째 묶음인 서비스 관리, 시간 동기화, 로그 설정을 자동화하겠습니다. 모두 RHCSA #9 서비스와 부팅에서 systemctl과 chronyc, journalctl로 손수 다뤘던 작업이며, 이번에는 같은 결과를 멱등성 있는 모듈로 선언하겠습니다.
이 영역의 채점 포인트는 한결같습니다. 서비스는 켜는 것(start)으로 끝나지 않고 부팅에도 켜져야(enable) 합니다. 시간 동기화는 설정 파일을 바꾼 뒤 데몬을 다시 띄워야 하고, 로그는 재부팅 후에도 남도록 영구 설정해야 합니다. 즉 “지금 동작"과 “재부팅 후에도 동작"을 동시에 보장하는 것이 자동화의 핵심입니다.
서비스 관리: service와 systemd 모듈 #
데몬을 켜고 끄고 부팅 등록하는 작업은 ansible.builtin.service 또는 ansible.builtin.systemd_service 모듈로 합니다. 손으로 치던 systemctl start와 systemctl enable을 한 task에 합쳐서 선언합니다.
service 모듈의 세 가지 핵심 키 #
| 키 | 의미 | 값 예시 |
|---|---|---|
| name | 대상 서비스 이름 | httpd, chronyd |
| state | 현재 동작 상태 | started, stopped, restarted, reloaded |
| enabled | 부팅 시 자동 시작 여부 | true, false |
여기서 가장 자주 놓치는 부분이 state와 enabled를 함께 지정하는 것입니다. state: started만 쓰면 지금은 켜지지만 재부팅 후에는 꺼져 있을 수 있고, enabled: true만 쓰면 부팅 등록은 되지만 지금은 멈춰 있습니다. 시험에서는 둘 다 요구하는 경우가 대부분이므로 두 키를 같이 적는 습관을 들이겠습니다.
- name: 웹 서버를 지금도 켜고 부팅에도 등록한다
hosts: webservers
become: true
tasks:
- name: httpd 패키지 설치
ansible.builtin.dnf:
name: httpd
state: present
- name: httpd 서비스 enable + start
ansible.builtin.service:
name: httpd
state: started
enabled: trueservice와 systemd_service의 차이 #
service 모듈은 init 시스템을 자동으로 감지하는 범용 모듈이고, systemd_service 모듈은 systemd 전용으로 daemon_reload나 masked 같은 systemd 고유 기능을 추가로 제공합니다. RHEL 9는 systemd를 쓰므로 둘 다 동작하지만, unit 파일을 직접 배치한 뒤 다시 읽어야 할 때는 systemd 모듈이 유리합니다.
- name: 사용자 정의 unit 배치 후 데몬 리로드
ansible.builtin.systemd_service:
name: myapp
state: started
enabled: true
daemon_reload: truedaemon_reload: true는 systemctl daemon-reload에 대응하며, /etc/systemd/system에 unit 파일을 새로 두거나 고친 직후 systemd가 변경을 인식하도록 합니다.
시간 동기화: timesync system role과 chrony 템플릿 #
시간 동기화는 RHCE 단골 주제입니다. RHEL 9의 NTP 구현은 chrony이며 데몬 이름은 chronyd입니다. 자동화 방법은 두 갈래가 있습니다. timesync system role을 쓰는 길과 chrony.conf를 직접 템플릿으로 배포하는 길입니다.
방법 1: timesync system role #
#13 system roles에서 다룬 rhel-system-roles를 쓰면 NTP 서버 목록만 변수로 넘기고 나머지는 role에 맡깁니다. 가장 짧고 안전한 길입니다.
- name: timesync system role로 NTP 구성
hosts: all
become: true
vars:
timesync_ntp_servers:
- hostname: 0.kr.pool.ntp.org
iburst: true
- hostname: 1.kr.pool.ntp.org
iburst: true
roles:
- redhat.rhel_system_roles.timesyncrole이 chrony 설치와 설정 파일 작성, 서비스 enable과 start까지 한 번에 처리하므로, 시험에서 “이 NTP 서버를 쓰도록 시간 동기화를 구성하라"는 문제에 가장 빠르게 대응할 수 있습니다.
방법 2: chrony.conf 템플릿 + handler #
system role을 쓰지 않고 설정 파일을 직접 다룰 수도 있습니다. template 모듈로 chrony.conf를 배포하고, 파일이 바뀌었을 때만 handler로 chronyd를 재시작하는 구조입니다. 이 패턴은 모든 “설정 파일 변경 후 서비스 재시작” 문제의 표준형이므로 반드시 익히겠습니다.
templates/chrony.conf.j2:
# Ansible managed
{% for server in chrony_servers %}
server {{ server }} iburst
{% endfor %}
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony플레이북:
- name: chrony.conf 템플릿으로 시간 동기화 구성
hosts: all
become: true
vars:
chrony_servers:
- 0.kr.pool.ntp.org
- 1.kr.pool.ntp.org
tasks:
- name: chrony 패키지 설치
ansible.builtin.dnf:
name: chrony
state: present
- name: chrony.conf 배포
ansible.builtin.template:
src: chrony.conf.j2
dest: /etc/chrony.conf
owner: root
group: root
mode: '0644'
notify: restart chronyd
- name: chronyd enable + start
ansible.builtin.service:
name: chronyd
state: started
enabled: true
handlers:
- name: restart chronyd
ansible.builtin.service:
name: chronyd
state: restarted여기서 흐름이 중요합니다. template 작업이 파일을 바꾸면 notify로 handler가 예약되고, 플레이북의 모든 작업이 끝난 뒤 handler가 한 번 실행되어 chronyd를 재시작합니다. 파일이 바뀌지 않으면 handler는 호출되지 않으므로, 두 번째 실행에서는 재시작이 일어나지 않아 멱등성이 유지됩니다.
작업 예약: cron과 at 모듈 #
정기 작업은 ansible.builtin.cron 모듈로 관리합니다. crontab 항목을 직접 편집하는 대신 모듈이 항목을 멱등성 있게 넣고 빼 줍니다.
cron 모듈의 주요 키 #
| 키 | 의미 |
|---|---|
| name | 항목 식별 이름. 멱등성의 기준 |
| job | 실행할 명령 |
| minute / hour / day / month / weekday | 실행 시각. 기본값은 * |
| user | 어느 사용자의 crontab인가 |
| state | present 또는 absent |
name이 멱등성의 기준이라는 점이 핵심입니다. cron 모듈은 crontab에 #Ansible: <name> 주석을 함께 기록하고, 다음 실행에서 같은 name을 만나면 새로 추가하지 않고 기존 항목을 갱신합니다. 따라서 name을 매번 바꾸면 중복 항목이 쌓이므로 일정한 name을 유지하겠습니다.
- name: 정기 백업 cron 작업 등록
hosts: dbservers
become: true
tasks:
- name: 매일 02:30 백업 스크립트 실행
ansible.builtin.cron:
name: nightly-backup
user: root
minute: "30"
hour: "2"
job: "/usr/local/bin/backup.sh"
state: present위 작업은 root의 crontab에 30 2 * * * /usr/local/bin/backup.sh 항목을 멱등성 있게 등록합니다. 지정하지 않은 day, month, weekday는 자동으로 *가 됩니다.
특정 디렉터리에 떨어뜨리는 방식이 필요하면 cron_file로 /etc/cron.d 아래 파일을 만들 수도 있습니다. 이때는 시스템 전역 crontab 형식이므로 user를 함께 지정합니다.
- name: /etc/cron.d 파일로 등록
ansible.builtin.cron:
name: log-rotate-check
user: root
minute: "0"
hour: "1"
job: "/usr/local/bin/check-logs.sh"
cron_file: custom-log-check일회성 작업은 ansible.builtin.at 모듈로 예약합니다. 예를 들어 ansible.builtin.at에 command와 count, units: minutes를 주면 지정 시간 뒤 한 번만 실행되는 at 작업을 등록합니다.
journald 영구 저장 자동화 #
기본 RHEL에서 journald 로그는 /run/log/journal의 메모리(휘발성) 영역에 저장되어 재부팅하면 사라집니다. 로그를 영구 보존하려면 /etc/systemd/journald.conf에서 Storage=persistent로 바꾸고 데몬을 재시작해야 합니다. 이 작업도 template과 handler 패턴으로 자동화합니다.
templates/journald.conf.j2:
# Ansible managed
[Journal]
Storage=persistent
SystemMaxUse={{ journald_max_use | default('500M') }}플레이북:
- name: journald 로그 영구 저장 설정
hosts: all
become: true
vars:
journald_max_use: 1G
tasks:
- name: 영구 저장 디렉터리 생성
ansible.builtin.file:
path: /var/log/journal
state: directory
owner: root
group: systemd-journal
mode: '2755'
- name: journald.conf 배포
ansible.builtin.template:
src: journald.conf.j2
dest: /etc/systemd/journald.conf
owner: root
group: root
mode: '0644'
notify: restart journald
handlers:
- name: restart journald
ansible.builtin.systemd_service:
name: systemd-journald
state: restarted/var/log/journal 디렉터리가 있어야 journald가 그곳에 영구 로그를 기록하므로 file 모듈로 먼저 만들어 둡니다. 설정 파일이 바뀌면 handler가 systemctl restart systemd-journald에 대응하는 재시작을 수행합니다.
tuned 프로파일 적용 #
성능 프로파일을 관리하는 tuned도 자동화 대상입니다. tuned-adm을 손으로 치는 대신 tuned system role 또는 command 모듈로 프로파일을 적용합니다. system role이 가장 깔끔합니다.
- name: tuned 프로파일 적용
hosts: dbservers
become: true
vars:
tuned_profile: throughput-performance
roles:
- redhat.rhel_system_roles.tunedsystem role을 쓰지 않는다면 tuned 서비스를 enable과 start로 띄운 뒤, tuned-adm profile <이름>을 command로 적용하되 이미 적용된 경우 changed가 나지 않도록 changed_when 조건을 다듬습니다.
시험 포인트 #
- enabled와 state는 짝. 서비스 문제는 거의 항상 “지금 켜고(state: started) 부팅에도 등록(enabled: true)“을 동시에 요구합니다. 한쪽만 쓰면 채점 절반만 충족합니다.
- 설정 변경은 handler로 재시작. chrony.conf, journald.conf처럼 설정 파일을 template으로 바꾼 뒤에는 반드시
notify와 handler로 데몬을 재시작합니다. task에서 매번 restart를 직접 부르면 파일이 안 바뀌어도 재시작되어 멱등성이 깨집니다. - NTP는 system role이 빠르다. 시간 동기화 문제는 timesync system role로 서버 목록만 넘기는 것이 가장 안전합니다. role을 못 쓰는 상황을 대비해 chrony.conf 템플릿 방식도 함께 익혀 둡니다.
- cron은 name으로 멱등성. cron 모듈의 name이 항목 식별자이므로, 같은 작업에는 같은 name을 유지해 중복 등록을 막습니다.
- journald 영구화는 디렉터리부터.
/var/log/journal생성과Storage=persistent설정, 그리고 systemd-journald 재시작이 한 묶음입니다. - 두 번 돌려 changed 0 확인. 모든 플레이북은 두 번째 실행에서 changed가 0이 되어야 합니다. handler가 매번 도는지, command/shell이 멱등성을 깨는지 점검합니다.
정리 #
이번 글에서 잡은 것:
- service / systemd_service 모듈. name,state,enabled로 데몬을 enable과 start까지 한 번에 선언. unit 변경 시 daemon_reload
- 시간 동기화. timesync system role(서버 목록만 변수로) 또는 chrony.conf 템플릿 + handler 재시작
- cron / at 모듈. cron의 name으로 멱등성, minute,hour,user,job,state로 정기 작업 등록. at으로 일회성 예약
- journald 영구 저장.
/var/log/journal생성 + journald.conf 템플릿 + systemd-journald 재시작 handler - tuned. system role 또는 command로 성능 프로파일 적용
- 공통 원칙. 설정 변경은 handler로, 서비스는 enabled와 state를 함께, 그리고 두 번 돌려 멱등성 검증
다음: RHCSA 자동화 3 #
서비스와 시간, 로그를 자동화했습니다. 다음은 RHCSA에서 가장 손이 많이 가던 영역인 스토리지입니다.
#16 RHCSA 자동화 3: 스토리지(LVM), 파일시스템(NFS)에서는 lvg와 lvol 모듈로 볼륨 그룹과 논리 볼륨을 만들고, filesystem과 mount 모듈로 파일시스템을 생성해 영구 마운트하며, storage system role로 한 번에 선언하는 방법, 그리고 NFS 클라이언트 마운트까지 플레이북으로 정리하겠습니다.