서버마다 시간이 다르면 같은 작업의 로그도 순서대로 맞춰 보기 어려워요. 내부 시간 서버를 두면 각 서버가 하나의 기준을 따라가도록 관리할 수 있습니다.
Rocky Linux 9에서는 chrony 패키지의 chronyd가 시간을 맞추고, chronyc로 상태를 확인합니다. 인터넷에 연결된 내부 NTP 서버와 외부 기준이 없는 폐쇄망 서버는 설정의 목적이 다릅니다. 먼저 외부 기준과 동기화해 내부에 제공하는 구성을 만들고, 폐쇄망에서 바꿔야 할 부분을 따로 정리합니다.
이 글의 목차
서버와 클라이언트 구성
NTP(Network Time Protocol)는 네트워크로 시계를 맞추는 프로토콜입니다. 아래 예제에서 시간 서버만 외부 NTP와 통신하고, 내부 클라이언트는 192.168.10.20을 바라봅니다.
| 구분 | 이름·주소 | 역할 |
|---|---|---|
| 내부 시간 서버 | ntp.lab.com / 192.168.10.20 | Rocky Linux 9, UDP 123번 제공 |
| 클라이언트 | node1.lab.com / 192.168.10.30 | 내부 시간 서버와 동기화 |
| 허용 네트워크 | 192.168.10.0/24 | 시간 질의를 허용할 대역 |
| 상위 시간 소스 | 2.rocky.pool.ntp.org | 인터넷 연결 예제, 사내 기준이 있으면 대체 |
IP 주소는 자신의 망에 맞게 바꿉니다. 서버는 고정 IP와 sudo 권한이 필요합니다. ntp.lab.com은 lab.com 내부 DNS 구성 글의 예제 이름이며, 여기서는 DNS가 없어도 진행할 수 있도록 클라이언트 설정에 IP를 사용합니다. lab.com은 예약된 예제 도메인이 아니므로 이 이름은 격리된 실습망에서만 사용합니다.
대표 사진은 Raspberry Pi와 GPS 보드를 이용한 별도 NTP 장비의 참고 사진입니다. 본문은 GPS/PPS 장치 없이 Rocky Linux 서버의 chronyd를 구성하며, 촬영자의 장비를 실습 서버로 소개하지 않습니다.
1. 패키지 설치와 현재 시간 확인
아래 명령은 시간 서버에서 실행합니다. 시간대는 화면에 표시하는 방식이고, NTP 동기화는 시계 자체를 맞추는 작업입니다. 서울 시간대로 바꾸는 것만으로 시계 오차가 보정되지는 않습니다.
sudo dnf install -y chrony
rpm -q chrony
timedatectl
sudo timedatectl set-timezone Asia/Seoul
sudo cp -a /etc/chrony.conf /etc/chrony.conf.before-local-ntp
sudo systemctl status chronyd --no-pager
기존 백업이 있다면 새 이름으로 보관합니다. 이미 다른 시간 동기화 데몬을 사용하고 있다면 chronyd와 동시에 시계를 보정하지 않도록 정리합니다. 운영 중인 서버는 시각이 크게 바뀌면 작업 예약이나 데이터베이스 등에 영향을 줄 수 있으므로 변경 시점을 정합니다.
2. 외부 기준과 동기화하는 내부 서버 설정
sudo vi /etc/chrony.conf로 파일을 엽니다. 새 실습 서버에서는 아래 구성을 사용할 수 있습니다. 기존 서버라면 키·NTS·로그 등 필요한 설정을 보존하면서 해당 항목을 병합합니다.
pool 2.rocky.pool.ntp.org iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
allow 192.168.10.0/24
bindaddress 192.168.10.20
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
pool은 여러 시간 서버 주소를 얻을 수 있는 풀을 지정합니다. 사내에서 승인한 상위 NTP가 있으면 이 줄을 실제 주소의 server ... iburst로 바꾸세요. iburst는 처음 통신할 때 질의를 묶어 보내 초기 측정을 빠르게 합니다. Rocky Linux chrony 안내에서 기본 소스와 server·pool의 차이를 확인할 수 있습니다.
allow가 내부 클라이언트의 NTP 질의를 허용하고, bindaddress는 NTP 서비스를 제공할 로컬 주소를 지정합니다. 상위 서버에 나가는 질의의 출발 주소를 고정하는 설정은 아닙니다. 두 항목의 역할은 chrony 설정 문서에 설명되어 있습니다.
driftfile은 시계가 빨라지거나 느려지는 경향을 저장하고, rtcsync는 Linux 커널이 시스템 시간을 RTC에 반영하도록 합니다. makestep 1.0 3은 chronyd 시작 후 처음 세 번의 시계 업데이트에서 오차가 1초를 넘으면 시각을 한 번에 이동할 수 있게 합니다. 단순히 부드럽게 보정하는 설정이라고 생각하면 안 됩니다.
이 구성에는 local stratum 10을 넣지 않습니다. 외부 기준과 아직 동기화되지 않은 서버를 내부 클라이언트가 정상 기준으로 받아들이지 않게 하기 위해서입니다. 상위 소스가 끊긴 뒤의 제공 상태는 마지막 동기화 이후의 오차 추정 등에 따라 달라지며, 단절 즉시 무조건 중지되거나 무기한 정확한 시간을 유지하는 것은 아닙니다.
3. 문법 검사와 UDP 123번 허용
설정을 적용하기 전에 문법을 검사합니다. -p는 설정을 출력하고 종료하며 시스템 시각을 변경하지 않습니다.
sudo chronyd -p -f /etc/chrony.conf
sudo firewall-cmd --get-active-zones
firewalld를 사용하는 서버에서 클라이언트 트래픽이 들어오는 zone을 고릅니다. 다음은 public인 경우입니다. 실제 zone이 다르면 바꿉니다.
sudo firewall-cmd --permanent --zone=public --add-service=ntp
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --query-service=ntp
sudo systemctl enable --now chronyd
sudo systemctl restart chronyd
sudo systemctl status chronyd --no-pager
sudo ss -lunp '( sport = :123 )'
ntp 서비스는 UDP 123번을 허용합니다. 클라이언트의 질의와 응답이 방화벽을 통과해야 하고, 인터넷 연결 방식은 시간 서버에서 상위 NTP로 나가는 UDP 123번도 허용되어야 합니다. 별도 방화벽을 사용한다면 그 정책을 적용합니다. SELinux는 기본 상태를 유지합니다.
시간 제공에는 cmdallow나 UDP 323번 개방이 필요하지 않습니다. 323번은 chronyc의 원격 상태 조회용이며, NTP 질의 허용과 별도입니다. 이 글에서는 관리 명령을 각 호스트에서 실행합니다.
4. 시간 서버가 상위 소스를 선택했는지 확인
서비스 실행 상태만으로 동기화 완료를 판단하지 않습니다. 시간 서버에서 다음을 확인합니다.
chronyc -n sources -v
chronyc tracking
chronyc activity
sources -v에서 ^*가 붙은 행은 현재 선택한 NTP 서버입니다. ^+는 결합에 사용하는 다른 소스이고, ^?는 도달 불가·미동기화·측정 부족 등으로 아직 선택할 수 없는 상태입니다. 시작 직후라면 몇 차례 측정을 기다린 뒤 다시 봅니다.
Reach는 최근 응답 이력을 8진수로 표시합니다. 377은 최근 여덟 번의 질의에 모두 응답했다는 뜻이며, 시작하자마자 이 값이어야 하는 것은 아닙니다. tracking에서는 실제 Reference ID, Stratum, 오차 정보와 Leap status를 함께 확인합니다. 각 항목은 chronyc 상태 출력 문서를 기준으로 해석합니다.
인터넷 연결 구성에서는 상위 소스가 선택되고 Leap status가 Normal인지 확인한 뒤 클라이언트로 넘어갑니다. Not synchronised가 계속되면 DNS 조회, 상위 서버 접근 정책, UDP 통신과 로그를 확인합니다.
5. Rocky Linux 클라이언트 설정
이번에는 192.168.10.30 클라이언트에서 실행합니다. 패키지 설치 후 기존 설정을 보관합니다.
sudo dnf install -y chrony
sudo cp -a /etc/chrony.conf /etc/chrony.conf.before-internal-ntp
sudo vi /etc/chrony.conf
내부 시간 서버만 사용하도록 아래와 같이 설정합니다. 기본 pool이나 다른 server 줄을 함께 남겨 두면 외부 서버가 선택될 수 있습니다. 기존 include, confdir, sourcedir로 불러오는 소스도 확인해 의도하지 않은 시간 소스를 제외합니다.
server 192.168.10.20 iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
클라이언트는 다른 호스트에 시간을 제공하지 않으므로 allow, bindaddress, local을 추가하지 않습니다. 일반적인 상태 추적 방화벽에서는 NTP 클라이언트만을 위해 수신용 ntp 서비스를 열 필요가 없습니다.
sudo chronyd -p -f /etc/chrony.conf
sudo systemctl enable --now chronyd
sudo systemctl restart chronyd
chronyc -n sources -v
chronyc tracking
클라이언트의 소스 목록에서 ^* 192.168.10.20이 선택되어야 합니다. 서버에서 외부 소스를 선택한 것과 클라이언트에서 내부 서버를 선택한 것을 따로 확인하세요. ping 성공이나 두 서버의 date 출력만으로는 NTP 동기화를 확인할 수 없습니다.
DNS가 준비되었다면 server ntp.lab.com iburst로 바꿀 수 있습니다. 이 경우 먼저 getent hosts ntp.lab.com이 192.168.10.20을 가리키는지 확인합니다. VM에서는 하이퍼바이저나 게스트 도구가 주기적으로 시간을 강제 조정하는지도 점검합니다.
6. 인터넷이 없는 폐쇄망에서는 local 기준 사용
외부 NTP나 GPS 같은 기준이 없는 폐쇄망에서는 한 서버의 시계를 기준으로 내부 시간을 맞출 수 있습니다. 서버끼리 같은 시간을 쓰도록 하는 것이며, 그 시간이 실제 UTC와 정확히 일치한다는 보장은 없습니다. chrony의 local 지시어는 외부와 동기화하지 않았어도 클라이언트에 기준 시간을 제공하도록 합니다.
이 방식을 선택한다면 시간 서버의 앞선 인터넷 연결용 설정을 다음 구성으로 바꿉니다. 외부 pool·server와 동적으로 불러오는 시간 소스는 제거하거나 주석 처리합니다. 클라이언트 설정은 앞 절의 내부 서버 IP 지정 그대로 사용합니다.
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
local stratum 10
allow 192.168.10.0/24
bindaddress 192.168.10.20
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
stratum은 기준 시계까지의 계층을 나타내며 정확도의 점수가 아닙니다. 여기서 10은 로컬 기준의 계층 값입니다. 일반적으로 이 서버를 따르는 클라이언트는 그보다 한 단계 높은 stratum을 표시합니다. 운영에서는 정확한 외부 기준을 확보할 수 있는지도 먼저 검토합니다.
폐쇄망 서버는 최초 시각을 신뢰할 수 있는 별도 기준으로 맞춘 뒤 제공해야 합니다. 다음 명령은 아직 서비스를 연결하지 않은 준비 단계나 정비 시간에만 실행합니다. 날짜 자리에는 고정 예제 값을 복사하지 말고, 실행 시점에 확인한 실제 현재 시각을 넣습니다.
sudo systemctl stop chronyd
sudo timedatectl set-time 'YYYY-MM-DD HH:MM:SS'
sudo hwclock --systohc
sudo chronyd -p -f /etc/chrony.conf
sudo systemctl start chronyd
chronyc tracking
YYYY-MM-DD HH:MM:SS는 교체할 자리표시자이며 그대로 실행할 값이 아닙니다. timedatectl에 설정한 시간대 기준으로 입력합니다. 가상머신 등 RTC 쓰기를 지원하지 않는 환경에서는 hwclock 단계의 적용 가능 여부를 확인합니다. 재부팅 후에도 기준 시각이 유지되는지, 장기간 고립되며 얼마나 오차가 생기는지 별도로 점검합니다.
로컬 기준에서는 상위 NTP가 없으므로 시간 서버의 sources 목록이 비어 있을 수 있습니다. tracking에 Normal이 보여도 외부 기준에 맞았다는 뜻으로 해석하면 안 됩니다. 대신 클라이언트가 192.168.10.20을 선택했는지와 서버의 기준 시각을 함께 관리합니다. 인터넷 단절을 숨기기 위해 이 설정을 일반 구성에 무심코 추가하지 않습니다.
클라이언트 접근과 장애 확인
시간 서버에서 다음 명령으로 허용 여부와 최근 접근을 확인합니다. clients는 기본 설정처럼 클라이언트 기록이 활성화된 경우에 표시됩니다.
sudo chronyc accheck 192.168.10.30
sudo chronyc clients
sudo journalctl -u chronyd -n 80 --no-pager
accheck는 chronyd의 접근 허용 규칙을 검사할 뿐, 실제 방화벽 통과나 왕복 통신까지 확인하지는 않습니다. 클라이언트에서 sources와 tracking을 함께 봐야 합니다.
| 증상 | 확인할 곳 |
|---|---|
서버가 Not synchronised | 상위 이름 해석·UDP 123번·측정 대기, 폐쇄망이면 의도한 local 설정 |
클라이언트의 Reach가 계속 0 | 서버 IP, allow, 수신 주소, 서버·중간 방화벽 |
^?가 계속 표시됨 | 응답 이력뿐 아니라 서버의 동기화 상태와 측정·선택 조건 |
| 내부 서버 대신 외부 서버가 선택됨 | 클라이언트의 남은 pool·server, 포함 파일과 DHCP 소스 |
506 Cannot talk to daemon | 명령을 실행한 호스트의 chronyd 상태와 로컬 소켓 |
수정 후에는 chronyd -p로 검사하고 systemctl restart chronyd로 적용합니다. chronyc reload sources는 소스 파일을 다시 읽는 명령이므로 일반 설정 전체를 다시 읽는 명령으로 대신 쓰지 않습니다.
큰 오차를 즉시 줄이려고 chronyc makestep을 실행하면 시간이 앞이나 뒤로 한 번에 바뀔 수 있습니다. 먼저 신뢰하는 소스가 선택되었는지와 서비스 영향을 확인하세요. 평소에는 선택한 소스와 오차 추이를 관찰하며 운영합니다.
확인 범위: 2026년 10월 23일 공식 문서를 확인했습니다. Rocky Linux 9 컨테이너에서 서버·클라이언트 설정 문법과 폐쇄망 로컬 기준의 NTP 응답을 검증했습니다. 컨테이너는 호스트 시계를 바꾸지 않는 방식으로 실행했습니다. 실제 시스템 시각 보정, RTC, firewalld·systemd와 재부팅 후 동작은 전체 VM에서 별도 확인이 필요합니다.



