

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# Windows 的最佳實務
<a name="windows"></a>

本指南提供有關執行 Windows 容器和節點的建議。

**Topics**
+ [Amazon EKS 最佳化 Windows AMI 管理](windows-ami.md)
+ [為 Windows Pod 和容器設定 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 伺服器和容器](windows-patching.md)
+ [執行異質工作負載](windows-scheduling.md)
+ [Pod 安全內容](windows-security.md)
+ [持久性儲存選項](windows-storage.md)
+ [強化 Windows 容器映像](windows-hardening-containers-images.md)

# Amazon EKS 最佳化 Windows AMI 管理
<a name="windows-ami"></a>

Amazon EKS 最佳化 AMI 是根據 Windows Server 2019 和 Windows Server 2022 所建置。這些 AMI 已設定為 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 參數存放區 API，以程式設計方式擷取 Amazon EKS 最佳化 AMIs 的 Amazon Machine Image (AMI) ID。此參數讓您無需手動查詢 Amazon EKS 最佳化 AMI ID。如需 Systems Manager 參數存放區 API 的詳細資訊，請參閱 [GetParameter](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetParameter.html)。您的使用者帳戶必須具有 ssm：GetParameter IAM 許可，才能擷取 Amazon EKS 最佳化 AMI 中繼資料。

下列範例會擷取適用於 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 發行日期和/或作業系統建置版本之間進行選取。建置元件步驟可讓您在現有的 EKS Optimized Windows Artifacts 和 kubelet 版本之間進行選取。如需詳細資訊：https：//https://docs.aws.amazon.com/eks/latest/userguide/eks-custom-ami-windows.html

