infra
Platform

모듈 맵

[Linux] chrony & NTP 서버 동기화로 트랜잭션 시간 오차 방지

0 / 37 완료

펼치기
0 / 37 완료0%

리눅스 서버 운영 · 26 / 37

[Linux] chrony & NTP 서버 동기화로 트랜잭션 시간 오차 방지

서버 시간이 틀리면 토큰이 만료된다 — chrony, timedatectl 완전 설정

🚨INCIDENT ALERT
HIGH

JWT 인증 토큰이 간헐적으로 거부된다는 문제 신고가 들어왔습니다. 로그를 보니 token issued in the future 에러입니다. 코드 변경은 없었는데 왜 갑자기? 원인을 추적해보니 서버 중 한 대의 시계가 다른 서버보다 30초 빠르게 맞춰져 있었습니다. 클라우드 VM이 마이그레이션된 이후 NTP 데몬이 재시작되지 않아 시계가 조금씩 벗어났던 겁니다. 분산 시스템에서는 서버마다 시간이 같아야 한다는 전제 조건이 있고, 그게 깨지면 인증과 로그 분석이 모두 엉킵니다.

시간 동기화 (NTP & chrony)

서버의 시스템 시계가 몇 초만 틀려도 JWT 인증 토큰 검증 실패, TLS 핸드셰이크 오류, 로그 순서 뒤집힘 같은 장애가 발생합니다. 클라우드 환경에서는 VM이 일시 정지(sleep/migrate)된 후 시계가 수십 초~수 분씩 틀어지는 일이 흔합니다. NTP(Network Time Protocol)와 chrony를 이용해 서버 시간을 정확하게 유지하는 방법을 배웁니다.


1. 서버 시간이 왜 중요한가

이번 챕터에서 배울 것
  • 1서버 시간 불일치가 JWT·TLS·로그에 미치는 영향을 설명할 수 있다
  • 2NTP Stratum 계층 구조와 시간 동기화 원리를 이해할 수 있다
  • 3chrony가 ntpd를 대체한 이유와 차이점을 설명할 수 있다
  • 4chrony를 설치하고 /etc/chrony.conf에 타임서버를 설정할 수 있다
  • 5chronyc tracking / sources로 동기화 상태를 모니터링할 수 있다
  • 6timedatectl로 타임존을 변경하고 hwclock을 동기화할 수 있다
실습 환경 준비
현재 시간 동기화 상태 확인
timedatectl status
chrony 데몬 상태 및 동기화 추적 확인
systemctl status chronyd && chronyc tracking
chrony 패키지 설치 (미설치 시)
sudo apt-get install -y chrony # 또는 sudo yum install -y chrony
타임존 설정 주의사항

export TZ=Asia/Seoul 은 현재 셸 세션에만 임시 적용되므로, 영구 변경은 반드시 timedatectl set-timezone 을 사용할 것

💡개념

시간 불일치가 만드는 장애 시나리오

서버 운영에서 시간 동기화는 '있으면 좋은 것'이 아니라 필수 인프라입니다. 시간이 틀렸을 때 발생하는 실제 장애 유형을 살펴보겠습니다.

JWT / OAuth 토큰 만료

JWT(JSON Web Token)에는 iat(발급 시각)와 exp(만료 시각)가 Unix timestamp로 저장됩니다. 인증 서버와 애플리케이션 서버 간 시계가 30초 이상 차이 나면 방금 발급된 토큰도 "이미 만료"로 처리됩니다.

AuthServer  time: 10:00:00  → JWT exp = 10:30:00
AppServer   time: 10:31:00  → "토큰 만료!" (실제 5분밖에 안 지남)

TLS 인증서 유효성 검증 실패

TLS 인증서에는 Not BeforeNot After 필드가 있습니다. 클라이언트 시계가 서버보다 1시간 앞서 있으면, 아직 유효한 인증서도 "미래 인증서"로 거부됩니다. HTTPS 연결 자체가 실패합니다.

분산 시스템 로그 추적 불가

마이크로서비스 환경에서 서비스 A → B → C 순서로 호출이 일어났는데 각 서버 시계가 제각각이면 로그를 시간순으로 정렬해도 실제 호출 순서와 다르게 보입니다. Jaeger, Zipkin 같은 분산 트레이싱 도구도 타임스탬프 기반이므로 시간 불일치 시 추적 그래프가 왜곡됩니다.

Kerberos / Active Directory 도메인 조인 실패

Kerberos 프로토콜은 보안상 클라이언트와 KDC(Key Distribution Center) 간 시계 차이가 5분 이내여야 한다고 강제합니다. 시간이 5분 이상 벗어나면 도메인 조인, 로그인, Kerberos 티켓 갱신이 모두 실패합니다.

KRB5KRB_AP_ERR_SKEW: Clock skew too great

데이터베이스 복제 및 분산 합의

PostgreSQL 스트리밍 복제, Cassandra, etcd, CockroachDB 등은 노드 간 시계 차이를 기반으로 이벤트 순서를 결정합니다. 시계 차이가 크면 데이터 충돌 해결이 틀려지거나 복제가 중단될 수 있습니다.


2. NTP 프로토콜과 계층 구조

💡개념

NTP Stratum 계층 구조 원리

NTP Stratum 계층 구조와 정확도 — Stratum 0(GPS·원자시계, 오차 수 마이크로초)→Stratum 1(time.google.com 등 직접 연결, 매우 정확)→Stratum 2(pool.ntp.org, 1ms 미만)→Stratum 3(일반 서버·VM·컨테이너, 수 ms). 숫자가 클수록 기준원에서 멀어 정확도가 낮아지며, 운영 환경은 Stratum 2~3로 충분. timedatectl로 동기화 상태 확인확대

chronyc tracking을 실행했을 때 "Stratum: 2"가 뜨는데, 이게 좋은 건지 나쁜 건지, 왜 Stratum 값이 낮을수록 더 정확한 건지 궁금합니다. 또 사내 NTP 서버를 따로 구성해야 한다는 말을 들었는데 왜 Google이나 AWS의 공개 NTP 서버를 바로 쓰면 안 되는지도 의문입니다. Stratum 계층 구조를 이해하면 이 질문들에 답이 생기고, timedatectl 출력에서 시간 동기화 품질을 판단할 수 있게 됩니다.

NTP(Network Time Protocol, RFC 5905)는 인터넷을 통해 클라이언트가 정확한 시각을 얻을 수 있게 해주는 프로토콜입니다. 계층(Stratum) 구조로 정확도를 등급화합니다.

Stratum 번호가 낮을수록 더 정확합니다. Stratum 16은 "동기화 안 됨"을 의미합니다.

NTP 동기화 메커니즘

클라이언트는 서버에 요청 패킷을 보내고 4개의 타임스탬프를 이용해 오프셋(offset)과 왕복 지연(round-trip delay)을 계산합니다:

T1 : 클라이언트가 요청 전송한 시각
T2 : 서버가 요청을 받은 시각
T3 : 서버가 응답을 전송한 시각
T4 : 클라이언트가 응답을 받은 시각

왕복 지연 = (T4 - T1) - (T3 - T2)
오프셋    = ((T2 - T1) + (T3 - T4)) / 2

