

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 로깅
<a name="windows-logging"></a>

컨테이너화된 애플리케이션은 일반적으로 애플리케이션 로그를 STDOUT으로 전달합니다. 컨테이너 런타임은 이러한 로그를 트래핑하고 이를 사용하여 일반적으로 파일에 씁니다. 이러한 파일이 저장되는 위치는 컨테이너 런타임 및 구성에 따라 달라집니다.

Windows 포드의 한 가지 근본적인 차이점은 STDOUT을 생성하지 않는다는 것입니다. [LogMonitor](https://github.com/microsoft/windows-container-tools/tree/master/LogMonitor)를 실행하여 실행 중인 Windows 컨테이너 및 파이프 형식의 로그 출력에서 STDOUT으로 ETW(Windows용 이벤트 추적), Windows 이벤트 로그 및 기타 애플리케이션별 로그를 검색할 수 있습니다. 그런 다음 fluent-bit를 사용하여 이러한 로그를 스트리밍하거나 Amazon CloudWatch와 같은 원하는 대상으로 유창하게 스트리밍할 수 있습니다.

로그 수집 메커니즘은 Kubernetes 포드에서 STDOUT/STDERR 로그를 검색합니다. [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)는 컨테이너에서 로그를 수집하는 일반적인 방법입니다. 애플리케이션과 독립적으로 로그 routing/filtering/enrichment을 관리할 수 있습니다. fluentd DaemonSet를 사용하여 이러한 로그와 기타 애플리케이션에서 생성한 로그를 원하는 로그 집계자로 스트리밍할 수 있습니다.

Windows 워크로드에서 CloudWatch로의 로그 스트리밍에 대한 자세한 내용은 [여기에서](https://aws.amazon.com/blogs/containers/streaming-logs-from-amazon-eks-windows-pods-to-amazon-cloudwatch-logs-using-fluentd/) 설명합니다.

## 로깅 권장 사항
<a name="_logging_recomendations"></a>

Kubernetes에서 Windows 워크로드를 운영할 때 일반적인 로깅 모범 사례는 다르지 않습니다.
+ 이러한 **구조화된** 형식에 대해 미리 작성된 파서가 많기 때문에 로그 항목을 더 쉽게 처리할 수 있도록 항상 구조화된 로그 항목(JSON/SYSLOG)을 로깅합니다.
+  로그 **중앙 집중화** - 전용 로깅 컨테이너를 사용하여 모든 컨테이너에서 대상으로 로그 메시지를 수집하고 전달할 수 있습니다.
+ 디버깅할 때**를 제외하고 로그 세부 정보를** 낮게 유지합니다. 세부 정보는 로깅 인프라에 많은 스트레스를 주며 노이즈에서 중요한 이벤트가 손실될 수 있습니다.
+ 추적성을 위해 항상 **트랜잭션/요청 ID**와 함께 **애플리케이션 정보를** 기록합니다. Kubernetes 객체는 애플리케이션 이름을 포함하지 않으므로 예를 들어 포드 이름은 로그를 디버깅할 때 의미를 갖지 않을 `windows-twryrqyw` 수 있습니다. 이렇게 하면 집계된 로그를 사용하여 애플리케이션을 추적하고 문제를 해결하는 데 도움이 됩니다.

  이러한 트랜잭션/상관성 ID를 생성하는 방법은 프로그래밍 구성에 따라 다릅니다. 그러나 매우 일반적인 패턴은 다음과 같이 [MDC](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html)(매핑된 진단 컨텍스트)를 사용하여 모든 수신 요청에 고유한 트랜잭션/상관성 ID를 주입할 수 있는 로깅 Aspect/Interceptor를 사용하는 것입니다.

```
import org.slf4j.MDC;
import java.util.UUID;
Class LoggingAspect { //interceptor

    @Before(value = "execution(* *.*(..))")
    func before(...) {
        transactionId = generateTransactionId();
        MDC.put(CORRELATION_ID, transactionId);
    }

    func generateTransactionId() {
        return UUID.randomUUID().toString();
    }
}
```