![\[建置元件\]](http://docs.aws.amazon.com/zh_tw/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 專業*、*Windows Out of Box Experience (OOBE)* 步驟，以及已完成的必要重新啟動。然後，這些快照會用於後續的啟動，以減少擴展或取代節點的時間。只有您透過 EC2 主控台或 AWS CLI *擁有*的 AMIs 才能啟用快速啟動，且可設定維護的快照數量。

 **注意：**快速啟動與預設 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。在 Pod 排程期間，容器映像必須完全提取並擷取在磁碟中，Pod 才會達到執行中狀態。

在此過程中，容器執行時間 （容器） 會在磁碟中提取和擷取整個容器映像。提取操作是平行程序，表示容器執行時間會平行提取容器映像層。相反地，擷取操作會在循序程序中發生，而且是 I/O 密集型操作。因此，容器映像可能需要超過 8 分鐘才能完全解壓縮，並準備好供容器執行時間 （容器） 使用，因此，Pod 啟動時間可能需要幾分鐘。

如**修補 Windows Server 和容器**主題所述，您可以選擇使用 EKS 建置自訂 AMI。在 AMI 準備期間，您可以新增額外的 EC2 映像建置器元件，以在本機提取所有必要的 Windows 容器映像，然後產生 AMI。此策略將大幅減少 Pod 達到**執行**中狀態的時間。

在 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 Builder (EC2InstanceProfileForImageBuilder) 所使用的 IAM 角色是否具有連接的政策：

![\[許可政策\]](http://docs.aws.amazon.com/zh_tw/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 Pod 和容器設定 gMSA
<a name="windows-gmsa"></a>

## 什麼是 gMSA 帳戶
<a name="_what_is_a_gmsa_account"></a>

.NET 應用程式等 Windows 型應用程式通常會使用 Active Directory 做為身分提供者，使用 NTLM 或 Kerberos 通訊協定提供授權/身分驗證。

與 Active Directory 交換 Kerberos 票證的應用程式伺服器需要加入網域。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 容器的形式執行的應用程式受益於 gMSA，因為 Windows 節點用於代表容器交換 Kerberos 票證。有兩個選項可用於設定 Windows 工作者節點以支援 gMSA 整合：

在此設定中，Windows 工作者節點在 Active Directory 網域中加入網域，Windows 工作者節點的 AD 電腦帳戶用於對 Active Directory 進行身分驗證，並擷取要與 Pod 搭配使用的 gMSA 身分。

在加入網域的方法中，您可以使用現有的 Active Directory GPOs 輕鬆管理和強化 Windows 工作者節點；不過，在加入 Kubernetes 叢集的 Windows 工作者節點期間會產生額外的操作額外負荷和延遲，因為它需要在節點啟動期間進行額外的重新啟動，並在 Kubernetes 叢集終止節點後進行 Active Directory 車庫清理。

在下列部落格文章中，您將找到如何實作加入網域的 Windows 工作者節點方法的詳細step-by-step說明：

 [Amazon EKS Windows Pod 上的 Windows 身分驗證](https://aws.amazon.com/blogs/containers/windows-authentication-on-amazon-eks-windows-pods/) 

在此設定中，Windows 工作者節點不會加入 Active Directory 網域，而且會使用「可攜式」身分 （使用者/密碼） 對 Active Directory 進行身分驗證，並擷取要與 Pod 搭配使用的 gMSA 身分。

![\[無網域 gmsa\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/windows/domainless_gmsa.png)


可攜式身分是 Active Directory 使用者；身分 （使用者/密碼） 存放在 AWS Secrets Manager 或 AWS System Manager 參數存放區中，而稱為 ccg\$1plugin 的 AWS 開發外掛程式將用於從 AWS Secrets Manager 或 AWS System Manager 參數存放區擷取此身分，並將其傳遞至容器化以擷取 gMSA 身分，並將其提供給 Pod。

在此無網域方法中，您可以在使用 gMSA 時，在 Windows 工作者節點啟動期間不進行任何 Active Directory 互動，並降低 Active Directory 管理員的操作開銷。

在下列部落格文章中，您將找到如何實作無網域 Windows 工作者節點方法的詳細step-by-step說明：

 [Amazon EKS Windows Pod 的無網域 Windows 身分驗證](https://aws.amazon.com/blogs/containers/domainless-windows-authentication-for-amazon-eks-windows-pods/) 

雖然 Pod 能夠使用 gMSA 帳戶，但也必須相應地設定應用程式或服務以支援 Windows 身分驗證，例如，若要設定 Microsoft IIS 以支援 Windows 身分驗證，您應該透過 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>

作業系統強化是作業系統組態、修補和移除不必要軟體套件的組合，旨在鎖定系統並減少攻擊面。最佳實務是使用貴公司所需的強化組態來準備您自己的 EKS Optimized Windows AMI。

AWS 每月提供新的 EKS 最佳化 Windows AMI，其中包含最新的 Windows Server 安全修補程式。不過，無論使用者是使用自我管理還是受管節點群組，使用者仍有責任透過套用必要的作業系統組態來強化其 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 Optimized Windows AMI 上實作。

## 使用 Windows Server Core 減少攻擊面
<a name="_reducing_attack_surface_with_windows_server_core"></a>

Windows Server Core 是最小的安裝選項，可作為 [EKS Optimized Windows AMI](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-windows-ami.html) 的一部分使用。部署 Windows Server Core 有幾個優點。首先，其磁碟佔用空間相對較小，在具有桌面體驗的 Windows Server 上，在 Server Core 上為 6GB，在 Windows Server 上為 10GB。其次，它具有較小的攻擊面，因為它的程式碼基礎和可用的 APIs 較小。

AWS 每月為客戶提供新的 Amazon EKS Optimized Windows AMIs，包含最新的 Microsoft 安全性修補程式，無論 Amazon EKS 支援的版本為何。根據最佳實務，Windows 工作者節點必須取代為以最新 Amazon EKS 最佳化 AMI 為基礎的新節點。任何執行超過 45 天的節點，如果沒有更新或節點替換，則缺少安全最佳實務。

## 避免 RDP 連線
<a name="_avoiding_rdp_connections"></a>

遠端桌面通訊協定 (RDP) 是由 Microsoft 開發的連線通訊協定，可提供使用者圖形界面，以透過網路連線至其他 Windows 電腦。

根據最佳實務，您應該將 Windows 工作者節點視為暫時性主機。這表示沒有管理連線、沒有更新，也沒有故障診斷。任何修改和更新都應實作為新的自訂 AMI，並以更新 Auto Scaling 群組取代。請參閱**修補 Windows 伺服器和容器**，以及 **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 Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html) 透過 AWS 主控台和 SSM 代理程式建立安全的 PowerShell 工作階段。若要了解如何實作解決方案，[請使用 AWS Systems Manager Session Manager 監看安全存取 Windows 執行個體](https://www.youtube.com/watch?v=nt6NTWQ-h6o) 

若要使用 System Manager Session Manager，必須將額外的 IAM 政策套用至用來啟動 Windows 工作者節點的 IAM 角色。以下是`eksctl`叢集資訊清單中指定 **AmazonSSMManagedInstanceCore** 的範例：

```
 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 Benchmark 評估，並且可以透過執行下列任務將其安裝在 Windows Server Core 上：

1. 下載下列 .exe 檔案：https：//https://inspector-agent.amazonaws.com/windows/installer/latest/AWSAgentInstall.exe

1. 將代理程式轉移到 Windows 工作者節點。

1. 在 PowerShell 上執行下列命令來安裝 Amazon Inspector Agent： `.\AWSAgentInstall.exe /install`

以下是第一次執行後的輸出。如您所見，它會根據 [CVE](https://cve.mitre.org/) 資料庫產生調查結果。您可以使用它來強化工作者節點，或根據強化的組態建立 AMI。

![\[檢測器代理程式\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/windows/inspector-agent.png)


如需 Amazon Inspector 的詳細資訊，包括如何安裝 Amazon Inspector 代理程式、設定 CIS 基準評估和產生報告，請觀看[透過 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，您對 Windows 工作者節點的惡意動作具有可見性，例如 RDP 暴力破解和 Port Probe 攻擊。

[使用 Amazon GuardDuty 影片觀看 Windows 工作負載的威脅偵測](https://www.youtube.com/watch?v=ozEML585apQ)，了解如何在最佳化 EKS Windows AMI 上實作和執行 CIS 基準

## Amazon EC2 for Windows 中的安全性
<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 管道整合。
+  [Anchore](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) 整合，請檢查：
+  [Anchore，在 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 Optimized Windows AMI 是以長期服務管道 (LTSC) 上的 Windows Server 2019 和 2022 Datacenter 版本為基礎。Datacenter 版本對工作者節點上執行的容器數量沒有限制。如需詳細資訊：https：//https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/faq

### 長期服務管道 (LTSC)
<a name="_long_term_servicing_channel_ltsc"></a>

先前稱為「長期服務分支」，這是您已熟悉的發行模型，其中每 2-3 年會發行新的 Windows Server 主要版本。使用者有權獲得 5 年的主流支援和 5 年延長支援。

## 授權
<a name="_licensing"></a>

使用 Windows Server 型 AMI 啟動 Amazon EC2 執行個體時，Amazon 會為您支付授權成本和授權合規。

# 日誌
<a name="windows-logging"></a>

容器化應用程式通常會將應用程式日誌導向 STDOUT。容器執行期會捕捉這些日誌，並對其執行一些操作 - 通常寫入檔案。這些檔案的儲存位置取決於容器執行時間和組態。

Windows Pod 的一個基本差異是它們不會產生 STDOUT。您可以執行 [LogMonitor](https://github.com/microsoft/windows-container-tools/tree/master/LogMonitor)，從執行 Windows 容器和管道格式化日誌輸出擷取 ETW （適用於 Windows 的事件追蹤）、Windows 事件日誌和其他應用程式特定日誌到 STDOUT。然後，您可以使用 fluent-bit 或 fluentd 將這些日誌串流到所需的目的地，例如 Amazon CloudWatch。

日誌收集機制會從 Kubernetes Pod 擷取 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/](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)，讓處理日誌項目變得更輕鬆，因為這類結構化格式有許多預先編寫的剖析器。
+  **集中日誌** - 專用日誌容器可用於收集日誌訊息，並將日誌訊息從所有容器轉送至目的地
+ 保持**日誌詳細程度**，除除除除除偵錯之外。Verbosity 會對日誌記錄基礎設施造成許多壓力，而且在噪音中可能會遺失重大事件。
+ 一律記錄**應用程式資訊**以及**交易/請求 ID **以供追蹤。Kubernetes 物件不會攜帶應用程式名稱，因此例如，偵錯日誌時，Pod 名稱`windows-twryrqyw`可能沒有任何意義。這有助於使用彙總日誌對應用程式進行可追蹤性和故障診斷。

  如何產生這些交易/關聯 ID 的方式取決於程式設計建構。但是，非常常見的模式是使用記錄 Aspect/攔截器，它可以使用 [MDC](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html) （映射診斷內容） 將唯一的交易/關聯 ID 注入到每個傳入的請求，如下所示：

```
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>

Prometheus，一個[漸進式 CNCF 專案](https://www.cncf.io/projects/)是到目前為止最熱門的監控系統，具有與 Kubernetes 的原生整合。Prometheus 會收集容器、Pod、節點和叢集的相關指標。此外，Prometheus 利用 AlertsManager，可讓您編寫警示程式，在叢集發生錯誤時警告您。Prometheus 會將指標資料儲存為由指標名稱和索引鍵/值對識別的時間序列資料。Prometheus 包括離開使用稱為 PromQL 的語言進行查詢，Prometheus 查詢語言很短。

Prometheus 指標集合的高階架構如下所示：

![\[Prometheus 指標集合\]](http://docs.aws.amazon.com/zh_tw/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 節點的主機硬體和作業系統指標，但不適用於 Windows 節點。

當您使用穩定的 [Prometheus Helm Chart](https://github.com/prometheus-community/helm-charts) 時，在**具有 Windows 節點的混合節點 EKS 叢集**中，您會在 Windows 節點上看到失敗的 Pod，因為此匯出工具不適用於 Windows。您需要分開處理 Windows 工作者集區，而是在 [Windows 工作者節點群組上安裝 Windows 匯出工具](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 防火牆中建立例外狀況。如果在沒有任何參數的情況下執行安裝程式，匯出程式將以已啟用收集器、連接埠等的預設設定執行。

您可以查看本指南的**排程最佳實務**章節，其中建議使用污點/容錯或 RuntimeClass 來選擇性地將節點匯出器僅部署到 linux 節點，而 Windows 匯出器在您引導節點或使用您選擇的組態管理工具 （例如 Chef、Ansible、SSM 等） 時安裝在 Windows 節點上。

請注意，與節點匯出器安裝為協助程式集 的 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 可以透過將下列 scrape\$1config 新增至 Prometheus 組態來取用指標

```
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 運算子](https://github.com/prometheus-operator/kube-prometheus/releases)的一部分】，為 ServiceMonitor 物件和控制器提供定義，以啟用我們定義的 ServiceMonitors，並自動建置所需的 Prometheus 組態。

ServiceMonitor 會明確指定應如何監控 Kubernetes 服務群組，用來定義您希望從 Kubernetes 內抓取指標的應用程式。在 ServiceMonitor 中，我們指定 Kubernetes 標籤，讓操作員用來識別 Kubernetes 服務，進而識別我們想要監控的 Pod。

為了利用 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 容器使用 Linux 建構，例如命名空間、聯集檔案系統和 cgroup。在 Windows 上，這些建構會從[主機運算服務 (HCS)](https://github.com/microsoft/hcsshim) 所容器化的 中抽象。HCS 充當位於 Windows 上容器實作上方的 API 層。Windows 容器也會利用 Host Network Service (HNS) 來定義節點上的網路拓撲。

![\[Windows 聯網\]](http://docs.aws.amazon.com/zh_tw/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) 來連線至 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 工作者節點可支援的 Pod 數量取決於節點的大小和可用的 IPv4 地址數量。您可以計算節點上可用的 IPv4 地址，如下所示：
+ 根據預設，只有次要 IPv4 地址會指派給 ENI。在這種情況下：

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

  我們從總數中減去一個，因為一個 IPv4 地址將用作 ENI 的主要地址，因此無法配置給 Pod。
+ 如果叢集已透過啟用[字首委派功能](prefix-mode-win.md)設定為高 Pod 密度，則

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

  在這裡，VPC 資源控制器將配置次要 IPv4 地址，`/28 prefixes`因此，可用 IPv4 地址的整體數量將增加 16 次。

使用上述公式，我們可以根據 m5.large 執行個體計算 Windows 工作者節點的 Pod 上限，如下所示：
+ 根據預設，在次要 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 個服務的節點會有連接埠耗盡的風險。當出現此條件時，節點會開始擲回錯誤，並顯示下列訊息：

 **「政策建立失敗：hcnCreateLoadBalancer 在 Win32 中失敗：指定的連接埠已存在。」** 

為了解決此問題，我們利用 Direct Server Return (DSR)。DSR 是非對稱網路負載分佈的實作。換句話說，請求和回應流量會使用不同的網路路徑。此功能可加速 Pod 之間的通訊，並降低連接埠耗盡的風險。因此，我們建議您在 Windows 節點上啟用 DSR。

預設會在 Windows Server SAC EKS 最佳化 AMIs 中啟用 DSR。對於 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/zh_tw/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 地址和字首委派的 Pod 密度優勢之間取得平衡。

使用指派次要 IPv4 地址的預設設定時，目前沒有支援的組態可操作 VPC 資源控制器請求和配置 IPv4 地址的方式。更具體地說， `minimum-ip-target`和 `warm-ip-target` 僅支援字首委派模式。另請注意，在次要 IP 模式中，視界面上的可用 IP 地址而定，VPC 資源控制器通常會代表您在節點上配置 3 個未使用的 IPv4 地址，以維持暖 IPs以加快 Pod 啟動時間。如果您想要將未使用的暖 IP 地址 IP 浪費降至最低，您可以瞄準在指定的 Windows 節點上排程更多 Pod，以便盡可能使用 ENI 的 IP 地址容量。更明確地說， IPs 如果節點和執行中的 Pod 已在使用 ENI 上的所有 IP 地址，您可以避免使用暖未使用的 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 耗盡。在這些情況下，可以使用 Calico CNI 取代 AWSVPC CNI。[Project Calico](https://www.projectcalico.org/) 是由 [Tigera](https://www.tigera.io/) 開發的開放原始碼軟體。該軟體包含可與 EKS 搭配使用的 CNI。您可以在專案 Calico EKS 安裝頁面上找到在 [EKS 中安裝 Calico CNI ](https://docs.projectcalico.org/getting-started/kubernetes/managed-public-cloud/eks)的說明。

## 網路政策
<a name="_network_polices"></a>

最佳實務是將 Kubernetes 叢集上 Pod 之間的預設開放通訊模式變更為根據網路政策限制存取。開放原始碼 [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 目前不支援某些功能，例如「Pod 安全群組」。

# 避免 OOM 錯誤
<a name="windows-oom"></a>

Windows 沒有與 Linux out-of-memory程序刪除程式。Windows 一律會將所有使用者模式記憶體配置視為虛擬，且 pagefile 是強制性的。淨效果是 Windows 不會像 Linux 那樣脫離記憶體條件。程序將分頁到磁碟，而不是因記憶體不足 (OOM) 而終止。如果記憶體過度佈建且所有實體記憶體都用盡，分頁可能會降低效能。

## 保留系統和 kubelet 記憶體
<a name="_reserving_system_and_kubelet_memory"></a>

與 Linux 不同，Linux 會`--kubelet-reserve`**擷取** kubelet、容器執行時間等 kubernetes 系統常駐程式的資源保留，以及`--system-reserve`**擷取** sshd、udev 等作業系統常駐程式的資源保留。在 **Windows** 上，這些標記不會**擷取**和**設定**在節點****上執行的 **kubelet** 或程序的記憶體限制。

不過，您可以結合這些旗標來管理 **NodeAllocatable**，以使用 Pod 資訊清單**記憶體資源限制**來減少節點上的容量，以控制每個 Pod 的記憶體配置。使用此策略，您可以更好地控制記憶體配置，以及將 Windows 節點上的out-of-memory(OOM) 降至最低的機制。

在 Windows 節點上，最佳實務是為作業系統和程序保留至少 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：//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。這些數字會隨著您新增 Windows 元件而增加，例如 .NET Framework、Web Services as IIS 和應用程式。

您必須了解 Windows 容器映像所需的最低記憶體量，即基礎映像及其應用程式層，並將其設定為 Pod 規格中的容器資源/請求。您也應該設定限制，以避免 Pod 在應用程式發生問題時消耗所有可用的節點記憶體。

在下面的範例中，當 Kubernetes 排程器嘗試在節點上放置 Pod 時，會使用 Pod 的請求來判斷哪個節點有足夠的資源可供排程。

```
 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 伺服器和容器
<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/zh_tw/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 發佈 EKS 最佳化 AMIs，其中包含兩個快取的 Windows 容器映像。

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

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


快取映像會在主要作業系統的更新之後更新。當 Microsoft 發行直接影響 Windows 容器基礎映像的新 Windows 更新時，更新將作為主要作業系統上的一般 Windows Update 啟動。讓環境保持在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 中的 layer 大小為 **533.05MB。**

![\[ecr 映像\]](http://docs.aws.amazon.com/zh_tw/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% 的 GB 已經在磁碟上做為快取的容器映像。

## 參考資料
<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 上執行的 Pod 和在 Windows 上執行的 Pod。您甚至可以在同一個叢集中執行多個版本的 Windows。不過，在做出此決策時，需要考慮幾個因素 （如下所述）。

## 將 PODs 指派給節點最佳實務
<a name="_assigning_pods_to_nodes_best_practices"></a>

為了將 Linux 和 Windows 工作負載保留在其各自的作業系統特定節點上，您需要使用節點選取器和污點/容錯的一些組合。在異質環境中排程工作負載的主要目標是避免中斷現有 Linux 工作負載的相容性。

## 確保作業系統特定的工作負載登陸適當的容器主機
<a name="_ensuring_os_specific_workloads_land_on_the_appropriate_container_host"></a>

使用者可以確保使用 nodeSelectors 在適當的主機上排程 Windows 容器。目前所有 Kubernetes 節點都有下列預設標籤：

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

如果 Pod 規格不包含如 的 nodeSelector`"kubernetes.io/os": windows`，則可以在任何主機、Windows 或 Linux 上排程 Pod。這可能會有問題，因為 Windows 容器只能在 Windows 上執行，Linux 容器只能在 Linux 上執行。

在企業環境中，針對 Linux 容器擁有大量預先存在的部署，以及 Helm Chart 等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 節點，排程器不會在這些節點上排程 Pod，除非它們能容忍污點。Pod 資訊清單範例：

```
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>

每個 Pod 使用的 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 版本。


| 產品名稱 | 組建編號 (s) | 
| --- | --- | 
|  伺服器完整 2022 LTSC  |  20348 年 10 月 0 日  | 
|  伺服器核心 2019 LTSC  |  10.0.17763  | 

您可以透過下列命令檢查作業系統建置版本：

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

KERNEL-VERSION 輸出符合 Windows 作業系統建置版本。

```
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
```

以下範例會將額外的 nodeSelector 套用至 Pod 資訊清單，以便在執行不同的 Windows 節點群組作業系統版本時符合正確的 Windows 建置版本。

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

## 使用 RuntimeClass 簡化 Pod 資訊清單中的 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 之後，請使用 做為 Pod 資訊清單上的規格來指派：

```
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 受管節點群組 (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：//https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html

若要進一步了解 Pod Networking (CNI) 的運作方式，請查看以下連結：https：//https://docs.aws.amazon.com/eks/latest/userguide/pod-networking.html

部署適用於 Windows on EKS 的受管節點群組的 AWS 部落格：https：//https://aws.amazon.com/blogs/containers/deploying-amazon-eks-windows-managed-node-groups/

# Pod 安全內容
<a name="windows-security"></a>

 **Pod 安全政策 (PSP)** 和 **Pod 安全標準 (PSS)** 是在 Kubernetes 中強制執行安全性的兩種主要方式。請注意，自 PodSecurityPolicy 已棄用，並將在 v1.25 中移除，且 Pod 安全標準 (PSS) 是 Kubernetes 建議的方法，可強制執行安全性。

Pod 安全政策 (PSP) 是 Kubernetes 中實作安全政策的原生解決方案。PSP 是叢集層級的資源，可控制 Pod 規格的安全敏感層面。使用 Pod 安全政策，您可以定義一組 Pod 必須滿足的條件，才能由叢集接受。PSP 功能已從 Kubernetes 的早期開始提供，旨在封鎖在指定叢集上建立設定錯誤的 Pod。

如需 Pod 安全政策的詳細資訊，請參閱 Kubernetes [文件](https://kubernetes.io/docs/concepts/policy/pod-security-policy/)。根據 [Kubernetes 棄用政策](https://kubernetes.io/docs/reference/using-api/deprecation-policy/)，較舊版本將在功能棄用九個月後停止取得支援。

另一方面，Pod 安全標準 (PSS) 是建議的安全性方法，通常使用安全內容實作，在 Pod 資訊清單中定義為 Pod 和容器規格的一部分。PSS 是 Kubernetes 專案團隊為解決 Pod 的安全相關最佳實務而定義的官方標準。它定義了政策，例如基準 （最低限制性、預設性）、特殊權限 （無限制性） 和限制性 （最高限制性）。

我們建議您從基準描述檔開始。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 Pod 與標準 Linux 型工作負載有一些限制和差異。

Windows 使用每個容器的任務物件搭配系統命名空間篩選條件，以包含容器中的所有程序，並提供與主機的邏輯隔離。如果沒有命名空間篩選，就無法執行 Windows 容器。這表示無法在主機的內容中宣告系統權限，因此 Windows 上無法使用特權容器。

以下是唯一記錄`windowsOptions`的 [Windows 安全內容選項](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#windowssecuritycontextoptions-v1-core)，其餘則是一般[安全內容選項](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)的官方文件。

Pod 特定設定會套用至所有容器。如果未指定，則會使用 PodSecurityContext 中的選項。如果同時在 SecurityContext 和 PodSecurityContext 中設定，則 SecurityContext 中指定的值優先。

例如，Pod 和容器的 runAsUserName 設定是 Windows 選項的大約相當於 Linux 特定 runAsUser 設定，並且在下列資訊清單中，Pod 特定安全內容會套用至所有容器

```
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
```

但在下列情況下，容器層級安全內容會覆寫 Pod 層級安全內容。

```
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 Pod 執行容器。容器和主機之間不會共用使用者，但 ContainerAdministrator 在容器中具有 的其他權限。請注意，有使用者名稱[限制](https://kubernetes.io/docs/tasks/configure-pod-container/configure-runasusername/#windows-username-limitations)需要注意。

使用 ContainerAdministrator 的良好範例是設定 PATH。您可以使用 USER 指令來執行此操作，如下所示：

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

另請注意，秘密會在節點磁碟區上以純文字撰寫 （相較於 linux 上的 tmpfs/記憶體內）。這表示您必須執行兩件事
+ 使用檔案 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 叢集上做為延伸模組。這可讓廠商更新out-of-band驅動程式，即與 Kubernetes 發行週期分開。這在很大程度上是可能的，因為 Kubernetes 已建立儲存界面或 CSI，為廠商提供與 k8 連接的標準方式。

您可以在 https://docs.aws.amazon.com/eks/latest/userguide/storage.html：// 查看有關 Amazon Elastic Kubernetes Services (EKS) 儲存類別和 CSI 驅動程式的詳細資訊

## 適用於 Windows 的樹狀內磁碟區外掛程式
<a name="_in_tree_volume_plugin_for_windows"></a>

Kubernetes 磁碟區可讓具有資料持久性需求的應用程式部署在 Kubernetes 上。持久性磁碟區的管理包含佈建/取消佈建/調整磁碟區大小、將磁碟區連接至 Kubernetes 節點或從 Kubernetes 節點移除磁碟區，以及將磁碟區掛載/卸載至 Pod 中的個別容器。針對特定儲存後端或通訊協定實作這些磁碟區管理動作的程式碼，會以 Kubernetes 磁碟區外掛程式 **（樹狀內磁碟區外掛程式）** 的形式運送。在 Amazon Elastic Kubernetes Services (EKS) 上，Windows 支援以下類別的 Kubernetes 磁碟區外掛程式：

 *樹狀內磁碟區外掛程式：*[awsElasticBlockStore](https://kubernetes.io/docs/concepts/storage/volumes/#awselasticblockstore) 

若要在 Windows 節點上使用樹狀內磁碟區外掛程式，必須建立額外的 StorageClass，才能使用 NTFS 做為 fsType。在 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>
```

若要建立新的 StorageClass 以支援 **NTFS**，請使用下列資訊清單：

```
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)。

PersistentVolume (PV) 是由管理員佈建或使用 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 Pod、將 VolumeMount 設定為 ，`C:\Data`並使用 PVC 做為 上連接的儲存體`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 Pod 來測試結果：

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

在 Windows Pod 中，執行： `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 磁碟區提供。

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

與 CSI 外掛程式相關聯的程式碼會以out-of-tree指令碼和二進位形式提供，通常以容器映像形式分佈，並使用 DaemonSets 和 StatefulSets 等標準 Kubernetes 建構模組進行部署。CSI 外掛程式可在 Kubernetes 中處理各種磁碟區管理動作。CSI 外掛程式通常由節點外掛程式 （以 DaemonSet 的形式在每個節點上執行） 和控制器外掛程式組成。

CSI 節點外掛程式 （特別是與以區塊型儲存設備或透過共用檔案系統公開的持久性磁碟區相關聯的外掛程式） 需要執行各種特殊權限操作，例如掃描磁碟裝置、掛載檔案系統等。這些操作會因每個主機作業系統而有所不同。對於 Linux 工作者節點，容器化 CSI 節點外掛程式通常會部署為特權容器。對於 Windows 工作者節點，使用 [csi-proxy 支援容器化 CSI 節點外掛程式的特權操作，csi-proxy](https://github.com/kubernetes-csi/csi-proxy) 是需要在每個 Windows 節點上預先安裝的社群受管、獨立二進位檔。

 [Amazon EKS Optimized Windows AMI 從 ](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-windows-ami.html)2022 年 4 月開始包含 CSI-proxy。客戶可以使用 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 Shares](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/)提供實作詳細資訊，說明如何設定 SMB CSI 驅動程式使用 Amazon FSx for Windows File Server 做為 Windows Pod 的持久性儲存體。

## 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 Pod 的持久性儲存體。

# 強化 Windows 容器映像
<a name="windows-hardening-containers-images"></a>

您是否正在強化 Windows 容器映像？ 多年來，我與全球客戶合作，協助他們將舊版工作負載遷移至容器，特別是 Windows 工作負載。憑藉 20 多年的經驗，我看到組織投入大量心力和資源來強化 Windows Server，實作從 CIS Benchmarks 到執行期防毒保護的所有項目，以保護敏感資料。

不過，出現了令人擔憂的趨勢。由於這些高度安全的虛擬機器會現代化為容器，因此許多重要的強化實務都會遭到忽略。從基礎映像 (OS) 到 IIS 等 Web 服務，Windows 安全最佳實務通常被忽略，其中大部分重點僅放在保護容器主機。請務必了解，當容器在隔離的命名空間中運作時，它們仍會與主機共用核心基本概念。攻擊者通常對橫向移動更感興趣，而不是直接鎖定容器主機，讓他們能夠利用脆弱的容器安全設定並存取敏感資料。

文件的目標是強調您應該特別針對 IIS 上託管`ASP.NET`網站的 Windows 容器實作的一些基本安全設定。我們將專注於四個關鍵領域：
+ 帳戶安全政策
+ 稽核政策
+ IIS 安全最佳實務
+ 最低權限準則

首先，我們將深入探討為什麼每個安全組態對於保護您的 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-14 個字元；預設值為六個字元。

1.  **MaximumPasswordAge (MAXPWAGE) = 60** 此設定會定義密碼有效的天數上限。使用 UNLIMITED 不會指定任何限制。/MAXPWAGE 不能小於 /MINPWAGE。範圍為 1-999；預設值為 90 天

1.  **鎖定閾值 (LOCKOUTTHRESHOLD) = 5** 此設定會定義失敗登入嘗試的閾值。5 次不正確的嘗試後，帳戶將被鎖定。

這些設定透過強制執行強式密碼政策，並在登入嘗試失敗一定次數後鎖定帳戶，協助改善密碼安全性並防止暴力攻擊。

## 2. 稽核政策
<a name="_2_audit_policies"></a>

稽核政策對於 Windows Containers 很重要，因為它們提供安全事件的關鍵可見性，例如登入嘗試和權限使用、協助偵測未經授權的存取、監控使用者活動，並確保符合法規標準。即使在容器的暫時性性質下，稽核日誌對於事件調查、主動威脅偵測以及跨容器化環境維持一致的安全狀態至關重要。

 **安全監控與合規：**
+ 追蹤使用者活動：稽核政策可讓管理員監控容器內的使用者活動，例如登入嘗試和權限使用。這對於偵測未經授權的存取或可疑行為至關重要。
+ 法規合規：許多組織需要記錄安全事件以符合 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 子類別：「登入」 ** 此設定可同時稽核成功和失敗登入事件。值 3 表示 Windows 將記錄成功和失敗的登入嘗試。這有助於監控誰正在存取系統和擷取失敗的登入嘗試。

這些稽核政策對於安全監控和合規至關重要，因為它們提供重要安全事件的詳細日誌，例如登入嘗試和使用特殊權限操作。

## 3. Windows 容器的 IIS 安全最佳實務
<a name="_3_iis_security_best_practices_for_windows_containers"></a>

在 Windows Containers 中實作 IIS 最佳實務很重要，有幾個原因可確保您的應用程式安全、高效能且可擴展。雖然容器提供隔離和輕量型環境，但它們仍需要適當的組態，以避免漏洞和操作問題。以下是為什麼在 Windows Containers 中遵循 IIS 的最佳實務至關重要：

 **安全性** 
+ 防止常見漏洞：IIS 通常是跨網站指令碼 (XSS)、點擊劫持和資訊揭露等攻擊的目標。實作安全標頭 （例如 X-Content-Type-Options、X-Frame-Options 和 Strict-Transport-Security) 有助於保護您的應用程式免受這些威脅。
+ 隔離不足：容器已隔離，但設定錯誤的 IIS 執行個體可能會公開敏感資訊，例如伺服器版本詳細資訊、目錄清單或未加密的通訊。透過停用目錄瀏覽和移除 IIS 版本標頭等功能，您可以將攻擊面降至最低。
+ 加密和 HTTPS：最佳實務，例如強制執行僅限 HTTPS 的連線，確保傳輸中的資料已加密，防止敏感資訊遭到攔截。

 **效能** 
+ 高效率資源使用：IIS 最佳實務，例如啟用動態和靜態壓縮，可減少頻寬使用量並縮短載入時間。這些最佳化在容器化環境中特別重要，其中資源會跨容器和主機系統共用。
+ 最佳化記錄：正確設定記錄 （例如，包括 X-Forwarded-For 標頭） 可確保您可以追蹤用戶端活動，同時將不必要的記錄開銷降至最低。這可協助您收集相關資料進行故障診斷，而不會降低效能。

 **可擴展性與可維護性** 
+ 跨環境一致性：透過遵循最佳實務，您可以確保 IIS 組態在多個容器執行個體之間保持一致。這可簡化擴展，並確保在部署新容器時，它們遵守相同的安全性和效能準則。
+ 自動化組態：Dockerfiles 中的最佳實務，例如設定資料夾許可和停用不必要的功能，確保每個新容器都已正確設定。這可降低手動介入並降低人為錯誤的風險。

 **合規** 
+ 符合法規要求：許多產業都有嚴格的法規要求 （例如 PCI-DSS、HIPAA)，要求特定的安全措施，例如加密通訊 (HTTPS) 和用戶端請求的記錄。遵循容器中的 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"
```

說明：

此命令會將 IIS 設定為記錄 X-Forwarded-For 標頭，該標頭通常用於在請求通過代理或負載平衡器時擷取原始用戶端 IP 地址。根據預設，IIS 只會記錄負載平衡器或反向代理的 IP 地址，因此新增此自訂日誌欄位有助於追蹤真正的用戶端 IP，以進行安全稽核、分析和故障診斷。

1.  **X-Forwarded-For 標頭**，通常用於在請求通過代理或負載平衡器時擷取原始用戶端 IP 地址。根據預設，IIS 只會記錄負載平衡器或反向代理的 IP 地址，因此新增此自訂日誌欄位有助於追蹤真正的用戶端 IP，以進行安全稽核、分析和故障診斷。

1.  **Strict-Transport-Security (HSTS)** 確保瀏覽器僅透過 HTTPS 進行通訊。max-age=31536000 指定此政策強制執行 1 年，且 includeSubDomains 會將政策套用至所有子網域。

1.  **X-Content-Type-Options** 防止瀏覽器「MIME-sniffing」回應離開宣告的內容類型。這有助於防止某些類型的攻擊。

1.  **X-XSS-Protection** 在瀏覽器中啟用跨網站指令碼 (XSS) 保護。

1.  **X-Frame-Options** 防止頁面內嵌在 iframe 中，防止點擊劫持攻擊。

1.  **停用 IIS 版本揭露** 此命令會在 HTTP 回應中停用伺服器標頭，預設會顯示正在使用的 IIS 版本。隱藏此資訊有助於降低攻擊者識別和鎖定 IIS 版本特定漏洞的風險。

1.  **啟用僅限 HTTPS 的連線** 此 （註解） 區段會強制執行 HTTPS 連線並停用 HTTP。如果未註解，Dockerfile 會將 IIS 設定為僅在連接埠 443 (HTTPS) 上接聽，並移除連接埠 80 上的預設 HTTP 繫結。這在終止容器內的 SSL 時非常有用，並確保所有流量都已加密。

1.  **停用目錄瀏覽** 在沒有預設文件時，防止 IIS 顯示目錄清單。這可避免將內部檔案結構公開給使用者。

1.  **傳遞自訂錯誤頁面** 確保如果應用程式有自己的錯誤處理，IIS 會讓應用程式的錯誤頁面傳遞，而不是顯示預設的 IIS 錯誤頁面。

1.  **詳細錯誤模式** 設定 IIS 僅顯示本機請求的詳細錯誤訊息，協助開發人員診斷問題，而不會向外部使用者公開敏感資訊。

1.  **確保適當的資料夾許可** 此區塊會設定 IIS Web 根目錄 (C：\$1inetpub\$1wwwroot) 的資料夾許可。它設定 IIS\$1IUSRS 和使用者群組的讀取和執行許可，確保這些使用者可以存取 資料夾，但不能修改檔案。設定正確的許可可將未經授權的存取或竄改 Web 伺服器託管的檔案的風險降至最低。

遵循 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 容器不只是一個選項，也是必要項目。