계산된 오프셋만큼 로컬 시계를 천천히 조정합니다. 급격한 시계 점프는 오히려 장애를 유발하므로, chrony는 시계를 slew(조금씩 당기거나 미루기) 방식으로 부드럽게 보정합니다.

사용 포트

NTP는 UDP 123번 포트를 사용합니다. 방화벽에서 이 포트가 막혀 있으면 동기화가 전혀 작동하지 않습니다.

💡개념

시계가 NTP로 맞춰지기까지 — 질의부터 drift 보정 반복까지 5단계

chronyc tracking에서 "System time"이 수 ms로 수렴하는 걸 보면 시계가 저절로 맞는 것처럼 보이지만, 그 뒤에는 질의 → 오차 계산 → 보정 → 하드웨어 반영이라는 정해진 절차가 돌고 있습니다. 이 흐름을 알면 "왜 동기화가 안 되지", "왜 재부팅하면 또 틀어지지", "왜 시각은 맞는데 표시가 UTC지"를 각각 어느 단계의 문제인지로 좁혀 진단할 수 있습니다.

TEXT
chronyd  ──질의(T1)──▶  타임서버
         ◀──응답(T4)──
   │
   ① 왕복 4개 타임스탬프 수집        (iburst면 부팅 직후 몰아서 질의)
   │
   ② 오프셋 계산 + 소스 교차검증      (여러 소스 중 truechimer 채택, 튀는 소스=falseticker 배제)
   │
   ── 오차 크기? ──
   │  작다 → ③a slew   (주파수를 미세조정해 서서히 당김/늦춤 — 시각이 뒤로 안 튐)
   │  크다 → ③b step   (makestep 임계 초과 → 즉시 점프)
   │
   ④ rtcsync → 하드웨어 클록(RTC)에 반영    (재부팅 후에도 시각 유지)
   │
   ⑤ driftfile에 주파수 오차 기록 → 폴링 반복
   ▼
   chronyc tracking: System time 0.000015s ...   (수 ms 이내 수렴)

각 단계에서 무슨 일이 일어나고, 어긋나면 어떤 증상인가:

단계하는 일여기서 어긋나면 (증상)
① 질의클라이언트가 UDP 123으로 타임서버에 패킷을 보내고 응답의 4개 타임스탬프를 모음. iburst는 부팅 직후 몰아 보내 첫 동기화를 앞당김123/udp 아웃바운드가 막히면 응답이 안 옴 → chronyc sources의 Reach 0·^?, 영영 동기화 안 됨
② 오차 계산왕복 지연을 빼고 오프셋(내 시계가 얼마나 틀렸는지)을 산출. 소스가 여럿이면 겹치는 다수를 truechimer로 채택소스가 1개뿐이면 교차검증 불가 → 그 소스가 조용히 틀어져도 못 거르고 함께 틀어짐(소스 3~4개 권장)
③ slew·step오차가 작으면 주파수를 미세조정해 서서히(slew), 크면 즉시 점프(step)로 보정. makestep이 임계·횟수를 정함makestep 미설정이면 부팅 초기 큰 오차도 slew만 → 수렴이 몇 시간씩 느림. 운영 중 잦은 step은 로그·DB 시각을 뒤로 튀게 함
④ RTC 반영rtcsync가 보정된 시스템 시각을 하드웨어 RTC에 주기적으로 기록rtcsync가 없으면 재부팅 직후 RTC의 옛 시각으로 시작 → NTP가 다시 맞출 때까지 잠깐 틀어짐
⑤ drift·반복시계 고유의 주파수 오차를 driftfile에 저장하고 폴링을 반복 → 다음 부팅·동기화가 빠름타임존은 별개 — 시각(UTC)이 맞아도 표시가 UTC면 timedatectl set-timezone으로 KST 매핑을 따로 해야 함

NTP synchronized: yes는 ①②가 성공해 어떤 소스와 맞았다는 뜻일 뿐, 그 소스가 옳은지(②의 교차검증)와 재부팅 후에도 유지되는지(④)는 별개입니다. 그래서 진단은 세 지점을 봅니다: chronyc sources^* 소스와 Reach가 살아있는지(①), chronyc tracking의 System time 오프셋이 수 ms 이내인지(②③), 시각은 맞는데 표시가 UTC면 타임존(⑤)을 확인합니다. 대부분의 "동기화가 안 돼요"는 ①의 123/udp 방화벽에서 끝납니다.


3. chrony vs ntpd

💡개념

chrony가 ntpd를 대체한 이유

chrony vs ntpd 비교 — 빠른 수렴과 불안정 네트워크 대응확대

새 Ubuntu 22.04 서버에서 시간 동기화 설정을 하려는데, 이전 팀원 문서는 전부 ntpd 기반이고 현재 운영 중인 일부 서버도 ntpd를 씁니다. 검색하면 chrony를 쓰라는 글이 나오는데, 그냥 두 개 다 설치해서 쓰면 안 되냐는 생각이 드는 상황입니다. 실제로 혼용하면 UDP 123 포트 충돌이나 시계 엇갈림으로 더 큰 문제가 생깁니다. chrony가 ntpd를 대체하게 된 배경을 알면 어떤 도구를 선택해야 하는지, 기존 ntpd 서버를 언제 마이그레이션해야 하는지 기준이 생깁니다.

과거에는 ntpd(NTP daemon)가 표준이었지만, RHEL 7 / CentOS 7부터 chrony가 기본으로 채택되었고, Ubuntu 18.04+, Debian 10+ 등 대부분의 최신 배포판이 chrony를 기본 NTP 클라이언트로 사용합니다.

항목chronyntpd
개발 연도1990s (현재도 활발히 개발)1980s (개발 축소)
빠른 초기 동기화매우 빠름 (수 초)느림 (수 분)
불안정한 네트워크잘 처리취약
VM / 컨테이너 환경최적화문제 많음
간헐적 인터넷 연결지원미지원
설정 파일/etc/chrony.conf/etc/ntp.conf
제어 도구chronycntpq, ntpdc
메모리 사용적음많음
RHEL 8/9 기본OX (제거됨)

VM과 컨테이너 환경에서 chrony가 특히 중요한 이유:

가상 머신은 하이퍼바이저가 CPU 자원을 다른 VM과 나누어 사용하기 때문에 VM 내부 시계가 실제보다 느리게 흐릅니다. VM이 일시 정지(suspend/migrate)된 후 깨어나면 몇 초~수 분의 시계 드리프트가 발생합니다. chrony는 이런 큰 오프셋도 빠르게 보정할 수 있도록 설계되어 있습니다.


3-1. NTP 포트 표 & 데몬 1개 원칙

💡개념

NTP 포트/프로토콜 표 — 방화벽 규칙 작성 기준

NTP UDP 123 방화벽 규칙 — 클라이언트/서버 설정확대

시간 동기화 트러블슈팅의 절반은 방화벽 문제입니다. 어떤 포트를 열어야 하는지 정확히 알아야 합니다.

서비스프로토콜/포트방향설명
NTP (chrony/ntpd)UDP 123Outbound외부 NTP 서버와 동기화 (필수)
NTP 서버로 동작UDP 123Inbound내부 클라이언트에게 시간 제공
chronyc 원격 관리UDP 323Inbound (선택)chronyc로 원격에서 chrony 관리
NTS-KE (키 교환)TCP 4460Outbound (선택)Network Time Security — 인증된 NTP

