제품에 사용되는 ntp 클라이언트를 모르고 시스템 시간이 NTP 서버에 동기화되었는지 확인하는 방법은 무엇입니까?

제품에 사용되는 ntp 클라이언트를 모르고 시스템 시간이 NTP 서버에 동기화되었는지 확인하는 방법은 무엇입니까?

제품에 사용되는 NTP 클라이언트를 모르고 시스템 시간이 NTP 서버에 동기화되었는지 확인하는 방법은 무엇입니까? 컨테이너 또는 독립 실행형 시스템 모두에서 실행될 것으로 예상되는 애플리케이션을 개발 중입니다. 내 응용 프로그램에는 특정 작업을 수행하기 전에 시스템 시간이 동기화되었는지 확인해야 하는 요구 사항이 있습니다. 그러나 NTP/chrony 패키지의 가용성은 호스트 OS에서 하나 또는 다른 NTP 클라이언트가 사용되더라도 컨테이너에서 사용 가능하다고 보장할 수 없습니다.

그렇다면 시스템 시간이 동기화되었는지 여부를 알 수 있는 통일된 방법을 찾고 있습니까?

답변1

범용 컴퓨팅의 애플리케이션은 실행 중인 호스트에서 시간 동기화가 작동하는 방식을 모든 경우에 알 수 없습니다. 컨테이너에서는 호스트에서 실행 중인 chronyd 또는 ntpd를 볼 수 없고 연결할 수 없지만 시간은 잘 유지됩니다. 또는 호스트 시간 동기화에 의존하는 VM 게스트도 표시되지 않습니다. 일반적인 대답을 더욱 어렵게 만드는 것은 생각보다 NTP 구현이 더 많다는 것입니다: chrony, ntp, ntpsec, openntpd, w32tm.

정확한 시간의 중요성을 문서화하는 것만으로도 충분할 때가 많습니다.

일부 플랫폼에서는 ntpd 시작에 대한 종속성을 만드는 것이 비교적 간단합니다. RHEL에서는시간 동기화를 기다려 systemctl enable chrony-wait시스템 장치에 추가하십시오.

After=time-sync.target
Requires=time-sync.target

그러나 엄격한 시간 요구 사항을 적용하는 애플리케이션이 있습니다. 제가 생각할 수 있는 가장 까다로운 것은 타임 스탬프 권한입니다.청구 표준 중 하나가 1초 미만의 상쇄를 요구하거나 아무 것도 발행될 수 없는 경우. 이러한 공격적인 응답은 애플리케이션이 자체 시간 확인을 수행함을 의미합니다.

아마도 구성 가능한 NTP 서버에 대해 애플리케이션의 NTP 오프셋을 확인하는 SNTP 클라이언트를 번들로 묶을 수도 있습니다. 적절한 ntpd 실행을 확인할 수 없지만 호스트에 대한 시간 동기화 작동 방식에 관계없이 온전성 검사 오프셋은 가능합니다.

답변2

이를 수행하는 방법에는 두 가지가 있습니다.

실행 중인 컨테이너에 전체 시스템 구현이 있는 경우 프로그램 timedatectl은 호스트가 동기화되었는지 여부를 알려줄 수 있습니다.

이것이 내부적으로 관리되는 방식은 systemd-timedated데몬과 통신하는 dbus를 통해 이루어집니다. 수행 중인 작업은 시스템 호출을 수행하는 것입니다. adjtimex이 호출에서 수행 중인 커널 조정(있는 경우)의 현재 상태를 나타내는 데이터를 다시 가져올 수 있습니다.

따라서 전체 구현 없이 이를 직접 수행하는 두 번째 방법은 adjtimex()시스템 호출을 사용하는 것입니다.

커널은 시간 보고에서 시간 점프(또는 시간이 거꾸로 이동하는 경우)를 원하지 않습니다. 따라서 몇 시간에 걸쳐 시스템 시간을 수정하는 시간 왜곡을 구현합니다(완료됨). 조정이 완료될 때까지 초당 몇 밀리초를 추가하거나 지연하여)

시스템 adjtimex호출은 일반적으로 NTP 시스템에서 시계가 직면하고 있는 현재 스큐를 변경하여 실제 시계 소스와 올바르게 동기화하도록 사용됩니다.하지만또한 클록 소스 왜곡의 현재 상태를 가져오는 데 사용할 수도 있습니다. 따라서 어떤 동기화가 수행되고 있는지(있는 경우) 커널 아이디어를 엿볼 수 있는 기능을 제공합니다.

매뉴얼 페이지는 adjtimex귀하가 요청한 내용과 관련된 몇 가지 흥미로운 부분을 제공합니다.

       The  buf.status  field  is a bit mask that is used to set and/or retrieve status bits associated with the NTP implementation.  Some bits in the mask
       are both readable and settable, while others are read-only.
...
       STA_UNSYNC (read-write)
              Clock unsynchronized.

그리고

RETURN VALUE
       On success, adjtimex() and ntp_adjtime() return the clock state; that is, one of the following values:
...
       TIME_ERROR  The system clock is not synchronized to a reliable server.  This value is returned when any of the following holds true:

                   *  Either STA_UNSYNC or STA_CLOCKERR is set.

                   *  STA_PPSSIGNAL is clear and either STA_PPSFREQ or STA_PPSTIME is set.

                   *  STA_PPSTIME and STA_PPSJITTER are both set.

                   *  STA_PPSFREQ is set and either STA_PPSWANDER or STA_PPSJITTER is set.

                   The symbolic name TIME_BAD is a synonym for TIME_ERROR, provided for backward compatibility.

