

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

# Windows 모범 사례
<a name="windows"></a>

이 가이드에서는 Windows 컨테이너 및 노드 실행에 대한 조언을 제공합니다.

**Topics**
+ [Amazon EKS 최적화 Windows AMI 관리](windows-ami.md)
+ [Windows 포드 및 컨테이너용 gMSA 구성](windows-gmsa.md)
+ [Windows 작업자 노드 강화](windows-hardening.md)
+ [컨테이너 이미지 스캔](windows-images.md)
+ [Windows Server 버전 및 라이선스](windows-licensing.md)
+ [로깅](windows-logging.md)
+ [모니터링](windows-monitoring.md)
+ [Windows 네트워킹](windows-networking.md)
+ [OOM 오류 방지](windows-oom.md)
+ [Windows Server 및 컨테이너 패치 적용](windows-patching.md)
+ [이기종 워크로드 실행](windows-scheduling.md)
+ [포드 보안 컨텍스트](windows-security.md)
+ [영구 스토리지 옵션](windows-storage.md)
+ [Windows 컨테이너 이미지 강화](windows-hardening-containers-images.md)

# Amazon EKS 최적화 Windows AMI 관리
<a name="windows-ami"></a>

Windows Amazon EKS 최적화 AMI는 Windows Server 2019 및 Windows Server 2022를 기반으로 빌드되었습니다. Amazon EKS 노드의 기본 이미지 역할을 하도록 구성되었습니다. 기본적으로 AMI에는 다음 구성 요소가 포함됩니다.
+  [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) 
+  [kube-proxy](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/) 
+  [Kubernetes용 AWS IAM Authenticator ](https://github.com/kubernetes-sigs/aws-iam-authenticator) 
+  [csi-proxy](https://github.com/kubernetes-csi/csi-proxy) 
+  [containerd](https://containerd.io/) 

AWS Systems Manager Parameter Store API를 쿼리하여 Amazon EKS 최적화 AMIs) ID를 프로그래밍 방식으로 검색할 수 있습니다. 이 파라미터를 사용하면 Amazon EKS 최적화 AMI ID를 수동으로 조회할 필요가 없습니다. Systems Manager 파라미터 스토어 API에 대한 자세한 내용은 [GetParameter](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetParameter.html) 섹션을 참조하세요. Amazon EKS 최적화 AMI 메타데이터를 검색하려면 사용자 계정에 ssm:GetParameter IAM 권한이 있어야 합니다.

다음 예시에서는 Windows Server 2019 LTSC Core용 최신 Amazon EKS 최적화 AMI의 AMI ID를 검색합니다. AMI 이름에 나열된 버전 번호는 준비된 해당 Kubernetes 빌드와 관련이 있습니다.

```
aws ssm get-parameter --name /aws/service/ami-windows-latest/Windows_Server-2019-English-Core-EKS_Optimized-1.21/image_id --region us-east-1 --query "Parameter.Value" --output text
```

출력 예시:

```
ami-09770b3eec4552d4e
```

## 자체 Amazon EKS 최적화 Windows AMI 관리
<a name="_managing_your_own_amazon_eks_optimized_windows_ami"></a>

프로덕션 환경을 위한 필수 단계는 Amazon EKS 클러스터에서 동일한 Amazon EKS 최적화 Windows AMI 및 kubelet 버전을 유지하는 것입니다.

Amazon EKS 클러스터에서 동일한 버전을 사용하면 문제 해결 시간이 단축되고 클러스터 일관성이 향상됩니다. [Amazon EC2 Image Builder](https://aws.amazon.com/image-builder/)는 Amazon EKS 클러스터에서 사용할 사용자 지정 Amazon EKS 최적화 Windows AMIs를 생성하고 유지 관리하는 데 도움이 됩니다.

Amazon EC2 Image Builder를 사용하여 Windows Server 버전, AWS Windows Server AMI 릴리스 날짜 및/또는 OS 빌드 버전 중에서 선택합니다. 빌드 구성 요소 단계에서는 기존 EKS 최적화 Windows 아티팩트와 kubelet 버전 중에서 선택할 수 있습니다. 자세한 내용은 https://docs.aws.amazon.com/eks/latest/userguide/eks-custom-ami-windows.html 참조하십시오.

![\[빌드 구성 요소\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/build-components.png)


 **참고:** 기본 이미지를 선택하기 전에 릴리스 채널 업데이트와 관련된 중요한 세부 정보는 [Windows Server 버전 및 라이선스](windows-licensing.md) 섹션을 참조하세요.

## 사용자 지정 EKS 최적화 AMIs 대한 더 빠른 시작 구성
<a name="_configuring_faster_launching_for_custom_eks_optimized_amis"></a>

사용자 지정 Windows Amazon EKS 최적화 AMI를 사용하는 경우 빠른 시작 기능을 활성화하여 Windows 작업자 노드를 최대 65% 더 빠르게 시작할 수 있습니다. 이 기능은 *Sysprep 전문,* *OOBE(Windows Out of Box Experience)* 단계 및 필요한 재부팅이 이미 완료된 사전 프로비저닝된 스냅샷 세트를 유지합니다. 그런 다음 이러한 스냅샷은 후속 시작 시 사용되므로 노드를 스케일 아웃하거나 교체하는 데 걸리는 시간이 줄어듭니다. 빠른 시작은 EC2 콘솔 또는 AWS CLI를 통해 *소유*AMIs에 대해서만 활성화할 수 있으며 유지 관리되는 스냅샷 수는 구성할 수 있습니다.

 **참고:** Fast Launch는 기본 Amazon 제공 EKS 최적화 AMI와 호환되지 않으므로 활성화하기 전에 위와 같이 사용자 지정 AMI를 생성합니다.

자세한 내용: [AWS Windows AMIs- 더 빠른 시작을 위해 AMI 구성](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/windows-ami-version-history.html#win-ami-config-fast-launch) 

## 사용자 지정 AMIs에서 Windows 기본 계층 캐싱
<a name="_caching_windows_base_layers_on_custom_amis"></a>

Windows 컨테이너 이미지는 Linux 컨테이너 이미지보다 큽니다. 컨테이너화된 .NET Framework 기반 애플리케이션을 실행하는 경우 평균 이미지 크기는 약 8.24GB입니다. 포드 예약 중에 포드가 실행 중 상태에 도달하기 전에 컨테이너 이미지를 완전히 가져와 디스크에서 추출해야 합니다.

이 프로세스 중에 컨테이너 런타임(컨테이너드)은 디스크에서 전체 컨테이너 이미지를 가져와 추출합니다. 풀 작업은 병렬 프로세스입니다. 즉, 컨테이너 런타임은 컨테이너 이미지 계층을 병렬로 가져옵니다. 반대로 추출 작업은 순차적 프로세스에서 수행되며 I/O 집약적입니다. 따라서 컨테이너 이미지를 완전히 추출하고 컨테이너 런타임(컨테이너드)에서 사용할 준비가 되는 데 8분 이상 걸릴 수 있으므로 포드 시작 시간이 몇 분 정도 걸릴 수 있습니다.

**Windows Server 및 컨테이너 패치 적용** 주제에서 언급했듯이 EKS를 사용하여 사용자 지정 AMI를 빌드하는 옵션이 있습니다. AMI 준비 중에 EC2 Image 빌더 구성 요소를 추가하여 필요한 모든 Windows 컨테이너 이미지를 로컬에서 가져온 다음 AMI를 생성할 수 있습니다. 이 전략은 포드가 **실행** 중 상태에 도달하는 시간을 크게 줄입니다.

Amazon EC2 Image Builder에서 구성 [요소를](https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html) 생성하여 필요한 이미지를 다운로드하고 이미지 레시피에 연결합니다. 다음 예시에서는 ECR 리포지토리에서 특정 이미지를 가져옵니다.

```
name: ContainerdPull
description: This component pulls the necessary containers images for a cache strategy.
schemaVersion: 1.0

phases:
  - name: build
    steps:
      - name: containerdpull
        action: ExecutePowerShell
        inputs:
          commands:
            - Set-ExecutionPolicy Unrestricted -Force
            - (Get-ECRLoginCommand).Password | docker login --username AWS --password-stdin 111000111000.dkr.ecr.us-east-1.amazonaws.com
            - ctr image pull mcr.microsoft.com/dotnet/framework/aspnet:latest
            - ctr image pull 111000111000.dkr.ecr.us-east-1.amazonaws.com/myappcontainerimage:latest
```

다음 구성 요소가 예상대로 작동하는지 확인하려면 EC2 Image 빌더(EC2InstanceProfileForImageBuilder)에서 사용하는 IAM 역할에 연결된 정책이 있는지 확인합니다.

![\[권한 정책\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/permissions-policies.png)


## 블로그 게시물
<a name="_blog_post"></a>

다음 블로그 게시물에서는 사용자 지정 Amazon EKS Windows AMIs에 캐싱 전략을 구현하는 방법에 대해 단계별로 설명합니다.

 [EC2 이미지 빌더 및 이미지 캐시 전략을 사용하여 Windows 컨테이너 시작 시간 단축](https://aws.amazon.com/blogs/containers/speeding-up-windows-container-launch-times-with-ec2-image-builder-and-image-cache-strategy/) 

# Windows 포드 및 컨테이너용 gMSA 구성
<a name="windows-gmsa"></a>

## gMSA 계정이란?
<a name="_what_is_a_gmsa_account"></a>

.NET 애플리케이션과 같은 Windows 기반 애플리케이션은 종종 Active Directory를 자격 증명 공급자로 사용하여 NTLM 또는 Kerberos 프로토콜을 사용하여 권한 부여/인증을 제공합니다.

Kerberos 티켓을 Active Directory와 교환하는 애플리케이션 서버는 도메인에 조인되어야 합니다. Windows 컨테이너는 도메인 조인을 지원하지 않으며 컨테이너가 임시 리소스이기 때문에 Active Directory RID 풀에 부담을 주지 않습니다.

그러나 관리자는 [gMSA Active Directory](https://docs.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/group-managed-service-accounts-overview) 계정을 활용하여 Windows 컨테이너, NLB 및 서버 팜과 같은 리소스에 대한 Windows 인증을 협상할 수 있습니다.

## Windows 컨테이너 및 gMSA 사용 사례
<a name="_windows_container_and_gmsa_use_case"></a>

Windows 인증을 활용하고 Windows 컨테이너로 실행되는 애플리케이션은 Windows 노드가 컨테이너를 대신하여 Kerberos 티켓을 교환하는 데 사용되므로 gMSA의 이점을 누릴 수 있습니다. gMSA 통합을 지원하도록 Windows 작업자 노드를 설정하는 데 사용할 수 있는 두 가지 옵션이 있습니다.

이 설정에서 Windows 작업자 노드는 Active Directory 도메인에 도메인 조인되며, Windows 작업자 노드의 AD 컴퓨터 계정은 Active Directory에 대해 인증하고 포드에 사용할 gMSA 자격 증명을 검색하는 데 사용됩니다.

도메인 조인 접근 방식에서는 기존 Active Directory GPOs를 사용하여 Windows 작업자 노드를 쉽게 관리하고 강화할 수 있지만, Kubernetes 클러스터에서 Windows 작업자 노드에 조인하는 동안 추가 운영 오버헤드와 지연이 발생합니다. Kubernetes 클러스터가 노드를 종료한 후 노드 시작 및 Active Directory 차고 정리 중에 추가 재부팅이 필요하기 때문입니다.

다음 블로그 게시물에서는 도메인에 조인된 Windows 작업자 노드 접근 방식을 구현하는 방법에 대한 step-by-step 내용을 확인할 수 있습니다.

 [Amazon EKS Windows 포드의 Windows 인증](https://aws.amazon.com/blogs/containers/windows-authentication-on-amazon-eks-windows-pods/) 

이 설정에서 Windows 작업자 노드는 Active Directory 도메인에 조인되지 않으며, "휴대용" 자격 증명(사용자/암호)은 Active Directory에 대해 인증하고 포드에 사용할 gMSA 자격 증명을 검색하는 데 사용됩니다.

![\[도메인 없는 gmsa\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/domainless_gmsa.png)


휴대용 자격 증명은 Active Directory 사용자입니다. 자격 증명(사용자/암호)은 AWS Secrets Manager 또는 AWS System Manager Parameter Store에 저장되며, ccg\$1plugin이라는 AWS에서 개발한 플러그인을 사용하여 AWS Secrets Manager 또는 AWS System Manager Parameter Store에서이 자격 증명을 검색하고 컨테이너로 전달하여 gMSA 자격 증명을 검색하고 포드에 사용할 수 있도록 합니다.

이 도메인 없는 접근 방식에서는 gMSA를 사용하고 Active Directory 관리자의 운영 오버헤드를 줄일 때 Windows 작업자 노드 시작 중에 Active Directory 상호 작용이 없는 이점을 누릴 수 있습니다.

다음 블로그 게시물에서는 Domainless Windows 작업자 노드 접근 방식을 구현하는 방법에 대한 step-by-step 내용을 확인할 수 있습니다.

 [Amazon EKS Windows 포드에 대한 도메인 없는 Windows 인증](https://aws.amazon.com/blogs/containers/domainless-windows-authentication-for-amazon-eks-windows-pods/) 

포드가 gMSA 계정을 사용할 수 있더라도 Windows 인증을 지원하도록 애플리케이션 또는 서비스를 적절히 설정해야 합니다. 예를 들어 Windows 인증을 지원하도록 Microsoft IIS를 설정하려면 dockerfile을 통해 준비해야 합니다.

```
RUN Install-WindowsFeature -Name Web-Windows-Auth -IncludeAllSubFeature
RUN Import-Module WebAdministration; Set-ItemProperty 'IIS:\AppPools\SiteName' -name processModel.identityType -value 2
RUN Import-Module WebAdministration; Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/anonymousAuthentication' -Name Enabled -Value False -PSPath 'IIS:\' -Location 'SiteName'
RUN Import-Module WebAdministration; Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/windowsAuthentication' -Name Enabled -Value True -PSPath 'IIS:\' -Location 'SiteName'
```

# Windows 작업자 노드 강화
<a name="windows-hardening"></a>

OS 강화는 시스템을 잠그고 공격 표면을 줄이는 것을 목표로 하는 불필요한 소프트웨어 패키지의 OS 구성, 패치 적용 및 제거의 조합입니다. 회사에서 요구하는 강화 구성을 사용하여 자체 EKS 최적화 Windows AMI를 준비하는 것이 모범 사례입니다.

AWS는 최신 Windows Server 보안 패치가 포함된 새로운 EKS 최적화 Windows AMI를 매월 제공합니다. 그러나 자체 관리형 또는 관리형 노드 그룹을 사용하는지 여부에 관계없이 필요한 OS 구성을 적용하여 AMI를 강화하는 것은 여전히 사용자의 책임입니다.

Microsoft는 보안 정책 요구 사항에 따라 강화하는 데 도움이 되는 [Microsoft 보안 규정 준수 도구 키트](https://www.microsoft.com/en-us/download/details.aspx?id=55319) 및 보안 [기준](https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-security-baselines)과 같은 다양한 도구를 제공합니다. [CIS 벤치마크](https://learn.cisecurity.org/benchmarks)도 사용할 수 있으며 프로덕션 환경을 위한 Amazon EKS 최적화 Windows AMI를 기반으로 구현해야 합니다.

## Windows Server Core를 사용하여 공격 표면 줄이기
<a name="_reducing_attack_surface_with_windows_server_core"></a>

Windows Server Core는 [EKS 최적화 Windows AMI](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-windows-ami.html)의 일부로 사용할 수 있는 최소 설치 옵션입니다. Windows Server Core 배포에는 몇 가지 이점이 있습니다. 첫째, 디스크 공간이 비교적 작아서 Server Core의 경우 6GB이고 데스크톱 환경이 있는 Windows Server의 경우 10GB입니다. 둘째, 더 작은 코드 베이스와 사용 가능한 APIs.

AWS는 Amazon EKS 지원 버전과 관계없이 최신 Microsoft 보안 패치가 포함된 새로운 Amazon EKS 최적화 Windows AMIs를 고객에게 매월 제공합니다. 모범 사례로 Windows 작업자 노드는 최신 Amazon EKS 최적화 AMI를 기반으로 새 노드로 교체해야 합니다. 업데이트 또는 노드 교체 없이 45일 이상 실행 중인 모든 노드에는 보안 모범 사례가 없습니다.

## RDP 연결 방지
<a name="_avoiding_rdp_connections"></a>

RDP(원격 데스크톱 프로토콜)는 네트워크를 통해 다른 Windows 컴퓨터에 연결할 수 있는 그래픽 인터페이스를 사용자에게 제공하기 위해 Microsoft에서 개발한 연결 프로토콜입니다.

가장 좋은 방법은 Windows 작업자 노드를 임시 호스트인 것처럼 취급하는 것입니다. 즉, 관리 연결, 업데이트 및 문제 해결이 없습니다. 모든 수정 및 업데이트는 새 사용자 지정 AMI로 구현되고 Auto Scaling 그룹을 업데이트하여 대체되어야 합니다. **Windows Server 및 컨테이너 패치 및** **Amazon EKS 최적화 Windows AMI 관리를** 참조하세요.

아래 예제와 같이 ssh 속성에 **false** 값을 전달하여 배포 중에 Windows 노드에서 RDP 연결을 비활성화합니다.

```
nodeGroups:
- name: windows-ng
  instanceType: c5.xlarge
  minSize: 1
  volumeSize: 50
  amiFamily: WindowsServer2019CoreContainer
  ssh:
    allow: false
```

Windows 노드에 액세스해야 하는 경우 [AWS System Manager 세션 관리자](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html)를 사용하여 AWS 콘솔 및 SSM 에이전트를 통해 안전한 PowerShell 세션을 설정합니다. 솔루션을 구현하는 방법을 보려면 [ AWS Systems Manager 세션 관리자를 사용하여 Windows 인스턴스에 안전하게 액세스](https://www.youtube.com/watch?v=nt6NTWQ-h6o)하기 

System Manager Session Manager를 사용하려면 Windows 작업자 노드를 시작하는 데 사용되는 IAM 역할에 추가 IAM 정책을 적용해야 합니다. 다음은 **AmazonSSMManagedInstanceCore**가 `eksctl` 클러스터 매니페스트에 지정되는 예입니다.

```
 nodeGroups:
- name: windows-ng
  instanceType: c5.xlarge
  minSize: 1
  volumeSize: 50
  amiFamily: WindowsServer2019CoreContainer
  ssh:
    allow: false
  iam:
    attachPolicyARNs:
      - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
      - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
      - arn:aws:iam::aws:policy/ElasticLoadBalancingFullAccess
      - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
      - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
```

## Amazon Inspector –
<a name="_amazon_inspector"></a>

 [Amazon Inspector](https://aws.amazon.com/inspector/)는 AWS에 배포된 애플리케이션의 보안 및 규정 준수를 개선하는 데 도움이 되는 자동화된 보안 평가 서비스입니다. Amazon Inspector는 애플리케이션의 노출, 취약성 및 모범 사례와의 편차를 자동으로 평가합니다. 평가를 수행한 후, Amazon Inspector는 상세한 보안 평가 결과 목록을 제공하며, 이 목록은 심각도 수준에 따라 구성되어 있습니다. 이러한 결과는 직접 검토하거나 Amazon Inspector 콘솔 또는 API를 통해 사용할 수 있는 세부 평가 보고서의 일부로 검토할 수 있습니다.

Amazon Inspector는 Windows 작업자 노드에서 CIS 벤치마크 평가를 실행하는 데 사용할 수 있으며 다음 작업을 수행하여 Windows Server Core에 설치할 수 있습니다.

1. .exe 파일을 다운로드합니다. https://inspector-agent.amazonaws.com/windows/installer/latest/AWSAgentInstall.exe

1. 에이전트를 Windows 작업자 노드로 전송합니다.

1. PowerShell에서 다음 명령을 실행하여 Amazon Inspector 에이전트를 설치합니다. `.\AWSAgentInstall.exe /install` 

다음은 첫 번째 실행 후 출력입니다. 보시다시피 [CVE](https://cve.mitre.org/) 데이터베이스를 기반으로 조사 결과를 생성했습니다. 이를 사용하여 작업자 노드를 강화하거나 강화된 구성을 기반으로 AMI를 생성할 수 있습니다.

![\[검사기 에이전트\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/inspector-agent.png)


Amazon Inspector 에이전트를 설치하고, CIS 벤치마크 평가를 설정하고, 보고서를 생성하는 방법을 포함하여 Amazon Inspector에 대한 자세한 내용은 [ Amazon Inspector로 Windows 워크로드의 보안 및 규정 준수 개선 동영상을 참조하세요](https://www.youtube.com/watch?v=nIcwiJ85EKU).

## Amazon GuardDuty
<a name="_amazon_guardduty"></a>

 [Amazon GuardDuty](https://aws.amazon.com/guardduty/)는 악의적인 활동 및 무단 동작을 지속적으로 모니터링하여 Amazon S3에 저장된 AWS 계정, 워크로드 및 데이터를 보호하는 위협 탐지 서비스입니다. 클라우드를 사용하면 계정 및 네트워크 활동의 수집 및 집계가 간소화되지만 보안 팀이 잠재적 위협에 대한 이벤트 로그 데이터를 지속적으로 분석하는 데 시간이 많이 걸릴 수 있습니다.

Amazon GuardDuty를 사용하면 RDP 무차별 대입 및 포트 프로브 공격과 같은 Windows 작업자 노드에 대한 악의적인 활동을 감시할 수 있습니다.

[Amazon GuardDuty를 사용하여 Windows 워크로드에 대한 위협 탐지](https://www.youtube.com/watch?v=ozEML585apQ) 비디오를 보고 최적화된 EKS Windows AMI에서 CIS 벤치마크를 구현하고 실행하는 방법을 알아봅니다.

## Windows용 Amazon EC2의 보안
<a name="_security_in_amazon_ec2_for_windows"></a>

[Amazon EC2 Windows 인스턴스의 보안 모범 사례를](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-security.html) 읽고 모든 계층에서 보안 제어를 구현하세요.

# 컨테이너 이미지 스캔
<a name="windows-images"></a>

이미지 스캔은 애플리케이션 컨테이너 이미지에 광범위한 운영 체제 취약성이 있는지 스캔하여 보안을 개선하는 데 도움이 되는 자동화된 취약성 평가 기능입니다.

현재 Amazon Elastic Container Registry(ECR)는 Linux 컨테이너 이미지의 취약성만 스캔할 수 있습니다. 하지만 Windows 컨테이너 이미지 스캔을 위해 기존 CI/CD 파이프라인과 통합할 수 있는 타사 도구가 있습니다.
+  [앵커](https://anchore.com/blog/scanning-windows-container-images/) 
+  [PaloAlto Prisma 클라우드](https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-admin-compute/vulnerability_management/windows_image_scanning.html) 
+  [Trend Micro - Deep Security Smart Check](https://www.trendmicro.com/en_us/business/products/hybrid-cloud/smart-check-image-scanning.html) 

이러한 솔루션을 Amazon Elastic Container Repository(ECR)와 통합하는 방법에 대해 자세히 알아보려면 다음을 확인하세요.
+  [고정, Amazon Elastic Container Registry(ECR)에서 이미지 스캔](https://anchore.com/blog/scanning-images-on-amazon-elastic-container-registry/) 
+  [PaloAlto, Amazon Elastic Container Registry(ECR)에서 이미지 스캔](https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-admin-compute/vulnerability_management/registry_scanning0/scan_ecr.html) 
+  [TrendMicro, Amazon Elastic Container Registry(ECR)에서 이미지 스캔](https://cloudone.trendmicro.com/docs/container-security/sc-about/) 

# Windows Server 버전 및 라이선스
<a name="windows-licensing"></a>

## Windows Server 버전
<a name="_windows_server_version"></a>

Amazon EKS 최적화 Windows AMI는 장기 서비스 채널(LTSC)의 Windows Server 2019 및 2022 Datacenter 에디션을 기반으로 합니다. 데이터 센터 버전에는 작업자 노드에서 실행되는 컨테이너 수에 대한 제한이 없습니다. 자세한 내용은 https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/faq 참조하십시오.

### 장기 서비스 채널(LTSC)
<a name="_long_term_servicing_channel_ltsc"></a>

이전에는 "장기 서비스 브랜치"라고 했던이 릴리스 모델은 이미 익숙한 릴리스 모델로, 2\$13년마다 새로운 메이저 버전의 Windows Server가 릴리스됩니다. 사용자는 5년간의 메인스트림 지원과 5년간의 추가 지원을 받을 수 있습니다.

## 라이선싱
<a name="_licensing"></a>

Windows Server 기반 AMI를 사용하여 Amazon EC2 인스턴스를 시작할 때 Amazon은 라이선스 비용 및 라이선스 규정 준수를 보장합니다.

# 로깅
<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();
    }
}
```

# 모니터링
<a name="windows-monitoring"></a>

[졸업된 CNCF 프로젝트](https://www.cncf.io/projects/)인 Prometheus는 Kubernetes에 기본적으로 통합되는 가장 인기 있는 모니터링 시스템입니다. Prometheus는 컨테이너, 포드, 노드 및 클러스터에 대한 지표를 수집합니다. 또한 Prometheus는 AlertsManager를 활용하여 클러스터에 문제가 있는 경우 경고를 프로그래밍할 수 있습니다. Prometheus는 지표 데이터를 지표 이름 및 키/값 페어로 식별되는 시계열 데이터로 저장합니다. Prometheus에는 Prometheus 쿼리 언어의 약어인 PromQL이라는 언어를 사용한 원격 쿼리가 포함되어 있습니다.

Prometheus 지표 컬렉션의 상위 수준 아키텍처는 다음과 같습니다.

![\[Prometheus 지표 컬렉션\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/prom.png)


Prometheus는 풀 메커니즘을 사용하고 내보내기를 사용하는 대상과 [kube 상태 지표를 사용하는 Kubernetes API에서 지표](https://github.com/kubernetes/kube-state-metrics)를 스크레이프합니다. 즉, 애플리케이션 및 서비스는 Prometheus 형식의 지표가 포함된 HTTP(S) 엔드포인트를 노출해야 합니다. 그러면 Prometheus는 구성에 따라 이러한 HTTP(S) 엔드포인트에서 지표를 주기적으로 가져옵니다.

내보내기를 사용하면 타사 지표를 Prometheus 형식의 지표로 사용할 수 있습니다. Prometheus 내보내기는 일반적으로 각 노드에 배포됩니다. 내보내기의 전체 목록은 Prometheus [내보내기](https://prometheus.io/docs/instrumenting/exporters/)를 참조하세요. [노드 내보내기](https://github.com/prometheus/node_exporter)는 Linux 노드의 호스트 하드웨어 및 OS 지표를 내보내는 데 적합하지만 Windows 노드에서는 작동하지 않습니다.

안정적인 [Prometheus helm 차트](https://github.com/prometheus-community/helm-charts)를 사용하는 경우 **Windows 노드가 있는 혼합 노드 EKS 클러스터**에서이 내보내기는 Windows용이 아니므로 Windows 노드에 실패한 포드가 표시됩니다. Windows 작업자 풀을 별도로 처리하고 대신 Windows 작업자 노드 그룹에 Windows [Exporter](https://github.com/prometheus-community/windows_exporter)를 설치해야 합니다.

Windows 노드에 대한 Prometheus 모니터링을 설정하려면 Windows 서버 자체에 WMI 내보내기를 다운로드하여 설치한 다음 Prometheus 구성 파일의 스크레이프 구성 내에 대상을 설정해야 합니다. [릴리스 페이지에서](https://github.com/prometheus-community/windows_exporter/releases)는 사용 가능한 모든 .msi 설치 프로그램과 각 기능 세트 및 버그 수정을 제공합니다. 설치 관리자는 Windows\$1exporter를 Windows 서비스로 설정하고 Windows 방화벽에서 예외를 생성합니다. 설치 관리자가 파라미터 없이 실행되는 경우, 활성화된 수집기, 포트 등에 대한 기본 설정으로 내보내기가 실행됩니다.

노드를 부트스트랩하거나 원하는 구성 관리 도구(예: Chef, Ansible, SSM 등)를 사용하여 Windows 노드에 Windows Exporter를 설치하는 동안 taints/tolerations 또는 RuntimeClass를 사용하여 linux 노드에만 선택적으로 배포하는 것을 제안하는이 가이드의 **예약 모범 사례** 섹션을 확인할 수 있습니다.

노드 내보내기가 데몬 세트 로 설치된 Linux 노드와 달리 Windows 노드에서는 WMI 내보내기가 호스트 자체에 설치됩니다. 내보내기 도구는 CPU 사용량, 메모리 및 디스크 I/O 사용량과 같은 지표를 내보내고 IIS 사이트 및 애플리케이션, 네트워크 인터페이스 및 서비스를 모니터링하는 데 사용할 수도 있습니다.

windows\$1exporter는 기본적으로 활성화된 수집기의 모든 지표를 노출합니다. 이는 오류를 방지하기 위해 지표를 수집하는 권장 방법입니다. 그러나 고급 사용의 경우 windows\$1exporter에 지표를 필터링하기 위한 선택적 수집기 목록을 전달할 수 있습니다. Prometheus 구성에서 collect[] 파라미터를 사용하면 됩니다.

Windows의 기본 설치 단계에는 필터링하려는 수집기와 같은 인수를 사용하여 부트스트래핑 프로세스 중에 서비스로 내보내기를 다운로드하고 시작하는 작업이 포함됩니다.

```
> Powershell Invoke-WebRequest https://github.com/prometheus-community/windows_exporter/releases/download/v0.13.0/windows_exporter-0.13.0-amd64.msi -OutFile <DOWNLOADPATH>

> msiexec /i <DOWNLOADPATH> ENABLED_COLLECTORS="cpu,cs,logical_disk,net,os,system,container,memory"
```

기본적으로 포트 9182의 /metrics 엔드포인트에서 지표를 스크레이프할 수 있습니다. 이때 Prometheus는 Prometheus 구성에 다음 scrape\$1config를 추가하여 지표를 사용할 수 있습니다.

```
scrape_configs:
    - job_name: "prometheus"
      static_configs:
        - targets: ['localhost:9090']
    ...
    - job_name: "wmi_exporter"
      scrape_interval: 10s
      static_configs:
        - targets: ['<windows-node1-ip>:9182', '<windows-node2-ip>:9182', ...]
```

를 사용하여 Prometheus 구성이 다시 로드됩니다.

```
> ps aux | grep prometheus
> kill HUP <PID>
```

대상을 추가하는 더 나은 권장 방법은 ServiceMonitor 객체에 대한 정의를 제공하고 필요한 [Prometheus 구성을 자동으로 빌드하는 컨트롤러와 ServiceMonitor 연산](https://github.com/prometheus-operator/kube-prometheus/releases)자]라는 사용자 지정 리소스 정의를 사용하는 것입니다. ServiceMonitor ServiceMonitors 

Kubernetes 서비스 그룹을 모니터링하는 방법을 선언적으로 지정하는 ServiceMonitor는 Kubernetes 내에서 지표를 스크레이프하려는 애플리케이션을 정의하는 데 사용됩니다. ServiceMonitor 내에서 운영자가 Kubernetes 서비스를 식별하는 데 사용할 수 있는 Kubernetes 레이블을 지정합니다. 그러면 모니터링하려는 포드가 식별됩니다.

ServiceMonitor를 활용하려면 특정 Windows 대상, 헤드리스 서비스 및 Windows 노드용 ServiceMontor를 가리키는 엔드포인트 객체를 생성합니다.

```
apiVersion: v1
kind: Endpoints
metadata:
  labels:
    k8s-app: wmiexporter
  name: wmiexporter
  namespace: kube-system
subsets:
- addresses:
  - ip: NODE-ONE-IP
    targetRef:
      kind: Node
      name: NODE-ONE-NAME
  - ip: NODE-TWO-IP
    targetRef:
      kind: Node
      name: NODE-TWO-NAME
  - ip: NODE-THREE-IP
    targetRef:
      kind: Node
      name: NODE-THREE-NAME
  ports:
  - name: http-metrics
    port: 9182
    protocol: TCP

---
apiVersion: v1
kind: Service ##Headless Service
metadata:
  labels:
    k8s-app: wmiexporter
  name: wmiexporter
  namespace: kube-system
spec:
  clusterIP: None
  ports:
  - name: http-metrics
    port: 9182
    protocol: TCP
    targetPort: 9182
  sessionAffinity: None
  type: ClusterIP

---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor ##Custom ServiceMonitor Object
metadata:
  labels:
    k8s-app: wmiexporter
  name: wmiexporter
  namespace: monitoring
spec:
  endpoints:
  - interval: 30s
    port: http-metrics
  jobLabel: k8s-app
  namespaceSelector:
    matchNames:
    - kube-system
  selector:
    matchLabels:
      k8s-app: wmiexporter
```

운영자 및 ServiceMonitor 사용에 대한 자세한 내용은 공식 [운영자](https://github.com/prometheus-operator/kube-prometheus) 설명서를 확인하세요. Prometheus는 많은 [서비스 검색 옵션을 사용하여 동적 대상 검색을](https://prometheus.io/blog/2015/06/01/advanced-service-discovery/) 지원합니다.

# Windows 네트워킹
<a name="windows-networking"></a>

## Windows 컨테이너 네트워킹 개요
<a name="_windows_container_networking_overview"></a>

Windows 컨테이너는 Linux 컨테이너와 근본적으로 다릅니다. Linux 컨테이너는 네임스페이스, 유니온 파일 시스템 및 cgroup과 같은 Linux 구문을 사용합니다. Windows에서는 이러한 구문이 [호스트 컴퓨팅 서비스(HCS)](https://github.com/microsoft/hcsshim)에 의해 컨테이너화된에서 추출됩니다. HCS는 Windows에서 컨테이너 구현 위에 있는 API 계층 역할을 합니다. Windows 컨테이너는 노드에서 네트워크 토폴로지를 정의하는 호스트 네트워크 서비스(HNS)도 활용합니다.

![\[Windows 네트워킹\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/windows-networking.png)


네트워킹 관점에서 HCS와 HNS는 Windows 컨테이너가 가상 머신처럼 작동하도록 합니다. 예를 들어 각 컨테이너에는 위의 다이어그램과 같이 Hyper-V 가상 스위치(vSwitch)에 연결된 가상 네트워크 어댑터(vNIC)가 있습니다.

## IP 주소 관리
<a name="_ip_address_management"></a>

Amazon EKS의 노드는 ENI(Elastic Network Interface)를 사용하여 AWS VPC 네트워크에 연결합니다. 현재 **Windows 작업자 노드당 단일 ENI만 지원됩니다**. Windows 노드의 IP 주소 관리는 컨트롤 플레인에서 실행되는 [VPC 리소스 컨트롤러](https://github.com/aws/amazon-vpc-resource-controller-k8s)에서 수행됩니다. Windows 노드의 IP 주소 관리를 위한 워크플로에 대한 자세한 내용은 [여기에서](https://github.com/aws/amazon-vpc-resource-controller-k8s#windows-ipv4-address-management) 확인할 수 있습니다.

Windows 작업자 노드가 지원할 수 있는 포드 수는 노드의 크기와 사용 가능한 IPv4 주소 수에 따라 결정됩니다. 노드에서 사용할 수 있는 IPv4 주소를 다음과 같이 계산할 수 있습니다.
+ 기본적으로 보조 IPv4 주소만 ENI에 할당됩니다. 이 경우:

  ```
  Total IPv4 addresses available for Pods = Number of supported IPv4 addresses in the primary interface - 1
  ```

  하나의 IPv4 주소가 ENI의 기본 주소로 사용되므로 포드에 할당할 수 없으므로 총 개수에서 하나를 뺍니다.
+ [접두사 위임 기능을](prefix-mode-win.md) 활성화하여 클러스터가 높은 포드 밀도에 맞게 구성된 경우

  ```
  Total IPv4 addresses available for Pods = (Number of supported IPv4 addresses in the primary interface - 1) * 16
  ```

  여기서는 보조 IPv4 주소를 할당하는 대신 VPC 리소스 컨트롤러가 할당`/28 prefixes`하므로 사용 가능한 전체 IPv4 주소 수가 16회 부스팅됩니다.

위의 공식을 사용하여 다음과 같이 m5.large 인스턴스를 기반으로 노드된 Windows 작업자의 최대 포드를 계산할 수 있습니다.
+ 기본적으로 보조 IP 모드에서 실행하는 경우 -

  ```
  10 secondary IPv4 addresses per ENI - 1 = 9 available IPv4 addresses
  ```
+ 사용 시 `prefix delegation`-

  ```
  (10 secondary IPv4 addresses per ENI - 1) * 16 = 144 available IPv4 addresses
  ```

인스턴스 유형이 지원할 수 있는 IP 주소 수에 대한 자세한 내용은 [인스턴스 유형별 네트워크 인터페이스당 IP 주소를](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#AvailableIpPerENI) 참조하세요.



또 다른 주요 고려 사항은 네트워크 트래픽의 흐름입니다. Windows를 사용하면 서비스가 100개 이상인 노드에서 포트가 고갈될 위험이 있습니다. 이 조건이 발생하면 노드에서 다음 메시지와 함께 오류가 발생하기 시작합니다.

 **“정책 생성 실패: Win32에서 hcnCreateLoadBalancer 실패: 지정된 포트가 이미 있습니다.”** 

이 문제를 해결하기 위해 DSR(Direct Server Return)을 활용합니다. DSR은 비대칭 네트워크 로드 배포를 구현한 것입니다. 즉, 요청 및 응답 트래픽은 서로 다른 네트워크 경로를 사용합니다. 이 기능은 포드 간의 통신을 가속화하고 포트 소진 위험을 줄입니다. 따라서 Windows 노드에서 DSR을 활성화하는 것이 좋습니다.

DSR은 Windows Server SAC EKS 최적화 AMIs에서 기본적으로 활성화됩니다. Windows Server 2019 LTSC EKS 최적화 AMIs 경우 아래 스크립트를 사용하고 Windows Server 2019 Full 또는 Core를 `eksctl` nodeGroup의 amiFamily로 사용하여 인스턴스 프로비저닝 중에 활성화해야 합니다. 자세한 내용은 [eksctl 사용자 지정 AMI](https://eksctl.io/usage/custom-ami-support/)를 참조하세요.

```
nodeGroups:
- name: windows-ng
  instanceType: c5.xlarge
  minSize: 1
  volumeSize: 50
  amiFamily: WindowsServer2019CoreContainer
  ssh:
    allow: false
```

Windows Server 2019 이상에서 DSR을 활용하려면 인스턴스 시작 중에 다음 [https://kubernetes.io/docs/setup/production-environment/windows/intro-windows-in-kubernetes/#load-balancing-and-services](https://kubernetes.io/docs/setup/production-environment/windows/intro-windows-in-kubernetes/#load-balancing-and-services) 플래그를 지정해야 합니다. [자체 관리형 노드 그룹 시작 템플릿](https://docs.aws.amazon.com/eks/latest/userguide/launch-windows-workers.html)과 연결된 사용자 데이터 스크립트를 조정하여이 작업을 수행할 수 있습니다.

```
<powershell>
[string]$EKSBinDir = "$env:ProgramFiles\Amazon\EKS"
[string]$EKSBootstrapScriptName = 'Start-EKSBootstrap.ps1'
[string]$EKSBootstrapScriptFile = "$EKSBinDir\$EKSBootstrapScriptName"
(Get-Content $EKSBootstrapScriptFile).replace('"--proxy-mode=kernelspace",', '"--proxy-mode=kernelspace", "--feature-gates WinDSR=true", "--enable-dsr",') | Set-Content $EKSBootstrapScriptFile
& $EKSBootstrapScriptFile -EKSClusterName "eks-windows" -APIServerEndpoint "https://<REPLACE-EKS-CLUSTER-CONFIG-API-SERVER>" -Base64ClusterCA "<REPLACE-EKSCLUSTER-CONFIG-DETAILS-CA>" -DNSClusterIP "172.20.0.10" -KubeletExtraArgs "--node-labels=alpha.eksctl.io/cluster-name=eks-windows,alpha.eksctl.io/nodegroup-name=windows-ng-ltsc2019 --register-with-taints=" 3>&1 4>&1 5>&1 6>&1
</powershell>
```

DSR 활성화는 [Microsoft 네트워킹 블로그](https://techcommunity.microsoft.com/t5/networking-blog/direct-server-return-dsr-in-a-nutshell/ba-p/693710) 및 [AWS Lab의 Windows 컨테이너의 지침에 따라 확인할 수 있습니다](https://catalog.us-east-1.prod.workshops.aws/workshops/1de8014a-d598-4cb5-a119-801576492564/en-US/module1-eks/lab3-handling-mixed-clusters).

![\[dsr\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/dsr.png)


서브넷에 사용 가능한 IPv4 주소를 보존하고 낭비를 최소화하는 것이 중요한 경우 [일반적으로 Windows용 접두사 모드 - 피해야 할 경우에 언급된 대로 접두사 위임 모드를 사용하지 않는](prefix-mode-win.md#windows-prefix-avoid) 것이 좋습니다. 접두사 위임을 계속 사용하려는 경우 서브넷의 IPv4 주소 사용률을 최적화하는 단계를 수행할 수 있습니다. IPv4 주소 요청 및 할당 프로세스를 미세 조정하는 방법에 대한 자세한 지침은 [접두사 위임을 위한 파라미터 구성을](prefix-mode-win.md#windows-network-conserve) 참조하세요. 이러한 구성을 조정하면 IPv4 주소 보존과 접두사 위임의 포드 밀도 이점 간에 균형을 맞출 수 있습니다.

보조 IPv4 주소 할당의 기본 설정을 사용하는 경우 현재 VPC 리소스 컨트롤러가 IPv4 주소를 요청하고 할당하는 방법을 조작하는 데 지원되는 구성이 없습니다. 보다 구체적으로, `minimum-ip-target` 및 `warm-ip-target`는 접두사 위임 모드에서만 지원됩니다. 또한 보조 IP 모드에서는 인터페이스에서 사용 가능한 IP 주소에 따라 VPC 리소스 컨트롤러가 일반적으로 노드에 미사용 IPv4 주소 3개를 할당하여 포드 시작 시간을 단축하기 위해 웜 IPs 유지합니다. 미사용 웜 IP 주소의 IP 낭비를 최소화하려면 ENI의 IP 주소 용량을 최대한 많이 사용하도록 지정된 Windows 노드에서 더 많은 포드를 예약하는 것이 좋습니다. 보다 명시적으로 말하면 ENI의 모든 IPs 주소가 노드에서 이미 사용 중이고 포드를 실행하는 경우 웜 미사용 IP를 사용하지 않도록 할 수 있습니다. 서브넷의 IP 주소 가용성 제약 조건을 해결하는 데 도움이 되는 또 다른 해결 방법은 [서브넷 크기를 늘리](https://docs.aws.amazon.com/vpc/latest/userguide/modify-subnets.html)거나 Windows 노드를 전용 서브넷으로 분리하는 것입니다.

또한 현재 Windows 노드에서는 IPv6가 지원되지 않는다는 점에 유의해야 합니다.

## 컨테이너 네트워크 인터페이스(CNI) 옵션
<a name="_container_network_interface_cni_options"></a>

AWSVPC CNI는 Windows 및 Linux 작업자 노드용 사실상의 CNI 플러그인입니다. AWSVPC CNI는 많은 고객의 요구 사항을 충족하지만 IP 소진을 방지하기 위해 오버레이 네트워크와 같은 대안을 고려해야 하는 경우가 있을 수 있습니다. 이러한 경우 AWSVPC CNI 대신 Calico CNI를 사용할 수 있습니다. [Project Calico](https://www.projectcalico.org/)는 [Tigera](https://www.tigera.io/)에서 개발한 오픈 소스 소프트웨어입니다. 이 소프트웨어에는 EKS와 함께 작동하는 CNI가 포함되어 있습니다. EKS에 Calico CNI를 설치하는 지침은 [Project Calico EKS 설치](https://docs.projectcalico.org/getting-started/kubernetes/managed-public-cloud/eks) 페이지에서 확인할 수 있습니다.

## 네트워크 정책
<a name="_network_polices"></a>

Kubernetes 클러스터의 포드 간 개방형 통신의 기본 모드에서 네트워크 정책에 따라 액세스를 제한하는 것으로 변경하는 것이 모범 사례로 간주됩니다. 오픈 소스 [Project Calico](https://www.tigera.io/tigera-products/calico/)는 Linux 및 Windows 노드 모두에서 작동하는 네트워크 정책을 강력하게 지원합니다. 이 기능은 별개이며 Calico CNI 사용에 의존하지 않습니다. 따라서 Calico를 설치하고 네트워크 정책 관리에 사용하는 것이 좋습니다.

EKS에 Calico를 설치하는 지침은 [Amazon EKS에 Calico 설치](https://docs.aws.amazon.com/eks/latest/userguide/calico.html) 페이지에서 확인할 수 있습니다.

또한 [Amazon EKS 보안 모범 사례 가이드 - 네트워크 섹션에](https://docs.aws.amazon.com/eks/latest/best-practices/network-security.html) 제공된 조언은 Windows 작업자 노드가 있는 EKS 클러스터에도 동일하게 적용되지만, "포드용 보안 그룹"과 같은 일부 기능은 현재 Windows에서 지원되지 않습니다.

# OOM 오류 방지
<a name="windows-oom"></a>

Windows에는 Linux처럼 out-of-memory 프로세스 킬러가 없습니다. Windows는 항상 모든 사용자 모드 메모리 할당을 가상으로 취급하며 페이지 파일은 필수입니다. 순 효과는 Windows가 Linux와 동일한 방식으로 메모리 조건을 벗어나지 않는다는 것입니다. 프로세스는 메모리 부족(OOM) 종료되는 대신 디스크로 페이징됩니다. 메모리가 과다 프로비저닝되고 모든 물리적 메모리가 소진되면 페이징으로 인해 성능이 저하될 수 있습니다.

## 시스템 및 kubelet 메모리 예약
<a name="_reserving_system_and_kubelet_memory"></a>

kubelet, 컨테이너 런타임 등과 같은 kubernetes 시스템 데몬에 대한 리소스 예약을 `--kubelet-reserve` **캡처**하고 sshd, udev 등과 같은 OS 시스템 데몬에 대한 리소스 예약을 `--system-reserve` **캡처**하는 Linux와 다릅니다. **Windows**에서 이러한 플래그는 노드에서 실행되는 **kubelet** 또는 **프로세스에** 대한 메모리 제한을 **캡처**하고 **설정**하지 않습니다.

그러나 이러한 플래그를 결합하여 **NodeAllocatable**을 관리하여 포드 매니페스트 **메모리 리소스 제한**으로 노드의 용량을 줄여 포드당 메모리 할당을 제어할 수 있습니다. 이 전략을 사용하면 Windows 노드에서 out-of-memory(OOM)을 최소화하는 메커니즘뿐만 아니라 메모리 할당을 더 잘 제어할 수 있습니다.

Windows 노드에서 모범 사례는 OS 및 프로세스를 위해 최소 2GB의 메모리를 예약하는 것입니다. `--kubelet-reserve` 및/또는 `--system-reserve`를 사용하여 NodeAllocatable을 줄입니다.

[Amazon EKS 자체 관리형 Windows 노드](https://docs.aws.amazon.com/eks/latest/userguide/launch-windows-workers.html) 설명서에 따라 CloudFormation 템플릿을 사용하여 kubelet 구성을 사용자 지정하여 새 Windows 노드 그룹을 시작합니다. CloudFormation에는와 `BootstrapArguments` 동일한 라는 요소가 있습니다`KubeletExtraArgs`. 다음 플래그 및 값과 함께를 사용합니다.

```
--kube-reserved memory=0.5Gi,ephemeral-storage=1Gi --system-reserved memory=1.5Gi,ephemeral-storage=1Gi --eviction-hard memory.available<200Mi,nodefs.available<10%"
```

eksctl이 배포 도구인 경우 다음 설명서를 확인하여 kubelet 구성을 사용자 지정합니다. https://eksctl.io/usage/customizing-the-kubelet/

## Windows 컨테이너 메모리 요구 사항
<a name="_windows_container_memory_requirements"></a>

[Microsoft 설명서에](https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/system-requirements) 따르면 NANO용 Windows Server 기본 이미지에는 최소 30MB가 필요한 반면 Server Core에는 45MB가 필요합니다. .NET Framework, Web Services as IIS 및 애플리케이션과 같은 Windows 구성 요소를 추가하면 이러한 수가 증가합니다.

Windows 컨테이너 이미지, 즉 기본 이미지와 애플리케이션 계층에 필요한 최소 메모리 양을 알고 포드 사양에서 컨테이너의 리소스/요청으로 설정해야 합니다. 또한 애플리케이션 문제가 발생할 경우 포드가 사용 가능한 모든 노드 메모리를 소비하지 않도록 제한을 설정해야 합니다.

아래 예제에서 Kubernetes 스케줄러가 노드에 포드를 배치하려고 하면 포드의 요청을 사용하여 예약에 사용할 수 있는 리소스가 충분한 노드를 결정합니다.

```
 spec:
  - name: iis
    image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
    resources:
      limits:
        cpu: 1
        memory: 800Mi
      requests:
        cpu: .1
        memory: 128Mi
```

## 결론
<a name="_conclusion"></a>

이 접근 방식을 사용하면 메모리 소진 위험을 최소화하지만 메모리 소진을 방지하지는 않습니다. Amazon CloudWatch 지표를 사용하면 메모리 소진 발생 시 알림 및 문제 해결을 설정할 수 있습니다.

# Windows Server 및 컨테이너 패치 적용
<a name="windows-patching"></a>

Windows Server 패치는 Windows 관리자의 표준 관리 작업입니다. 이는 Amazon System Manager - Patch Manager, WSUS, System Center Configuration Manager 등과 같은 다양한 도구를 사용하여 수행할 수 있습니다. 그러나 Amazon EKS 클러스터의 Windows 노드는 일반 Windows 서버로 취급해서는 안 됩니다. 변경 불가능한 서버로 취급해야 합니다. 간단히 말해서 기존 노드를 업데이트하지 말고 새로 업데이트된 AMI를 기반으로 새 노드를 시작하면 됩니다.

[EC2 Image Builder](https://aws.amazon.com/image-builder/)를 사용하면 레시피를 생성하고 구성 요소를 추가하여 AMIs 빌드를 자동화할 수 있습니다.

다음 예제에서는 AWS에서 구축한 기존 **구성 요소**(Amazon 관리형)와 사용자가 생성한 구성 요소(내 소유)일 수 있는 구성 요소를 보여줍니다. **update-windows**라는 Amazon 관리형 구성 요소에 주의하세요. 그러면 EC2 Image Builder 파이프라인을 통해 AMI를 생성하기 전에 Windows Server가 업데이트됩니다.

![\[연결된 구성 요소\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/associated-components.png)


EC2 Image Builder를 사용하면 Amazon Managed Public AMI를 기반으로 AMIs 빌드하고 비즈니스 요구 사항에 맞게 사용자 지정할 수 있습니다. 그런 다음 이러한 AMIs 시작 템플릿과 연결하여 새 AMI를 EKS 노드 그룹에서 생성한 Auto Scaling 그룹에 연결할 수 있습니다. 완료되면 기존 Windows 노드 종료를 시작할 수 있으며 업데이트된 새 AMI를 기반으로 새 노드가 시작됩니다.

## Windows 이미지 푸시 및 가져오기
<a name="_pushing_and_pulling_windows_images"></a>

Amazon은 캐시된 두 개의 Windows 컨테이너 이미지가 포함된 EKS 최적화 AMIs를 게시합니다.

```
mcr.microsoft.com/windows/servercore
mcr.microsoft.com/windows/nanoserver
```

![\[이미지\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/images.png)


캐시된 이미지는 기본 OS의 업데이트에 따라 업데이트됩니다. Microsoft가 Windows 컨테이너 기본 이미지에 직접 영향을 미치는 새 Windows 업데이트를 릴리스하면 기본 OS에서 일반 Windows 업데이트로 업데이트가 시작됩니다. 환경을 up-to-date 상태로 유지하면 노드 및 컨테이너 수준에서 보다 안전한 환경이 제공됩니다.

Windows 컨테이너 이미지의 크기는 푸시/풀 작업에 영향을 미치므로 컨테이너 시작 시간이 느려질 수 있습니다. [Windows 컨테이너 이미지를 캐싱](https://aws.amazon.com/blogs/containers/speeding-up-windows-container-launch-times-with-ec2-image-builder-and-image-cache-strategy/)하면 컨테이너 시작 대신 AMI 빌드 생성 시 비용이 많이 드는 I/O 작업(파일 추출)이 발생할 수 있습니다. 따라서 필요한 모든 이미지 계층이 AMI에서 추출되고 사용할 준비가 되어 Windows 컨테이너가 시작되고 트래픽 수락을 시작할 수 있는 시간이 단축됩니다. 푸시 작업 중에는 이미지를 구성하는 계층만 리포지토리에 업로드됩니다.

다음 예제는 Amazon ECR에서 **fluentd-windows-sac2004** 이미지의 크기가 **390.18MB**에 불과함을 보여줍니다. 푸시 작업 중에 발생한 업로드 양입니다.

다음 예제는 Amazon ECR [리포지토리로 푸시된 유창한 Windows ltsc](https://github.com/fluent/fluentd-docker-image/blob/master/v1.14/windows-ltsc2019/Dockerfile) 이미지를 보여줍니다. ECR에 저장된 계층의 크기는 **533.05MB**입니다.

![\[ecr 이미지\]](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/windows/ecr-image.png)


아래 `docker image ls`의 출력인 fluentd v1.14-windows-ltsc2019-1의 크기는 디스크에서 **6.96GB**이지만 해당 양의 데이터를 다운로드하고 추출했음을 의미하지는 않습니다.

실제로 풀 작업 중에는 **압축된 533.05MB**만 다운로드되고 추출됩니다.

```
REPOSITORY                                                              TAG                        IMAGE ID       CREATED         SIZE
111122223333.dkr.ecr.us-east-1.amazonaws.com/fluentd-windows-coreltsc   latest                     721afca2c725   7 weeks ago     6.96GB
fluent/fluentd                                                          v1.14-windows-ltsc2019-1   721afca2c725   7 weeks ago     6.96GB
amazonaws.com/eks/pause-windows                                         latest                     6392f69ae6e7   10 months ago   255MB
```

크기 열에는 이미지의 전체 크기인 6.96GB가 표시됩니다. 분류:
+ Windows Server Core 2019 LTSC 기본 이미지 = 5.74GB
+ Fluentd 비압축 기본 이미지 = 6.96GB
+ 디스크 차이 = 1.2GB
+ Fluentd [압축된 최종 이미지 ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-info.html) = 533.05MB

기본 이미지가 이미 로컬 디스크에 있으므로 디스크의 총량은 1.2GB가 추가됩니다. 다음에 크기 열에 GBs의 양이 표시되면 너무 많이 걱정하지 마세요. 70% 이상이 이미 캐시된 컨테이너 이미지로 디스크에 있을 가능성이 높습니다.

## 레퍼런스
<a name="_reference"></a>

 [EC2 이미지 빌더 및 이미지 캐시 전략을 사용하여 Windows 컨테이너 시작 시간 단축](https://aws.amazon.com/blogs/containers/speeding-up-windows-container-launch-times-with-ec2-image-builder-and-image-cache-strategy/) 

# 이기종 워크로드 실행
<a name="windows-scheduling"></a>

Kubernetes는 동일한 클러스터에 Linux 노드와 Windows 노드를 혼합할 수 있는 이기종 클러스터를 지원합니다. 해당 클러스터 내에서 Linux에서 실행되는 포드와 Windows에서 실행되는 포드가 혼합되어 있을 수 있습니다. 동일한 클러스터에서 여러 버전의 Windows를 실행할 수도 있습니다. 그러나이 결정을 내릴 때 고려해야 할 몇 가지 요인(아래 참조)이 있습니다.

## 노드PODs 할당 모범 사례
<a name="_assigning_pods_to_nodes_best_practices"></a>

Linux 및 Windows 워크로드를 해당 OS별 노드에 유지하려면 노드 선택기와 테인트/내결함의 조합을 사용해야 합니다. 이기종 환경에서 워크로드를 예약하는 주요 목표는 기존 Linux 워크로드와의 호환성 저하를 방지하는 것입니다.

## OS별 워크로드가 적절한 컨테이너 호스트에 도달하도록 보장
<a name="_ensuring_os_specific_workloads_land_on_the_appropriate_container_host"></a>

사용자는 nodeSelectors. 오늘날 모든 Kubernetes 노드에는 다음과 같은 기본 레이블이 있습니다.

```
kubernetes.io/os = [windows|linux]
kubernetes.io/arch = [amd64|arm64|...]
```

포드 사양에와 같은 nodeSelector가 포함되지 않은 경우 모든 호스트, Windows 또는 Linux에서 포드`"kubernetes.io/os": windows`를 예약할 수 있습니다. 이는 Windows 컨테이너는 Windows에서만 실행할 수 있고 Linux 컨테이너는 Linux에서만 실행할 수 있기 때문에 문제가 될 수 있습니다.

엔터프라이즈 환경에서는 Linux 컨테이너에 대한 많은 수의 기존 배포와 Helm 차트와 같은 off-the-shelf 구성 에코시스템을 사용하는 것이 드문 일이 아닙니다. 이러한 상황에서는 배포의 nodeSelectors. **대안은 Taints를 사용하는** 것입니다.

예: `--register-with-taints='os=windows:NoSchedule'` 

EKS를 사용하는 경우 eksctl은 clusterConfig를 통해 테인트를 적용하는 방법을 제공합니다.

```
NodeGroups:
  - name: windows-ng
    amiFamily: WindowsServer2022FullContainer
    ...
    labels:
      nodeclass: windows2022
    taints:
      os: "windows:NoSchedule"
```

모든 Windows 노드에 테인트를 추가하면 스케줄러는 테인트를 허용하지 않는 한 해당 노드에서 포드를 예약하지 않습니다. 포드 매니페스트 예제:

```
nodeSelector:
    kubernetes.io/os: windows
tolerations:
    - key: "os"
      operator: "Equal"
      value: "windows"
      effect: "NoSchedule"
```

## 동일한 클러스터에서 여러 Windows 빌드 처리
<a name="_handling_multiple_windows_build_in_the_same_cluster"></a>

각 포드에서 사용하는 Windows 컨테이너 기본 이미지는 노드와 동일한 커널 빌드 버전과 일치해야 합니다. 동일한 클러스터에서 여러 Windows Server 빌드를 사용하려면 추가 노드 레이블, nodeSelectors를 설정하거나 **windows-build**라는 레이블을 활용해야 합니다.

Kubernetes 1.17은 자동으로 새 레이블 **node.kubernetes.io/windows-build** 추가하여 동일한 클러스터에서 여러 Windows 빌드의 관리를 간소화합니다. 이전 버전을 실행하는 경우이 레이블을 Windows 노드에 수동으로 추가하는 것이 좋습니다.

이 레이블은 호환성을 위해 일치해야 하는 Windows 메이저, 마이너 및 빌드 번호를 반영합니다. 다음은 현재 각 Windows Server 버전에 사용되는 값입니다.

Windows Server가 기본 릴리스 채널로 장기 서비스 채널(LTSC)로 이동하고 있다는 점에 유의해야 합니다. Windows Server 반기 채널(SAC)은 2022년 8월 9일에 사용 중지되었습니다. 향후 Windows Server의 SAC 릴리스는 없습니다.


| 제품 이름 | 빌드 번호(들) | 
| --- | --- | 
|  서버 전체 2022 LTSC  |  20348년 10월 0일  | 
|  서버 코어 2019 LTSC  |  10.0.17763  | 

다음 명령을 통해 OS 빌드 버전을 확인할 수 있습니다.

```
kubectl get nodes -o wide
```

KERNEL-VERSION 출력은 Windows OS 빌드 버전과 일치합니다.

```
NAME                          STATUS   ROLES    AGE   VERSION                INTERNAL-IP   EXTERNAL-IP     OS-IMAGE                         KERNEL-VERSION                  CONTAINER-RUNTIME
ip-10-10-2-235.ec2.internal   Ready    <none>   23m   v1.24.7-eks-fb459a0    10.10.2.235   3.236.30.157    Windows Server 2022 Datacenter   10.0.20348.1607                 containerd://1.6.6
ip-10-10-31-27.ec2.internal   Ready    <none>   23m   v1.24.7-eks-fb459a0    10.10.31.27   44.204.218.24   Windows Server 2019 Datacenter   10.0.17763.4131                 containerd://1.6.6
ip-10-10-7-54.ec2.internal    Ready    <none>   31m   v1.24.11-eks-a59e1f0   10.10.7.54    3.227.8.172     Amazon Linux 2                   5.10.173-154.642.amzn2.x86_64   containerd://1.6.19
```

아래 예제에서는 다른 Windows 노드 그룹 OS 버전을 실행할 때 올바른 Windows 빌드 버전과 일치하도록 포드 매니페스트에 추가 nodeSelector를 적용합니다.

```
nodeSelector:
    kubernetes.io/os: windows
    node.kubernetes.io/windows-build: '10.0.20348'
tolerations:
    - key: "os"
    operator: "Equal"
    value: "windows"
    effect: "NoSchedule"
```

## RuntimeClass를 사용하여 포드 매니페스트에서 NodeSelector 및 허용치 간소화
<a name="_simplifying_nodeselector_and_toleration_in_pod_manifests_using_runtimeclass"></a>

RuntimeClass를 사용하여 테인트 및 허용치 사용 프로세스를 간소화할 수도 있습니다. 이러한 테인트와 허용치를 캡슐화하는 데 사용되는 RuntimeClass 객체를 생성하여이 작업을 수행할 수 있습니다.

다음 매니페스트를 실행하여 RuntimeClass를 생성합니다.

```
apiVersion: node.k8s.io/v1beta1
kind: RuntimeClass
metadata:
  name: windows-2022
handler: 'docker'
scheduling:
  nodeSelector:
    kubernetes.io/os: 'windows'
    kubernetes.io/arch: 'amd64'
    node.kubernetes.io/windows-build: '10.0.20348'
  tolerations:
  - effect: NoSchedule
    key: os
    operator: Equal
    value: "windows"
```

Runtimeclass가 생성되면를 포드 매니페스트의 사양으로 사용하여 할당합니다.

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: iis-2022
  labels:
    app: iis-2022
spec:
  replicas: 1
  template:
    metadata:
      name: iis-2022
      labels:
        app: iis-2022
    spec:
      runtimeClassName: windows-2022
      containers:
      - name: iis
```

## 관리형 노드 그룹 지원
<a name="_managed_node_group_support"></a>

고객이 보다 간소화된 방식으로 Windows 애플리케이션을 실행할 수 있도록 AWS는 2022년 12월 15일에 [Windows 컨테이너에 대한 Amazon EKS Managed Node Group(MNG) 지원](https://aws.amazon.com/about-aws/whats-new/2022/12/amazon-eks-automated-provisioning-lifecycle-management-windows-containers/) 지원을 시작했습니다. 운영 팀을 조정하기 위해 [Windows MNGs](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)는 [Linux MNGs](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)와 동일한 워크플로 및 도구를 사용하여 활성화됩니다. Windows Server 2019 및 2022의 전체 및 코어 AMI(Amazon Machine Image) 패밀리 버전이 지원됩니다.

관리형 노드 그룹(MNG)에는 다음 AMI 패밀리가 지원됩니다.


| AMI 패밀리 | 
| --- | 
|  WINDOWS\$1CORE\$12019\$1x86\$164  | 
|  WINDOWS\$1FULL\$12019\$1x86\$164  | 
|  WINDOWS\$1CORE\$12022\$1x86\$164  | 
|  WINDOWS\$1FULL\$12022\$1x86\$164  | 

## 추가 설명서
<a name="_additional_documentations"></a>

AWS 공식 설명서: https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html

포드 네트워킹(CNI)의 작동 방식을 더 잘 이해하려면 https://docs.aws.amazon.com/eks/latest/userguide/pod-networking.html 링크를 확인하세요.

EKS에서 Windows용 관리형 노드 그룹 배포에 대한 AWS 블로그: https://aws.amazon.com/blogs/containers/deploying-amazon-eks-windows-managed-node-groups/

# 포드 보안 컨텍스트
<a name="windows-security"></a>

 **포드 보안 정책(PSP)**과 **포드 보안 표준(PSS)**은 Kubernetes에서 보안을 적용하는 두 가지 주요 방법입니다. PodSecurityPolicy는 Kubernetes v1.21부터 더 이상 사용되지 않으며 v1.25에서 제거되며 포드 보안 표준(PSS)은 향후 보안을 적용하기 위한 Kubernetes 권장 접근 방식입니다.

포드 보안 정책(PSP)은 보안 정책을 구현하기 위한 Kubernetes의 기본 솔루션입니다. PSP는 포드 사양의 보안에 민감한 측면을 제어하는 클러스터 수준 리소스입니다. 포드 보안 정책을 사용하여 클러스터에서 포드를 수락하기 위해 충족해야 하는 조건 세트를 정의할 수 있습니다. PSP 기능은 Kubernetes 초기부터 사용할 수 있으며 잘못 구성된 포드가 지정된 클러스터에서 생성되는 것을 차단하도록 설계되었습니다.

포드 보안 정책에 대한 자세한 내용은 Kubernetes [설명서를](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) 참조하세요. [Kubernetes 사용 중단 정책에](https://kubernetes.io/docs/reference/using-api/deprecation-policy/) 따라 이전 버전은 기능 사용 중단 후 9개월이 지나면 지원 받기가 중단됩니다.

반면 권장되는 보안 접근 방식이며 일반적으로 보안 컨텍스트를 사용하여 구현되는 포드 보안 표준(PSS)은 포드 매니페스트의 포드 및 컨테이너 사양의 일부로 정의됩니다. PSS는 Kubernetes 프로젝트 팀이 포드에 대한 보안 관련 모범 사례를 해결하기 위해 정의한 공식 표준입니다. 기준(최소 제한, 기본값), 권한(비제한) 및 제한(가장 제한적)과 같은 정책을 정의합니다.

기준 프로파일부터 시작하는 것이 좋습니다. PSS 기준 프로파일은 최소한의 예외 목록이 필요한 보안과 잠재적 마찰 간에 견고한 균형을 제공하며 워크로드 보안을 위한 좋은 출발점 역할을 합니다. 현재 PSPs 사용하는 경우 PSS로 전환하는 것이 좋습니다. PSS 정책에 대한 자세한 내용은 Kubernetes [설명서](https://kubernetes.io/docs/concepts/security/pod-security-standards/)에서 확인할 수 있습니다. 이러한 정책은 [OPA](https://www.openpolicyagent.org/) 및 [Kyverno](https://kyverno.io/)의 도구를 포함한 여러 도구를 사용하여 적용할 수 있습니다. 예를 들어 Kyverno는 [여기에](https://kyverno.io/policies/pod-security/) PSS 정책의 전체 컬렉션을 제공합니다.

보안 컨텍스트 설정을 사용하면 프로세스를 선택하고, 프로그램 프로파일을 사용하여 기능을 개별 프로그램으로 제한하고, 권한 에스컬레이션을 허용하고, 시스템 호출을 필터링할 수 있는 권한을 부여할 수 있습니다.

Kubernetes의 Windows 포드에는 보안 컨텍스트와 관련하여 표준 Linux 기반 워크로드와 몇 가지 제한 사항 및 차이점이 있습니다.

Windows는 시스템 네임스페이스 필터와 함께 컨테이너당 작업 객체를 사용하여 컨테이너의 모든 프로세스를 포함하고 호스트와의 논리적 격리를 제공합니다. 네임스페이스 필터링 없이 Windows 컨테이너를 실행할 수 있는 방법은 없습니다. 즉, 호스트의 컨텍스트에서 시스템 권한을 어설션할 수 없으므로 Windows에서 권한 있는 컨테이너를 사용할 수 없습니다.

다음은 유일하게 문서화된 [Windows 보안 컨텍스트 옵션](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#windowssecuritycontextoptions-v1-core)이고 나머지`windowsOptions`는 일반 [보안 컨텍스트 옵션](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#securitycontext-v1-core)입니다.

Windows와 Linux에서 지원되는 보안 컨텍스트 속성 목록은 [여기에서](https://kubernetes.io/docs/setup/production-environment/windows/_print/#v1-container) 공식 설명서를 참조하세요.

포드별 설정은 모든 컨테이너에 적용됩니다. 지정하지 않으면 PodSecurityContext의 옵션이 사용됩니다. SecurityContext와 PodSecurityContext 모두에 설정된 경우 SecurityContext에 지정된 값이 우선합니다.

예를 들어 Windows 옵션인 포드 및 컨테이너에 대한 runAsUserName 설정은 Linux별 runAsUser 설정과 대략적으로 동일하며 다음 매니페스트에서 포드별 보안 컨텍스트가 모든 컨테이너에 적용됩니다.

```
apiVersion: v1
kind: Pod
metadata:
  name: run-as-username-pod-demo
spec:
  securityContext:
    windowsOptions:
      runAsUserName: "ContainerUser"
  containers:
  - name: run-as-username-demo

  nodeSelector:
    kubernetes.io/os: windows
```

다음에서는 컨테이너 수준 보안 컨텍스트가 포드 수준 보안 컨텍스트를 재정의합니다.

```
apiVersion: v1
kind: Pod
metadata:
  name: run-as-username-container-demo
spec:
  securityContext:
    windowsOptions:
      runAsUserName: "ContainerUser"
  containers:
  - name: run-as-username-demo
    ..
    securityContext:
        windowsOptions:
            runAsUserName: "ContainerAdministrator"
  nodeSelector:
    kubernetes.io/os: windows
```

runAsUserName 필드에 허용되는 값의 예: ContainerAdministrator, ContainerUser, NT AUTHORITY\$1NETWORK SERVICE, NT AUTHORITY\$1LOCAL SERVICE

일반적으로 ContainerUser for Windows 포드를 사용하여 컨테이너를 실행하는 것이 좋습니다. 사용자는 컨테이너와 호스트 간에 공유되지 않지만 ContainerAdministrator는 컨테이너의에 대한 추가 권한을 가집니다. 참고로 알아야 할 사용자 이름 [제한](https://kubernetes.io/docs/tasks/configure-pod-container/configure-runasusername/#windows-username-limitations) 사항이 있습니다.

ContainerAdministrator를 사용해야 하는 경우의 좋은 예는 PATH를 설정하는 것입니다. 다음과 같이 사용자 지시문을 사용하여 이를 수행할 수 있습니다.

```
USER ContainerAdministrator
RUN setx /M PATH "%PATH%;C:/your/path"
USER ContainerUser
```

또한 보안 암호는 노드 볼륨에 일반 텍스트로 작성됩니다(linux의 tmpfs/in-memory와 비교). 즉, 두 가지 작업을 수행해야 합니다.
+ 파일 ACLs 사용하여 보안 암호 파일 위치 보호
+ [BitLocker](https://docs.microsoft.com/en-us/windows/security/information-protection/bitlocker/bitlocker-how-to-deploy-on-windows-server)를 사용한 볼륨 수준 암호화 사용 

# 영구 스토리지 옵션
<a name="windows-storage"></a>

## 트리 내 볼륨 플러그인과 out-of-tree 볼륨 플러그인이란 무엇입니까?
<a name="_what_is_an_in_tree_vs_out_of_tree_volume_plugin"></a>

컨테이너 스토리지 인터페이스(CSI)가 도입되기 전에는 모든 볼륨 플러그인이 트리 내에 있었습니다. 즉, 코어 Kubernetes 바이너리와 함께 빌드, 연결, 컴파일 및 제공되고 코어 Kubernetes API를 확장했습니다. 즉, Kubernetes(볼륨 플러그인)에 새 스토리지 시스템을 추가하려면 코어 Kubernetes 코드 리포지토리에 코드를 확인해야 했습니다.

Out-of-tree 볼륨 플러그인은 Kubernetes 코드 베이스와 독립적으로 개발되며 Kubernetes 클러스터에 확장 프로그램으로 배포(설치)됩니다. 이를 통해 공급업체는 Kubernetes 릴리스 주기와 별도로 대out-of-band 드라이버를 업데이트할 수 있습니다. 이는 Kubernetes가 공급업체에 k8s와 인터페이스하는 표준 방법을 제공하는 스토리지 인터페이스 또는 CSI를 생성했기 때문에 대부분 가능합니다.

Amazon Elastic Kubernetes Services(EKS) 스토리지 클래스 및 CSI 드라이버에 대한 자세한 내용은 https://docs.aws.amazon.com/eks/latest/userguide/storage.html 확인할 수 있습니다.

## Windows용 인트리 볼륨 플러그인
<a name="_in_tree_volume_plugin_for_windows"></a>

Kubernetes 볼륨을 사용하면 데이터 지속성 요구 사항이 있는 애플리케이션을 Kubernetes에 배포할 수 있습니다. 영구 볼륨 관리는 볼륨 프로비저닝/프로비저닝 해제/크기 조정, Kubernetes 노드에 볼륨 연결/분리, 포드의 개별 컨테이너에 볼륨 탑재/분리로 구성됩니다. 특정 스토리지 백엔드 또는 프로토콜에 대해 이러한 볼륨 관리 작업을 구현하기 위한 코드는 Kubernetes 볼륨 플러그인**(트리 내 볼륨 플러그인)**의 형태로 제공됩니다. Amazon Elastic Kubernetes Services(EKS)에서는 Windows에서 다음 Kubernetes 볼륨 플러그인 클래스가 지원됩니다.

 *트리 내 볼륨 플러그인:* [awsElasticBlockStore](https://kubernetes.io/docs/concepts/storage/volumes/#awselasticblockstore) 

Windows 노드에서 트리 내 볼륨 플러그인을 사용하려면 NTFS를 fsType으로 사용하려면 추가 StorageClass를 생성해야 합니다. EKS에서 기본 StorageClass는 ext4를 기본 fsType으로 사용합니다.

StorageClass는 관리자가 제공하는 스토리지의 "클래스"를 설명할 수 있는 방법을 제공합니다. 클래스마다 quality-of-service 수준, 백업 정책 또는 클러스터 관리자가 결정한 임의 정책에 매핑될 수 있습니다. Kubernetes는 클래스가 무엇을 나타내는지에 대한 의견이 없습니다. 이 개념을 다른 스토리지 시스템에서 "프로파일"이라고도 합니다.

다음 명령을 실행하여 확인할 수 있습니다.

```
kubectl describe storageclass gp2
```

출력:

```
Name:            gp2
IsDefaultClass:  Yes
Annotations:     kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"storage.k8s.io/v1","kind":"StorageClas
","metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"},"name":"gp2"},"parameters":{"fsType"
"ext4","type":"gp2"},"provisioner":"kubernetes.io/aws-ebs","volumeBindingMode":"WaitForFirstConsumer"}
,storageclass.kubernetes.io/is-default-class=true
Provisioner:           kubernetes.io/aws-ebs
Parameters:            fsType=ext4,type=gp2
AllowVolumeExpansion:  <unset>
MountOptions:          <none>
ReclaimPolicy:         Delete
VolumeBindingMode:     WaitForFirstConsumer
Events:                <none>
```

**NTFS**를 지원하는 새 StorageClass를 생성하려면 다음 매니페스트를 사용합니다.

```
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: gp2-windows
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
  fsType: ntfs
volumeBindingMode: WaitForFirstConsumer
```

다음 명령을 실행하여 StorageClass를 생성합니다.

```
kubectl apply -f NTFSStorageClass.yaml
```

다음 단계는 영구 볼륨 클레임(PVC)을 생성하는 것입니다.

PV(PersistentVolume)는 관리자가 프로비저닝하거나 PVC를 사용하여 동적으로 프로비저닝한 클러스터의 스토리지 조각입니다. 노드가 클러스터 리소스인 것처럼 클러스터의 리소스입니다. 이 API 객체는 NFS, iSCSI 또는 cloud-provider-specific 스토리지 시스템 등 스토리지 구현에 대한 세부 정보를 캡처합니다.

PersistentVolumeClaim(PVC)은 사용자의 스토리지 요청입니다. 클레임은 특정 크기 및 액세스 모드를 요청할 수 있습니다(예: ReadWriteOnce, ReadOnlyMany 또는 ReadWriteMany를 탑재할 수 있음).

사용자는 다양한 사용 사례에 대해 성능과 같은 다양한 속성을 가진 PersistentVolumes가 필요합니다. 클러스터 관리자는 사용자가 해당 볼륨이 구현되는 방법에 대한 세부 정보에 노출되지 않고 크기 및 액세스 모드보다 더 다양한 방식으로 다양한 PersistentVolumes을 제공할 수 있어야 합니다. 이러한 요구 사항에는 StorageClass 리소스가 있습니다.

아래 예제에서 PVC는 네임스페이스 기간 내에 생성되었습니다.

```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-windows-pv-claim
  namespace: windows
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: gp2-windows
  resources:
    requests:
      storage: 1Gi
```

다음 명령을 실행하여 PVC를 생성합니다.

```
kubectl apply -f persistent-volume-claim.yaml
```

다음 매니페스트는 Windows 포드를 생성하고 VolumeMount를 로 설정하고 PVC를에 연결된 스토리지로 `C:\Data` 사용합니다`C:\Data`.

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: windows-server-ltsc2019
  namespace: windows
spec:
  selector:
    matchLabels:
      app: windows-server-ltsc2019
      tier: backend
      track: stable
  replicas: 1
  template:
    metadata:
      labels:
        app: windows-server-ltsc2019
        tier: backend
        track: stable
    spec:
      containers:
      - name: windows-server-ltsc2019
        image: mcr.microsoft.com/windows/servercore:ltsc2019
        ports:
        - name: http
          containerPort: 80
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: "C:\\data"
          name: test-volume
      volumes:
        - name: test-volume
          persistentVolumeClaim:
            claimName: ebs-windows-pv-claim
      nodeSelector:
        kubernetes.io/os: windows
        node.kubernetes.io/windows-build: '10.0.17763'
```

PowerShell을 통해 Windows 포드에 액세스하여 결과를 테스트합니다.

```
kubectl exec -it podname powershell -n windows
```

Windows 포드 내에서 다음을 실행합니다. `ls` 

출력:

```
PS C:\> ls


    Directory: C:\


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----          3/8/2021   1:54 PM                data
d-----          3/8/2021   3:37 PM                inetpub
d-r---          1/9/2021   7:26 AM                Program Files
d-----          1/9/2021   7:18 AM                Program Files (x86)
d-r---          1/9/2021   7:28 AM                Users
d-----          3/8/2021   3:36 PM                var
d-----          3/8/2021   3:36 PM                Windows
-a----         12/7/2019   4:20 AM           5510 License.txt
```

**데이터 디렉터리**는 EBS 볼륨에서 제공됩니다.

## Windows용 Out-of-tree
<a name="_out_of_tree_for_windows"></a>

CSI 플러그인과 연결된 코드는 일반적으로 컨테이너 이미지로 배포되고 DaemonSets 및 StatefulSets와 같은 표준 Kubernetes 구문을 사용하여 배포되는 out-of-tree 스크립트 및 바이너리로 제공됩니다. CSI 플러그인은 Kubernetes에서 다양한 볼륨 관리 작업을 처리합니다. CSI 플러그인은 일반적으로 노드 플러그인(각 노드에서 DaemonSet로 실행됨)과 컨트롤러 플러그인으로 구성됩니다.

CSI 노드 플러그인(특히 블록 디바이스 또는 공유 파일 시스템을 통해 노출된 영구 볼륨과 관련된 플러그인)은 디스크 디바이스 스캔, 파일 시스템 탑재 등과 같은 다양한 권한 있는 작업을 수행해야 합니다. 이러한 작업은 호스트 운영 체제마다 다릅니다. Linux 작업자 노드의 경우 컨테이너화된 CSI 노드 플러그인은 일반적으로 권한 있는 컨테이너로 배포됩니다. Windows 작업자 노드의 경우 컨테이너화된 CSI 노드 플러그인에 대한 권한 있는 작업은 각 Windows 노드에 사전 설치해야 하는 커뮤니티 관리형 독립형 바이너리인 [csi-proxy](https://github.com/kubernetes-csi/csi-proxy)를 사용하여 지원됩니다.

 [Amazon EKS 최적화 Windows AMI에는 ](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-windows-ami.html)2022년 4월부터 CSI 프록시가 포함되어 있습니다. 고객은 Windows 노드의 [SMB CSI 드라이버](https://github.com/kubernetes-csi/csi-driver-smb)를 사용하여 [Amazon FSx for Windows File Server](https://aws.amazon.com/fsx/windows/), [Amazon FSx for NetApp ONTAP SMB 공유](https://aws.amazon.com/fsx/netapp-ontap/) 및/또는 [AWS Storage Gateway - File Gateway](https://aws.amazon.com/storagegateway/file/)에 액세스할 수 있습니다.

다음 [블로그](https://aws.amazon.com/blogs/modernizing-with-aws/using-smb-csi-driver-on-amazon-eks-windows-nodes/)에는 Amazon FSx for Windows File Server를 Windows 포드의 영구 스토리지로 사용하도록 SMB CSI 드라이버를 설정하는 방법에 대한 구현 세부 정보가 나와 있습니다.

## Amazon FSx for Windows File Server
<a name="_amazon_fsx_for_windows_file_server"></a>

옵션은 [SMB Global Mapping](https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/persistent-storage)이라는 SMB 기능을 통해 Amazon FSx for Windows File Server를 사용하는 것입니다. 이를 통해 호스트에 SMB 공유를 탑재한 다음 해당 공유의 디렉터리를 컨테이너에 전달할 수 있습니다. 컨테이너는 특정 서버, 공유, 사용자 이름 또는 암호로 구성할 필요가 없습니다.이 모든 작업은 호스트에서 대신 처리됩니다. 컨테이너는 로컬 스토리지가 있는 것처럼 작동합니다.

SMB 글로벌 매핑은 오케스트레이터에 투명하며**, 보안 문제를 암시**할 수 있는 HostPath를 통해 탑재됩니다.

아래 예제에서 경로`G:\Directory\app-state`는 Windows 노드의 SMB 공유입니다.

```
apiVersion: v1
kind: Pod
metadata:
  name: test-fsx
spec:
  containers:
  - name: test-fsx
    image: mcr.microsoft.com/windows/servercore:ltsc2019
    command:
      - powershell.exe
      - -command
      - "Add-WindowsFeature Web-Server; Invoke-WebRequest -UseBasicParsing -Uri 'https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.6/ServiceMonitor.exe' -OutFile 'C:\\ServiceMonitor.exe'; echo '<html><body><br/><br/><marquee><H1>Hello EKS!!!<H1><marquee></body><html>' > C:\\inetpub\\wwwroot\\default.html; C:\\ServiceMonitor.exe 'w3svc'; "
    volumeMounts:
      - mountPath: C:\dotnetapp\app-state
        name: test-mount
  volumes:
    - name: test-mount
      hostPath:
        path: G:\Directory\app-state
        type: Directory
  nodeSelector:
      beta.kubernetes.io/os: windows
      beta.kubernetes.io/arch: amd64
```

다음 [블로그](https://aws.amazon.com/blogs/containers/using-amazon-fsx-for-windows-file-server-on-eks-windows-containers/)에는 Amazon FSx for Windows File Server를 Windows 포드의 영구 스토리지로 설정하는 방법에 대한 구현 세부 정보가 나와 있습니다.

# Windows 컨테이너 이미지 강화
<a name="windows-hardening-containers-images"></a>

Windows 컨테이너 이미지를 강화하시나요? 수년 동안 전 세계 고객과 협력하여 레거시 워크로드를 컨테이너, 특히 Windows 워크로드로 마이그레이션하는 데 도움을 주고 있습니다. 20년 이상의 경험을 바탕으로 조직이 Windows Server를 강화하는 데 많은 노력과 리소스를 할애하여 CIS 벤치마크에서 런타임 바이러스 백신 보호에 이르기까지 민감한 데이터를 보호하는 모든 것을 구현하는 것을 보았습니다.

그러나 우려되는 추세가 나타났습니다. 이러한 매우 안전한 가상 머신이 컨테이너로 현대화됨에 따라 많은 중요한 강화 관행이 간과되고 있습니다. 기본 이미지(OS)에서 IIS와 같은 웹 서비스에 이르기까지 Windows 보안 모범 사례는 무시되는 경우가 많으며 대부분 컨테이너 호스트 보안에만 중점을 둡니다. 컨테이너는 격리된 네임스페이스에서 작동하지만 여전히 커널 프리미티브를 호스트와 공유한다는 점을 인식해야 합니다. 공격자는 일반적으로 컨테이너 호스트를 직접 타겟팅하는 것보다 측면 이동에 더 관심이 있어 취약한 컨테이너 보안 설정을 악용하고 민감한 데이터에 액세스할 수 있습니다.

설명서의 목표는 IIS에서 `ASP.NET` 웹 사이트를 호스팅하는 Windows 컨테이너에 특별히 구현해야 하는 몇 가지 필수 보안 설정을 강조하는 것입니다. 다음 네 가지 주요 영역에 초점을 맞출 것입니다.
+ 계정 보안 정책
+ 감사 정책
+ IIS 보안 모범 사례
+ 최소 권한의 원칙

먼저 이러한 각 보안 구성이 Windows 컨테이너를 보호하는 데 중요한 이유를 살펴보고, Windows 컨테이너가 완화하는 특정 위험과 컨테이너가 제공하는 보안 이점을 살펴보겠습니다. 다음으로 Dockerfile에서 이러한 구성을 올바르게 구현하여 잠재적 위협에 대비하여 컨테이너를 강화하는 방법을 보여주는 코드 조각을 살펴보겠습니다. 마지막으로 각 설정을 자세히 분석하여 함수, 컨테이너 보안에 미치는 영향, 애플리케이션 보호에 기여하는 방식에 대한 포괄적인 설명을 제공합니다. 이 접근 방식은 이러한 모범 사례를 적용하는 방법을 보여줄 뿐만 아니라 컨테이너화된 환경에서 강력한 보안 태세를 유지하는 데 필수적인 이유를 이해할 수 있는 통찰력을 제공합니다.

## 1. 로컬 보안 정책 및 레지스트리를 사용하여 계정 정책(암호 또는 잠금) 구성
<a name="_1_configure_account_policies_password_or_lockout_using_local_security_policies_and_registry"></a>

Windows Server Core는 [EKS Optimized Windows AMI](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-windows-ami.html)의 일부로 사용할 수 있는 최소 설치 옵션입니다. 로컬 보안 정책 및 레지스트리를 사용하여 계정 정책(암호 또는 잠금)을 구성하면 강력한 암호 및 잠금 규칙을 적용하여 시스템 보안이 강화됩니다. 이러한 정책은 사용자가 정의된 최소 길이와 복잡성으로 강력한 암호를 생성하여 일반적인 암호 관련 공격으로부터 보호하도록 요구합니다.

최대 암호 수명을 설정하면 사용자에게 암호를 정기적으로 업데이트하라는 메시지가 표시되므로 자격 증명이 손상될 가능성이 줄어듭니다. 잠금 정책은 지정된 수의 로그인 시도가 실패한 후 계정을 일시적으로 잠가 보호 계층을 추가하여 무차별 대입 공격을 방지하는 데 도움이 됩니다. Windows 레지스트리를 통해 이러한 설정을 구성하면 관리자가 시스템 수준에서 이러한 보안 조치를 적용하여 조직 전체에서 균일성과 규정 준수를 보장할 수 있습니다. 이러한 계정 정책을 Windows 컨테이너에 적용하는 것은 컨테이너가 종종 임시적이고 격리된 워크로드를 위한 것이더라도 보안 일관성을 유지하는 데 필수적입니다.

### 보안 일관성
<a name="_security_consistency"></a>
+ 규정 준수: 컨테이너에 일관된 암호 정책 및 잠금 규칙을 적용하면 특히 엄격한 액세스 제어(예: HIPAA, PCI-DSS와 같은 규정 준수)가 필요한 환경에서 보안 규정 준수를 유지하는 데 도움이 됩니다.
+ 강화된 컨테이너: 이러한 설정을 적용하면 무단 액세스 또는 암호 기반 공격에 대비하여 Windows 컨테이너가 강화되어 컨테이너의 보안 태세가 광범위한 시스템 보안 정책에 맞게 조정됩니다.

### 무차별 대입 공격으로부터 보호
<a name="_protection_against_brute_force_attacks"></a>
+ 계정 잠금: 이러한 설정은 특정 수의 로그인 시도 실패 후 계정을 잠가 무차별 대입 로그인 시도를 방지하는 데 도움이 됩니다. 이렇게 하면 공격자가 무제한의 암호를 시도할 수 없습니다.
+ 암호 복잡성: 길이가 충분한 복잡한 암호를 요구하면 컨테이너화된 격리된 환경에서도 취약한 암호가 악용될 가능성이 줄어듭니다.

### 다중 사용자 시나리오
<a name="_multi_user_scenarios"></a>
+ 컨테이너화된 애플리케이션이 여러 사용자를 처리하도록 설계되었거나 사용자 인증이 필요한 경우 암호 정책을 적용하면 컨테이너 내의 사용자 계정이 엄격한 보안 규칙을 준수하도록 하여 권한이 부여된 사용자로만 액세스를 제한할 수 있습니다.

### 영구 Windows 컨테이너
<a name="_persistent_windows_containers"></a>
+ 컨테이너는 일반적으로 임시로 간주되지만 특정 Windows 컨테이너는 장기 서비스를 실행하거나 사용자 관리를 처리할 수 있으므로 일반 Windows 서버와 유사한 적절한 보안 정책을 적용하는 것이 중요합니다.

### 하이브리드 환경의 일관성
<a name="_consistency_in_hybrid_environments"></a>
+ 인프라에서 가상 머신과 컨테이너를 모두 실행하는 경우 모든 환경에 동일한 보안 정책(예: 암호/잠금 정책)을 적용하면 균일한 보안 표준을 보장하여 거버넌스 및 관리를 간소화할 수 있습니다.

요약하면 Windows 컨테이너 내에 이러한 계정 정책을 적용하면 컨테이너가 보안 전략의 약점이 되지 않아 암호 공격으로부터 보호하고 전체 환경에서 일관성을 유지할 수 있습니다.

Dockerfile:

```
# Configure account policies for password complexity and lockout
RUN powershell -Command \
      "Write-Output 'Configuring Account Policies (Password/Lockout)...'; \
      NET ACCOUNTS /MINPWLEN:14 /MAXPWAGE:60 /MINPWAGE:14 /LOCKOUTTHRESHOLD:5
```

 **설명:** 

이 섹션에서는 Windows 레지스트리를 통한 암호 및 잠금 설정에 대한 계정 정책을 구성합니다. 이러한 정책은 암호 요구 사항 및 계정 잠금 임계값을 제어하여 보안을 강화하는 데 도움이 됩니다.

1.  **MinimumPasswordLength(MINPWLEN) = 14**이 설정은 암호의 최소 문자 수를 정의합니다. 범위는 0\$114자이고 기본값은 6자입니다.

1.  **MaximumPasswordAge(MAXPWAGE) = 60**이 설정은 암호가 유효한 최대 일수를 정의합니다. UNLIMITED를 사용하면 제한이 지정되지 않습니다. /MAXPWAGE는 /MINPWAGE보다 작을 수 없습니다. 범위는 1\$1999이고 기본값은 90일입니다.

1.  **잠금 임계값(LOCKOUTTHRESHOLD) = 5**이 설정은 실패한 로그인 시도에 대한 임계값을 정의합니다. 5번 잘못 시도하면 계정이 잠깁니다.

이러한 설정은 특정 횟수의 로그인 시도 실패 후 강력한 암호 정책을 적용하고 계정을 잠가 암호 보안을 개선하고 무차별 대입 공격을 방지하는 데 도움이 됩니다.

## 2. 감사 정책
<a name="_2_audit_policies"></a>

감사 정책은 로그인 시도 및 권한 사용과 같은 보안 이벤트에 대한 중요한 가시성을 제공하여 무단 액세스를 감지하고 사용자 활동을 모니터링하며 규제 표준 준수를 보장하는 데 도움이 되므로 Windows 컨테이너에 중요합니다. 컨테이너의 일시적 특성에서도 감사 로그는 인시던트 조사, 선제적 위협 탐지 및 컨테이너화된 환경 전반에서 일관된 보안 태세 유지에 필수적입니다.

 **보안 모니터링 및 규정 준수:** 
+ 사용자 활동 추적: 감사 정책을 통해 관리자는 컨테이너 내에서 로그인 시도 및 권한 사용과 같은 사용자 활동을 모니터링할 수 있습니다. 이는 무단 액세스 또는 의심스러운 동작을 감지하는 데 중요합니다.
+ 규정 준수: 많은 조직이 HIPAA, PCI-DSS 및 GDPR과 같은 규정을 준수하기 위해 보안 이벤트를 로깅해야 합니다. 컨테이너에서 감사 정책을 활성화하면 컨테이너화된 환경에서도 이러한 요구 사항을 충족할 수 있습니다.

 **인시던트 조사:** 
+ 포렌식 및 분석: 컨테이너화된 애플리케이션 또는 서비스가 손상된 경우 감사 로그는 인시던트 후 분석에 유용한 인사이트를 제공할 수 있습니다. 보안 팀이 공격자가 취한 조치를 추적하거나 침해가 발생한 방식을 식별하는 데 도움이 됩니다.
+ 실시간 감지: 감사 로그를 통해 관리자는 중요한 이벤트(예: 로그인 시도 실패, 권한 에스컬레이션)에 대한 실시간 알림을 설정할 수 있습니다. 이 선제적 모니터링은 공격을 조기에 탐지하고 대응 시간을 단축하는 데 도움이 됩니다.

 **환경 간 일관성:** 
+ 균일한 보안 태세: 레지스트리를 통해 컨테이너에 감사 정책을 적용하면 컨테이너화된 환경과 컨테이너화되지 않은 환경 모두에서 일관된 보안 관행을 보장할 수 있습니다. 이렇게 하면 컨테이너가 보안 모니터링의 사각지대가 되지 않습니다.
+ 하이브리드 환경의 가시성: 기존 Windows 서버와 컨테이너를 모두 실행하는 조직의 경우 감사 정책은 모든 플랫폼에서 유사한 가시성과 제어를 제공하여 관리를 더 쉽고 효과적으로 만듭니다.

 **권한 있는 작업 추적:** 
+ 권한 감사 사용: 애플리케이션이 승격된 권한으로 실행되거나 관리 작업이 수행되는 컨테이너 환경에서 권한 있는 작업을 감사하면 책임이 보장됩니다. 컨테이너 내에서 누가 민감한 리소스에 액세스했거나 중요한 작업을 수행했는지 로깅할 수 있습니다.
+ 권한 남용 방지: 권한 사용을 모니터링하여 권한이 없는 사용자가 권한을 높이거나 컨테이너 내의 제한된 영역에 액세스하려고 할 때 이를 감지하여 내부 또는 외부 공격을 방지할 수 있습니다.

 **무단 액세스 시도 감지:** 
+ 실패한 로그인 시도: 실패한 로그인 시도에 대한 감사 정책을 활성화하면 무차별 대입 공격 또는 컨테이너화된 애플리케이션에 대한 무단 액세스를 식별하는 데 도움이 됩니다. 이를 통해 시스템에 액세스하려는 사용자와 빈도를 파악할 수 있습니다.
+ 계정 잠금 모니터링: 계정 잠금 이벤트를 감사하면 관리자가 의심스럽거나 악의적인 활동으로 인한 잠재적 잠금을 감지하고 조사할 수 있습니다.

 **임시 환경에서도 지속적인 보안:** 
+ 임시 보안: 컨테이너는 임시적이므로 자주 삭제하고 다시 생성할 수 있지만 감사는 컨테이너가 실행되는 동안 보안 이벤트가 캡처되도록 하는 데 여전히 중요한 역할을 합니다. 이렇게 하면 컨테이너의 수명 주기 동안 중요한 보안 이벤트가 기록됩니다.

 **중앙 집중식 로깅:** 
+ 중앙 집중식 시스템으로 로그 전달: 컨테이너를 중앙 집중식 로깅 시스템(예: ELK 스택, AWS CloudWatch)과 통합하여 여러 컨테이너 인스턴스의 감사 로그를 캡처할 수 있습니다. 이를 통해 인프라 전반의 보안 이벤트를 더 잘 분석하고 상관관계를 파악할 수 있습니다.

Dockerfile:

```
# Configure audit policies for logging security events
RUN powershell -Command \
    "Write-Host 'Configuring Audit Policy..'; \
    Set-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa' -Name 'SCENoApplyLegacyAuditPolicy' -Value 0; \
    auditpol /set /category:"Logon/Logoff" /subcategory:"Logon" /failure:enable

# Creates STDOUT on Windows Containers (check GitHub LogMonitor:: https://github.com/microsoft/windows-container-tools/blob/main/LogMonitor/README.md)
COPY LogMonitor.exe LogMonitorConfig.json 'C:\\LogMonitor\\'
WORKDIR /LogMonitor
```

 **설명:** 

이 섹션에서는 레지스트리 수정을 사용하여 감사 정책을 구성합니다. 감사 정책은 Windows에서 기록되는 보안 이벤트를 제어하므로 무단 액세스 시도를 모니터링하고 감지하는 데 도움이 됩니다.

1.  **SCENoApplyLegacyAuditPolicy = 0** 레거시 감사 정책 형식을 비활성화하여 이후 버전의 Windows에 도입된 보다 세분화된 감사 정책을 활성화합니다. 이는 최신 감사 구성에 중요합니다.

1.  **Auditpol 하위 범주: "Logon" **이 설정을 사용하면 성공 및 실패 로그온 이벤트 모두에 대한 감사를 수행할 수 있습니다. 값 3은 Windows가 성공한 로그인 시도와 실패한 로그인 시도를 모두 로깅함을 의미합니다. 이렇게 하면 시스템에 액세스하는 사용자를 모니터링하고 실패한 로그인 시도를 포착하는 데 도움이 됩니다.

이러한 감사 정책은 로그인 시도 및 권한 있는 작업 사용과 같은 중요한 보안 이벤트에 대한 자세한 로그를 제공하므로 보안 모니터링 및 규정 준수에 매우 중요합니다.

## 3. Windows 컨테이너에 대한 IIS 보안 모범 사례
<a name="_3_iis_security_best_practices_for_windows_containers"></a>

Windows Containers에서 IIS 모범 사례를 구현하는 것은 애플리케이션이 안전하고 고성능이며 확장 가능하도록 하는 여러 가지 이유로 중요합니다. 컨테이너는 격리와 경량 환경을 제공하지만 취약성 및 운영 문제를 방지하기 위해 적절한 구성이 필요합니다. Windows 컨테이너의 IIS에 대한 다음 모범 사례가 중요한 이유는 다음과 같습니다.

 **보안** 
+ 일반적인 취약성 방지: IIS는 교차 사이트 스크립팅(XSS), 클릭재킹 및 정보 공개와 같은 공격의 대상인 경우가 많습니다. 보안 헤더(예: X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security)를 구현하면 이러한 위협으로부터 애플리케이션을 보호하는 데 도움이 됩니다.
+ 격리만으로는 충분하지 않음: 컨테이너는 격리되어 있지만 잘못 구성된 IIS 인스턴스는 서버 버전 세부 정보, 디렉터리 목록 또는 암호화되지 않은 통신과 같은 민감한 정보를 노출할 수 있습니다. 디렉터리 브라우징 및 IIS 버전 헤더 제거와 같은 기능을 비활성화하면 공격 표면을 최소화할 수 있습니다.
+ 암호화 및 HTTPS: HTTPS 전용 연결 적용과 같은 모범 사례는 전송 중인 데이터가 암호화되도록 하여 민감한 정보가 가로채지 않도록 보호합니다.

 **성능** 
+ 효율적인 리소스 사용: 동적 및 정적 압축 활성화와 같은 IIS 모범 사례는 대역폭 사용량을 줄이고 로드 시간을 개선합니다. 이러한 최적화는 리소스가 컨테이너와 호스트 시스템 간에 공유되는 컨테이너화된 환경에서 특히 중요합니다.
+ 최적화된 로깅: 로깅(예: X-Forwarded-For 헤더 포함)을 올바르게 구성하면 불필요한 로깅 오버헤드를 최소화하면서 클라이언트 활동을 추적할 수 있습니다. 이렇게 하면 성능 저하 없이 문제 해결을 위한 관련 데이터를 수집할 수 있습니다.

 **확장성 및 유지 관리성** 
+ 환경 간 일관성: 모범 사례를 따르면 IIS 구성이 여러 컨테이너 인스턴스에서 일관되게 유지됩니다. 이렇게 하면 크기 조정이 간소화되고 새 컨테이너가 배포될 때 동일한 보안 및 성능 지침을 준수할 수 있습니다.
+ 자동 구성: 폴더 권한 설정 및 불필요한 기능 비활성화와 같은 Dockerfiles의 모범 사례는 각 새 컨테이너가 자동으로 올바르게 구성되도록 합니다. 이렇게 하면 수동 개입이 줄어들고 인적 오류의 위험이 줄어듭니다.

 **규정 준수** 
+ 규제 요구 사항 충족: 많은 산업에는 암호화된 통신(HTTPS) 및 클라이언트 요청 로깅과 같은 특정 보안 조치를 요구하는 엄격한 규제 요구 사항(예: PCI-DSS, HIPAA)이 있습니다. 컨테이너의 IIS 모범 사례를 따르면 이러한 표준을 준수하는 데 도움이 됩니다.
+ 감사 가능성: 감사 정책 및 보안 로깅을 구현하면 감사에 중요한 이벤트를 추적할 수 있습니다. 예를 들어 X-Forwarded-For 헤더를 로깅하면 프록시 기반 아키텍처에 클라이언트 IP 주소가 올바르게 기록됩니다.

 **공유 환경의 위험 최소화** 
+ 잘못된 구성 방지: 컨테이너는 호스트의 커널을 공유하며, 서로 격리되어 있는 동안 잘못 구성된 IIS 인스턴스는 취약성을 노출하거나 성능 병목 현상을 일으킬 수 있습니다. 모범 사례는 각 IIS 인스턴스가 최적으로 실행되도록 하여 컨테이너 간 문제의 위험을 줄입니다.
+ 최소 권한 액세스: 컨테이너 내의 폴더 및 파일에 대한 적절한 권한을 설정하면(예: PowerShell의 Set-Acl 사용) 컨테이너 내의 사용자 및 프로세스가 필요한 액세스 권한만 가질 수 있으므로 권한 에스컬레이션 또는 데이터 변조의 위험이 줄어듭니다.

 **임시 환경의 복원력** 
+ 컨테이너의 임시 특성: 컨테이너는 수명이 짧고 자주 재구축되는 경우가 많습니다. IIS 모범 사례를 적용하면 재배포 횟수에 관계없이 각 컨테이너가 안전하고 일관되게 구성됩니다. 이렇게 하면 시간이 지남에 따라 잘못된 구성이 도입되는 것을 방지할 수 있습니다.
+ 잠재적 구성 오류 완화: 모범 사례(예: 취약한 프로토콜 또는 헤더 비활성화)를 자동으로 적용하면 컨테이너 재시작 또는 업데이트 중에 구성이 잘못될 위험이 최소화됩니다.

Dockerfile:

```
# Enforce HTTPS (disable HTTP) -- Only if container is target for SSL termination
RUN powershell -Command \
    "$httpBinding = Get-WebBinding -Name 'Default Web Site' -Protocol http | Where-Object { $_.bindingInformation -eq '*:80:' }; \
    if ($httpBinding) { Remove-WebBinding -Name 'Default Web Site' -Protocol http -Port 80; } \
    $httpsBinding = Get-WebBinding -Name 'Default Web Site' -Protocol https | Where-Object { $_.bindingInformation -eq '*:443:' }; \
    if (-not $httpsBinding) { New-WebBinding -Name 'Default Web Site' -Protocol https -Port 443 -IPAddress '*'; }"

# Use secure headers
RUN powershell -Command \
    "Write-Host 'Adding security headers...'; \
    Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter 'system.applicationHost/sites/siteDefaults/logFile/customFields' -name "." -value @{logFieldName='X-Forwarded-For';sourceName='X-Forwarded-For';sourceType='RequestHeader'}; \
    Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/httpProtocol/customHeaders" -name "." -value @{name='Strict-Transport-Security';value='max-age=31536000; includeSubDomains'}; \
    Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/httpProtocol/customHeaders" -name "." -value @{name='X-Content-Type-Options';value='nosniff'}; \
    Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/httpProtocol/customHeaders" -name "." -value @{name='X-XSS-Protection';value='1; mode=block'}; \
    Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/httpProtocol/customHeaders" -name "." -value @{name='X-Frame-Options';value='DENY'};"

# Disable IIS version disclosure
RUN powershell -Command \
    "Write-Host 'Disabling IIS version disclosure...'; \
    Import-Module WebAdministration; \
    Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/security/requestFiltering" -name "removeServerHeader" -value "true";"

# Set IIS Logging Best Practices
RUN powershell -Command \
    Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/directoryBrowse" -name "enabled" -value "false"; \
    Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/httpErrors" -name "existingResponse" -value "PassThrough"; \

# Enable IIS dynamic and static compression to optimize performance
RUN powershell -Command \
    "Write-Host 'Enabling IIS compression...'; \
    Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpCompressionDynamic; \
    Import-Module WebAdministration; \
    Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/urlCompression" -name "doDynamicCompression" -value "true"; \
    Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/urlCompression" -name "doStaticCompression" -value "true"

# Ensure proper folder permissions using PowerShell's Set-Acl

RUN powershell -Command \
    "Write-Host 'Setting folder permissions for IIS...'; \
    $path = 'C:\\inetpub\\wwwroot'; \
    $acl = Get-Acl $path; \
    $iusr = New-Object System.Security.Principal.NTAccount('IIS_IUSRS'); \
    $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($iusr, 'ReadAndExecute', 'ContainerInherit, ObjectInherit', 'None', 'Allow'); \
    $acl.SetAccessRule($rule); \
    $users = New-Object System.Security.Principal.NTAccount('Users'); \
    $rule2 = New-Object System.Security.AccessControl.FileSystemAccessRule($users, 'ReadAndExecute', 'ContainerInherit, ObjectInherit', 'None', 'Allow'); \
    $acl.SetAccessRule($rule2); \
    Set-Acl -Path $path -AclObject $acl"
```

설명:

이 명령은 요청이 프록시 또는 로드 밸런서를 통과할 때 원래 클라이언트 IP 주소를 캡처하는 데 일반적으로 사용되는 X-Forwarded-For 헤더를 로깅하도록 IIS를 구성합니다. 기본적으로 IIS는 로드 밸런서 또는 역방향 프록시의 IP 주소만 로깅하므로이 사용자 지정 로그 필드를 추가하면 보안 감사, 분석 및 문제 해결을 위한 실제 클라이언트 IP를 추적하는 데 도움이 됩니다.

1.  요청이 프록시 또는 로드 밸런서를 통과할 때 원래 클라이언트 IP 주소를 캡처하는 데 일반적으로 사용되는 **X-Forwarded-For 헤더**입니다. 기본적으로 IIS는 로드 밸런서 또는 역방향 프록시의 IP 주소만 로깅하므로이 사용자 지정 로그 필드를 추가하면 보안 감사, 분석 및 문제 해결을 위한 실제 클라이언트 IP를 추적하는 데 도움이 됩니다.

1.  **Strict-Transport-Security(HSTS)** 브라우저가 HTTPS를 통해서만 통신하도록 합니다. max-age=31536000은이 정책이 1년 동안 적용되도록 지정하고 includeSubDomains는 모든 하위 도메인에 정책을 적용합니다.

1.  **X-Content-Type-Options** 브라우저가 선언된 Content-Type에서 다른 응답을 "MIME-sniffing"하는 것을 방지합니다. 이렇게 하면 일부 유형의 공격을 방지하는 데 도움이 됩니다.

1.  **X-XSS-Protection** 브라우저에서 교차 사이트 스크립팅(XSS) 보호를 활성화합니다.

1.  **X-Frame-Options** 페이지가 iframe에 임베딩되는 것을 방지하여 클릭재킹 공격으로부터 보호합니다.

1.  **IIS 버전 공개 비활성화**이 명령은 HTTP 응답에서 서버 헤더를 비활성화하며, 기본적으로 사용 중인 IIS 버전을 표시합니다. 이 정보를 숨기면 공격자가 IIS 버전과 관련된 취약성을 식별하고 대상으로 지정할 위험을 줄이는 데 도움이 됩니다.

1.  **HTTPS 전용 연결 활성화**이 (코멘트 출력) 섹션에서는 HTTPS 연결을 적용하고 HTTP를 비활성화합니다. 주석 처리되지 않은 경우 Dockerfile은 포트 443(HTTPS)에서만 수신 대기하도록 IIS를 구성하고 포트 80에서 기본 HTTP 바인딩을 제거합니다. 이는 컨테이너 내에서 SSL을 종료할 때 유용하며 모든 트래픽이 암호화되도록 합니다.

1.  **디렉터리 찾아보기 비활성화** 기본 문서가 없을 때 IIS가 디렉터리 목록을 표시하지 못하도록 합니다. 이렇게 하면 내부 파일 구조가 사용자에게 노출되지 않습니다.

1.  **사용자 지정 오류 페이지 전달** 애플리케이션에 자체 오류 처리가 있는 경우 IIS는 기본 IIS 오류 페이지를 표시하는 대신 애플리케이션의 오류 페이지를 통과하도록 합니다.

1.  **세부 오류 모드** 로컬 요청에 대해서만 자세한 오류 메시지를 표시하도록 IIS를 구성하므로 개발자가 외부 사용자에게 민감한 정보를 노출하지 않고 문제를 진단할 수 있습니다.

1.  **적절한 폴더 권한 보장**이 블록은 IIS 웹 루트(C:\$1inetpub\$1wwwroot)에 대한 폴더 권한을 구성합니다. IIS\$1IUSRS 및 사용자 그룹에 대한 읽기 및 실행 권한을 설정하여 이러한 사용자가 폴더에 액세스하지만 파일을 수정할 수 없도록 합니다. 올바른 권한을 설정하면 웹 서버에서 호스팅하는 파일에 대한 무단 액세스 또는 변조 위험이 최소화됩니다.

Windows Containers의 IIS 모범 사례를 따르면 컨테이너화된 애플리케이션의 보안, 고성능 및 확장성이 보장됩니다. 이러한 관행은 취약성을 방지하고, 리소스 사용을 최적화하고, 규정 준수를 보장하고, 컨테이너 인스턴스 간 일관성을 유지하는 데 도움이 됩니다. 컨테이너는 격리되도록 설계되었지만 위험을 최소화하고 프로덕션 환경에서 애플리케이션의 신뢰성을 보장하려면 적절한 구성이 필요합니다.

## 4. 최소 권한의 원칙
<a name="_4_principle_of_least_privilege"></a>

최소 권한 원칙(PoLP)은 특히 컨테이너화된 환경 내에서 보안을 강화하고 위험을 최소화하는 등 몇 가지 중요한 이유로 Windows 컨테이너에 매우 중요합니다. 이 원칙은 시스템 또는 애플리케이션이 제대로 작동하는 데 필요한 최소 권한 수준으로 작동해야 한다고 규정합니다. Windows 컨테이너에서 중요한 이유는 다음과 같습니다.

 **공격 표면 최소화** 
+ 컨테이너는 다양한 시스템 구성 요소와 상호 작용하는 애플리케이션을 실행하는 경우가 많으며, 애플리케이션이 더 많은 권한을 가질수록 해당 구성 요소에 대한 액세스 범위가 넓어집니다. 컨테이너의 권한을 필요한 것으로만 제한하면 PoLP는 공격 표면을 크게 줄여 공격자가 컨테이너가 손상된 경우 컨테이너를 악용하기가 더 어려워집니다.

 **손상된 컨테이너의 영향 제한** 
+ Windows 컨테이너가 손상된 경우 과도한 권한(예: 관리자 또는 루트 수준 액세스)이 있는 애플리케이션을 실행하면 공격자가 중요한 시스템 파일을 제어하거나 컨테이너 호스트 전체에 권한을 에스컬레이션할 수 있습니다. PoLP를 적용하면 컨테이너가 침해되더라도 공격자가 수행할 수 있는 작업이 제한되어 민감한 리소스 또는 기타 컨테이너에 대한 추가 에스컬레이션 및 액세스를 방지할 수 있습니다.

 **멀티테넌트 환경의 보호** 
+ 클라우드 또는 엔터프라이즈 환경에서는 동일한 물리적 또는 가상 인프라에서 여러 컨테이너를 실행할 수 있습니다. PoLP는 손상된 컨테이너가 다른 테넌트에 속한 리소스 또는 데이터에 액세스할 수 없도록 합니다. 이 격리는 공유 멀티테넌트 환경에서 보안을 유지하여 컨테이너 간의 측면 이동을 방지하는 데 매우 중요합니다.

 **권한 에스컬레이션 완화** 
+ 공격자는 높은 권한으로 실행되는 컨테이너를 사용하여 시스템 내에서 권한을 에스컬레이션할 수 있습니다. PoLP는 시스템 리소스에 대한 컨테이너의 액세스를 제한하여 이러한 위험을 완화함으로써 컨테이너 환경을 넘어 무단 작업 또는 권한 에스컬레이션을 방지합니다.

 **규정 준수 및 감사** 
+ 많은 규제 표준 및 보안 프레임워크(예: PCI DSS, HIPAA, GDPR)에서는 시스템이 PoLP를 준수하여 민감한 데이터에 대한 액세스를 제한해야 합니다. 제한된 권한으로 Windows 컨테이너를 실행하면 조직이 이러한 규정을 준수하고 애플리케이션에 특별히 필요한 리소스에 대한 액세스 권한만 부여할 수 있습니다.

 **구성 오류 위험 줄이기** 
+ 컨테이너가 불필요한 권한으로 실행되는 경우 사소한 구성 오류로도 심각한 보안 취약성이 발생할 수 있습니다. 예를 들어 관리자로 실행되는 컨테이너가 실수로 인터넷에 노출된 경우 공격자가 시스템을 제어할 수 있습니다. PoLP는 기본적으로 제한된 권한으로 인해 이러한 위험을 방지하는 데 도움이 되므로 잘못된 구성이 위험하지 않습니다.

 **컨테이너 보안 태세 개선** 
+ PoLP를 따르면 컨테이너가 기본 호스트 시스템과 서로 더 잘 격리됩니다. 이렇게 하면 컨테이너화된 애플리케이션이 정의된 범위를 벗어나 시스템 파일 또는 프로세스에 액세스하거나 수정할 가능성이 줄어들어 호스트 운영 체제 및 기타 워크로드의 무결성이 유지됩니다.

Dockerfile:

```
# Strongly recommended that when deploying a Windows server container to any multi-tenant environment that your application runs via the ContainerUser account
USER ContainerUser
```

 **설명:** 

이 단원에서 USER ContainerUser 명령은 Windows 컨테이너 내의 애플리케이션이 기본 관리자 계정 대신 ContainerUser 계정에서 실행되도록 지정합니다.

특히 멀티테넌트 환경에서 이것이 중요한 이유는 다음과 같습니다.

1.  **최소 권한 원칙**: ContainerUser 계정은 권한이 제한된 관리자가 아닌 사용자입니다. 이 계정에서 애플리케이션을 실행하면 최소 권한 원칙을 준수하므로 악용 위험을 최소화하는 데 도움이 됩니다. 공격자가 애플리케이션을 손상시키려면 시스템에 대한 액세스가 제한되어 잠재적 손상이 줄어듭니다.

1.  **향상된 보안**: 멀티테넌트 환경에서 컨테이너는 동일한 기본 인프라를 공유할 수 있습니다. ContainerUser로 실행하면 한 컨테이너가 손상되더라도 중요한 시스템 파일 또는 기타 컨테이너에 액세스하거나 수정할 수 있는 관리 권한이 없습니다. 이렇게 하면 공격 표면이 크게 줄어듭니다.

1.  **루트 액세스 방지**: 기본적으로 컨테이너는 승격된 권한(Linux 컨테이너의 루트 액세스와 유사)으로 실행될 수 있으며, 이는 악용될 경우 위험할 수 있습니다. ContainerUser를 사용하면 애플리케이션이 불필요한 관리 권한으로 실행되지 않으므로 공격자가 권한을 에스컬레이션하는 것이 더 어려워집니다.

1.  **멀티테넌트 환경 모범 사례**: 여러 사용자 또는 조직이 동일한 인프라(예: 클라우드)를 공유하는 환경에서는 보안이 중요합니다. 제한된 권한으로 애플리케이션을 실행하면 한 테넌트의 애플리케이션이 다른 테넌트의 애플리케이션에 영향을 미치지 않으므로 플랫폼 전체에서 민감한 데이터와 리소스를 보호할 수 있습니다.

**USER ContainerUser** 명령은 애플리케이션이 최소한의 권한으로 실행되도록 하여 컨테이너가 손상된 경우 발생할 수 있는 손상을 제한하여 멀티테넌트 환경에서 보안을 강화합니다. 이는 컨테이너화된 환경에서 무단 액세스 또는 권한 에스컬레이션을 방지하는 모범 사례입니다.

최소 권한 원칙은 보안 침해의 잠재적 영향을 제한하고, 공격 표면을 줄이며, 중요한 시스템 구성 요소에 대한 무단 액세스를 방지하기 때문에 Windows 컨테이너에 필수적입니다. 필요한 권한으로만 컨테이너화된 애플리케이션을 실행하면 조직은 특히 멀티테넌트 및 공유 인프라에서 컨테이너 환경의 보안과 안정성을 크게 향상시킬 수 있습니다.

## 최종 생각: 오늘날의 위협 환경에서 Windows 컨테이너를 보호해야 하는 이유
<a name="_final_thoughts_why_securing_your_windows_containers_is_a_must_have_in_todays_threat_landscape"></a>

위협이 점점 더 정교해지고 풍부해지는 오늘날의 빠르게 진화하는 디지털 세계에서는 Windows 컨테이너를 보호하는 것이 단순한 권장 사항이 아니라 절대적으로 필요합니다. 컨테이너는 애플리케이션을 패키징하고 배포하는 가볍고 유연한 방법을 제공하지만 보안 취약성에 영향을 받지 않습니다. 더 많은 기업이 인프라를 간소화하기 위해 컨테이너를 채택함에 따라 제대로 보호되지 않으면 사이버 공격의 잠재적 대상이 됩니다.

인터넷에는 패치되지 않은 취약성을 대상으로 하는 악의적인 공격자부터 잘못된 구성에 대한 자동 봇 스캔에 이르기까지 다양한 위협이 넘쳐납니다. 올바른 보안 조치가 없으면 컨테이너를 악용하여 민감한 데이터를 노출하거나, 권한을 에스컬레이션하거나, 광범위한 인프라를 손상시킬 수 있는 공격의 진입점 역할을 할 수 있습니다. 이렇게 하면 환경의 다른 부분을 보호하는 것만큼 컨테이너 보안이 중요합니다.

Windows 컨테이너를 사용할 때는 여전히 많은 기존 보안 모범 사례가 적용됩니다. 강력한 계정 정책을 구현하고, IIS 구성을 보호하고, HTTPS를 적용하고, 엄격한 방화벽 규칙을 사용하고, 중요 파일에 최소 권한 액세스를 적용하는 것은 모두 컨테이너가 공격에 대한 복원력을 유지하도록 하는 주요 조치입니다. 또한 정기적인 감사 및 로깅을 통해 컨테이너 내에서 발생하는 상황을 파악할 수 있으므로 의심스러운 활동이 완전히 중단된 인시던트로 전환되기 전에 이를 포착할 수 있습니다.

또한 Windows 컨테이너 보안은 민감한 데이터를 보호하고 애플리케이션 무결성을 보장해야 하는 규제 요구 사항에 부합합니다. 클라우드 네이티브 아키텍처와 컨테이너화된 아키텍처가 점점 더 보편화됨에 따라 기본 이미지부터 실행 중인 컨테이너에 이르기까지 모든 계층에서 보안을 보장하면 운영을 보호하고 고객 신뢰를 유지하는 데 도움이 됩니다.

요약하면, 컨테이너화된 애플리케이션의 증가는 점점 더 많은 사이버 위협과 함께 컨테이너 보안을 최신 인프라 관리의 타협할 수 없는 측면으로 만듭니다. 모범 사례를 준수하고 취약성을 지속적으로 모니터링하면 기업은 보안을 손상시키지 않고 Windows 컨테이너의 민첩성과 효율성을 누릴 수 있습니다. 위협이 많은이 환경에서는 Windows 컨테이너를 보호하는 것이 단순한 옵션이 아니라 필수 항목입니다.