실무 포인트: 대부분의 서버는 UDP 123 Outbound 만 열면 됩니다. NTS는 최신 보안 기능이며 아직 범용 사용은 드뭅니다.

로컬 터미널
# 방화벽에서 NTP 허용 확인 (클라이언트)
sudo firewall-cmd --list-all | grep ntp
# 또는
sudo iptables -L OUTPUT -n | grep 123

# UDP 123 포트 테스트 (서버 도달 여부)
nc -uzv pool.ntp.org 123
# 결과: Connection to pool.ntp.org 123 port [udp/ntp] succeeded!
💡개념

동기화 데몬 1개 원칙 — timesyncd vs chrony vs ntpd 충돌 방지

동기화 데몬 충돌 방지 — timesyncd vs chrony vs ntpd확대

한 서버에서 NTP 데몬은 반드시 1개만 실행해야 합니다. 두 데몬이 동시에 UDP 123 포트를 소유하려 해서 충돌하거나, 서로 다른 서버를 참조해 시계가 엇갈릴 수 있습니다.

3가지 데몬 비교:

데몬패키지기본 탑재 배포판권장 여부
systemd-timesyncdsystemd 내장Ubuntu 18.04+, Debian 12+단순 클라이언트 용도로 적합
chronychronyRHEL 8+, Ubuntu 20.04+권장 — VM/클라우드 환경에 최적화
ntpdntp구형 배포판신규 설치 비권장 (chrony로 대체)

충돌 징후 진단:

서버 터미널
# 동시에 실행 중인 NTP 관련 데몬 확인
systemctl is-active systemd-timesyncd chrony ntpd 2>/dev/null

# 충돌 로그 확인 (chrony가 시작 실패하는 경우)
journalctl -u chrony --since "10 min ago" | grep -E "error|fail|conflict"
# 흔한 메시지: "Could not open /dev/pps0" 또는 "Already running as NTP daemon"

# UDP 123 포트를 점유한 프로세스 확인
sudo ss -ulnp | grep 123

올바른 전환 절차 (timesyncd → chrony):

서버 터미널
# Step 1: timesyncd 중지 및 비활성화 (충돌 방지)
sudo systemctl disable --now systemd-timesyncd

# Step 2: chrony 설치 및 시작
sudo apt install -y chrony          # Ubuntu/Debian
sudo dnf install -y chrony          # RHEL/CentOS

sudo systemctl enable --now chronyd

# Step 3: 데몬 1개만 실행 중인지 확인
systemctl is-active systemd-timesyncd   # → inactive
systemctl is-active chronyd             # → active

# Step 4: 동기화 확인
chronyc tracking | grep "System time"

클라우드 환경 주의: AWS EC2, GCP, Azure는 각자 내부 NTP 서버(169.254.169.123 등)를 제공합니다. 인스턴스 내 chrony 설정에서 이 주소를 우선 사용하면 외부 UDP 123 포트를 열지 않아도 됩니다.

chronyc 출력 판독 — 동기화 상태를 어떻게 읽나
chronyc tracking의 Leap status`Normal`이면 동기화 정상. `Not synchronised`면 아직 시간서버와 못 맞춤 — 소스·방화벽(123/udp) 점검. '동기화 됐나'의 첫 판정
System time offset(시계 오차)수 ms~수십 ms면 정상. 수백 ms~초 단위면 드리프트 — 로그·인증·분산 추적에 영향(이 모듈 시나리오). 'offset이 크면 시간 의존 기능이 깨진다'
chronyc sources의 `^*`현재 동기화 중인 소스(* 표시). `^+`=후보, `^-`=제외, `^?`=미도달. '*이 하나도 없으면 어떤 소스와도 동기화 안 됨'
Reach 값(소스 도달성)8진수 377이 최근 8회 전부 응답(최상). 0이나 낮으면 그 소스에 패킷이 안 닿음 — 방화벽/소스 다운. '377이 건강, 0은 불통'
동기화가 안 맞는다① 데몬 1개인지(timesyncd·ntpd 충돌) ② 123/udp 아웃바운드 열렸나 ③ sources에 * 있나 순으로. '충돌·방화벽·소스'가 3대 원인
큰 오차를 즉시 맞출까운영 중 급격한 시간 점프는 로그·DB에 혼란 → chrony는 makestep으로 초기 한 번만 점프, 이후 서서히(slew) 보정. '운영 중엔 천천히 맞춘다'

4. chrony 설치 및 기본 설정

실습 전 디렉토리와 예제 파일을 먼저 준비합니다.

로컬 터미널
# 실습 디렉토리 준비
mkdir -p /tmp/linux/part5/exam_233 && cd /tmp/linux/part5/exam_23

# NTP 설정 샘플 파일
cat > chrony.conf.sample << 'EOF'
# /etc/chrony.conf 예제
# 공개 NTP 풀 서버 사용
pool 2.pool.ntp.org iburst maxsources 4

# 한국 NTP 서버 (KT, KRISS)
server time.bora.net iburst
server ntp.kornet.net iburst

# 로컬 시계 허용 오차 (초)
makestep 1.0 3

# 하드웨어 타임스탬프 사용 (지원하는 경우)
# hwtimestamp *

# 동기화 로그
logdir /var/log/chrony
log measurements statistics tracking
EOF

이제 실습을 진행합니다.

chrony 설치 및 서비스 활성화

RHEL / CentOS / Rocky Linux / AlmaLinux:

로컬 터미널
# 설치 (RHEL 8/9는 기본 설치되어 있음)
sudo dnf install -y chrony

# 서비스 시작 및 부팅 자동 시작 등록
sudo systemctl enable --now chronyd

# 서비스 상태 확인
sudo systemctl status chronyd

Ubuntu / Debian:

로컬 터미널
# 설치
sudo apt update && sudo apt install -y chrony

# 서비스 활성화
sudo systemctl enable --now chrony

# Ubuntu에서는 서비스 이름이 'chrony' (d 없음)
sudo systemctl status chrony

기존 timesyncd 비활성화 (Ubuntu):

Ubuntu 18.04+는 systemd-timesyncd라는 가벼운 NTP 클라이언트가 기본으로 실행됩니다. chrony와 충돌하므로 비활성화합니다:

서버 터미널
# systemd-timesyncd 중지 및 비활성화
sudo systemctl disable --now systemd-timesyncd

# 비활성화 확인
systemctl is-active systemd-timesyncd
# 출력: inactive

ntpd가 있다면 충돌 방지:

서버 터미널
# ntpd가 실행 중인지 확인
systemctl is-active ntpd 2>/dev/null || echo "ntpd 없음"