따라서 완전한 기능을 갖춘 컨테이너가 없어도 이 데이터를 얻을 수 있습니다. 나는 C를 통해 커널 왜곡 상태를 가져오는 간단한 프로그램을 작성했습니다 adjtimex. 예를 들어 컴파일할 수 있습니다.gcc -o timex timex.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#include <sys/timex.h>

/* Written for https://serverfault.com/questions/1077601/how-to-check-whether-the-system-time-is-synchronised-to-ntp-server-without-knowi */

void test_status(
    int st) 
{
  if (st & STA_PLL)
    printf("Phase locked loop\n");
  if (st & STA_PPSFREQ)
    printf("Pulse per second frequency discipline\n");
  if (st & STA_FLL)
    printf("PPS Time discipline\n");
  if (st & STA_INS)
    printf("Insert leap second and end-of-day\n");
  if (st & STA_DEL)
    printf("Delete leap second and end-of-day\n");
  if (st & STA_UNSYNC)
    printf("Clock is not syncronized\n");
  if (st & STA_FREQHOLD)
    printf("Hold frequency\n");
  if (st & STA_PPSSIGNAL)
    printf("Valid PPS signal is present\n");
  if (st & STA_PPSJITTER)
    printf("PPS signal jitter exceeded\n");
  if (st & STA_PPSWANDER)
    printf("PPS Signal wander exceeded\n");
  if (st & STA_PPSERROR)
    printf("PPS signal calibration error\n");
  if (st & STA_CLOCKERR)
    printf("Clock hardware fault\n");

  if (st & STA_NANO)
    printf("Nanosecond resolution\n");
  else
    printf("Microsecond resolution\n");

  if (st & STA_MODE)
    printf("Frequency locked loop\n");
  else
    printf("Phase locked loop\n");
}

int main() {
  struct timex tx = {};
  tx.modes = ADJ_OFFSET_SS_READ;
  int err = adjtimex(&tx);

  switch(err) {
    case -1:
      printf("Time error: %s\n", strerror(errno));
    break;

    case TIME_WAIT:
      printf("Leap second insert/delete completed\n");
    break;

    case TIME_INS:
      printf("Leap second to be added next UTC day\n");
    break;

    case TIME_DEL:
      printf("Leap second to be deleted next UTC day\n");
    break;

    case TIME_OOP:
      printf("Leap second insertion in progress\n");
    break;

    case TIME_ERROR:
      printf("Error getting time\n");
    break;

    case TIME_OK:
      printf("Time OK\n");
    break;

    default:
      printf("Time default: %x (%d)\n", err, err);
    break;
  }

  test_status(tx.status);
  exit(0);
}

동기화되지 않은 시스템에서 실행 중:

$ ./timex 
Error getting time
Clock is not syncronized
Microsecond resolution
Phase locked loop

동기화되지 않은 동일한 호스트의 컨테이너에서 실행:

# podman run -v /tmp/timex/timex:/timex  docker.io/gammabytehosting/rockylinux /timex
Error getting time
Clock is not syncronized
Microsecond resolution
Phase locked loop

동기화할 호스트 시스템의 시간 설정:

# systemctl start chronyd
# chronyc sources
210 Number of sources = 9
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* _gateway            2   6     7     1  +5568ns[ -720ms] +/-   32ms
# ./timex 
Time OK
Microsecond resolution
Phase locked loop

동일한 호스트의 컨테이너에서 동일한 프로그래밍 방식 검사 수행:

# podman run -v /tmp/timex/timex:/timex  docker.io/gammabytehosting/rockylinux /timex
Time OK
Microsecond resolution
Phase locked loop

adjtimex시간 네임스페이스에는 잠재적으로 몇 가지 문제가 있을 수 있습니다 . 별도의 컨텍스트(참조)에서 다르거나 존중되는지 확인하기 위해 테스트하지 않았지만(실제로는 매우 새롭지만) man 7 time_namespaces제가 읽은 내용에 따르면 여전히 작동할 것입니다. - 그건 당신이 결정하도록 맡기겠습니다.

답변3

시스템 시간이 NTP 서버와 동기화되었는지 확인하는 방법은 무엇입니까?

없습니다.

내 애플리케이션에는 특정 작업을 수행하기 전에 시스템 시간이 동기화되었는지 확인해야 하는 요구 사항이 있습니다.

실행할 올바른 환경을 설정하는 것은 응용 프로그램의 책임이 아니며 시스템과 해당 관리자의 책임입니다.

애플리케이션은 시스템에서 반환된 날짜/시간에 의존합니다. 그 시간이 아니면"옳은"또는"잘못된"; 응용프로그램은 일반적으로 이를 알 수 있는 방법이 없습니다. 단순히 해당 시스템 날짜/시간을 사용합니다.

클라이언트-서버 모델이 있는 경우 (극단적인) 날짜/시간 오프셋으로 인해 트랜잭션이 거부될 때마다 유용한 오류 메시지를 제공하는 것이 좋습니다.
이러한 오프셋이 존재한다고 해서 클라이언트가 잘못된 시계에 있는지, 서버에 있는지, 아니면 둘 다에 있는지 알 수는 없습니다.

관련 정보