# ntpd가 있다면 중지
sudo systemctl disable --now ntpd 2>/dev/null
🔍실행 후 확인할 것
  • systemctl status chronyd 에서 'active (running)' 상태가 확인된다
  • timedatectl status 에서 'NTP synchronized: yes' 항목이 표시된다
  • chronyc tracking 에서 'System time' 오프셋이 수 밀리초 이내로 줄어들어 있다
  • chronyc sources -v 에서 타임서버 목록이 나타나고 * 표시가 현재 동기화 중인 서버를 가리킨다
  • 읽기 순서: timedatectl → 'NTP synchronized: yes' 확인 → chronyc sources 에서 * 마크 서버 확인 → chronyc tracking 으로 오프셋 정밀도 확인
  • chronyc sources 에서 * 마크가 있어야 현재 동기화 중인 것 — ? 마크이면 해당 서버에 연결 불가, 모두 ? 이면 방화벽 UDP 123 차단 의심
  • chronyc tracking 의 System time 오프셋 기준: 50ms 이하 정상 / 500ms 이상이면 주의 / 1s 이상이면 심각 — JWT 인증 오류나 TLS 핸드셰이크 실패가 발생할 수 있는 수준
  • chronyc tracking 의 Stratum 값이 16이면 동기화 서버를 찾지 못한 상태 — chronyd 설정 또는 네트워크 연결을 확인한다
  • 오프셋이 크면서 CPU도 정상이라면 VM 마이그레이션 후 makestep 미적용 가능성 — sudo chronyc makestep 으로 즉시 강제 보정

5. chrony.conf 타임서버 설정

/etc/chrony.conf 타임서버 설정

chrony의 핵심 설정 파일은 /etc/chrony.conf입니다. 기본 설정을 확인하고 한국 환경에 맞게 수정합니다.

로컬 터미널
# 현재 설정 확인
sudo cat /etc/chrony.conf

기본 설정 파일 구조 (RHEL 계열):

INI
# /etc/chrony.conf

# -- 타임서버 설정 --
# pool: 여러 서버를 자동으로 선택 (권장)
# iburst: 초기 동기화를 빠르게 (첫 연결 시 패킷을 연속 전송)
pool 2.rhel.pool.ntp.org iburst

# -- 한국/아시아 권장 타임서버 --
# pool.ntp.org: 지역 기반 서버 자동 선택
pool kr.pool.ntp.org iburst

# KT 한국 타임서버
server time.bora.net iburst

# Google 공개 NTP (IPv4/IPv6 지원, Stratum 1)
server time.google.com iburst

# AWS Time Sync Service (EC2 인스턴스에서 권장)
# 링크-로컬 주소, 외부 네트워크 불필요
server 169.254.169.123 prefer iburst

# Cloudflare NTP
server time.cloudflare.com iburst

# -- 드리프트 파일 --
# 시계 주파수 오차를 저장, 재시작 후 빠른 보정에 사용
driftfile /var/lib/chrony/drift

# -- 큰 시간 차이 자동 수정 --
# 오프셋이 1초 이상이면 즉시 수정 (최초 3회만)
makestep 1.0 3

# -- 하드웨어 클럭 동기화 --
rtcsync

# -- 로컬 네트워크에 NTP 서버로 제공 --
# (내부 NTP 서버로 운용할 때만 활성화)
# allow 192.168.0.0/16

# -- 로그 설정 --
logdir /var/log/chrony

AWS EC2 환경 전용 설정:

로컬 터미널
# EC2에서는 AWS Time Sync를 우선 사용
sudo tee /etc/chrony.conf > /dev/null <<'EOF'
# AWS Time Sync Service (링크-로컬, 항상 사용 가능)
server 169.254.169.123 prefer iburst

# 백업 서버
pool kr.pool.ntp.org iburst
server time.google.com iburst

driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
EOF

설정 변경 후 chrony 재시작:

서버 터미널
sudo systemctl restart chronyd

# 문법 오류 확인 (재시작 실패 시)
sudo chronyd -Q 'server time.bora.net iburst'

6. 동기화 상태 확인

chronyc로 동기화 상태 모니터링

chronyc는 chronyd와 통신하는 명령줄 도구입니다. 동기화 상태를 확인하는 두 가지 핵심 명령을 살펴봅니다.

chronyc sources — 타임서버 목록 및 상태:

로컬 터미널
chronyc sources -v
  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = synced, '+' = combined, '-' = not combined,
| /   '?' = unreachable, 'x' = time may be in error, '~' = time too variable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 169.254.169.123               3   6   377    42    +15us[  +8us] +/-  473us
^+ time.bora.net                 2   7   377   107    -2ms[ -2ms] +/-   12ms
^+ time.google.com               1   8   255    43    +1ms[ +1ms] +/-   15ms
^- kr.pool.ntp.org               2   9   177   212    -5ms[ -5ms] +/-   25ms

상태 기호 해석:

기호의미
*현재 동기화 중인 서버 (최적 서버)
+보조로 함께 사용 중인 서버
-선택되지 않은 서버
?연결 불가 서버
x시간 오류 가능성 있는 서버

Reach 컬럼: 최근 8번의 폴링 성공 여부를 8진수로 표현합니다. 377은 8번 모두 성공, 0은 연결 안 됨.

chronyc tracking — 전체 동기화 상태:

로컬 터미널
chronyc tracking
Reference ID    : A9FEA97B (169.254.169.123)
Stratum         : 4
Ref time (UTC)  : Thu Mar 26 01:23:45 2026
System time     : 0.000015372 seconds fast of NTP time
Last offset     : +0.000015372 seconds
RMS offset      : 0.000018521 seconds
Frequency       : 2.345 ppm fast
Residual freq   : +0.012 ppm
Skew            : 0.234 ppm
Root delay      : 0.000946234 seconds
Root dispersion : 0.001234567 seconds
Update interval : 64.2 seconds
Leap status     : Normal

핵심 항목 해석:

항목의미정상 범위
Reference ID현재 동기화 서버-
Stratum현재 계층 번호1~4
System timeNTP 기준 대비 로컬 오프셋수 ms 이내
Frequency시계 주파수 오차 (ppm)±100 ppm 이내
Leap status윤초 상태Normal

chronyc makestep — 즉시 시간 강제 보정:

로컬 터미널
# 큰 오프셋이 있을 때 즉시 시계를 맞춤 (서비스 재시작 없이)
sudo chronyc makestep

# 확인
chronyc tracking | grep "System time"

기타 유용한 chronyc 명령:

로컬 터미널
# 현재 NTP 소스 간단 요약
chronyc sourcestats

# chrony 서버 활동 통계
chronyc activity

# 특정 서버 정보 상세 확인
chronyc ntpdata 169.254.169.123

7. timedatectl로 시간대 및 NTP 관리

timedatectl의 대안: 로우레벨 시스템 타임존 수동 강제 매핑

timedatectl 도구가 유실되었거나 레거시 컨테이너 환경에서는 아래와 같이 타임존 zoneinfo 정보를 시스템 로컬타임 경로에 심볼릭 링크로 맵핑해야 합니다.

로컬 터미널
# 1. 기존 localtime 매핑 링크 제거
$ sudo rm -f /etc/localtime

# 2. zoneinfo DB에서 원하는 타임존(Asia/Seoul)을 /etc/localtime으로 심볼릭 링크 생성
$ sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

이러면 timedatectl 없이도 시스템 전체 트랜잭션 타임이 한국 표준시(KST)로 수동 강제 고정됩니다.

timedatectl 명령어 완전 가이드

timedatectl은 systemd가 제공하는 시간 관리 통합 도구입니다. 시간대 변경, NTP 활성화/비활성화, 현재 상태 확인을 한 도구에서 처리합니다.

현재 시간 설정 상태 확인:

로컬 터미널
timedatectl
               Local time: Thu 2026-03-26 10:23:45 KST
           Universal time: Thu 2026-03-26 01:23:45 UTC
                 RTC time: Thu 2026-03-26 01:23:45
                Time zone: Asia/Seoul (KST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

항목 설명:

항목의미
Local time현재 시간대 기준 로컬 시각
Universal timeUTC 기준 시각
RTC time하드웨어(BIOS) 시계
Time zone현재 시간대
System clock synchronizedNTP 동기화 완료 여부
NTP serviceNTP 클라이언트 동작 여부
RTC in local TZHW 시계가 로컬 시간대 사용 여부 (no = UTC 권장)

Asia/Seoul 시간대 설정:

로컬 터미널
# 사용 가능한 시간대 목록 검색
timedatectl list-timezones | grep -i seoul
# 출력: Asia/Seoul

timedatectl list-timezones | grep -i asia | head -20

# 시간대 설정
sudo timedatectl set-timezone Asia/Seoul

# 확인
timedatectl | grep "Time zone"
# 출력: Time zone: Asia/Seoul (KST, +0900)

다른 시간대 예시:

로컬 터미널
# UTC (국제 표준)
sudo timedatectl set-timezone UTC

# 미국 동부
sudo timedatectl set-timezone America/New_York

# 일본 (한국과 같은 UTC+9, 하지만 JST)
sudo timedatectl set-timezone Asia/Tokyo

NTP 동기화 활성화/비활성화:

로컬 터미널
# NTP 동기화 활성화
sudo timedatectl set-ntp true

# NTP 동기화 비활성화 (수동 시간 설정 시 필요)
sudo timedatectl set-ntp false

# 상태 확인
timedatectl show | grep NTP

수동으로 시간 설정 (NTP 비활성화 상태에서만):

로컬 터미널
# NTP 먼저 비활성화
sudo timedatectl set-ntp false

# 날짜+시간 설정
sudo timedatectl set-time "2026-03-26 10:30:00"

# 날짜만 설정
sudo timedatectl set-time "2026-03-26"

# NTP 다시 활성화
sudo timedatectl set-ntp true

8. date 명령어와 hwclock

date 명령어와 hwclock로 시간 확인 및 동기화

datehwclock은 NTP 없이도 시간을 확인하고 조정할 수 있는 전통적인 도구입니다.

date 명령어 — 현재 시간 확인:

로컬 터미널
# 현재 시간 (기본: 로컬 시간대)
date
# 출력: Thu Mar 26 10:23:45 KST 2026

# UTC로 출력
date -u
# 출력: Thu Mar 26 01:23:45 UTC 2026

# 포맷 지정 출력
date "+%Y-%m-%d %H:%M:%S"
# 출력: 2026-03-26 10:23:45

# Unix timestamp 출력
date +%s
# 출력: 1774687425

# Unix timestamp를 날짜로 변환
date -d @1774687425

date 명령어 — 시간 수동 설정 (NTP 비활성화 상태에서):

로컬 터미널
# 날짜와 시간 설정 (MMDDHHmmYYYY.ss 형식)
sudo date 032610302026.00
# 2026년 3월 26일 10시 30분 00초

# 또는 문자열 형식 (GNU date)
sudo date -s "2026-03-26 10:30:00"
sudo date -s "Thu Mar 26 10:30:00 KST 2026"

hwclock — 하드웨어(RTC) 시계 관리:

하드웨어 시계(RTC, Real-Time Clock)는 서버 전원이 꺼져도 배터리로 계속 작동하는 BIOS 내장 시계입니다. 시스템 시계(커널이 관리)와 별개로 존재합니다.

로컬 터미널
# 하드웨어 시계 현재 값 읽기
sudo hwclock --show
# 출력: 2026-03-26 01:23:45.234567+00:00

# 시스템 시계 → 하드웨어 시계 동기화 (-w: write to hw)
sudo hwclock --systohc

# 하드웨어 시계 → 시스템 시계 동기화 (-s: set system)
sudo hwclock --hctosys

# 하드웨어 시계를 UTC 기준으로 설정 (서버 권장)
sudo hwclock --systohc --utc

# 하드웨어 시계를 로컬 시간 기준으로 설정 (비권장)
sudo hwclock --systohc --localtime

서버 권장 구성: HW 시계를 UTC로 유지

로컬 터미널
# /etc/adjtime 파일로 HW 시계 모드 확인
cat /etc/adjtime
# 마지막 줄이 UTC → 하드웨어 시계가 UTC 사용 중
# 마지막 줄이 LOCAL → 로컬 시간 사용 중 (Windows 듀얼부팅 환경)

부팅 시 시간 복원 순서:

1. BIOS/UEFI: HW 시계(RTC) 읽기
2. 커널: HW 시계 → 시스템 시계 설정
3. systemd: chronyd 시작
4. chronyd: NTP 서버와 동기화 → 시스템 시계 보정
5. chronyd: rtcsync 설정 시 HW 시계도 갱신
로컬 터미널
# chrony의 rtcsync 옵션으로 HW 시계 자동 갱신 확인
grep rtcsync /etc/chrony.conf
# 출력: rtcsync

9. 실무 활용: JobContext

💼
실무 맥락
현업 패턴

신규 서버 투입 체크리스트

새 서버를 프로덕션에 투입하기 전 시간 설정 확인은 기본 점검 항목입니다:

로컬 터미널
#!/bin/bash
# 신규 서버 시간 동기화 점검 스크립트

echo "=== 시간대 확인 ==="
timedatectl | grep "Time zone"

echo "=== NTP 서비스 상태 ==="
timedatectl | grep "NTP service"

echo "=== 동기화 상태 ==="
timedatectl | grep "synchronized"

echo "=== chrony 소스 ==="
chronyc sources 2>/dev/null || echo "chrony 미설치"

echo "=== 시스템 오프셋 ==="
chronyc tracking 2>/dev/null | grep "System time"

AWS EC2 AMI 빌드 시 chrony 설정 포함

EC2 인스턴스를 AMI로 만들 때 AWS Time Sync Service(169.254.169.123)를 최우선 타임서버로 설정하는 것이 AWS 공식 권장사항입니다. 이 링크-로컬 주소는 인터넷 접속 없이도 항상 사용 가능합니다.

Ansible로 다수 서버 시간 설정 배포:

YAML
# time-sync.yml
---
- name: NTP 시간 동기화 설정
  hosts: all
  become: true
  tasks:
    - name: chrony 설치
      package:
        name: chrony
        state: present

    - name: chrony.conf 배포
      template:
        src: chrony.conf.j2
        dest: /etc/chrony.conf
        backup: yes
      notify: restart chronyd

    - name: 시간대 설정
      community.general.timezone:
        name: Asia/Seoul

    - name: chronyd 활성화
      service:
        name: chronyd
        state: started
        enabled: true

  handlers:
    - name: restart chronyd
      service:
        name: chronyd
        state: restarted

Kubernetes Pod 시간 동기화

컨테이너(Pod)는 호스트 노드의 시스템 시계를 공유합니다. 별도의 NTP 클라이언트 불필요. 따라서 Kubernetes 노드의 chrony 설정이 중요합니다. 노드 시계가 틀리면 모든 Pod의 시각이 틀립니다.

Kubernetes
# 노드 시간 확인 (kubectl exec으로 파드 내부)
kubectl exec -it <pod-name> -- date
# 노드와 동일한 시각이 출력되어야 함

모니터링: Prometheus + Alertmanager로 시간 드리프트 경보

YAML
# Prometheus 알람 규칙 예시
groups:
  - name: time-sync
    rules:
      - alert: NTPNotSynchronized
        expr: node_timex_sync_status != 1
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "{{ $labels.instance }} NTP 동기화 실패"

      - alert: ClockOffsetTooLarge
        expr: abs(node_timex_offset_seconds) > 0.1
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "시계 오프셋 100ms 초과: {{ $value }}s"

10. 트러블슈팅

증상:

로컬 터미널
chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^? time.bora.net                 0   8     0     -     +0ns[   +0ns] +/-    0ns
^? time.google.com               0   8     0     -     +0ns[   +0ns] +/-    0ns
^? 169.254.169.123               0   8     0     -     +0ns[   +0ns] +/-    0ns

모든 서버에 ? 표시, Reach0 — 연결이 전혀 안 됨.

원인 진단:

로컬 터미널
# NTP 서버에 UDP 123 포트 연결 테스트
# ntpdate로 단발성 쿼리 (진단 목적)
sudo ntpdate -q time.google.com 2>&1 | head -5

# tcpdump로 NTP 패킷 확인
sudo tcpdump -i any port 123 -n

# firewalld 규칙 확인 (RHEL 계열)
sudo firewall-cmd --list-all

# iptables 규칙 확인
sudo iptables -L OUTPUT -n | grep 123
sudo iptables -L INPUT -n | grep 123

# nmap으로 외부에서 포트 확인 (다른 서버에서 실행)
nmap -sU -p 123 <서버IP>

해결 방법:

로컬 터미널
# firewalld에서 NTP 허용 (RHEL/CentOS/Rocky)
sudo firewall-cmd --permanent --add-service=ntp
sudo firewall-cmd --reload

# 또는 포트 번호로 직접 허용
sudo firewall-cmd --permanent --add-port=123/udp
sudo firewall-cmd --reload

# ufw에서 허용 (Ubuntu)
sudo ufw allow 123/udp
sudo ufw reload

# iptables 직접 규칙 추가
sudo iptables -A OUTPUT -p udp --dport 123 -j ACCEPT
sudo iptables -A INPUT -p udp --sport 123 -j ACCEPT

# 규칙 저장
sudo service iptables save  # RHEL
sudo iptables-save > /etc/iptables/rules.v4  # Debian/Ubuntu

# AWS EC2: Security Group에서 Outbound UDP 123 허용 확인
# AWS Management Console → EC2 → Security Groups → Outbound Rules
# 또는 AWS CLI:
aws ec2 describe-security-groups --group-ids sg-xxxxxxxx \
  --query 'SecurityGroups[].IpPermissionsEgress'

방화벽 해결 후 chrony 재시작:

서버 터미널
sudo systemctl restart chronyd
sleep 10
chronyc sources
# Reach 값이 점점 올라가야 함: 1, 3, 7, 17, 37, 77, 177, 377

증상:

서버를 재시작하거나 VM 마이그레이션 후 시계가 수 분씩 틀어집니다. chronyc tracking에서 오프셋이 수 초 이상으로 나타납니다.

로컬 터미널
chronyc tracking | grep "System time"
# System time     : 45.234567890 seconds slow of NTP time
# ← 45초나 느림!

원인 분석:

VM 환경에서 시간 드리프트가 발생하는 원인:

  1. CPU Steal Time: 하이퍼바이저가 CPU를 다른 VM과 공유하면서 VM의 타이머 인터럽트가 지연됨
  2. VM 일시 정지: 스냅샷, 라이브 마이그레이션, 절전 모드 후 복구 시 시계가 멈췄다 재개됨
  3. 시계 소스 불안정: VM 내부의 가상 시계(TSC)가 불안정

해결 방법:

로컬 터미널
# 1. chrony.conf에 makestep 설정 확인 및 조정
sudo grep makestep /etc/chrony.conf
# makestep 1.0 3  ← 1초 이상 오프셋이면 즉시 수정 (최초 3회)

# 큰 드리프트 허용을 위해 수정 (VM 환경 권장)
sudo sed -i 's/^makestep.*/makestep 1.0 -1/' /etc/chrony.conf
# -1: 횟수 제한 없이 항상 즉시 수정

# 2. 지금 당장 시계 강제 보정
sudo chronyc makestep
chronyc tracking | grep "System time"

# 3. VM 환경에서 빠른 폴링 설정 (chrony.conf 추가)
# maxpoll 6 → 최대 64초마다 폴링 (기본값보다 자주)
echo "maxpoll 6" | sudo tee -a /etc/chrony.conf
sudo systemctl restart chronyd

# 4. KVM/QEMU 게스트: 호스트 시계 사용 (가장 안정적)
# /etc/chrony.conf에 refclock 추가
echo "refclock PHC /dev/ptp0 poll 3 dpoll -2 offset 0" | sudo tee -a /etc/chrony.conf
sudo systemctl restart chronyd

# 5. 시스템 클럭 소스 확인
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
# kvm-clock → KVM 최적화 시계 (좋음)
# tsc → TSC (VM에서 불안정 가능)
# hpet → HPET (느리지만 안정)

# TSC를 사용 중이라면 kvm-clock으로 변경 (KVM 환경)
echo kvm-clock | sudo tee /sys/devices/system/clocksource/clocksource0/current_clocksource

Docker/컨테이너 환경 주의사항:

Docker
# 컨테이너는 호스트 커널 공유 → 컨테이너 내부에서 NTP 실행 불필요/불가
# 호스트 노드의 시계를 동기화해야 함

# 컨테이너 내부에서 시간 확인
docker exec my-container date
# 호스트와 동일해야 함

# 다르다면 호스트 chrony 상태 확인
chronyc tracking

증상:

Linux 서버를 Active Directory 도메인에 조인할 때 다음 오류 발생:

realm join example.com
# 오류:
# adcli: joining domain failed: kinit: Clock skew too great
# KRB5KRB_AP_ERR_SKEW: Clock skew too great while getting initial credentials

또는 이미 조인된 서버에서 SSH 로그인, sudo, samba 인증이 실패:

pam_krb5: TGT expired
kinit: Clock skew too great while renewing credentials

원인:

Kerberos 프로토콜 사양(RFC 4120)에 따라 클라이언트와 KDC(도메인 컨트롤러) 간 시계 차이가 5분(300초)을 초과하면 보안상 모든 인증을 거부합니다. 이는 재전송 공격(Replay Attack) 방지를 위한 필수 보안 설계입니다.

진단 절차:

로컬 터미널
# 1. 현재 서버 시각과 도메인 컨트롤러 시각 비교
date -u
# 현재 서버 UTC 시각

# 도메인 컨트롤러에 NTP 쿼리 (DC 주소로 변경)
ntpdate -q dc01.example.com 2>&1
# 출력에서 offset 값 확인
# offset 320.456789 sec  ← 5분 20초 차이, Kerberos 거부

# 또는 chronyc로 DC를 임시 타임서버로 테스트
chronyc -a 'server dc01.example.com iburst'
chronyc sources | grep dc01

# 2. 현재 오프셋 확인
chronyc tracking | grep "System time"

# 3. DC와 직접 시간 비교
ssh dc01.example.com "date -u"  # Windows DC라면 원격 PowerShell 사용
# 또는 smbclient로 DC 시각 확인
smbclient -N -L dc01.example.com 2>/dev/null | grep -i time

해결 방법:

로컬 터미널
# 방법 1: DC를 NTP 서버로 설정 (도메인 환경 표준)
sudo tee /etc/chrony.conf > /dev/null <<EOF
# 도메인 컨트롤러를 타임서버로 사용 (Kerberos 동기화 보장)
server dc01.example.com iburst prefer
server dc02.example.com iburst

# 백업: 공개 NTP
pool kr.pool.ntp.org iburst

driftfile /var/lib/chrony/drift
makestep 1.0 -1
rtcsync
EOF

sudo systemctl restart chronyd

# 방법 2: 즉시 강제 동기화 (큰 오프셋 수정)
sudo chronyc makestep

# 방법 3: ntpdate로 즉시 수동 동기화 (긴급 시)
sudo ntpdate dc01.example.com

# 동기화 후 도메인 조인 재시도
chronyc tracking | grep "System time"
# System time: 0.002345678 seconds fast of NTP time  ← OK

sudo realm join example.com -U Administrator

Windows DC의 NTP 설정 확인:

도메인 환경에서 시간 권위 체계: DC(PDC Emulator) → 외부 NTP → 도메인 멤버

POWERSHELL
# Windows DC에서 NTP 소스 확인
w32tm /query /source
w32tm /query /status

# PDC Emulator를 외부 NTP와 동기화 (Windows PowerShell)
w32tm /config /manualpeerlist:"time.google.com,0x8 time.bora.net,0x8" /syncfromflags:manual /reliable:yes /update
net stop w32tm && net start w32tm
w32tm /resync /force

예방: 도메인 환경 NTP 정책

  1. PDC Emulator: 외부 Stratum 1/2 서버와 동기화
  2. 다른 DC들: PDC Emulator와 동기화
  3. 도메인 멤버 서버: DC와 동기화 (w32tm /resync 또는 chrony)
  4. 비도메인 Linux: 공개 NTP pool 사용

심화 — chrony는 어떻게 '거짓말하는 시계'를 걸러내나

💡개념

심화: 소스 선택과 falseticker — 왜 NTP 서버는 최소 3~4개여야 하나

stratum이 '기준 시계에서 얼마나 먼가'를 말한다면, 이제 그 위층 질문이 남습니다 — 여러 시계가 서로 다른 시각을 주장하면 chrony는 무엇을 믿을까요? chrony가 소스를 하나만 믿지 않는 데는 이유가 있고, 이 원리를 알아야 '동기화됐다는데 왜 틀리지'를 설명할 수 있습니다.

  • chrony는 다수결로 진실한 시계를 고릅니다: 각 NTP 소스는 시각을 '점'이 아니라 왕복 지연을 고려한 '구간'으로 제시합니다. chrony는 이 구간들이 겹치는 다수 그룹을 찾아 **truechimer(참된 시계)**로 보고, 겹치지 않고 튀는 소스는 **falseticker(거짓 시계)**로 판단해 배제합니다.
  • 그래서 소스 개수가 내구성을 정합니다: 소스가 2개면 둘이 갈릴 때 누가 옳은지 판정할 수 없습니다. 하나의 잘못된 소스를 '투표로' 걸러내려면 최소 3~4개가 필요합니다(비잔틴 내성과 같은 논리). NTP 풀을 쓰면 자동으로 여러 서버가 잡혀 이 조건을 만족합니다.
  • chronyc sources의 상태 문자가 판정 결과입니다: 맨 앞 기호가 곧 chrony의 결정입니다 — *는 현재 동기화 기준으로 선택된 소스, +는 조합에 함께 쓰이는 후보, -는 truechimer지만 조합에서 제외됨, x는 falseticker로 배제됨, ?는 응답 없음·도달 불가입니다.
  • 단일 소스는 조용히 위험합니다: 소스가 하나뿐이면 그 소스가 틀려도 chrony는 비교 대상이 없어 그대로 따라갑니다. 'NTP synchronized: yes'는 '내가 참조하는 것과 맞다'일 뿐 '실제 시각이 맞다'의 보증이 아닙니다.

핵심은 NTP의 정확성이 한 서버의 정확성이 아니라 여러 서버의 교차 검증에서 나온다는 것입니다. chronyc sources의 기호와 chronyc sourcestats의 오차·지터를 함께 읽어야 '지금 무엇을, 왜 믿고 있는지'가 보입니다.

상황: 로그 타임스탬프가 실제와 미묘하게 어긋나고, JWT·인증서 검증이 간헐적으로 실패합니다. 그런데 각 서버에서 timedatectl은 'NTP synchronized: yes'라 문제가 없어 보입니다. 여러 대가 '똑같이' 틀어져 있는 것이 단서입니다.

원인: 내부 표준화를 이유로 모든 서버를 사내 NTP 서버 한 대만 참조하도록 설정해 뒀는데, 그 상위 서버가 조용히 틀어졌습니다(상위 참조 실패 후 로컬 시계로 표류). 클라이언트들은 비교할 다른 소스가 없어 falseticker 판정을 할 수 없었고, 그래서 '틀린 기준'에 충실히 동기화된 채 다 함께 틀어졌습니다. 'synchronized: yes'는 그 한 소스와 맞다는 뜻이었을 뿐입니다.

진단: 얼마나 틀렸는지가 아니라 '무엇을 믿고 있는지'를 봅니다.

로컬 터미널
chronyc sources -v
# 상태 문자와 소스 개수 확인
# ^* internal-ntp   3   ...   ← 참조 소스가 이것 하나뿐이면 교차검증 불가
# (falseticker를 걸러낼 다른 소스가 없음)

chronyc tracking | grep -E 'Reference|Stratum|System time'
# Reference ID가 그 사내 서버 하나로 고정, Stratum이 비정상적으로 높지 않은지

# 상위 서버 자체를 외부 기준과 비교
chronyc -a 'server time.google.com iburst'
chronyc sources

소스가 하나뿐이고, 그 소스를 외부 기준과 대보니 offset이 크면 확정입니다.

해결: 클라이언트가 최소 3~4개 소스(사내 서버 + 공개 풀 백업)를 참조하도록 바꿔, 한 소스가 틀어져도 falseticker로 걸러지게 합니다. 사내 NTP 서버 자체는 신뢰할 수 있는 상위(외부 stratum 1~2 또는 GPS)와 여러 개로 동기화하고, 그 서버의 상위 참조 상태를 모니터링합니다. 즉 '표준화'를 단일 소스로 오해하지 말고, 표준 서버를 이중화하고 클라이언트에 백업 풀을 남겨 교차 검증이 항상 성립하게 만드는 것이 핵심입니다.


11. 빠른 참조

필수 명령어 요약

로컬 터미널
# 현재 시간 상태 전체 확인
timedatectl

# 동기화 서버 목록 확인
chronyc sources -v

# 동기화 상세 상태 확인
chronyc tracking

# 시간대 변경 (한국)
sudo timedatectl set-timezone Asia/Seoul

# NTP 활성화
sudo timedatectl set-ntp true

# 즉시 시계 강제 보정
sudo chronyc makestep

# chrony 서비스 재시작
sudo systemctl restart chronyd

# HW 시계 → 시스템 시계 동기화
sudo hwclock --hctosys

# 시스템 시계 → HW 시계 저장
sudo hwclock --systohc

# 현재 시각 확인 (UTC)
date -u

# chrony 로그 확인
sudo journalctl -u chronyd -f

시간대(Timezone) 자주 쓰는 목록

로컬 터미널
timedatectl list-timezones | grep -E "Seoul|Tokyo|Shanghai|Singapore|UTC|London|New_York"
# Asia/Seoul       → KST (UTC+9)
# Asia/Tokyo       → JST (UTC+9)
# Asia/Shanghai    → CST (UTC+8)
# Asia/Singapore   → SGT (UTC+8)
# UTC              → UTC (UTC+0)
# Europe/London    → GMT/BST
# America/New_York → EST/EDT (UTC-5/-4)

chrony.conf 타임서버 빠른 선택 가이드

로컬 터미널
# 한국 서버 (권장)
server time.bora.net iburst        # KT (Stratum 1)
pool kr.pool.ntp.org iburst        # 한국 NTP 풀

# 글로벌 서버
server time.google.com iburst      # Google (Stratum 1)
server time.cloudflare.com iburst  # Cloudflare (Stratum 1)

# AWS EC2 전용
server 169.254.169.123 prefer iburst  # AWS Time Sync (링크-로컬)

# GCP 전용
server metadata.google.internal iburst  # GCP 메타데이터 서버

# Azure 전용
server time.windows.com iburst     # Microsoft Azure

동기화 확인 자동화 스크립트

로컬 터미널
#!/bin/bash
# /usr/local/bin/check-ntp-sync.sh

OFFSET=$(chronyc tracking 2>/dev/null | grep "System time" | awk '{print $4}')
THRESHOLD=1.0  # 1초 이상이면 경고

if [ -z "$OFFSET" ]; then
    echo "ERROR: chrony not running"
    exit 2
fi

# Python으로 부동소수점 비교
OVER=$(python3 -c "print(1 if abs(float('$OFFSET')) > $THRESHOLD else 0)" 2>/dev/null)

if [ "$OVER" = "1" ]; then
    echo "WARNING: NTP offset ${OFFSET}s exceeds ${THRESHOLD}s threshold"
    exit 1
else
    echo "OK: NTP offset ${OFFSET}s"
    exit 0
fi
로컬 터미널
chmod +x /usr/local/bin/check-ntp-sync.sh

# cron으로 5분마다 실행
echo "*/5 * * * * root /usr/local/bin/check-ntp-sync.sh >> /var/log/ntp-check.log 2>&1" \
  | sudo tee /etc/cron.d/ntp-check

정리

서버 시간 동기화는 인증, 보안, 로깅, 분산 시스템 모두에 영향을 미치는 인프라 기초입니다.

작업명령어
현재 상태 확인timedatectl
한국 시간대 설정timedatectl set-timezone Asia/Seoul
NTP 활성화timedatectl set-ntp true
동기화 서버 확인chronyc sources -v
오프셋 확인chronyc tracking
즉시 시계 보정chronyc makestep
설정 파일/etc/chrony.conf

명령어·단축키 빠른 참조

이 모듈에서 다룬 시간 동기화 명령을 실전 옵션과 함께 모았습니다. 상태 확인 → 소스 점검 → 보정 순서로 쓰면 됩니다.

명령어/단축키용도자주 쓰는 예
timedatectl시간·시간대·NTP 동기화 상태 한눈에timedatectlSystem clock synchronized: yes 확인
timedatectl set-timezone시스템 시간대 영구 변경sudo timedatectl set-timezone Asia/Seoul
timedatectl set-ntpNTP 자동 동기화 켜기/끄기sudo timedatectl set-ntp true (수동 설정은 false)
chronyc sources -v타임서버 목록·선택 상태 확인chronyc sources -v^* 마크가 현재 동기화 소스
chronyc trackingNTP 기준 대비 현재 오차(offset) 확인chronyc tracking | grep "System time"
chronyc makestep큰 오차를 즉시 강제 보정sudo chronyc makestep (VM 마이그레이션 후)
systemctl restart chronydchrony 데몬 재시작sudo systemctl restart chronyd (설정 변경 후)
systemctl disable --now systemd-timesyncd충돌 데몬 정지(데몬 1개 원칙)sudo systemctl disable --now systemd-timesyncd
hwclock하드웨어(RTC) 시계 읽기·저장sudo hwclock --systohc (시스템→HW 저장)
date현재 시각 확인·포맷 출력date -u (UTC) / date +%s (Unix 타임스탬프)
nc -uzv <서버> 123UDP 123 포트 도달 여부 테스트nc -uzv pool.ntp.org 123
journalctl -u chronydchrony 로그 실시간 추적sudo journalctl -u chronyd -f

관련 모듈로 더 깊이:

다음 모듈에서는 OS 하드닝을 통해 SSH 설정, 계정 보안, fail2ban으로 브루트포스를 차단하는 리눅스 보안 체크리스트를 다룹니다.

지식 확인

퀴즈 — 10문제

Q1

`timedatectl status` 출력에서 'NTP synchronized: yes'가 표시되지 않을 때 가장 먼저 확인해야 할 명령어는?

Q2

분산 서비스에서 두 서버의 시간이 500밀리초 이상 벌어지기 시작했습니다. 이 상황에서 발생할 수 있는 실질적인 장애는?

Q3

`timedatectl status`에서 'NTP synchronized: yes'가 뜨는데 실제 시간이 여전히 수 초 벗어나 있습니다. chrony를 통해 현재 오차가 얼마인지 정확히 확인하는 명령과 확인해야 할 항목은?

Q4

NTP로 시스템 시계를 동기화한 뒤, 서버 재부팅 시 시간이 다시 틀어지는 현상이 발생했습니다. 하드웨어 RTC가 이전 값을 유지하고 있기 때문입니다. 이를 해결하는 명령은?

Q5

한국 기반 서비스를 위해 서버를 구성하는데, `date` 명령에 UTC가 출력됩니다. 모든 서비스 로그가 KST(UTC+9)로 찍히도록 타임존을 영구 변경하는 올바른 명령은?

Q6

NTP의 'Stratum' 계층 구조에서 stratum 번호가 의미하는 것은?

Q7

[심화] NTP 클라이언트에 시간 서버를 최소 3~4개 지정하라고 권장하는 이유는?

Q8

[심화] 여러 서버가 NTP synchronized: yes인데도 다 함께 시각이 틀어졌다. chronyc sources를 봤더니 참조 소스가 사내 서버 하나뿐이다. 이 상황의 핵심 문제는?

Q9

[1급] chrony는 기본적으로 작은 시각 오차는 서서히 보정(slew)하고 큰 오차만 즉시 점프(step)한다. 부팅 초기 큰 오차를 빠르게 잡으려고 chrony.conf에 `makestep 1.0 3`을 넣었다. 이 지시어의 의미는?

Q10

[1급] chrony.conf의 `pool 2.pool.ntp.org iburst`에서 `iburst` 옵션이 하는 일로 옳은 것은?

0 / 10 답변

🧪 실습으로 확인하기

새 서버 인수인계 — 처음 30분

초급

낯선 Linux 서버를 인수받았을 때 OS, 서비스, 로그를 빠르게 파악하는 루틴을 직접 수행한다.

30📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요