

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

# 上的容器型產品 AWS Marketplace
<a name="container-based-products"></a>

**重要**  
2026 年 3 月 1 日， AWS Marketplace 將在 Amazon EKS 上停止 Helm Chart 部署的快速啟動。現有的部署將繼續正常執行。您仍然可以在 Amazon ECS 上使用標準 Helm 命令或容器映像進行部署。

AWS Marketplace 支援使用 Docker 容器的軟體產品。容器產品包含交付選項，這些選項是一組容器映像和共同的部署範本。您為您的產品提交至少一個交付選項，最多四個。對於每個交付選項，您提供一組容器映像、使用說明和部署範本的連結，供客戶啟動該交付選項。本主題提供 上容器型產品的相關資訊 AWS Marketplace。

AWS Marketplace 買方會在發佈的產品詳細資訊頁面上看到可用的交付選項，這些選項可供他們使用。在他們訂閱產品並選擇他們偏好的交付選項後，買方會看到有關啟動和使用產品的資訊和指示。對於容器映像交付選項，買方會看到可用部署範本和容器映像 URLs的連結。他們也會收到如何提取個別容器映像的指示。對於 Helm Chart 交付選項，買方將看到使用 Helm 啟動step-by-step說明。

如需購買體驗的演練，您可以參考此影片：[在 Amazon ECS 叢集上部署 AWS Marketplace 容器 ](https://www.youtube.com/watch?v=XaiUAiQQJtk)(3：34)。

您可以在任何環境中的任何 Kubernetes 叢集 AWS Marketplace 上，從 尋找、訂閱和部署第三方 Kubernetes 應用程式。您可以在 Amazon Elastic Container Service (Amazon ECS) AWS Fargate、Amazon Elastic Kubernetes Service (Amazon EKS) 和內部部署上使用 Amazon EKS Anywhere (EKS Anywhere) 來部署第三方 Kubernetes 應用程式。您也可以在內部部署或 Amazon Elastic Compute Cloud (Amazon EC2) 的自我管理 Kubernetes 叢集上進行部署。

您可以在任何 Docker 相容執行時間執行免費和自攜授權模型 (BYOL) 容器產品。

**Topics**
+ [取得說明](#container-help)
+ [容器產品入門](container-product-getting-started.md)
+ [的容器型產品需求 AWS Marketplace](container-product-policies.md)
+ [的容器產品定價 AWS Marketplace](pricing-container-products.md)
+ [容器產品計費、計量和授權整合](container-products-billing-integration.md)
+ [容器產品的 Amazon SNS 通知](container-notification.md)

## 取得說明
<a name="container-help"></a>

如需容器產品的協助，請聯絡您的 業務開發合作夥伴 AWS Marketplace 或 [AWS Marketplace 賣方營運](https://aws.amazon.com/marketplace/management/contact-us/)團隊。

# 容器產品入門
<a name="container-product-getting-started"></a>

身為 AWS Marketplace 賣方，您可以建立容器型軟體產品。容器產品由一組容器映像和部署範本組成的交付選項組成。下列主題說明如何開始使用容器產品。
+ [產品生命週期](#container-product-lifecycle)
+ [先決條件](#container-prereq)
+  [步驟 1：為您的容器產品建立產品 ID 和產品代碼](#create-initial-container-product) 
+ [步驟 2：建立初始清單](#container-initial-listing)
+ [步驟 3：新增產品的初始版本](#container-add-version-gs)
+ [步驟 4：（僅適用於付費產品） 整合計量或合約定價](#getting-started-integrate-metering)
+ [後續步驟](#getting-started-integrate-metering)
+ [容器產品掃描安全問題](#container-security)

## 產品生命週期
<a name="container-product-lifecycle"></a>

當您在 中建立產品時 AWS Marketplace，它最初會以有限的可見性發佈，以便允許清單上的帳戶可以查看它，包括建立產品的帳戶。當您準備好時，您可以將其發佈至 AWS Marketplace 目錄，以允許買方訂閱和購買您的產品。

在[伺服器產品](https://aws.amazon.com/marketplace/management/products/server)頁面上，您可以檢視您的產品清單。視其所在階段而定，產品將具有下列其中一種狀態。
+ **預備**：您仍在為其新增資訊的不完整產品。在第一次**儲存並退出**自助式體驗時，成功的變更請求會建立未發佈的產品，其中包含您提交之已完成步驟中的資訊。在此狀態中，您可以繼續將資訊新增至產品，或透過變更請求變更已提交的詳細資訊。
+ **有限** – 產品在提交至系統後即完成，並在系統中傳遞所有驗證。然後，產品會釋出為**有限**狀態。此時，產品有一個詳細資訊頁面，只有您的帳戶和允許列入清單的對象才能存取。您可以透過詳細資訊頁面測試您的產品。如需詳細資訊或協助，請聯絡[AWS Marketplace 賣方營運](https://aws.amazon.com/marketplace/management/contact-us/)團隊。
+ **公開** – 當您準備好發佈產品，以便買方可以檢視和訂閱產品時，您可以使用**更新可見性**變更請求。此請求會啟動工作流程，讓 AWS Marketplace 賣方營運團隊根據 AWS 政策檢閱和稽核您的產品。核准產品並處理變更請求後，產品的狀態會從**限制**為**公開**。如需 AWS 準則的資訊，請參閱 [的容器型產品需求 AWS Marketplace](container-product-policies.md)。
+ **受限** – 如果您想要停止新使用者訂閱您的產品，您可以使用**更新可見**性變更請求來限制產品。**受限**狀態表示現有的允許清單使用者可以繼續使用產品。不過，公開或新使用者將無法再看到該產品。

## 先決條件
<a name="container-prereq"></a>

開始之前，您必須先完成下列先決條件：

1. 存取和使用 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)。這是您用來註冊為賣方和管理您銷售產品的工具 AWS Marketplace。如需詳細資訊，請參閱[AWS Marketplace 管理入口網站](https://docs.aws.amazon.com/marketplace/latest/userguide/user-guide-for-sellers.html#management-portal)。

1. 註冊為賣方，並提交您的稅務和銀行資訊。如需詳細資訊，請參閱[註冊程序](registration-process.md)。

1. 在 Amazon Elastic Container Service (Amazon ECS)、Amazon Elastic Kubernetes Service (Amazon EKS) 或 中建立至少一個容器 AWS Fargate。請確定您有關聯映像的連結。

1. 規劃您將如何建立和整合容器產品 AWS Marketplace。

   我們建議您在公開發佈產品之前預先規劃定價、權利和計量策略。
   + 如需容器型產品需求的相關資訊，請參閱 [的容器型產品需求 AWS Marketplace](container-product-policies.md)。
   + 如需設定產品定價的資訊，請參閱 [的容器產品定價 AWS Marketplace](pricing-container-products.md)。
   + 如需付費容器型產品的自訂計量資訊，請參閱 [使用 的每小時和自訂計量 AWS Marketplace Metering Service](container-products-billing-integration.md#entitlement-and-metering-for-paid-products)。

## 概觀：建立容器產品
<a name="create-container-product"></a>

建立容器產品需要下列步驟：

1. [步驟 1：為您的容器產品建立產品 ID 和產品代碼](#create-initial-container-product)

1. [步驟 2：建立初始清單](#container-initial-listing)

1. [步驟 3：新增產品的初始版本](#container-add-version-gs)

1. [步驟 4：（僅適用於付費產品） 整合計量或合約定價](#getting-started-integrate-metering)

1. [更新產品可見性](#container-product-visibility)

如需產品生命週期的資訊，請參閱 [產品生命週期](#container-product-lifecycle)。

## 步驟 1：為您的容器產品建立產品 ID 和產品代碼
<a name="create-initial-container-product"></a>

若要開始使用容器產品，您必須在其中建立產品 ID 和產品代碼記錄 AWS Marketplace。產品 ID 用於追蹤產品的整個生命週期。

使用下列程序在 中建立新的容器產品 AWS Marketplace 管理入口網站，並產生產品 ID。

**注意**  
此程序也會為與您產品配對的容器建立公有金鑰。

**建立容器產品 ID**

1. 開啟 Web 瀏覽器並登入 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)。

1. 從選單列中選取**產品**，然後選擇**伺服器**。

1. 選擇**建立伺服器產品**，然後選擇**容器**。

1. 產生容器產品 ID 和程式碼。
**注意**  
（選用） 您可以為產品加上標籤型授權的標籤。如需詳細資訊，請參閱[標記您的 AWS 資源](https://docs.aws.amazon.com/tag-editor/latest/userguide/tagging.html)。

1. 選擇**繼續**以繼續建立您的產品。

## 步驟 2：建立初始清單
<a name="container-initial-listing"></a>

產生產品 ID、產品代碼和公有金鑰後，您將使用精靈建立初始清單。

1. 提供產品清單的產品資訊。

1. 判斷您產品的定價模式。
**注意**  
如需詳細資訊，請參閱[容器產品定價](https://docs.aws.amazon.com/marketplace/latest/userguide/pricing-container-products.html)。
**注意**  
對於付費產品，您的產品將從 0.01 USD 定價開始，允許您和 AWS Marketplace 賣方營運團隊測試產品，而不會產生高成本。您會在公開時提供實際價格。

1. 提供其他優惠資訊，包括退款政策、EULA 和優惠可用性。

1. 為您的容器產品新增初始儲存庫。

1. 在最後一個步驟選擇**提交**，將產品移至有限可見性。
**注意**  
您的容器產品最初是使用預留位置版本建立的。當產品可見性有限時，您將新增最終版本。

## 步驟 3：新增產品的初始版本
<a name="container-add-version-gs"></a>

您的產品在其生命週期內可能有多個版本。每個版本都有一組特定於該版本的容器映像。若要新增產品的初始版本，請參閱 [在 上新增新版本的容器產品 AWS Marketplace](container-add-version.md)。

## 步驟 4：（僅適用於付費產品） 整合計量或合約定價
<a name="getting-started-integrate-metering"></a>

對於使用量定價的容器型產品，您可以使用 [AWS Marketplace Metering Service](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html) 來檢查是否有權使用您的產品和計量用量來計費。您必須測量您在設定定價資訊時建立的定價模型。如需詳細資訊，請參閱[使用 的每小時和自訂計量 AWS Marketplace Metering Service](container-products-billing-integration.md#entitlement-and-metering-for-paid-products)。

### 合約定價
<a name="container-integrate-LM"></a>

對於具有合約定價的容器型產品，您可以使用 AWS License Manager 將授權與產品建立關聯。

如需 與 整合的詳細資訊 AWS License Manager，請參閱 [使用 的容器產品的合約定價 AWS License Manager](container-license-manager-integration.md)。

## 步驟 5：更新產品可見性
<a name="container-product-visibility-allowlist"></a>

當您在 中建立產品時 AWS Marketplace，它最初會以有限的可見性發佈，以便允許清單上的帳戶可以查看它，包括建立產品的帳戶。您可以更新產品可見性，以允許買方訂閱和購買您的產品。或者，您可以更新要新增的產品允許清單 AWS 帳戶。本主題說明如何管理哪些買方可以檢視您的產品 AWS Marketplace。

如需產品可見性和生命週期的詳細資訊，請參閱 [產品生命週期](#container-product-lifecycle)。

**Topics**
+ [更新產品可見性](#container-product-visibility)
+ [更新 AWS 帳戶 IDs的允許清單](#container-update-allowlist)

### 更新產品可見性
<a name="container-product-visibility"></a>

**更新可見性**

1. 在 開啟 AWS Marketplace 管理入口網站 [https://aws.amazon.com/marketplace/management/tour/](https://aws.amazon.com/marketplace/management/tour/)，然後登入您的賣方帳戶。

1. 前往[https://aws.amazon.com/marketplace/management/products/server](https://aws.amazon.com/marketplace/management/products/server)頁面，在**目前伺服器產品**索引標籤上，選取您要修改的容器型產品。

1. 從**請求變更**下拉式清單中，選擇**更新可見性**。
**注意**  
您可以使用此變更請求，請求將產品從**有限**狀態移至**公**有狀態。不過，變更請求必須經過 AWS Marketplace 賣方營運團隊核准程序，才能移至**公**有。

1. 選擇**提交**以提交您的請求以供檢閱。

1. 確認**請求**索引標籤顯示**請求狀態**為**審核中**。當請求完成時，狀態會變成**成功**。

### 更新 AWS 帳戶 IDs的允許清單
<a name="container-update-allowlist"></a>

您可以變更可在有限狀態下檢視產品的 AWS 帳戶 IDs 清單。允許列出的帳戶會在產品詳細資訊頁面上顯示產品版本的有限徽章。

1. 在 AWS Marketplace 管理入口網站 https：//[https://aws.amazon.com/marketplace/management/tour/](https://aws.amazon.com/marketplace/management/tour/) 開啟 並登入您的賣方帳戶。

1. 在[https://aws.amazon.com/marketplace/management/products/server](https://aws.amazon.com/marketplace/management/products/server)頁面中，選取要修改的容器產品。

1. 從**請求變更**下拉式清單中，選取**更新允許清單**。隨即顯示允許列出的目前帳戶清單。

1. 在**允許清單 AWS 帳戶**欄位中，輸入 AWS 帳戶 IDs並使用逗號分隔。

1. 選擇**提交**以提交您的請求以供檢閱。

1. 確認**請求**索引標籤顯示**請求狀態**為**審核中**。當請求完成時，狀態會更新為**成功**或**失敗**。

## 後續步驟
<a name="container-next-steps"></a>

建立容器產品之後，您可以使用下列主題中的資訊來設定和管理它：
+ [在 上更新容器產品的產品資訊 AWS Marketplace](update-container-product-info.md)
+ [在 上新增新版本的容器產品 AWS Marketplace](container-add-version.md)
+ [在 上管理容器產品定價 AWS Marketplace](container-pricing.md)
+ [在 中依國家/地區更新容器產品可用性 AWS Marketplace](container-update-offer-avail-country.md)
+ [在 上更新容器產品的最終使用者授權合約 (EULA) AWS Marketplace](container-update-eula.md)
+ [在 上測試並發行您的容器產品 AWS Marketplace](test-release-product.md)

## 容器產品掃描安全問題
<a name="container-security"></a>

當您建立變更請求以將新版本新增至容器產品時，我們會掃描該新版本中包含的容器映像，並檢查是否有安全漏洞。為此，我們在映像上執行layer-by-layer靜態掃描。如果我們找到具有可遠端利用風險向量的關鍵漏洞，我們會為您提供找到的問題清單。我們強烈建議您使用 容器映像掃描器執行自己的安全分析Twistlock，例如 Clair、Aqua Security、 或 Trend Micro ，以避免擷取和發佈程序延遲。

您選擇的建置容器映像的基礎映像可能會對最終映像的安全性設定檔產生重大影響。如果您選擇已具有已知關鍵漏洞的基礎映像，即使應用程式軟體層是乾淨的，也會因為底層而標記這些映像。我們建議您在建置映像並將其提交至 之前，先驗證您是否從沒有漏洞的基本容器開始 AWS Marketplace。

# 在 上更新容器產品的產品資訊 AWS Marketplace
<a name="update-container-product-info"></a>

建立產品 ID 並設定定價後，您可以編輯產品資訊，包括客戶在 中看到的容器產品相關資訊 AWS Marketplace。例如，如果新版本修改產品的描述或重點，您可以使用新資料編輯產品資訊。您也可以更新其他產品資訊，包括產品標題、SKU 描述、類別、關鍵字等。下列程序概述為您的產品建立產品詳細資訊。

**建立或更新容器產品的產品詳細資訊**

1. 登入 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)。

1. 從**產品**功能表中選取**伺服器**。

1. 在**伺服器產品**索引標籤上，選取您要修改的產品。

1. 從**請求變更**下拉式清單中，選擇**更新產品資訊**。

1. 更新您要變更的下列任何欄位：
   + **產品標題**
   + **SKU**
   + **簡短描述**
   + **長描述**
   + **產品標誌影像 URL**
   + **重點標示**
   + **產品類別**
   + **關鍵字**
   + **產品影片 URL**
   + **資源**
   + **支援資訊**
**注意**  
影像 URLs位於可公開存取的 Amazon S3 儲存貯體中。如需標誌格式的詳細資訊，請參閱 [公司和產品標誌要求](product-submission.md#seller-and-product-logos)。

1. 選擇**提交**。

1. 確認請求顯示在檢閱**中**狀態的**請求**索引標籤上。您可能需要重新整理頁面，才能在清單中查看請求。

您可以隨時從[伺服器產品](https://aws.amazon.com/marketplace/management/products/server)頁面的請求索引標籤檢查**請求**的狀態。

# 在 上新增新版本的容器產品 AWS Marketplace
<a name="container-add-version"></a>

身為 AWS Marketplace 賣方，您可以新增容器產品的新版本、管理版本和更新版本資訊。您的產品在其生命週期內可能有多個版本。每個版本都有一組特定於該版本的容器映像。下列主題說明如何管理容器產品的產品版本。

**注意**  
您必須先建立產品 ID 和產品定價，才能將版本新增至您的產品。如需這些步驟的詳細資訊，請參閱 [步驟 1：為您的容器產品建立產品 ID 和產品代碼](container-product-getting-started.md#create-initial-container-product)。

**Topics**
+ [步驟 1：新增儲存庫](#add-repositories)
+ [步驟 2：將容器映像和成品上傳至儲存庫](#upload-resources)
+ [步驟 3：將新版本新增至您的容器產品](#add-new-version)
+ [步驟 4：更新版本資訊](#container-product-updating-version)
+ [限制 Amazon EKS 附加元件的版本](#restriciting-version-eks-addon)

## 步驟 1：新增儲存庫
<a name="add-repositories"></a>

您產品的容器映像和其他成品會存放在 的儲存庫中 AWS Marketplace。一般而言，您可以為每個所需的成品建立一個儲存庫，但儲存庫可以存放多個版本的成品 （具有不同的標籤）。

**注意**  
產品部署中的所有映像都必須使用來自 儲存庫的 AWS Marketplace 映像。

下列程序說明如何在 中新增任何所需的儲存庫 AWS Marketplace。

**新增儲存庫**

1. 登入 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)。

1. 從**產品**功能表中選取**伺服器**。

1. 在**伺服器產品**索引標籤上，選取您要修改的產品，然後從**請求變更**下拉式清單中選擇**新增儲存庫**。

1. 輸入您要建立之儲存庫的名稱。如果您想要建立多個新儲存庫：
   + 為每個額外的**儲存庫選擇新增**儲存庫。
   + 提供唯一的名稱。您選擇的唯一名稱必須跨賣方帳戶中的所有產品。
**注意**  
儲存庫將具有此結構：`<repositoryID>.dkr.ecr.us-east-1.amazonaws.com/<sellerName>/<repositoryName>`。當您將項目新增至儲存庫時 （在下列程序中），它們會取得標籤並具有此結構：`<repositoryID>.dkr.ecr.us-east-1.amazonaws.com/<sellerName>/<repositoryName>:<tag>`。  
`repositoryID` 是 的內部 ID AWS Marketplace。
`sellerName` 是根據您為賣方帳戶建立的名稱。當您的賣方顯示名稱產生`sellerName`無效的儲存庫字首時，AWS Marketplace 會自動取代 UUID （通用唯一識別碼） 取代賣方名稱。若要變更儲存庫名稱中的 UUID 字首，請聯絡 AWS Marketplace 操作團隊。
在此步驟中`respositoryName`定義 。
當您將成品上傳到儲存庫時，`tag`會設定 。

1. 選取**提交**。

**注意**  
每個產品最多可以有 70 個儲存庫。

系統會建立新的請求，並顯示在**請求**索引標籤上。完成後，您可以在幾分鐘內開始將容器映像和其他成品新增至您建立的儲存庫。

## 步驟 2：將容器映像和成品上傳至儲存庫
<a name="upload-resources"></a>

**將容器映像和成品上傳至儲存庫**

1. 登入 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)。

1. 從**產品**功能表中，選擇**伺服器**。

1. 在**伺服器產品**索引標籤上，選取您要修改的產品。

1. 從**請求變更**下拉式清單中選擇**新增儲存庫**。

1. 選擇**檢視現有的儲存庫**。

1. 選取您要上傳的儲存庫。

1. 選取**檢視推送命令**以開啟指示清單，包括可用來將Docker容器映像和Helm圖表推送至該儲存庫的命令。

   如需如何將容器映像和其他成品推送至儲存庫的一般資訊，請參閱《*Amazon Elastic Container Registry 使用者指南*》中的[推送映像](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-push.html)。
**注意**  
您可以在呼叫 `docker pull`或 時使用下列 Amazon Elastic Container Registry (Amazon ECR) API 操作`docker push`：  
`DescribeImages` – 用來檢閱儲存庫中映像的相關中繼資料。
`GetAuthorizationToken` – 在將成品上傳到儲存庫之前，使用 進行驗證，然後使用 `docker pull`或 `docker push`命令。
`ListImages` – 使用 來檢視您推送的映像清單。

1. 使用列出的命令，將任何必要的成品從本機儲存庫推送至您產品的 AWS Marketplace 儲存庫。
**注意**  
**tag** 您在`push`命令中提供的 用於區分您上傳到儲存庫的成品版本。使用對成品所屬版本有意義的標籤。

1. 針對版本中所需的每個容器映像或成品重複此步驟。
**注意**  
您的版本在每個交付選項中最多可包含 50 個容器映像或成品。如需交付選項的詳細資訊，請參閱下列程序。

上傳成品之後，您就可以建立產品的版本。

**注意**  
您的容器映像會自動掃描，以查看是否符合 [的容器型產品需求 AWS Marketplace](container-product-policies.md)。如需詳細資訊，請參閱[容器產品掃描安全問題](container-product-getting-started.md#container-security)。

### 新增交付選項
<a name="add-delivery-option"></a>

每個版本的容器產品都需要一個交付選項。交付選項指定買方可用的部署選項。根據以下其中一個交付選項，您需要將適當的成品上傳到儲存庫。
+ 對於**容器映像**交付選項，請將產品安裝所需的所有容器映像上傳至 AWS Marketplace 主控台中建立的 Amazon Elastic Container Registry (Amazon ECR) 儲存庫。
+ 對於**Helm圖表**交付選項，請將Helm圖表和容器映像上傳到 AWS Marketplace 主控台中建立的 Amazon ECR 儲存庫。
+ 對於 **Amazon EKS 主控台附加元件**交付選項，請將Helm圖表和容器映像上傳到主控台中建立的 Amazon ECR 儲存庫 AWS Marketplace 。

## 步驟 3：將新版本新增至您的容器產品
<a name="add-new-version"></a>

**注意**  
如果您在將新版本新增至容器時收到任何錯誤，請參閱 *AWS Marketplace Catalog API 參考*中的[新增新版本非同步錯誤表格](https://docs.aws.amazon.com/marketplace-catalog/latest/api-reference/container-products.html#container-add-version)。

**將新版本新增至您的容器產品**

1. 登入 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)。

1. 從**產品**功能表中選擇**伺服器**。

1. 在**伺服器產品**索引標籤上，選取您要新增版本的產品。然後從**請求變更**下拉式清單中選擇**新增版本**。

1. 在**新增版本**頁面上，輸入您**版本的版本標題**和**版本備註**。

1. 輸入版本詳細資訊後，下一個步驟是新增交付選項。交付選項是一組指示和資訊，買方可用來從您的產品版本啟動軟體。交付選項稱為買方*履行選項*。
**注意**  
您的產品可以支援具有不同容器映像的多個平台 （例如 Kubernetes和 Ubuntu 部署）。您可以為每個客戶設定產品的方式建立一個交付選項，每個產品版本最多四個交付選項。

   1. 如果產品在其他版本中已有交付選項，您可以使用現有選項做為範本，將交付選項新增至新版本。在**交付選項**中，從清單中選擇您要新增的交付選項。您可以使用下列步驟中的指示來編輯 選項。

   1. 若要新增交付選項，請選擇**新增交付選項**。新增選項後，請依照下列步驟中的指示進行設定。

1. 選擇交付選項的交付方法。交付方法決定買方如何啟動您的軟體。
   + 對於**容器映像**交付選項，提供在主控台中建立的 Amazon Elastic Container Registry (Amazon ECR) 儲存庫中容器映像的 AWS Marketplace 路徑。買方使用容器映像路徑，透過直接將映像提取至其環境來啟動軟體。
   + 對於**Helm圖表**交付選項，提供在 AWS Marketplace 主控台中建立的 Amazon ECR 儲存庫中的Helm圖表路徑。買方會在其部署環境中安裝Helm圖表以啟動軟體。
   + 對於 **Amazon EKS 主控台附加元件**交付選項，提供在主控台中建立的 Amazon ECR 儲存庫中的Helm AWS Marketplace 圖表路徑。買方使用 Amazon EKS 主控台或原生 Amazon EKS 附加元件 APIs 安裝容器，以啟動軟體。如需詳細資訊，請參閱[來自 Amazon EKS 的可用 Amazon EKS 附加元件](https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html#workloads-add-ons-available-eks)。

   1. 若要新增**容器映像**交付選項，請執行下列步驟：

      1. 在**容器映像**中，將 Amazon ECR URL 新增至包含產品版本軟體的容器映像。

      1. 在**交付選項標題**和**部署選項描述**中，輸入此交付選項的標題和描述。

      1. 在**使用說明**中，輸入詳細資訊，以協助您的買方在啟動軟體後使用您的軟體。

      1. 在**支援的 服務**中，選取買方可以在其中啟動軟體的環境。

      1. 在**部署範本**中，新增買方可用來啟動軟體的資源。為每個範本輸入資源的標題和 URL。

   1. 若要新增**Helm圖表**交付選項，請執行下列步驟：

      1. 在**Helm圖表**中，將 Amazon ECR URL 新增至購買者將在其部署環境中安裝的Helm圖表，以啟動您的軟體。

      1. 在**容器映像**中，將 Amazon ECR URL 新增至包含產品版本軟體的容器映像。

      1. 在**交付選項標題**和**部署選項描述**中，輸入此交付選項的標題和描述。

      1. 在**使用說明**中，輸入詳細資訊，以協助您的買方在啟動軟體後使用您的軟體。

      1. 在**支援的 服務**中，選取買方可以在其中啟動軟體的環境。

      1. *選用 - * 在**Helm發行名稱**中，輸入要安裝Helm圖表的Kubernetes命名空間名稱。

      1. *選用 - * 在**Helm安裝命名空間**中，輸入 `helm install`命令將使用的Helm發行版本名稱。

      1. *選用 - * 在**Kubernetes服務帳戶名稱**中，輸入將用於連線至 AWS Identity and Access Management (IAM) Kubernetes的服務帳戶名稱。Kubernetes 服務帳戶會呼叫 AWS 授權或計量等服務。

      1. 在**覆寫參數**中，輸入將在啟動軟體的 CLI Helm 命令中使用的參數。這些參數可讓買方覆寫提供的預設值。使用 AWS Marketplace 管理主控台時有 15 個參數的限制，但使用 時沒有限制 AWS Marketplace Catalog API。如需詳細資訊，請參閱[將新版本新增至容器型產品](https://docs.aws.amazon.com/marketplace-catalog/latest/api-reference/container-products.html#container-add-version)。
**注意**  
某些**覆寫參數**是必要的。Amazon EKS Anywhere 產品需要具有 `DefaultValue`的 授權秘密的**覆寫參數**`"${AWSMP_LICENSE_SECRET}"`。對於付費產品，您必須使用 `DefaultValue`的 為服務帳戶組態提供一個**覆寫參數**`"${AWSMP_SERVICE_ACCOUNT}"`。

      1. 選擇**隱藏密碼和秘密**，以在主控台、命令列工具和 APIs 中遮罩敏感資訊。如需詳細資訊，請參閱*AWS CloudFormation 《 使用者指南*》中的[參數](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)`NoEcho`文件。

   1. 若要新增 **Amazon EKS 主控台附加元件**交付選項，請確定成品符合 [Amazon EKS 附加元件產品的需求](container-product-policies.md#publishing-eks-add-on)，然後執行下列步驟：
**注意**  
每個版本僅支援一個 Amazon EKS 附加元件交付選項。在 Amazon EKS 主控台上發佈您正在使用的目前版本之前，您無法新增版本。

      1. 在**Helm圖表**中，將 Amazon ECR URL 新增至購買者將在其部署環境中安裝的Helm圖表，以啟動您的軟體。

      1. 在**容器映像**中，將 Amazon ECR URL 新增至包含產品版本軟體的容器映像。確定已列出Helm圖表中的所有影像。

      1. 在**交付選項標題**和**部署選項描述**中，輸入此交付選項的標題和描述。

      1. 在**可見性**中，保持**選取 Limited** 的預設值。

      1. 在**附加元件名稱**中，輸入此附加元件的唯一名稱。您在 Amazon EKS 主控台中顯示時，您輸入的附加元件名稱會附加賣方的名稱。

      1. 在**附加元件版本**中，輸入安裝或升級此附加元件時可見的附加元件版本。遵循格式 `major.minor.patch`。

      1. 在**附加元件類型**中，從下拉式清單中選取附加元件的類別。

      1. 在**Kubernetes版本**中，選取您的附加元件將支援的所有Kubernetes版本。

      1. 在**架構**中，選取您的附加元件支援的平台架構。選項為 **AMD64** 和 **ARM64**。我們建議您支援這兩個架構，以最大化相容性。如果您的附加元件不支援 ARM64 裝置，您必須先指定新增支援的計劃日期，才能將產品發佈到所有商業廣告中 AWS 區域。

      1. 在**命名空間**中，輸入要安裝附加元件的唯一Kubernetes命名空間。安裝第三方附加元件時，不支援 `kube-system`、 `default`和 `kube-public`命名空間。

      1. 在**環境覆寫參數**中，您可以從 Amazon EKS 附加元件架構中選取最多 2 個環境參數。您可以將參數名稱從 values.yaml 映射到這些環境變數，即 `${AWS_REGION}`和 `${AWS_EKS_CLUSTER_NAME}`。

1. 若要新增其他交付選項，請選擇**新增交付選項**，然後重複先前步驟中的指示來設定這些選項。

1. 選擇**提交**。

## 步驟 4：更新版本資訊
<a name="container-product-updating-version"></a>

建立版本之後，透過修改與該版本相關的資訊，將更新的資訊提供給買方會很有幫助。例如，如果您計劃在發行 1.1 版之後限制 1.0 版，您可以更新 1.0 版的描述，將買方導向 1.1 版。提供 1.0 版將受到限制的日期。您可以從 更新版本資訊 AWS Marketplace 管理入口網站。

**更新版本資訊**

1. 登入 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)。

1. 從**產品**功能表中選取**伺服器**。

1. 在**伺服器產品**索引標籤上，選取您要修改的產品。

1. 從**請求變更**下拉式清單中，選擇**更新版本資訊**。

1. 在**更新版本**頁面上，選取您要更新的版本。

1. 更新所選版本。可供更新的欄位取決於產品版本或交付選項的狀態。

   1. 對於所有版本，您可以更新**版本備註**。

   1. 對於尚未公開提供的版本，您可以更新**版本標題**。

   1. 對於尚未受到限制的交付選項，您可以更新下列欄位：
      + **Description**
      + **使用說明**
      + **支援的服務**

   1. 對於尚未公開提供的版本中的交付選項，您可以更新下列欄位：
      + **交付選項標題**
      + **Helm 圖表** （僅適用於**Helm圖表**交付選項）
      + **容器映像**
      + **部署資源**
      + **AddOn名稱**
      + **AddOn 版本**
      + **AddOn 類型**
      + **Helm 圖表 URI**
      + **CompatibleKubernetesVersions**
      + **SupportedArchitectures**
      + **命名空間**
      + **EnvironmentOverrideParameters**

   1. 對於公開提供的版本中的交付選項，您可以更新 **SupportedArchitectures**。

1. 選擇**提交**。

1. 確認請求顯示在**請求**索引標籤上，且狀態為**審核中**。

您可以隨時從[伺服器產品](https://aws.amazon.com/marketplace/management/products/server)頁面的請求索引標籤檢查**請求**的狀態。

## 限制 Amazon EKS 附加元件的版本
<a name="restriciting-version-eks-addon"></a>

若要限制以附加元件發佈的容器產品版本，請使用 底部的聯絡我們表單聯絡 AWS Marketplace 營運團隊[AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)。

# 在 上管理容器產品定價 AWS Marketplace
<a name="container-pricing"></a>

身為 AWS Marketplace 賣方，您可以管理和更新容器產品定價。對於容器產品，您可以列出免費產品、自攜授權模型 (BYOL) 產品，以及 Amazon Elastic Container Service (Amazon ECS)、Amazon Elastic Kubernetes Service (Amazon EKS) 和 的付費產品 AWS Fargate。每個產品只能設定一個價格。您可以新增或更新定價維度。根據您的定價模式，您可以新增合約和用量維度。您也可以更新定價條款或退款政策。如需詳細資訊，請參閱下列區段。

 如需 容器產品定價模型的詳細資訊 AWS Marketplace，請參閱 [的容器產品定價 AWS Marketplace](pricing-container-products.md)。

**Topics**
+ [新增定價維度](#container-add-pricing-dimensions)
+ [更新維度資訊](#container-update-dimensions-information)
+ [更新定價條款](#container-update-pricing-terms)
+ [更新產品的退款政策](#container-update-refund-policy)

## 新增定價維度
<a name="container-add-pricing-dimensions"></a>

您可以將定價維度新增至您用於產品帳單的定價模型。如需定價模型的詳細資訊，請參閱 [容器定價模型](pricing-container-products.md#pricing-models-for-server-products)。

**注意**  
上無法使用為具有消耗定價的合約新增定價維度 （例如，pay-as-you-go定價） AWS Marketplace 管理入口網站。  
您無法在合約、用量和使用定價的合約之間變更定價模式。如需協助，請聯絡[AWS Marketplace 賣方營運](https://aws.amazon.com/marketplace/management/contact-us/)團隊。

1. 在 AWS Marketplace 管理入口網站 https：//[https://aws.amazon.com/marketplace/management/tour/](https://aws.amazon.com/marketplace/management/tour/) 開啟 並登入您的賣方帳戶。

1. 在[https://aws.amazon.com/marketplace/management/products/server](https://aws.amazon.com/marketplace/management/products/server)頁面中，選取要修改的容器產品。

1. 從**請求變更**下拉式清單中，選取**更新定價維度**，然後選取**新增定價維度**。

1. 根據定價模型，您可以透過提供 **API 識別符**、**顯示名稱**和**描述**的資訊來新增合約維度或用量維度。

1. 選擇**下一步**，然後輸入您的合約維度定價。

1. 選擇**提交**以提交您的請求以供檢閱。

1. 確認**請求**索引標籤顯示**請求狀態**為**審核中**。當請求完成時，狀態會更新為**成功**或**失敗**。

## 更新維度資訊
<a name="container-update-dimensions-information"></a>

您可以變更產品的維度資訊。如需定價模型的詳細資訊，請參閱 [容器定價模型](pricing-container-products.md#pricing-models-for-server-products)。

1. 在 AWS Marketplace 管理入口網站 https：//[https://aws.amazon.com/marketplace/management/tour/](https://aws.amazon.com/marketplace/management/tour/) 開啟 並登入您的賣方帳戶。

1. 在[https://aws.amazon.com/marketplace/management/products/server](https://aws.amazon.com/marketplace/management/products/server)頁面中，選取要修改的容器產品。

1. 從**請求變更**下拉式清單中，選取**更新定價維度**，然後選取**更新維度資訊**。

1. 您可以透過提供要更新之維度的**顯示名稱**和**描述**的資訊來新增維度資訊。

1. 選擇**提交**以提交您的請求以供檢閱。

1. 確認**請求**索引標籤顯示**請求狀態**為**審核中**。當請求完成時，狀態會更新為**成功**或**失敗**。

## 更新定價條款
<a name="container-update-pricing-terms"></a>

您可以變更產品的定價條款。如果您變更產品提供的國家/地區，定價條款可能需要更新。

1. 在 AWS Marketplace 管理入口網站 https：//[https://aws.amazon.com/marketplace/management/tour/](https://aws.amazon.com/marketplace/management/tour/) 開啟 並登入您的賣方帳戶。

1. 在[https://aws.amazon.com/marketplace/management/products/server](https://aws.amazon.com/marketplace/management/products/server)頁面中，選取要修改的容器產品。

1. 從**請求變更**清單中，選取**更新公開優惠**，然後選取**更新定價條件**。

1. 目前定價會預先填入供您編輯。您可以刪除目前的定價並新增您的新價格。我們建議您在提交審核請求之前，先審核您請求的價格。

1. 選擇**提交**以提交您的請求以供檢閱。

1. 確認**請求**索引標籤顯示**請求狀態**為**審核中**。當請求完成時，狀態會更新為**成功**或**失敗**。

**注意**  
如果您使用**更新定價條件**來提高維度的價格，您將無法更新定價 90 天。價格調高會將價格自您啟動變更之日起鎖定 90 天。此價格鎖定僅在提高價格時生效，而不是降低價格。

## 更新產品的退款政策
<a name="container-update-refund-policy"></a>

您可以更新產品的退款政策。所有使用者的退款政策更新都會生效。如需詳細資訊，請參閱[中的退款和取消 AWS Marketplace](refunds.md)。

1. 在 AWS Marketplace 管理入口網站 https：//[https://aws.amazon.com/marketplace/management/tour/](https://aws.amazon.com/marketplace/management/tour/) 開啟 並登入您的賣方帳戶。

1. 在[https://aws.amazon.com/marketplace/management/products/server](https://aws.amazon.com/marketplace/management/products/server)頁面中，選取要修改的容器產品。

1. 從**請求變更**下拉式清單中，選取**更新公開優惠**，然後選取**更新退款政策**。

1. 目前的退款政策已預先填入供您編輯。您可以刪除目前的退款政策，並新增新的退款政策。我們建議您在提交請求以供檢閱之前，先檢閱您請求的退款政策。提交請求會覆寫目前的退款政策。

1. 選擇**提交**以提交您的請求以供檢閱。

1. 確認**請求**索引標籤顯示**請求狀態**為**審核中**。當請求完成時，狀態會更新為**成功**或**失敗**。

# 在 中依國家/地區更新容器產品可用性 AWS Marketplace
<a name="container-update-offer-avail-country"></a>

身為 AWS Marketplace 賣方，您可以變更提供和訂閱容器產品的國家/地區。如需詳細資訊，請參閱[國家/地區](regions-and-countries.md#product-countries)。下列程序說明如何依國家/地區更新您的容器產品可用性。

1. 在 AWS Marketplace 管理入口網站 https：//[https://aws.amazon.com/marketplace/management/tour/](https://aws.amazon.com/marketplace/management/tour/) 開啟 並登入您的賣方帳戶。

1. 在[https://aws.amazon.com/marketplace/management/products/server](https://aws.amazon.com/marketplace/management/products/server)頁面中，選取要修改的容器產品。

1. 從**請求變更**下拉式清單中，選取**更新公開優惠**，然後選取**依國家/地區更新可用性**。

1. 選取以下其中一個選項：
   + **所有國家** - 在所有支援的國家/地區提供。
   + **具有排除的所有國家**/地區 – 適用於所有支援的國家/地區，但所選國家/地區除外。
   + **僅限允許列出的國家**/地區 – 僅供買方在您指定的國家/地區購買。

1. 選擇**提交**以提交您的請求以供檢閱。

1. 確認**請求**索引標籤顯示**請求狀態**為**審核中**。當請求完成時，狀態會更新為**成功**或**失敗**。

# 在 上更新容器產品的最終使用者授權合約 (EULA) AWS Marketplace
<a name="container-update-eula"></a>

身為 AWS Marketplace 賣方，您可以更新最終使用者授權合約 (EULA)，以使用 [的標準合約 AWS Marketplace](standardized-license-terms.md#standard-contracts)或自訂 EULA。針對訂閱您產品和產品續約的新使用者，EULA 的更新會生效。若要更新您的 EULA，請使用下列程序。

1. 在 https：//[https://aws.amazon.com/marketplace/management/tour/](https://aws.amazon.com/marketplace/management/tour/) AWS Marketplace 管理入口網站 開啟 並登入您的賣方帳戶。

1. 在[https://aws.amazon.com/marketplace/management/products/server](https://aws.amazon.com/marketplace/management/products/server)頁面中，選取要修改的容器產品。

1. 從**請求變更**下拉式清單中，選取**更新公開優惠**，然後選取**更新 EULA**。

1. 選取 **的標準合約 AWS Marketplace**或提交您的自訂 EULA。對於自訂 EULA，您必須提供來自 Amazon S3 儲存貯體的合約。

1. 選擇**提交**以提交您的審核請求。

1. 確認**請求**索引標籤顯示**請求狀態**為**審核中**。當請求完成時，狀態會更新為**成功**或**失敗**。

# 在 上更新以容器為基礎的產品的退款政策 AWS Marketplace
<a name="update-container-refund-policy"></a>

身為 AWS Marketplace 賣方，您可以為容器型產品設定退款政策。如果您想要變更產品的退款政策，您可以使用**更新退款政策**。下列程序說明如何更新退款政策。

**更新退款政策**

1. 在 開啟 AWS Marketplace 管理入口網站 [https://aws.amazon.com/marketplace/management/tour/](https://aws.amazon.com/marketplace/management/tour/)，然後登入您的賣方帳戶。

1. 前往[伺服器產品](https://aws.amazon.com/marketplace/management/products/server)頁面，然後選取您要修改的產品。

1. 從**請求變更**下拉式清單中，選擇**更新公開優惠**，然後選擇**更新退款政策**。

1. 目前的退款政策詳細資訊會在文字方塊中提供，供您編輯。提交請求會覆寫目前的退款政策。

1. 選擇**提交**以提交您的請求以供檢閱。

1. 確認**請求**索引標籤顯示**請求狀態**為**審核中**。當請求完成時，狀態會變成**成功**。

# 在 上測試並發行您的容器產品 AWS Marketplace
<a name="test-release-product"></a>

將新版本的容器產品新增至 後 AWS Marketplace，您可以測試您的產品，然後將其發佈給大眾。本主題概述測試和公開發行您的產品所需的特定步驟和程序。

**Topics**
+ [容器映像和Helm圖表交付選項](#container-helm-delivery)
+ [Amazon EKS 附加元件交付選項](#eks-addon-delivery)

## 容器映像和Helm圖表交付選項
<a name="container-helm-delivery"></a>

本節提供有關發行容器映像和Helm圖表的指引。

您的新版本請求已建立，應該會在幾分鐘內完成。您可以從**伺服器產品**頁面的請求索引標籤追蹤**請求**。如果您在測試或釋出附加元件時收到任何錯誤，請參閱《 *AWS Marketplace Catalog API 參考*》中的[新增新版本的](https://docs.aws.amazon.com/marketplace-catalog/latest/api-reference/container-products.html#container-add-version)非同步錯誤資料表。

**注意**  
如果您的產品目前設為有限可用性，則只有產品可用的買方才能存取產品版本。如果您的產品目前設為公有可用性，所有 AWS Marketplace 買方都可以存取產品版本。

如果這是您的第一個版本集，您的產品現在已準備好發佈。

## Amazon EKS 附加元件交付選項
<a name="eks-addon-delivery"></a>

本節提供測試和發行 Amazon EKS 附加元件的指引。

**測試您的附加元件**
+ 提交附加元件之後， 會 AWS Marketplace 處理您的請求，並以有限狀態發佈附加元件，供您在 Amazon EKS 附加元件目錄中進行驗證。您可以從 中**伺服器產品**頁面的**請求**索引標籤追蹤請求 AWS Marketplace 管理入口網站。擷取時間從 5 到 10 個工作日不等，具體取決於我們正在處理的請求量。

  當您的請求處於**審核中**狀態時， AWS 團隊仍會從 將附加元件發佈 AWS Marketplace 至 Amazon EKS 附加元件目錄。一旦附加元件發佈至**有限**狀態，請求狀態就會變更為**成功**。您可以在之後開始測試您的附加元件。
+ 您的附加元件可供使用後，您可以在亞太區域 （首爾） 區域中找到它以供測試。 AWS Marketplace 仰賴您的專業知識來驗證軟體的功能。若要測試您的附加元件，您必須在允許附加元件的賣方帳戶中的亞太區域 （首爾） 區域中建立 Amazon EKS 叢集。若要測試您的附加元件，請遵循[這些詳細說明](https://aws.amazon.com/blogs/awsmarketplace/deploy-third-party-software-add-ons-aws-marketplace-amazon-eks-clusters/)。請務必測試軟體支援的每個Kubernetes版本。
+ 如果您要提供付費產品，請為下列內部 建立私有優惠 AWS 帳戶。這些帳戶有助於將您的軟體整合到所有商業廣告中的 Amazon EKS 主控台 AWS 區域。

  ```
  288092140294, 288092140294, 408202761791
  ```
+ 將您的測試叢集與附加元件保持作用中狀態，直到 AWS Marketplace 核准並將附加元件版本移至公有。
**注意**  
AWS Marketplace 不會承擔在 Amazon EKS 叢集上測試容器產品時產生的 AWS 基礎設施成本。您可以遵循正確的大小調整機制，將節點調低到最低的操作成本，同時驗證測試結果。

**將附加元件發佈至公有**

透過 Amazon EKS 叢集驗證軟體做為附加元件後，您可以使用 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)或 提交請求，將 Amazon EKS 附加元件的版本發佈至公有 AWS Marketplace Catalog API。

 如需詳細資訊，請參閱《 *AWS Marketplace Catalog API 參考*》中的[更新 Amazon EKS 附加元件的可見](https://docs.aws.amazon.com/marketplace-catalog/latest/api-reference/container-products.html#update-delivery-option-visibility)性。

您可以從 中**伺服器產品**頁面的**請求**索引標籤追蹤請求 AWS Marketplace 管理入口網站。擷取時間會有所不同。

# 的容器型產品需求 AWS Marketplace
<a name="container-product-policies"></a>

AWS Marketplace 會維護所有容器型產品和方案的下列需求 AWS Marketplace。這些要求有助於為客戶提升安全、可靠且可靠的目錄。我們也鼓勵賣方審查適用的其他控制和協定的實作，以滿足其特定產品的需求。

提交時，會檢閱所有產品及其相關中繼資料，以確保它們符合或超過目前的 AWS Marketplace 政策。這些政策會定期更新，以符合不斷發展的安全準則。 AWS Marketplace 會持續掃描產品，以確認現有的清單持續符合這些要求的任何變更。如果產品不合規， AWS Marketplace 將聯絡賣方以更新其產品以符合新標準。在某些情況下，在問題解決之前，新訂閱用戶可能會暫時無法使用產品。此程序有助於為所有使用者維護 AWS Marketplace 平台的安全性和可信度。

**Topics**
+ [安全政策](#container-security-requirements)
+ [客戶資訊要求](#container-customer-info-requirements)
+ [產品使用需求](#container-usage-requirements)
+ [架構需求](#container-architecture-requirements)
+ [Helm Chart 結構需求](#helm-chart-structure-requirements)
+ [容器產品使用說明](#container-product-usage-instructions)
+ [Amazon EKS 附加元件產品的需求](#publishing-eks-add-on)

## 安全政策
<a name="container-security-requirements"></a>

 所有容器型產品都必須遵守下列安全要求：
+ 容器映像不得包含任何已知的漏洞、惡意軟體或End-of-Life(EoL) 軟體套件和作業系統。
+ 容器不得請求 AWS 登入資料來存取 AWS 服務。當您的產品需要存取 AWS 服務時，您必須使用下列其中一項：
  + 服務帳戶的 IAM 角色，適用於 Amazon Elastic Kubernetes Service (Amazon EKS) 工作負載。
  + 任務的 IAM 角色，適用於 Amazon Elastic Container Service (Amazon ECS) 工作負載。
+ 容器型產品必須只需要最低權限才能執行。如需詳細資訊，請參閱 [Amazon Elastic Container Service 中的安全性](https://docs.aws.amazon.com//AmazonECS/latest/developerguide/security.html)和 [Amazon EKS 中的安全性](https://docs.aws.amazon.com//eks/latest/userguide/security.html)。
+ 根據預設，容器映像應設定為使用非根權限執行。
+ 容器不得包含任何硬式編碼秘密，例如系統使用者和服務的密碼 （即使是雜湊）、私有金鑰、登入資料等。
+ 在容器內執行的任何服務中的身分驗證都不得使用密碼型身分驗證，即使使用者在啟動時產生、重設或定義密碼。也不允許使用空密碼和空白密碼。
+ 容器映像不得包含具有不支援架構的層 （例如，傳入認證架構中繼資料）。

## 客戶資訊要求
<a name="container-customer-info-requirements"></a>

 所有容器型產品都必須遵守下列客戶資訊要求：
+ 除非 BYOL （自帶授權） 要求，否則軟體不得在客戶不知情且明確同意的情況下收集或匯出客戶資料。收集或匯出客戶資料的應用程式必須遵循下列準則：
  + 客戶資料的收集必須是自助式、自動化且安全的。買方不需要等待賣方核准部署軟體。
  + 客戶資料的收集必須符合您與 的協議 AWS，包括但不限於 [AWS Marketplace 條款與條件](https://aws.amazon.com/legal/seller-terms/)、[AWS 服務條款](https://aws.amazon.com/service-terms/)、[AWS 隱私權聲明](https://aws.amazon.com/privacy/)和[AWS 客戶協議](https://aws.amazon.com/agreement/)。
  + 不得收集付款資訊。

## 產品使用需求
<a name="container-usage-requirements"></a>

 所有容器型產品都必須遵守下列產品使用需求：
+ 賣方只能列出功能完整的產品。不允許用於試用或評估目的的 Beta 版或發行前產品。如果賣方 AWS Marketplace 在提供免費版本的 90 天內提供對等的付費版本，則支援商業軟體版本的開發人員、社群和 BYOL 版本。
+ 所有容器型產品的使用說明必須包含部署容器型產品的所有步驟。使用說明必須提供指向 上對應容器映像的命令和部署資源 AWS Marketplace。
+ 容器型產品必須包含訂閱者使用軟體所需的所有容器映像。此外，容器型產品不得要求使用者使用來自外部的任何映像來啟動產品 AWS Marketplace （例如，來自第三方儲存庫的容器映像）。
+ 容器及其軟體必須以自助方式部署，且不得需要額外的付款方式或成本。需要部署外部相依性的應用程式必須遵循下列準則：
  + 要求必須在清單的描述或使用說明中公開。例如，*此產品需要網際網路連線才能正確部署。下列套件會在部署時下載：<list of package>。*
  + 賣方負責使用並確保所有外部相依性的可用性和安全性。
  + 如果外部相依性不再可用， AWS Marketplace 也必須從 中移除產品。
  + 外部相依性不得需要額外的付款方式或成本。
+ 需要持續連線到不受買方直接控制的外部資源的容器，例如外部 APIs 或由賣方或第三方 AWS 服務 管理的容器，必須遵循下列準則：
  + 要求必須在清單的描述或使用說明中公開。例如，*此產品需要持續的網際網路連線。需要下列持續的外部服務才能正常運作：<list of resources>。*
  + 賣方負責使用並確保所有外部資源的可用性和安全性。
  + 如果外部資源不再可用， AWS Marketplace 也必須從 移除產品。
  + 外部資源不得需要額外的付款方式或成本，且連線的設定必須自動化。
+ 產品軟體和中繼資料不得包含將使用者重新導向至其他雲端平台、其他產品或不可使用的追加銷售服務的語言 AWS Marketplace。
+ 如果您的產品是另一個產品或其他 ISV 產品的附加元件，您的產品描述必須指出它擴展了另一個產品的功能，如果沒有它，您的產品具有非常有限的公用程式。例如，*此產品擴展了 <product name> 的功能，如果沒有它，此產品的公用程式非常有限。請注意，<product name> 可能需要自己的授權才能使用此清單的完整功能。*

## 架構需求
<a name="container-architecture-requirements"></a>

 所有容器型產品都必須遵守下列架構要求：
+ 的來源容器映像 AWS Marketplace 必須推送至 擁有的 Amazon Elastic Container Registry (Amazon ECR) 儲存庫 AWS Marketplace。您可以在伺服器產品下的 AWS Marketplace 管理入口網站 中，為每個容器產品清單建立這些儲存庫。
+ 容器映像必須以 Linux 為基礎。
+ 付費容器型產品必須能夠部署在 [Amazon ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html)、[Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html) 或 上[AWS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/userguide/what-is-fargate.html)。
+ 具有合約定價和 整合的付費容器型產品 AWS License Manager 應該部署在 Amazon EKS、Amazon ECS AWS Fargate、Amazon EKS Anywhere、Amazon ECS Anywhere、Red Hat OpenShift Service on AWS (ROSA)、內部部署或 Amazon Elastic Compute Cloud 上。
+ 對於 Helm Chart 產品，容器映像參考必須根據 進行結構化[Helm Chart 結構需求](#helm-chart-structure-requirements)，以支援跨區域部署。
+ 如果您的容器型產品需要買方部署 Amazon Machine Image (AMI)，則必須是 AWS受管 AMI 或 中發佈的個別 AMI AWS Marketplace。如果您在 中發佈自己的 AMI AWS Marketplace，則必須符合 ，[的 AMI 型產品需求 AWS Marketplace](product-and-ami-policies.md)而且您必須指出它是 中所需的附加產品[產品使用政策](product-and-ami-policies.md#product-usage)。您可以將 AMI 型產品定價為 BYOL，因為它是容器型產品的延伸。 會 AWS Marketplace 掃描 AMI 型產品是否有未修補的常見漏洞和暴露 (CVEs) 和安全性需求。您的買方也必須訂閱 AMI 型產品，才能進行部署。

## Helm Chart 結構需求
<a name="helm-chart-structure-requirements"></a>

提交至 的所有 Helm Chart 產品 AWS Marketplace 都必須遵守下列結構要求，以確保跨 AWS 區域的適當區域化和部署：
+ 容器映像參考必須僅在 `values.yaml` 檔案中定義，而不是在 Helm Chart 內的任何其他檔案中進行硬式編碼。這可讓 在將產品複寫至不同區域時 AWS Marketplace 自動取代這些參考。
+ `values.yaml` 檔案必須對所有容器映像參考使用變數。
+ 或者，您可以在與儲存庫相同的層級`tag`將 `registry`和 分成不同的欄位，以建置映像參考。
+ Helm 範本必須使用標準 Helm 範本語法 （例如 `{{ .Values.image.repository }}:{{ .Values.image.tag }}`) 來參考這些變數。
+ 避免在會略過 中定義之映像參考的範本中使用條件式邏輯`values.yaml`。
+ 使用不同的 AWS 區域測試 Helm Chart 時，請確保在 中變更區域會`values.yaml`正確更新已部署資源中的所有影像參考。

AWS Marketplace 在產品提交程序`values.yaml`期間， 會驗證檔案中所有容器映像參考是否已正確定義。不符合這些要求的產品將被拒絕。

### Helm Chart 中容器映像參考的需求
<a name="helm-chart-best-practices"></a>

以下示範在 Helm Chart 中建構容器映像參考的方法：

**`values.yaml` （建議的格式）：**

```
image:
  registry: "709825985650.dkr.ecr.us-east-1.amazonaws.com"
  repository: "accuknox/kubearmor"
  tag: "v1.1.1"
```

**注意**  
我們建議針對 `values.yaml` 的結構採用上述方法，但以下替代方法也有效。

**`values.yaml` （替代格式）：**

```
image:
  repository: "709825985650.dkr.ecr.us-east-1.amazonaws.com/guance/datakit"
  tag: "1.0"
```

**`values.yaml` （替代格式）：**

```
image:
  repository: "709825985650.dkr.ecr.us-east-1.amazonaws.com/guance/datakit:1.0"
```

**注意**  
對於部署範本，以下格式是唯一可用的有效格式。

**部署範本：**

```
containers:
- name: kubearmor
  image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
```

**不正確的方法 （請勿使用）：**

```
containers:
- name: kubearmor
  image: "709825985650.dkr.ecr.us-east-1.amazonaws.com/accuknox/kubearmor:v1.1.1"
```

### 可能的 Helm Chart 驗證錯誤
<a name="helm-chart-validation-errors"></a>

在產品提交過程中， 會對 Helm Chart 產品 AWS Marketplace 執行驗證檢查，以確保符合容器映像參考要求。如果您的 Helm Chart 不符合這些要求，您可能會遇到下列驗證錯誤：


| 錯誤 | 說明 | 
| --- | --- | 
| INCOMPATIBLE\$1HELM\$1OBJECTS | EKS 附加元件不支援指定的 Helm 物件。請參閱 [Amazon EKS 附加元件產品的需求](#publishing-eks-add-on)。 | 
| INVALID\$1DEPENDENT\$1HELM\$1CHARTS | 相依 Helm Chart 必須包含在父圖表目錄中，而非外部來源。 | 
| INVALID\$1HELM\$1SENSITIVE\$1CONFIG | 組態結構描述不能包含收集敏感資訊的欄位。組態結構描述不得接受密碼、API 金鑰、憑證或秘密。請改為提供客戶將分別建立的 Kubernetes 秘密名稱欄位。 | 
| INVALID\$1HELM\$1CHART\$1IMAGES | 所有映像，包括開放原始碼相依性，都必須推送至透過新增儲存庫請求建立的 AWS Marketplace Amazon ECR 儲存庫。 [步驟 1：新增儲存庫](container-add-version.md#add-repositories) | 
| INVALID\$1HELM\$1UNDECLARED\$1IMAGES | 所有容器映像參考都必須明確列在[新增版本](container-add-version.md#add-new-version)請求中。 | 
| INVALID\$1HELM\$1LINT | Helm Chart helm lint 驗證失敗。在helm lint本機執行 以識別和修正結構或語法問題。使用 Helm 版本 3.19.0 或更新版本。 | 
| INVALID\$1HELM\$1TEMPLATE | Helm Chart helm template 驗證失敗。圖表無法轉譯為有效的 Kubernetes 資訊清單。在本機使用 進行測試helm template，以識別範本語法或邏輯錯誤。使用 Helm 版本 3.19.0 或更新版本。 | 
| MISSING\$1HELM\$1DEPLOYMENT\$1CONFIG | Amazon EKS 附加元件的 Helm Chart 必須包含部署或 DaemonSet 資源。Amazon EKS 至少需要其中一個工作負載類型，才能進行附加元件生命週期管理。請參閱 [Amazon EKS 附加元件產品的需求](#publishing-eks-add-on)。 | 
| INCOMPATIBLE\$1CONFIGURATION\$1SCHEMA\$1VERSION | aws\$1mp\$1configuration\$1schema.json 不支援 中的 JSON 結構描述版本。如需支援的結構描述版本[結構描述要求](#schema-requirements)，請參閱 。 | 
| INVALID\$1IMAGE\$1REFERENCE | 所有映像都必須定義為 中的變數，values.yaml並使用 Helm 範本語法加以參考，如中所述[Helm Chart 結構需求](#helm-chart-structure-requirements)。 | 
| MISSING\$1VALUES\$1IMAGE\$1REFERENCE | 每個容器映像參考都必須在 中具有對應的項目values.yaml。 | 
| MISSING\$1IMAGE\$1TAG | 中的容器映像參考values.yaml必須包含明確的標籤值，或是來自 的圖表版本預設值Chart.yaml。 | 

## 容器產品使用說明
<a name="container-product-usage-instructions"></a>

建立容器產品的使用說明時，請遵循 中的步驟和指引[建立 的 AMI 和容器產品使用說明 AWS Marketplace](ami-container-product-usage-instructions.md)。

### Helm Chart 使用說明
<a name="helm-chart-usage-instructions"></a>

建立 Helm Chart 產品的使用說明時：
+ 在您的 `values.yaml` 檔案中明確記錄所有可設定的參數，包括映像儲存庫、標籤和登錄參數。
+ 提供安裝 Helm Chart 時如何覆寫這些參數的範例。
+ 安裝圖表時，請勿指示使用者修改 `values.yaml`或 以外的任何檔案，以使用`--set`參數。
+ 包含有關產品如何處理容器映像區域化的資訊。

## Amazon EKS 附加元件產品的需求
<a name="publishing-eks-add-on"></a>

Amazon EKS 附加元件是一種軟體，可為Kubernetes應用程式提供操作功能，但並非特定於應用程式。例如，Amazon EKS 附加元件包含可觀測性代理程式或Kubernetes驅動程式，允許叢集與網路、運算和儲存的基礎 AWS 資源互動。

身為容器產品的賣方，您可以選擇多種部署選項，包括 Amazon EKS。您可以將產品版本做為 AWS Marketplace 附加元件發佈至 Amazon EKS 附加元件目錄。您的附加元件會顯示在 Amazon EKS 主控台中，位於 AWS 和其他廠商維護的附加元件旁。您的買方可以將軟體部署為附加元件，就像部署其他附加元件一樣輕鬆。

如需詳細資訊，請參閱《Amazon EKS 使用者指南》中的 [Amazon EKS 附加元件](https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html)。

### 將容器產品準備為 AWS Marketplace 附加元件
<a name="preparing-eks-addon"></a>

若要將容器產品發佈為 AWS Marketplace 附加元件，必須符合下列要求：
+ 您的容器產品必須在 中發佈 AWS Marketplace。
+ 您的容器產品必須同時與 AMD64 和 ARM64 架構相容。
+ 您的容器產品不得使用自帶授權 (BYOL) [定價模型](https://docs.aws.amazon.com/marketplace/latest/userguide/pricing-container-products.html)。
**注意**  
Amazon EKS 附加元件交付不支援 BYOL。
+ 您必須遵守所有[容器型產品需求](https://docs.aws.amazon.com/marketplace/latest/userguide/container-product-policies.html)，包括將所有容器映像和Helm圖表推送至 AWS Marketplace 受管 Amazon ECR 儲存庫。此需求包含開放原始碼映像，例如 `nginx`。映像和圖表無法託管在其他外部儲存庫中，包括但不限於 [Amazon ECR Public Gallery](https://docs.aws.amazon.com/AmazonECR/latest/public/public-repositories.html)Docker Hub、 和 Quay。
+ **Helm 圖表** - 準備並封裝您的軟體做為Helm圖表。Amazon EKS 附加元件架構會將Helm圖表轉換為 Kubernetes 資訊清單。Amazon EKS 系統不支援某些Helm功能。以下清單說明將軟體加入為 Amazon EKS 附加元件之前必須符合的要求。在此清單中，所有Helm命令都使用 3.19.0 Helm版：
  + 支援所有`Capabilities`物件，但 除外`.APIVersions`。 `.APIVersions`不支援非內建的自訂 Kubernetes APIs。 non-built-in 
  + 僅支援 ```Release.Name`和 `Release.Namespace` 物件。
  + Helm 不支援勾點和 `lookup`函數。
  + 所有相依圖表都必須位於主Helm圖表中 （以儲存庫路徑檔案：//... 指定）。
  + Helm 圖表必須成功通過 Helm Lint 和 Helm 範本，沒有錯誤。命令如下所示：
    + Helm Lint – `helm lint helm-chart`

      常見問題包括父圖表中繼資料中未宣告的圖表。例如 `chart metadata is missing these dependencies: chart-base Error: 1 chart(s) linted, 1 chart(s) failed`
    + Helm 範本 – `helm template chart-name chart-location --set k8version=Kubernetes-version --kube-version Kubernetes-version --namespace addon-namespace --include-crds --no-hooks -f any-overriden-values`

      使用 `-f`旗標傳遞任何覆寫的組態。
  + 將所有容器二進位檔存放在 AWS Marketplace Amazon ECR 儲存庫中。若要建立資訊清單，請使用先前顯示的Helm範本命令。搜尋資訊清單以取得任何外部影像參考，例如 `busybox`或 `gcr` 影像。使用請求下拉式清單中的**新增儲存庫**選項，將所有容器映像以及相依性上傳至建立的 AWS Marketplace Amazon ECR 儲存庫。
+ **自訂組態** – 您可以在部署期間新增自訂變數。如需如何識別最終使用者體驗、命名軟體`aws_mp_configuration_schema.json`，以及使用Helm圖表封裝成包裝函式的詳細資訊，請參閱 [Amazon EKS 附加元件：進階組態](https://aws.amazon.com/blogs/containers/amazon-eks-add-ons-advanced-configuration/)。

  根據[「\$1schema」關鍵字](https://json-schema.org/draft/2020-12/json-schema-core#name-the-schema-keyword)， `$schema` 必須是指向有效`application/schema+json`資源的 URI。

  此檔案不得接受任何敏感資訊，例如密碼、授權金鑰和憑證。

  若要處理秘密和憑證安裝，您可以為最終使用者提供安裝後或pre-Add-on元件安裝步驟。產品不應依賴任何外部授權。產品應該根據 AWS Marketplace 權利運作。

  如需 限制的詳細資訊`aws_mp_configuration_schema.json`，請參閱 [附加元件供應商的附加元件組態需求和最佳實務](#eks-addon-configuration)。
+ **識別並建立要部署軟體的命名空間** – 在產品的第一個版本中，您必須新增範本化命名空間，以識別要部署軟體的命名空間。
+ **自訂資源定義 (CRDs)** – Amazon EKS 附加元件架構不支援根據使用相同附加元件套用的 CRDs 和自訂資源宣告。如果您的附加元件具有自訂資源並依賴 CRDs，您可以：
  + 將**兩個附加元件：分割 CRD 定義發佈**至單獨的附加元件 （單獨的 Helm Chart)，並將實際的[自訂資源](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)安裝發佈至單獨的附加元件。
  + **發佈具有其他手動指示的單一附加元件：**發佈在叢集上安裝 CRDs單一附加元件。提供使用說明以及 kubernetes 資訊清單檔案，以供最終使用者設定依賴這些 CRDs自訂資源。
+ 如果**適用，`serviceAccount`請建立** - 如果軟體是 上的付費軟體 AWS Marketplace 或必須與其他軟體連線 AWS 服務，請確定Helm圖表`serviceAccount`預設會建立。如果`serviceAccount`建立是由`values.yaml`檔案中的參數處理，請將參數值設定為 `true`。例如 `serviceAccount.create = true`。這是必要的，因為客戶可能會選擇從已具有必要許可的基礎節點執行個體繼承許可來安裝附加元件。如果 Helm Chart 未建立 `serviceAccount`，則許可無法繫結至 `serviceAccount`。
+ **可追蹤的部署或協助程式集** – 確保您的 Helm Chart 具有協助程式集或部署。Amazon EKS 附加元件架構會使用它們來追蹤 Amazon EKS 資源的部署。如果沒有可追蹤的部署或協助程式集，您的附加元件將面臨部署錯誤。如果您的附加元件沒有部署或協助程式集，例如，如果您的附加元件部署了大量自訂資源或無法追蹤的 Kubernetes 任務，請新增虛擬部署或協助程式集物件。
+ **支援 AMD 和 ARM 架構** – 許多 Amazon EKS 客戶現在使用 ARM64 來使用 AWS Graviton 執行個體。第三方軟體必須支援這兩種架構。
+ **與來自 的授權或計量 APIs 整合 AWS Marketplace** - AWS Marketplace 支援多個帳單模型。如需詳細資訊，請參閱[容器產品計費、計量和授權整合](container-products-billing-integration.md)。如果您想要透過 PAYG 機制銷售產品，請參閱 [使用 AWS Marketplace Metering Service 設定容器產品的自訂計量](container-metering-meterusage.md)。如果您想要透過預付或合約模型銷售產品，請參閱 [使用 的容器產品的合約定價 AWS License Manager](container-license-manager-integration.md)。
+ **上傳軟體和所有成品和相依性** – Helm Chart 必須獨立，且不得需要來自外部來源的相依性，例如 GitHub。如果軟體需要外部相依性，則必須將相依性推送至相同 AWS Marketplace 清單下的 AWS Marketplace 私有 Amazon ECR 儲存庫。
+ **在您的網站上提供部署指示** – 我們要求您託管部署指南，讓客戶了解如何透過 [create-addon](https://docs.aws.amazon.com/cli/latest/reference/eks/create-addon.html) 命令部署您的軟體。
+ **附加元件許可/IAM 角色** – 如果您從 發佈的附加元件 AWS Marketplace 需要存取 AWS 服務，您的軟體應該有一個 Kubernetes 服務帳戶，並標註 IAM 政策來存取 AWS 服務。您可以從服務帳戶的兩個選項中選擇，以向 AWS 服務提出 API 請求：
  + 透過 IRSA 的登入資料：此選項可讓您的軟體從 Identity and Access Management (IAM) Role Service (IRSA) 取得擔任登入資料。如需詳細資訊，請參閱[服務帳戶的 IAM 角色。 ](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)
  + Amazon EKS Pod 身分：此選項可讓您的軟體使用 Amazon EKS Pod 的 Pod 身分向 AWS 服務提出 API 請求。如需詳細資訊，請參閱[了解 EKS Pod Identity 如何授予 Pod 對 AWS 服務的存取權](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html)

  您的附加元件必須在與目前自訂組態結構描述 () 相同的目錄中，在 Helm Chart `aws_mp_addon_parameters.json` 的最上層具有名為 的額外組態檔案`aws_mp_configuration_schema.json`。目前，此檔案僅處理 Pod 身分相容的許可。檔案格式如下：

  ```
  {
    "permissions": {
        "isPodIdentityCompatible" : true,
        "permissionsList": [
         {
          "serviceAccount" : "String",
          "managedPolicies" : ["Policy Arn"],
         }
       ]
      }
    }
  ```

  **檔案名稱： `aws_mp_addon_parameters.json` **
**注意**  
`aws_mp_addon_parameters.json` 檔案會在 **Amazon EKS 主控台的附加元件組態設定頁面中啟用附加元件存取**區段 ****     
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/marketplace/latest/userguide/container-product-policies.html)
**注意**  
來自 Pay-as-you-go(PAYG) 附加元件產品 AWS Marketplace 無法使用 Amazon EKS Pod 身分，且必須使用 IAM Roles for Service Accounts (IRSA) 進行存取控制。
+ **版本更新** – Amazon EKS 會在上游發行數週後發行新的 Kubernetes 版本。隨著新的 Amazon EKS 叢集版本正式推出，廠商有 45 天的時間來認證或更新其軟體，使其與新的 Amazon EKS 叢集版本版本相容。如果您目前的附加元件版本支援新的 Kubernetes 版本，請驗證並認證相同的 ，以便我們可以更新版本相容性矩陣。如果需要新的附加元件版本來支援新的 Kubernetes 版本版本，請提交新版本以供加入。
+ 合作夥伴的軟體必須屬於下列其中一種類型，或是可增強 Kubernetes 或 Amazon EKS 的操作軟體：Gitops \$1 監控 \$1 記錄 \$1 cert-management \$1 政策管理 \$1 成本管理 \$1 Autoscaling \$1 儲存 \$1 kubernetes-management \$1 service-mesh \$1 etcd-backup \$1 ingress-service-type \$1 load-balancer \$1 local-registry \$1 networking \$1 Security \$1 備份 \$1 輸入控制器 \$1 可觀測性
+ 軟體不能是[容器網路界面 (CNI)](https://github.com/containernetworking/cni)。
+ 軟體必須透過 銷售， AWS Marketplace 並與付費產品的授權和計量 APIs整合。不接受 BYOL 產品。

### 附加元件供應商的附加元件組態需求和最佳實務
<a name="eks-addon-configuration"></a>

Amazon EKS 需要來自附加元件供應商的 [Helm JSON 結構描述](https://helm.sh/docs/topics/charts/#schema-files)字串組態。需要必要組態或允許選用組態的附加元件必須包含提交 Helm Chart `aws_mp_configuration_schema.json` 的檔案 AWS Marketplace。Amazon EKS 將使用此結構描述來驗證客戶的組態輸入，並拒絕具有不符合結構描述之輸入值的 API 呼叫。附加元件組態通常分為兩個類別：
+ 一般 Kubernetes 屬性的組態，例如標籤、公差、 nodeSelector 等。
+ 附加元件特定的組態，例如授權金鑰、功能啟用、URLs等。

本節著重於與一般 Kubernetes 屬性相關的第一個類別。

Amazon EKS 建議遵循有關 Amazon EKS 附加元件組態的最佳實務。
+ [結構描述要求](#schema-requirements)
+ [允許組態的一般參數](#parameters-allowed)
+ [不允許用於組態的常見參數](#parameters-not-available)

#### 結構描述要求
<a name="schema-requirements"></a>

定義 json 結構描述時，請確定您使用 Amazon EKS 附加元件支援的 jsonschema 版本。

支援的結構描述清單：
+ https://json-schema.org/draft-04/schema
+ https://json-schema.org/draft-06/schema
+ https://json-schema.org/draft-07/schema
+ https://json-schema.org/draft/2019-09/schema

使用任何其他 json 結構描述版本與 Amazon EKS 附加元件不相容，將導致附加元件無法釋出，直到修正此問題為止。

**範例 Helm 結構描述檔案**

```
{
"$schema": "http://json-schema.org/schema#",
  "type": "object",
  "properties": {
"podAnnotations": {
"description": "Pod Annotations"
"type": "object"
    },
    "podLabels": {
"description": "Pod Labels"
"type": "string"
    },
    "resources": {
"type": "object"
"description": "Resources"
    },
    "logLevel": {
"description": "Logging Level"
"type": "string",
      "enum": [
        "info",
        "debug"
      ]
    },
    "config": {
"description": "Custom Configuration"
"type": "object"
    }
  }
}
```

**camelCase**  
組態參數必須是 camelCase，如果未遵循此格式，則會遭到拒絕。

**描述為必要項目**  
一律包含結構描述屬性的有意義的描述。此描述將用於在每個組態參數的 Amazon EKS 主控台中轉譯標籤名稱。

**RBAC 定義**  
附加元件提供者需要使用最低權限原則來定義和提供成功安裝附加元件所需的 RBAC 許可。如果 RBAC 許可需要變更較新版本的附加元件或任何修正以解決 CVE，則附加元件提供者將需要將此變更通知 Amazon EKS 團隊。每個 Kubernetes 資源的必要許可應限於物件的資源名稱。  

```
apiGroups: ["apps"]
resources: ["daemonsets"]
resourceNames: ["ebs-csi-node"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
```

**秘密管理**  
本節僅適用於需要客戶設定機密資訊的附加元件，例如應用程式金鑰、API 金鑰、密碼等。由於安全性影響，Amazon EKS APIs 目前不支援以純文字傳遞秘密資訊。不過，客戶可以使用組態來傳入包含附加元件所需金鑰的 Kubernetes Secret 名稱。客戶需要建立 Kubernetes Secret 物件，其中包含與先決條件步驟具有相同命名空間的金鑰，然後在建立附加元件時使用組態 Blob 傳入 Secret 的名稱。我們建議附加元件提供者為結構描述屬性命名，這樣客戶就不會意外誤認為實際金鑰。例如：appSecretName、connectionSecretName 等。  
總而言之，附加元件提供者可以利用結構描述，允許客戶傳入秘密的名稱，但不能傳遞實際上會保留秘密本身的金鑰。

**範例組態值**  
您可以在結構描述中包含組態範例，以協助客戶設定附加元件。下列範例來自 AWS Distro for OpenTelemetry 附加元件的結構描述。  

```
"examples": [
      {
        "admissionWebhooks": {
          "namespaceSelector": {},
          "objectSelector": {}
        },
        "affinity": {},
        "collector": {
          "amp": {
            "enabled": true,
            "remoteWriteEndpoint": "https://aps-workspaces.us-west-2.amazonaws.com/workspaces/ws-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/api/v1/remote_write"
          },
          "cloudwatch": {
            "enabled": true
          },
          "mode": "deployment",
          "replicas": 1,
          "resources": {
            "limits": {
              "cpu": "256m",
              "memory": "512Mi"
            },
            "requests": {
              "cpu": "64m",
              "memory": "128Mi"
            }
          },
          "serviceAccount": {
            "annotations": {},
            "create": true,
            "name": "adot-collector"
          },
          "xray": {
            "enabled": true
          }
        },
        "kubeRBACProxy": {
          "enabled": true,
          "resources": {
            "limits": {
              "cpu": "500m",
              "memory": "128Mi"
            },
            "requests": {
              "cpu": "5m",
              "memory": "64Mi"
            }
          }
        },
        "manager": {
          "env": {},
          "resources": {
            "limits": {
              "cpu": "100m",
              "memory": "128Mi"
            },
            "requests": {
              "cpu": "100m",
              "memory": "64Mi"
            }
          }
        },
        "nodeSelector": {},
        "replicaCount": 1,
        "tolerations": []
      }
    ]
```

#### 允許組態的一般參數
<a name="parameters-allowed"></a>

以下是面向客戶的 Helm 結構描述檔案中的建議參數。


| 參數 | Description | 應該有預設值嗎？ | 
| --- | --- | --- | 
| additionalLabels | 將 Kubernetes 標籤新增至附加元件管理的所有 Kubernetes 物件。 | 否 | 
| additionalAnnotations | 將 Kubernetes 註釋新增至附加元件管理的所有 Kubernetes 物件。 | 否 | 
| podLabels | 將 Kubernetes 標籤新增至 附加元件管理的 Pod。 | 否 | 
| podAnnotations | 將 Kubernetes 註釋新增至附加元件管理的 Pod。 | 否 | 
| logLevel | 由附加元件管理之元件的日誌層級。 | 是 | 
| nodeSelector | 建議最簡單的節點選取限制條件。您可以將 nodeSelector 欄位新增至 Pod 規格，並指定您希望目標節點擁有的節點標籤。 | 可能，例如僅限 Linux 節點 | 
| 容差 | 公差會套用至 Pod。容錯允許排程器使用相符的污點來排程 Pod。容錯允許排程，但不保證排程。 | 或許， 協助程式集更常見 | 
| 親和性 | 親和性功能包含兩種類型的親和性：節點親和性函數，例如 nodeSelector 欄位，但更具表達性，並可讓您指定軟性規則，Pod 間親和性/反親和性可讓您限制 Pod 與其他 Pod 上的標籤。 | 也許可以 | 
| topologySpreadConstraints | 您可以使用拓撲分散限制來控制 Pod 如何在故障網域之間分散到叢集，例如區域、區域、節點和其他使用者定義的拓撲網域。這有助於實現高可用性以及高效的資源使用率。 | 也許可以 | 
| 資源請求/限制 | 指定每個容器需要多少 cpu/記憶體。強烈建議設定請求。限制是選用的。 | 是 | 
| 複本 | 附加元件管理的 Pod 複本數量。不適用於協助程式集。 | 是 | 

**注意**  
對於工作負載排程組態參數，您可能需要在必要時將結構描述中的頂層元件分開。例如，Amazon EBS CSI 驅動程式包含兩個主要元件：控制器和節點代理程式 - 客戶需要每個元件的不同節點選擇器/容錯。

**注意**  
JSON 結構描述中定義的預設值僅用於使用者文件，不會取代`values.yaml`檔案中具有正確預設值的需求。如果使用預設屬性，請確保 中的預設值`values.yaml`符合結構描述中的預設值，且每當對 Helm Chart 進行變更時，兩個成品 (`values.schema.json` 和 `values.yaml`) 都會保持同步。

```
"affinity": {
            "default": {
              "affinity": {
                "nodeAffinity": {
                  "preferredDuringSchedulingIgnoredDuringExecution": [
                    {
                      "preference": {
                        "matchExpressions": [
                          {
                            "key": "eks.amazonaws.com/compute-type",
                            "operator": "NotIn",
                            "values": [
                              "fargate"
                            ]
                          }
                        ]
                      },
                      "weight": 1
                    }
                  ]
                },
                "podAntiAffinity": {
                  "preferredDuringSchedulingIgnoredDuringExecution": [
                    {
                      "podAffinityTerm": {
                        "labelSelector": {
                          "matchExpressions": [
                            {
                              "key": "app",
                              "operator": "In",
                              "values": [
                                "ebs-csi-controller"
                              ]
                            }
                          ]
                        },
                        "topologyKey": "kubernetes.io/hostname"
                      },
                      "weight": 100
                    }
                  ]
                }
              }
            },
            "description": "Affinity of the controller pod",
            "type": [
              "object",
              "null"
            ]
          }
```

### 不允許用於組態的常見參數
<a name="parameters-not-available"></a>

各種附加元件 （例如 Elastic Load Balancing 控制器） `clusterName` `region`可能需要叢集中繼資料參數，例如 `vpcId`、`accountId`、、 和其他參數。Amazon EKS 服務已知的任何類似參數都會由 Amazon EKS 附加元件自動注入，而不會承擔使用者將 指定為組態選項的責任。這些參數包括：
+ AWS 區域
+ Amazon EKS 叢集名稱
+ 叢集的 VPC ID
+ 容器登錄檔，特別是用於 build-prod 帳戶，供聯網附加元件使用
+ DNS 叢集 IP，特別是核心附加元件
+ Amazon EKS 叢集 API 端點
+ 叢集上已啟用 IPv4 
+ 叢集上已啟用 IPv6 
+ 叢集上啟用 IPv6 的字首委派

附加元件提供者需要確保您已為此類適用參數定義範本。上述每個參數都有由 Amazon EKS 定義的預先定義`parameterType`屬性。發行中繼資料將指定 範本中 參數`parameterType`的名稱/路徑之間的映射。如此一來，Amazon EKS 即可動態傳入這些值，而無需客戶透過組態指定這些值，也提供附加元件提供者彈性來定義自己的範本名稱/路徑。Amazon EKS 動態注入所需的上述參數應該從結構描述檔案中排除。

**來自發行中繼資料的範例映射**

```
"defaultConfiguration": [
       {
            "key": "image.containerRegistry",
            "parameterType": "CONTAINER_REGISTRY"
       }
]
```

以下是不建議在面向客戶的 Helm 結構描述檔案中設定的參數。這些參數應具有不可修改的預設值，或完全不包含在附加元件範本中。


| 參數 | Description | 應該有預設值嗎？ | 
| --- | --- | --- | 
| image | 將部署在 Kubernetes 叢集上的容器映像。 | 否，透過附加元件定義進行管理 | 
| imagePullSecrets | 設定 Pod 以使用秘密從私有登錄檔提取。 | N/A | 
| livenessProbe | Kubelet 程序使用活體探查來知道何時重新啟動容器。例如，活體探測可能會捕捉應用程式正在執行但無法進行進度的死結。重新啟動處於此類狀態的容器有助於讓應用程式在發生錯誤時更可用。 | 是 | 
| readinessProbe | 請務必為您的容器建立整備探查。如此一來，在資料平面上執行的 Kubelet 程序就會知道容器何時準備好為流量提供服務。當 Pod 的所有容器都就緒時，就會將其視為就緒。此訊號的其中一個用途是控制哪些 Pod 用作 服務的後端。當 Pod 尚未就緒時，會從服務負載平衡器中移除。 | 是 | 
| startupProbe | kubelet 使用啟動探查來了解容器應用程式何時啟動。如果已設定此類探查，則會停用活體和準備度檢查，直到成功為止，確保這些探查不會干擾應用程式啟動。這可用於在啟動緩慢的容器上採用活體檢查，避免它們在啟動和執行之前被 kubelet 刪除。 | 選用 | 
| podDisruptionBudget | 定義 Pod 中斷預算 (PDB)，以確保在自願中斷期間持續執行的 PODS 數量下限。PDB 會限制複寫應用程式因自願中斷而同時關閉的 Pod 數量。例如，以規定人數為基礎的應用程式想要確保執行的複本數目永遠不會低於規定人數所需的數目。Web 前端可能想要確保提供負載的複本數目永遠不會低於總數的特定百分比。 | 是，如果預設為兩個以上的複本 | 
| serviceAccount （名稱） | 服務帳戶 Pod 的名稱將在 下執行。 | 是 | 
| serviceAccount （註釋） | 套用至服務帳戶的註釋。通常用於服務帳戶的 IAM 角色功能 | 否，IAM 服務帳戶角色 ARN 是在頂層 Amazon EKS 附加元件 API 中設定。此規則的例外是，如果您的附加元件有多個部署/控制器 （例如 Flux)，並且需要單獨的 IRSA 角色 ARNs。 | 
| priorityClassName | 優先順序表示 Pod 相對於其他 Pod 的重要性。如果無法排程 Pod，排程器會嘗試先佔 （移出） 優先順序較低的 Pod，以便排程擱置中的 Pod。 | 是。大多數附加元件對叢集功能至關重要，且預設應設定優先順序類別。 | 
| podSecurityContext | 安全內容會定義 Pod 或容器的權限和存取控制設定。通常用於設定 fsGroup - 這是 v1.19 和較低叢集中 IRSA 所需的。 | 不太可能，指定的 Amazon EKS 不再支援 Kubernetes v1.19 | 
| securityContext | 安全內容會定義 Pod 或容器的權限和存取控制設定。 | 是 | 
| updateStrategy | 指定用來將舊 Pod 取代為新 Pod 的策略。 | 是 | 
| nameOverride | 覆寫 Pod 的名稱。 | 否 | 
| podSecurityPolicy |  對參數強制執行限制。  | 否 - PSPs已棄用 | 
| extraVolumeMounts/extraVolumes |  用於非 Amazon EKS 叢集中的 IRSA。  | 否 | 

# 的容器產品定價 AWS Marketplace
<a name="pricing-container-products"></a>

在 上 AWS Marketplace，您可以列出免費產品、自攜授權模型 (BYOL) 產品，以及 Amazon Elastic Container Service (Amazon ECS)、Amazon Elastic Kubernetes Service (Amazon EKS) 和 的付費產品 AWS Fargate。每個產品只能設定一個價格。本主題概述容器產品的可用定價模型。

**注意**  
您可以使用 [AWS Marketplace 計量服務](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html)來強制執行付費產品的權利和計量用量。對於每個任務或每個 Pod 定價，用量會自動計量 AWS。

您為容器產品設定的價格適用於所有 AWS 區域。每當您降低容器產品的價格時，就會立即為您的買方實作新價格。對於價格上漲，現有買方會在變更影響其帳單的 90 天前收到變更通知。新買方需支付新金額的費用。

**注意**  
對於新訂閱者，價格變更會立即生效。對於現有的訂閱者，價格變更會在從傳送價格變更通知當日起算的 90 天期間之後的下個月第一天生效。例如，假設您在 3 月 16 日傳送價格變更通知。6 月 16 日大約是 3 月 16 日之後的 90 天。由於價格變更發生在 90 天期間之後當月的第一天，因此變更的生效日期為 7 月 1 日。

**Topics**
+ [容器定價模型](#pricing-models-for-server-products)

## 容器定價模型
<a name="pricing-models-for-server-products"></a>

AWS Marketplace 有多個容器產品的定價模型。

下表提供有關容器型產品的定價模型的一般資訊。


**容器產品的定價模型**  

| 定價方式 | Description | 
| --- | --- | 
| 使用自有授權 (BYOL) | BYOL 是透過您與買方維持 AWS Marketplace 的外部帳單關係在 外部進行管理。容器中的軟體不會與 整合 AWS Marketplace 以進行計費。 | 
| 每月 | **每月固定價格**每月固定價格，為使用者提供下個月無限的產品用量。範例：您將產品的價格設定為每月 99 美元。您的產品包含三個使用 Amazon ECS 任務定義部署的不同容器映像。買方訂閱您的產品後，會立即向他們收費 99 USD，每月重複此動作，直到他們取消訂閱為止。買方也會無限制地使用產品。買方也會針對任務執行所在的任何基礎設施單獨付費。訂閱後，他們可以存取您的容器映像。他們可以在任何組態中從 Amazon ECS 或 Amazon EKS 上的這些映像啟動和執行任意數量的容器。如果買方在一個月中取消其訂閱，他們將無法存取 AWS Marketplace 存放容器映像的 Amazon ECR 儲存庫。買方可能已提取並存放原始映像。不過，他們無法再提取您提供的新容器映像版本 AWS Marketplace。買方會收到最後一個月未使用部分的退款。您是根據買方的使用量減去約定 AWS Marketplace 費用來支付。 | 
| 自訂計量定價維度 |  根據您定義的維度 （例如使用者、節點、儲存庫或 GB) 自訂計量價格，每個產品最多 24 個維度。 範例：使用者收取您的產品費用。您有管理員使用者和一般使用者，而您將定價定義為管理員使用者 2 USD，一般使用者 1 USD。您可以在列出產品時將它們設定為個別維度。您每天會由登入的使用者收費，並計量每天的用量。 若要進一步了解以用量為基礎的定價自訂計量，請參閱 [使用 AWS Marketplace Metering Service 設定容器產品的自訂計量](container-metering-meterusage.md)。  | 
| 每個任務或每個 Pod 每小時價格 |  **Amazon ECS 任務或 Amazon EKS Pod** 每個 Amazon ECS 任務或每個 Amazon EKS Pod 定價，我們以每小時的價格設定來測量到第二個。 範例：您的產品包含三種不同的容器映像：控制器節點、工作者節點和分析節點。由於在沒有控制器節點的情況下，您的產品無法正常運作或沒有用，因此您決定 是您想要收取用量費用的映像。您設定每小時 6 美元的價格。 您可以修改控制器節點的容器映像中的軟體，以與 [AWS Marketplace Metering Service](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html) `RegisterUsage` API 操作整合。這可確保只有具有作用中訂閱的買方才能啟動和執行該容器映像，並根據其執行時間來衡量其用量。 每個執行中的 Amazon EKS 控制器 Pod 每小時都會向買方收取 6 USD 的費用。如果買方啟動五個包含控制器節點容器的 Amazon EKS 控制器 Pod，則會收取每小時 30 USD 的費用 （每個 Pod 6 USD)。買方也會單獨支付 Pod 執行所在的任何基礎設施。 對於每小時定價，計費為每秒，最少 1 分鐘。如果客戶執行此控制器容器 20 分鐘又 30 秒，則會向 收費`20 x ($6/60) + 30 x ($6/60/60) = $2 + $0.05 = $2.05`。您是根據買方的使用量減去約定 AWS Marketplace 費用來支付。 若要進一步了解每個任務或每個 Pod 的每小時定價，請參閱 [使用 AWS Marketplace Metering Service 設定每小時計量](container-metering-registerusage.md)。  | 
| 具有長期合約的每小時定價或自訂計量定價 |  長期合約，以較低的價格預付或定期分期付款。長期合約可以新增至具有自訂計量定價的現有產品，或每個任務和每個 Pod 定價。買方使用超過長期合約中購買的價格時，支付計量價格。 範例：對於計量定價模型，您可以為買方新增長期合約價格，以獲得預付的折扣。假設您通常會針對使用的某些單位收取 1 USD。使用每小時 1 個單位的買方每年將支付 8760 美元 (`365 days x 24 hours x $1 per hour`)。您可以啟用合約，讓買方以該價格的一半 (4380 USD) 對這 365 天每小時使用 1 個單位。在此情況下，買方承諾預付一年合約的費用，價格從每單位 1 美元降至每單位 0.5 美元。您也可以讓買方購買其中多個合約。如果計量的數量顯示買方在一小時內耗用 10 個單位，而且他們有兩個合約，則 2 個單位將包含在 2 個合約中。8 個額外單位將以每小時 1 USD 的固定費率計費，該小時總計 8 USD。 對於每個任務或每個 Pod 範例，您也可以為買方新增長期合約價格，以取得預付的折扣。如果您通常為每個 Pod 收取 6 USD，您可以設定 365 天的長期合約持續時間，價格為 13，140 USD (`365 days x 24 hours x $3 per pod per hour`)。然後，在這 365 天內，一份合約會讓客戶每小時 1 個 Pod。客戶可以選擇購買多個合約。例如，客戶可以購買兩個合約，讓他們每小時 2 個 Pod。如果客戶每小時執行的 Pod 超過授權的合約，則多餘的 Pod 將按您正常的每小時價格計費。 在這兩種情況下，購買長期合約的買方都會預先計費，可以是一次性付款或定期排程的未來付款。買方也會依計量費率支付超出合約的任何額外使用量。  | 
| 容器合約定價 |  **具有合約定價的容器** – 買方預付費用的容器型產品。 若要進一步了解合約定價，請參閱 [使用 的容器產品的合約定價 AWS License Manager](container-license-manager-integration.md)。  | 

# 容器產品計費、計量和授權整合
<a name="container-products-billing-integration"></a>

AWS Marketplace 與其他 整合 AWS 服務 ，為您的容器產品提供計量和以合約為基礎的定價。對於使用量定價的容器型產品，您可以使用 [AWS Marketplace Metering Service](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html)來檢查是否有權使用您的產品和計量用量來計費。對於具有合約定價的容器型產品，您可以使用 AWS License Manager 將授權與產品建立關聯。下列各節提供每小時和自訂計量 AWS Marketplace Metering Service 以及 合約定價的詳細資訊 AWS License Manager。

**Topics**
+ [使用 的每小時和自訂計量 AWS Marketplace Metering Service](#entitlement-and-metering-for-paid-products)
+ [使用 的合約定價 AWS License Manager](#container-products-contracts-license-manager)
+ [使用 AWS Marketplace Metering Service 設定每小時計量](container-metering-registerusage.md)
+ [使用 AWS Marketplace Metering Service 設定容器產品的自訂計量](container-metering-meterusage.md)
+ [使用 的容器產品的合約定價 AWS License Manager](container-license-manager-integration.md)

## 使用 的每小時和自訂計量 AWS Marketplace Metering Service
<a name="entitlement-and-metering-for-paid-products"></a>

若要同時檢查使用您產品的權利和計量帳單用量，請使用 [AWS Marketplace 計量服務](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html)。如果您想要定義自己的定價單位和計量單位，以向我們計費，請使用 [MeterUsage](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html) API 操作整合 。如果您想要根據使用的任務數量或 Pod 定價產品，並自動讓 AWS 計量該用量，請使用 [RegisterUsage](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_RegisterUsage.html) API 操作進行整合。對於這兩種定價類型，您可以新增長期合約價格，而無需變更與 整合的方式 AWS Marketplace Metering Service。

當您在 中建立新的容器產品時 AWS Marketplace 管理入口網站，我們會提供一組產品識別符 （產品代碼和公有金鑰），用於整合您的產品與 AWS Marketplace Metering Service。

### Entitlement
<a name="seller-container-entitlement"></a>

與 整合 AWS Marketplace Metering Service 可讓您驗證執行付費軟體的客戶是否已訂閱您的產品 AWS Marketplace，以防止您在容器啟動時遭到未經授權的使用。若要驗證權利，請根據您的定價模型，使用 [MeterUsage](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html) 或 [RegisterUsage](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_RegisterUsage.html) API 操作。對於每小時和固定每月定價模型，請使用 `RegisterUsage` API 操作。對於自訂計量定價模型，請使用 `MeterUsage` API 操作。

如果買方無權使用您的產品，這些 API 操作會傳回`CustomerNotEntitledException`例外狀況。

**注意**  
如果買方在執行產品時取消訂閱，他們有權繼續執行產品。不過，它們無法為您的產品啟動其他容器。

### 整合準則
<a name="integration-guidelines"></a>

當您建立和發佈容器產品，並使用 `MeterUsage`或 `RegisterUsage` API 操作進行權利和計量時，請記住下列準則：
+ 請勿在軟體或 Docker 容器映像中設定 AWS 登入資料。當容器映像在 Amazon ECS 任務或 Amazon EKS Pod 中執行時，會在執行時間自動取得買方的 AWS 登入資料。
+  若要從 Amazon EKS 呼叫 `MeterUsage`或 `RegisterUsage` API 操作，您必須[使用支援的 AWS SDK](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html)。若要測試`MeterUsage`或`RegisterUsage`整合 Amazon EKS，您必須執行執行 Kubernetes 1.13.x 或更新版本的 Amazon EKS 叢集。 AWS Identity and Access Management (IAM) 角色需要 Kubernetes 1.13 才能支援 Pod。執行中的 Pod 需要 IAM 角色，才能取得在 Amazon EKS 上叫用這些動作所需的 AWS 登入資料。
+ 您可以進行本機開發，但會收到`PlatformNotSupportedException`例外狀況。當您在容器服務 (Amazon ECS、Amazon EKS 和 Fargate) 上啟動 AWS 容器時，不會發生此例外狀況。

### 支援的 AWS 區域
<a name="supported-regions-metering"></a>

如需所有 AWS Marketplace 支援的清單 AWS 區域，請參閱 全球基礎設施網站上的[區域表](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/)。

#### 取得用於計量 AWS 區域 的
<a name="metering-aws-region-configuration"></a>

將用於計量的容器與 `MeterUsage`或 `RegisterUsage` API 操作整合時，請勿將 AWS SDK 設定為使用特定 AWS 區域。區域必須在執行時間動態取得。

**Example**  
例如，客戶啟動 Amazon ECS 任務或 Amazon EKS Pod。`RegisterUsage` API 操作會在與啟動 Amazon ECS 任務或 Amazon EKS Pod 的區域不同的區域中呼叫。因此，`RegisterUsage`API 操作會擲回`InvalidRegionException`錯誤。



AWS SDK 語言不會`AWS_REGION`以 一致 的方式判斷 。如果您的 SDK 未自動挑選 `AWS_REGION`，則需要手動撰寫軟體來判斷 `AWS_Region`。例如，當環境變數或其他組態不存在時， 適用於 Java 的 AWS SDK 會自動使用 [Amazon EC2 執行個體中繼資料](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) （特別是 `ec2InstanceMetadata`) 來取得 區域。在此執行個體中，只有在環境`AWS_REGION`變數不存在`ec2InstanceMetadata`時才呼叫 。

如需有關如何在 AWS 區域 執行時間動態取得 的資訊，請參閱適用於您的程式設計語言的 [AWS SDK 開發人員指南](https://aws.amazon.com/tools)。

### 防止計量修改
<a name="prevent-metering-modification"></a>

介紹買方修改或覆寫對 的呼叫，`RegisterUsage`或`MeterUsage`可能導致不良帳單和付款問題的方法。我們強烈建議您整合計量和權利邏輯。

設計您的產品以防止計量修改時，請記住下列事項：
+ 如果買方可以插入包含 `CMD`或 `ENTRYPOINT`指示的新映像層，請直接將 `RegisterUsage`或 整合`MeterUsage`到買方透過容器映像執行的軟體中。否則，買方可能會覆寫透過`RegisterUsage`基本映像`CMD`或從`ENTRYPOINT`基本映像`MeterUsage`執行的呼叫。
+ 我們建議您管理軟體用作輸入 AWS Marketplace 的產品代碼`MeterUsage`，`RegisterUsage`或以買方無法修改的方式進行。不過，如果您的產品以客戶可以覆寫的方式管理產品代碼，例如 AWS CloudFormation、Helm Chart 或 Kubernetes 資訊清單，您必須維護*信任* AWS Marketplace 的產品代碼清單。這是為了確保軟體做為輸入傳遞至 `RegisterUsage`或 的產品程式碼`MeterUsage`有效。
+  如果您信任的任何產品代碼是免費產品，請確保它們不能用來取代付費產品代碼。

## 使用 的合約定價 AWS License Manager
<a name="container-products-contracts-license-manager"></a>

對於具有合約定價的容器型產品，您可以使用 AWS License Manager 將授權與產品建立關聯。

AWS License Manager 是一種授權管理工具，可讓您的應用程式追蹤和更新客戶購買的授權 （也稱為權利）。本節提供如何將您的 產品與 整合的相關資訊 AWS License Manager。整合完成後，您可以在其上發佈您的產品清單 AWS Marketplace。

如需詳細資訊 AWS License Manager，請參閱 [AWS License Manager 使用者指南](https://docs.aws.amazon.com/license-manager/latest/userguide/license-manager.html)和 *AWS CLI 命令參考*的 [AWS License Manager](https://docs.aws.amazon.com/cli/latest/reference/license-manager/index.html)一節。

**注意**  
客戶無法在合約到期期間之後啟動容器的新執行個體。不過，在合約期間，他們可以啟動任意數量的執行個體。這些授權不會繫結至特定節點或執行個體。只要授權具有指派 AWS 的登入資料，任何節點上任何容器上執行的任何軟體都可以簽出授權。
**私有優惠建立** – 賣方可以使用 中的私有優惠建立工具，為產品產生私有優惠 AWS Marketplace 管理入口網站。
**報告** – 您可以在 **的報告**區段中設定 Amazon S3 儲存貯體，以設定資料摘要 AWS Marketplace 管理入口網站。如需詳細資訊，請參閱[中的賣方報告、資料饋送和儀表板 AWS Marketplace](reports-and-data-feed.md)。

### 整合工作流程
<a name="container-LM-LM-workflow"></a>

下列步驟顯示將容器產品與 整合的工作流程 AWS License Manager：

1. 賣方建立具有 AWS License Manager 整合的產品。

1. 賣方列出產品 AWS Marketplace。

1. 買方在 上找到 AWS Marketplace 並購買產品。

1. 授權會傳送給其 中的買方 AWS 帳戶。

1. 買方透過啟動 Amazon EC2 執行個體、Amazon ECS 任務或 Amazon EKS Pod 軟體來使用軟體。客戶使用 IAM 角色部署 。

1. 軟體會讀取買方 AWS License Manager 帳戶中的授權、探索購買的權利，並相應地佈建功能。
**注意**  
License Manager 不會執行任何追蹤或更新；這由賣方的應用程式完成。

# 使用 AWS Marketplace Metering Service 設定每小時計量
<a name="container-metering-registerusage"></a>

**注意**  
 對於 Amazon EKS 部署，您的軟體必須使用[服務帳戶 (IRSA) 的 IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)來簽署 API 操作的 [https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_RegisterUsage.html](https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_RegisterUsage.html) API 呼叫。不支援使用 [EKS Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html)、節點角色或長期存取金鑰。  
對於 Amazon ECS 部署，您的軟體必須使用 [Amazon ECS 任務 IAM](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) 角色來簽署 API 操作的 [https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_RegisterUsage.html](https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_RegisterUsage.html) API 呼叫。不支援使用節點角色或長期存取金鑰。

如果您的容器產品使用每小時每個任務或每個 Pod 定價，而不是自訂計量定價維度，則不需要定義自訂計量維度。您可以使用 AWS Marketplace Metering Service 搭配 中的容器產品進行每小時計量 AWS Marketplace。下列各節說明如何使用 AWS Marketplace Metering Service 設定每小時計量。

`RegisterUsage` API 操作會測量每個 Amazon Elastic Container Service (Amazon ECS) 任務或每個 Amazon Elastic Kubernetes Service (Amazon EKS) Pod 每小時使用的軟體，並將用量按比例分配到第二個。最少 1 分鐘的用量適用於短期使用的任務或 Pod。軟體使用的持續計量由 自動處理 AWS Marketplace Metering Control Plane。除了呼叫`RegisterUsage`一次 開始計量軟體使用之外，您的軟體不需要執行任何計量特定動作。

`RegisterUsage` 必須在啟動容器時立即呼叫 。如果您在容器啟動的前 6 小時內未註冊容器，AWS Marketplace Metering Service 不會提供前幾個月的任何計量保證。不過，計量會在當月繼續，直到容器結束為止。

無論客戶的訂閱狀態為何， AWS Marketplace Metering Control Plane都會繼續向客戶收取執行 Amazon ECS 任務和 Amazon EKS Pod 的費用。這消除了軟體在任務或 Pod 初次成功啟動後執行權利檢查的需求。

如需以每小時定價整合 AWS Marketplace Metering Service API 與容器產品的詳細資訊，請參閱 [與賣方研討會的每小時計量實驗室整合](https://catalog.workshops.aws/mpseller/en-US/container/integrate-hourly)。 *AWS Marketplace *

**Topics**
+ [每小時計量先決條件](#hourly-metering-prereqs)
+ [測試 的整合 `RegisterUsage`](#testing-integration-for-registerusage)
+ [的錯誤處理 `RegisterUsage`](#hourly-metering-entitlement-error-handling)
+ [使用 整合您的容器產品與 AWS Marketplace Metering Service 適用於 Java 的 AWS SDK](java-integration-example-registerusage.md)

## 每小時計量先決條件
<a name="hourly-metering-prereqs"></a>

在發佈產品之前，您必須執行下列動作：

1. 在 中建立新的容器產品 AWS Marketplace 管理入口網站，並記下其產品代碼。

   如需詳細資訊，請參閱[概觀：建立容器產品](container-product-getting-started.md#create-container-product)。

1. 針對具有呼叫 所需 IAM 許可的任務或執行應用程式的 Pod，使用 AWS Identity and Access Management (IAM) 角色`RegisterUsage`。IAM 受管政策`AWSMarketplaceMeteringRegisterUsage`具有這些許可。如需政策的詳細資訊，請參閱《 *AWS 受管政策參考*》中的 [ AWSMarketplaceMeteringFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSMarketplaceMeteringFullAccess.html)。

1. （選用） 如果您想要查看記錄，建議您在任務或 Pod 定義中啟用 AWS CloudTrail 記錄。

1. 使用您定義的所有定價維度的記錄測試呼叫 `RegisterUsage` API 操作。

## 測試 的整合 `RegisterUsage`
<a name="testing-integration-for-registerusage"></a>

使用 `RegisterUsage` API 操作來測試整合，然後再將映像提交至 AWS Marketplace 進行發佈。

在 Amazon ECS 或 Amazon EKS 上執行您的產品，`RegisterUsage`從容器映像呼叫 。使用您用來列出產品的 AWS 帳戶 AWS Marketplace。您的計量整合必須動態設定 AWS 區域，而不是硬式編碼。不過，在測試時，請在美國東部 （維吉尼亞北部） 區域啟動至少一個 Amazon ECS 任務或包含已付費容器的 Amazon EKS Pod。透過這樣做， AWS Marketplace 操作團隊可以驗證您在該區域中使用日誌的工作。

**注意**  
如果您的產品同時支援 Amazon ECS 和 Amazon EKS，您只需要在 Amazon EKS 中啟動，我們就能驗證您的整合。

在使用所有必要中繼資料和定價資訊發佈產品之前，您無法完整測試整合。如果請求， AWS Marketplace 目錄操作團隊可以驗證是否收到您的計量記錄。

## 的錯誤處理 `RegisterUsage`
<a name="hourly-metering-entitlement-error-handling"></a>

如果您的容器映像與 整合， AWS Marketplace Metering Service 並收到容器啟動`ThrottlingException`時 以外的例外狀況，您應該終止容器，以防止未經授權的使用。

以外的例外`ThrottlingException`狀況只會在初始呼叫 `RegisterUsage` API 操作時擲回。`CustomerNotSubscribedException` 即使客戶在任務或 Pod 仍在執行時取消訂閱，來自相同 Amazon ECS 任務或 Amazon EKS Pod 的後續呼叫也不會擲回。這些客戶在取消訂閱並追蹤其用量後，仍需支付執行中容器的費用。

下表說明 `RegisterUsage` API 操作可能擲回的錯誤。每個 AWS SDK 程式設計語言都有一組錯誤處理準則，如需其他資訊，請參閱這些準則。


|  **錯誤**  |  **Description**  | 
| --- | --- | 
|  InternalServiceErrorException  |  RegisterUsage 無法使用。 | 
|  CustomerNotEntitledException  |  客戶沒有產品的有效訂閱。 | 
|  InvalidProductCodeException  |  在請求中傳入ProductCode的值不存在。 | 
|  InvalidPublicKeyException  |  在請求中傳入PublicKeyVersion的值不存在。 | 
|  PlatformNotSupportedException  |  AWS Marketplace 不支援從基礎平台計量用量。僅 AWS Fargate 支援 Amazon ECS、Amazon EKS 和 。 | 
|  ThrottlingException  |  對 的呼叫RegisterUsage會受到調節。 | 
|  InvalidRegionException  |  RegisterUsage 必須在與啟動 Amazon ECS 任務或 Amazon EKS Pod AWS 區域 相同的 中呼叫 。這可防止容器在呼叫 時選擇區域 （例如 withRegion(“us-east-1”))RegisterUsage。 | 

# 使用 整合您的容器產品與 AWS Marketplace Metering Service 適用於 Java 的 AWS SDK
<a name="java-integration-example-registerusage"></a>

您可以使用 適用於 Java 的 AWS SDK 與 AWS Marketplace Metering Service 整合。軟體使用的持續計量由 自動處理 AWS Marketplace Metering Control Plane。除了呼叫`RegisterUsage`一次 開始計量軟體使用之外，您的軟體不需要執行任何計量特定動作。本主題提供使用 適用於 Java 的 AWS SDK 與 [AWS Marketplace Metering Service](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html) `RegisterUsage`動作整合的範例實作。

`RegisterUsage` 必須在啟動容器時立即呼叫 。如果您在容器啟動的前 6 小時內未註冊容器，AWS Marketplace Metering Service 不會提供前幾個月的任何計量保證。不過，計量會在當月繼續，直到容器結束為止。

如需完整的原始程式碼，請參閱 [RegisterUsage Java 範例](#registerusage-java-example)。無論 AWS SDK 語言為何，這些步驟都適用。



**AWS Marketplace Metering Service 整合的範例步驟**

1. 登入 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/tour)。

1. 從**資產**選擇**容器**以開始建立新的容器產品。建立產品會產生產品的產品代碼，以與您的容器映像整合。如需設定 IAM 許可的詳細資訊，請參閱 [AWS Marketplace 計量和權利 API 許可](iam-user-policy-for-aws-marketplace-actions.md)。

1.  下載公有 [AWS Java 開發套件](https://aws.amazon.com/sdk-for-java/)。
**重要**  
 若要從 Amazon EKS 呼叫計量 APIs，您必須[使用支援的 AWS SDK，](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html)並在執行 Kubernetes 1.13 或更新版本的 Amazon EKS 叢集上執行。

1.  （選用） 如果您要與 `RegisterUsage`動作整合，而且想要執行數位簽章驗證，則需要在應用程式 classpath 中設定 [BouncyCastle](https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on) 簽章驗證程式庫。

   如果您想要使用 JSON Web Token (JWT)，您還必須在應用程式 classpath 中包含 [JWT Java](https://jwt.io/) 程式庫。使用 JWT 提供更簡單的簽章驗證方法，但並非必要，您可以改為使用獨立的 BouncyCastle。無論您是使用 JWT 或 BouncyCastle，您都需要使用 Maven 等建置系統，在應用程式類別路徑中包含 BouncyCastle 或 JWT 的傳輸相依性。

   ```
   // Required for signature verification using code sample
   <dependency>
       <groupId>org.bouncycastle</groupId>
       <artifactId>bcpkix-jdk15on</artifactId>
       <version>1.60</version>
   </dependency>
   
   // This one is only required for JWT
   <dependency>
       <groupId>com.nimbusds</groupId>
       <artifactId>nimbus-jose-jwt</artifactId>
       <version>6.0</version>
   </dependency>
   ```

1.  `RegisterUsage` 從您的產品方案中的每個付費容器映像呼叫 。 `ProductCode`和 `PublicKeyVersion`是必要的參數，而所有其他輸入都是選用的。以下是 的範例承載`RegisterUsage`。

   ```
   {
       "ProductCode" : "string", // (required)
       "PublicKeyVersion": 1,    // (required)
       "Nonce": "string",        // (optional) to scope down the registration
                                 //            to a specific running software
                                 //            instance and guard against
                                 //            replay attacks
   }
   ```
**注意**  
連接到 AWS Marketplace Metering Service 時，可能會出現暫時性問題。 AWS Marketplace 強烈建議在指數退避的情況下，實作重試最多 30 分鐘，以避免短期中斷或網路問題。

1.  `RegisterUsage` 使用 SHA-256 產生 RSA-PSS 數位簽章，可用於驗證請求真偽。簽章包含下列欄位：`ProductCode`、 `PublicKeyVersion`和 `Nonce`。若要驗證數位簽章，您必須保留請求中的這些欄位。下列程式碼是對`RegisterUsage`呼叫的回應範例。

   ```
   {
   "Signature": "<<JWT Token>>"
   }
   
   // Where the JWT Token is composed of 3 dot-separated, 
   // base-64 URL Encoded sections.
   // e.g. eyJhbGcVCJ9.eyJzdWIMzkwMjJ9.rrO9Qw0SXRWTe
   
   // Section 1: Header/Algorithm
   {
   "alg": "PS256",
   "typ": "JWT"
   }
   
   // Section 2: Payload
   {
   "ProductCode" : "string",
   "PublicKeyVersion": 1,
   "Nonce": "string",
   "iat": date // JWT issued at claim 
   }
   
   // Section 3: RSA-PSS SHA256 signature
   "rrO9Q4FEi3gweH3X4lrt2okf5zwIatUUwERlw016wTy_21Nv8S..."
   ```

1. 重建新版本的容器映像，其中包含`RegisterUsage`呼叫、標記容器，並將其推送至與 Amazon ECS 或 Amazon EKS 相容的任何容器登錄檔，例如 Amazon ECR 或 Amazon ECR Public。如果您使用的是 Amazon ECR，請確定啟動 Amazon ECS 任務或 Amazon EKS Pod 的帳戶具有 Amazon ECR 儲存庫的許可。否則，啟動會失敗。

1.  建立 [IAM](https://aws.amazon.com/iam/) 角色，授予容器呼叫 的許可`RegisterUsage`，如下列程式碼所定義。您必須在 Amazon ECS 任務或 Amazon EKS Pod 定義的[任務角色](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_role_arn)參數中提供此 IAM 角色。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Action": [
                   "aws-marketplace:RegisterUsage"
                   ],
                   "Effect": "Allow",
                   "Resource": "*"
           }
       ]
   }
   ```

------

1. 建立 Amazon ECS 任務或 Amazon EKS Pod 定義，參考與 整合的容器， AWS Marketplace 並參考您在步驟 7 中建立的 IAM 角色。如果您想要查看 AWS CloudTrail 記錄，您應該在任務定義中啟用記錄。

1. 建立 Amazon ECS 或 Amazon EKS 叢集來執行您的任務或 Pod。如需建立 Amazon ECS 叢集的詳細資訊，請參閱《*Amazon Elastic Container Service 開發人員指南*》中的[建立叢集](https://docs.aws.amazon.com/AmazonECS/latest/userguide/create_cluster.html)。如需建立 Amazon EKS 叢集 （使用 Kubernetes 1.1.3.x 版或更新版本） 的詳細資訊，請參閱[建立 Amazon EKS 叢集](https://docs.aws.amazon.com/eks/latest/userguide/create_cluster.html)。

1. 在 us-east-1 中設定 Amazon ECS 或 Amazon EKS 叢集，並啟動您建立的 Amazon ECS 任務定義或 Amazon EKS Pod AWS 區域。只有在此測試程序期間，在產品上線之前，您必須使用此區域。

1. 當您從 取得有效的回應時`RegisterUsage`，您可以開始建立您的容器產品。如有疑問，請聯絡[AWS Marketplace 賣方營運](https://aws.amazon.com/marketplace/management/contact-us/)團隊。

## RegisterUsage Java 範例
<a name="registerusage-java-example"></a>

下列範例使用 適用於 Java 的 AWS SDK 和 AWS Marketplace Metering Service 來呼叫 `RegisterUsage`操作。簽章驗證是選用的，但如果您想要執行簽章驗證，則必須包含必要的數位簽章驗證程式庫。此範例僅供說明之用。

```
import com.amazonaws.auth.PEM;
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMetering;
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMeteringClientBuilder;
import com.amazonaws.services.marketplacemetering.model.RegisterUsageRequest;
import com.amazonaws.services.marketplacemetering.model.RegisterUsageResult;
import com.amazonaws.util.json.Jackson;
import com.fasterxml.jackson.databind.JsonNode;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
import java.util.Optional;
import java.util.UUID;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * Class for making calls out to &MKT; Metering Service.
 */
class RegisterUsage {

    private static final String PRODUCT_CODE = ".......";

    private final AWSMarketplaceMetering registerUsageClient;
    private final SignatureVerifier signatureVerifier;
    private final int publicKeyVersion;

    public RegisterUsage(final SignatureVerifier signatureVerifier) {
        this.signatureVerifier = signatureVerifier;
        this.publicKeyVersion = PublicKeyProvider.PUBLIC_KEY_VERSION;
        this.registerUsageClient = AWSMarketplaceMeteringClientBuilder.standard().build();
    }

    /**
     * Shows how to call RegisterUsage client and verify digital signature.
     */
    public void callRegisterUsage() {
        RegisterUsageRequest request = new RegisterUsageRequest()
                .withProductCode(PRODUCT_CODE)
                .withPublicKeyVersion(publicKeyVersion)
                .withNonce(UUID.randomUUID().toString());

        // Execute call to RegisterUsage (only need to call once at container startup)
        RegisterUsageResult result = this.registerUsageClient.registerUsage(request);

        // Verify Digital Signature w/o JWT
        boolean isSignatureValid = this.signatureVerifier.verify(request, result);
        if (!isSignatureValid) {
            throw new RuntimeException("Revoke entitlement, digital signature invalid.");
        }
    }
}

/**
 * Signature verification class with both a JWT-library based verification
 * and a non-library based implementation.
 */
class SignatureVerifier {
    private static BouncyCastleProvider BC = new BouncyCastleProvider();

    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA/PSS";

    private final PublicKey publicKey;

    public SignatureVerifier(PublicKeyProvider publicKeyProvider) {
        this.publicKey = publicKeyProvider.getPublicKey().orElse(null);
        Security.addProvider(BC);
    }

    /**
     * Example signature verification using the NimbusJOSEJWT library to verify the JWT Token.
     *
     * @param request RegisterUsage Request.
     * @param result  RegisterUsage Result.
     * @return true if the token matches.
     */
    public boolean verifyUsingNimbusJOSEJWT(final RegisterUsageRequest request, final RegisterUsageResult result) {
        if (!getPublicKey().isPresent()) {
            return false;
        }

        try {
            JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) getPublicKey().get());
            JWSObject jwsObject = JWSObject.parse(result.getSignature());
            return jwsObject.verify(verifier) && validatePayload(jwsObject.getPayload().toString(), request, result);
        } catch (Exception e) {
            // log error
            return false;
        }
    }

    /**
     * Example signature verification without any JWT library support.
     *
     * @param request RegisterUsage Request.
     * @param result  RegisterUsage Result.
     * @return true if the token matches.
     */
    public boolean verify(final RegisterUsageRequest request, final RegisterUsageResult result) {
        if (!getPublicKey().isPresent()) {
            return false;
        }
        try {
            String[] jwtParts = result.getSignature().split("\\.");
            String header = jwtParts[0];
            String payload = jwtParts[1];
            String payloadSignature = jwtParts[2];

            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM, BC);
            signature.initVerify(getPublicKey().get());
            signature.update(String.format("%s.%s", header, payload).getBytes(StandardCharsets.UTF_8));
            boolean verified = signature.verify(Base64.getUrlDecoder()
                    .decode(payloadSignature.getBytes(StandardCharsets.UTF_8)));

            String decodedPayload = new String(Base64.getUrlDecoder().decode(payload));
            return verified && validatePayload(decodedPayload, request, result);
        } catch (Exception e) {
            // log error
            return false;
        }
    }

    /**
     * Validate each value in the returned payload matches values originally
     * supplied in the request to RegisterUsage. TimeToLiveInMillis and
     * PublicKeyExpirationTimestamp will have the values in the payload compared
     * to values in the signature
     */
    private boolean validatePayload(final String payload, final RegisterUsageRequest request,
                                    final RegisterUsageResult result) {
        try {
            JsonNode payloadJson = Jackson.getObjectMapper().readTree(payload);
            boolean matches = payloadJson.get("productCode")
                    .asText()
                    .equals(request.getProductCode());
            matches = matches && payloadJson.get("nonce")
                    .asText()
                    .equals(request.getNonce());
            return matches = matches && payloadJson.get("publicKeyVersion")
                    .asText()
                    .equals(String.valueOf(request.getPublicKeyVersion()));

        } catch (Exception ex) {
            // log error
            return false;
        }
    }

    private Optional<PublicKey> getPublicKey() {
        return Optional.ofNullable(this.publicKey);
    }
}

/**
 * Public key provider taking advantage of the &AWS; PEM Utility.
 */
class PublicKeyProvider {
    // Replace with your public key. Ensure there are new-lines ("\n") in the
    // string after "-----BEGIN PUBLIC KEY-----\n" and before "\n-----END PUBLIC KEY-----".
    private static final String PUBLIC_KEY =
            "-----BEGIN PUBLIC KEY-----\n"
                    + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd\n"
                    + "UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs\n"
                    + "HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D\n"
                    + "o2kQ+X5xK9cipRgEKwIDAQAB\n"
                    + "-----END PUBLIC KEY-----";

    public static final int PUBLIC_KEY_VERSION = 1;

    public Optional<PublicKey> getPublicKey() {
        try {
            return Optional.of(PEM.readPublicKey(new ByteArrayInputStream(
                    PUBLIC_KEY.getBytes(StandardCharsets.UTF_8))));
        } catch (Exception e) {
            // log error
            return Optional.empty();
        }
    }
}
```

# 使用 AWS Marketplace Metering Service 設定容器產品的自訂計量
<a name="container-metering-meterusage"></a>

**注意**  
 對於 Amazon EKS 部署，您的軟體必須使用[服務帳戶 (IRSA) 的 IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)來簽署 API 操作的 [https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_MeterUsage.html](https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_MeterUsage.html) API 呼叫。不支援使用 [EKS Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html)、節點角色或長期存取金鑰。  
對於 Amazon ECS 部署，您的軟體必須使用 [Amazon ECS 任務 IAM](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) 角色來簽署 API 操作的 [https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_MeterUsage.html](https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_MeterUsage.html) API 呼叫。不支援使用節點角色或長期存取金鑰。  
對於 Amazon Bedrock AgentCore 執行期部署，您的軟體必須使用 [AgentCore 執行期執行角色](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html#runtime-permissions-execution)來簽署 API 操作的 [https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_MeterUsage.html](https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_MeterUsage.html) API 呼叫。不支援長期存取金鑰。

AWS Marketplace 容器產品可以對每個產品最多 24 個不同的定價維度進行自訂計量。每個維度都可以有與其相關聯的長期合約價格。若要啟用自訂計量，請將您的容器產品與 AWS Marketplace Metering Service 整合。您可以使用 [https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html) API 操作，為該用量定義自己的定價單位和自訂計量到 AWS 進行計費。下列各節說明如何設定容器產品的自訂計量。

價格維度在兩個位置中定義，一次是在 AWS Marketplace 管理入口網站 （賣方入口網站） 中建立產品時，另一次在軟體中定義以執行`MeterUsage`操作。此雙因素方法可確保後續優惠在公開前如預期般運作。

若要設定自訂計量，您需要選擇用量類別、單位類型和定價維度：
+ **用量類別** – 用量類別可協助買方了解您的產品是什麼，以及如何使用它。
+ **單位類型** – 單位類型定義計費的度量單位。例如，以 GBps 或 MBps 測量的頻寬、主機數量或以 MB、GB 或 TB 測量的資料。
+ **定價維**度 – 定價維度代表您已設定每單位價格的功能或服務 （例如使用者、掃描、vCPUs 或部署的代理程式）。定價維度為公有。不過，您仍然可以為公有產品定義私有和自攜授權 (BYOL) 優惠。請勿在計量記錄中傳送定價。您可以測量單位數量，並使用它以及您建立產品以計算買方帳單時定義的價格。

  如果您的產品定價不符合任何預先定義的類別或單位類型，您可以選擇一般**單位**類別。然後，使用維度描述來描述什麼是單位。

或者，您可以根據您追蹤的屬性，將用量分配到配置。配置會以標籤表示給買方。這些標籤可讓買方檢視依標籤值分割為用量的成本。例如，如果您由使用者收費，且使用者具有「部門」屬性，則可以使用索引鍵為「部門」的標籤建立用量配置，每個值一個配置。這不會變更您報告的價格、維度或總用量，但可讓您的客戶依適合您產品的類別檢視其成本。

建議您每小時傳送計量記錄。不過，您也可以彙總每日或每月期間的用量。如果您遇到中斷，您可以彙總買方軟體的使用，並在下列時間計量中傳送。您無法每小時傳送超過一筆記錄。

如需整合容器產品的 AWS Marketplace Metering Service API 與自訂計量定價的詳細資訊，請參閱 [與賣方研討會的自訂計量實驗室整合](https://catalog.workshops.aws/mpseller/en-US/container/integrate-custom)。 *AWS Marketplace *

**重要**  
免費試用和預付權利會每小時追蹤一次。因此，在 中分別傳送這些記錄可能會導致買方過度收費。

**Topics**
+ [自訂計量先決條件](#custom-metering-prereqs)
+ [測試 ECS 和 EKS 的`MeterUsage`整合](#testing-meterusage-integration)
+ [測試 AgentCore 的 MeterUsage 整合](#testing-agentcore-metering)
+ [的錯誤處理 `MeterUsage`](#custom-metering-entitlement-error-handling)
+ [（選用） 廠商計量標記](#container-vendor-metered-tagging)
+ [程式碼範例](#container-meter-code-example)
+ [使用自訂計量與 AWS Marketplace Metering Service 和 整合您的容器產品 適用於 Java 的 AWS SDK](java-integration-example-meterusage.md)

## 自訂計量先決條件
<a name="custom-metering-prereqs"></a>

在發佈產品之前，您必須執行下列動作：

1. 在 中建立新的容器產品 AWS Marketplace 管理入口網站，並記下其產品代碼。

1. 將 AWS Identity and Access Management (IAM) 角色用於執行應用程式的任務、Pod 或 AgentCore 執行期端點，並具有呼叫 所需的 IAM 許可`MeterUsage`。IAM 受管政策`AWSMarketplaceMeteringRegisterUsage`具有這些許可。如需政策的詳細資訊，請參閱《 *AWS 受管政策參考*》中的 [ AWSMarketplaceMeteringFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSMarketplaceMeteringFullAccess.html)。

1. （選用） 如果您想要查看 AWS CloudTrail 記錄，建議您在任務或 Pod 定義中啟用記錄。

1. 使用您定義的所有定價維度的記錄測試呼叫 `MeterUsage` API 操作。

## 測試 ECS 和 EKS 的`MeterUsage`整合
<a name="testing-meterusage-integration"></a>

使用 `MeterUsage`操作來測試整合，然後再將映像提交至 AWS Marketplace 進行發佈。

透過在 Amazon Elastic Container Service (Amazon ECS) 或 Amazon Elastic Kubernetes Service (Amazon EKS) 上執行您的產品，並使用 AWS 帳戶 在 上列出產品，`MeterUsage`從容器映像呼叫 AWS Marketplace。您的計量整合必須動態設定 AWS 區域，而不是硬式編碼。不過，在測試時，請至少啟動一個 Amazon ECS 任務或包含美國東部 （維吉尼亞北部） 區域中已付費容器的 Amazon EKS Pod，以便 AWS Marketplace 操作團隊可以驗證您在該區域中使用日誌的工作。

**注意**  
如果您的產品同時支援 Amazon ECS 和 Amazon EKS，您只需要在 Amazon EKS 中啟動，我們就能驗證您的整合。
在將產品啟動到公有環境之前，以及在新增維度之後，測試每個維度。如果您未針對與容器產品相關聯的每個維度傳送計量記錄，則會導致請求失敗的錯誤。

在使用所有必要中繼資料和定價資訊發佈產品之前，您無法完整測試整合。如果請求， AWS Marketplace 目錄操作團隊可以驗證是否收到您的計量記錄。

## 測試 AgentCore 的 MeterUsage 整合
<a name="testing-agentcore-metering"></a>

使用 `MeterUsage`操作來測試整合，然後再將映像提交至 AWS Marketplace 進行發佈。

使用用來列出產品的 AWS 帳戶在 Amazon Bedrock AgentCore 上執行您的產品，`MeterUsage`從容器映像呼叫 AWS Marketplace。您的計量整合必須動態設定 AWS 區域，而不是硬式編碼。不過，在測試時，請至少啟動一個 Amazon Bedrock AgentCore 代理程式，其中包含您在美國東部 （維吉尼亞北部） 區域的付費容器，以便 AWS Marketplace 營運團隊可以驗證您在該區域中使用日誌的工作。

 您不需要彙總每小時用量記錄。`MeterUsage` 在每次客服人員調用時呼叫該調用的使用量。

您必須使用最新版本的 AWS SDK 做為您的語言。這會自動將自動產生的值填入 `ClientToken` 參數，以協助處理冪等性。未填入此欄位的舊版軟體開發套件不適用於來自 Amazon Bedrock AgentCore 的`MeterUsage`呼叫。由於網路問題，您必須在重試時重複使用相同的確切請求。這樣做可確保以等冪方式處理請求。

由於 Amazon Bedrock AgentCore 和其他容器產品之間的預期計量行為差異，我們不建議共用相同的容器映像，以便在 Amazon Bedrock AgentCore 和 Amazon ECS 或 EKS 上使用。

## 的錯誤處理 `MeterUsage`
<a name="custom-metering-entitlement-error-handling"></a>

呼叫在容器啟動時將 `DryRun` 參數`MeterUsage`設定為 true，以驗證計量整合是否正常運作。如果您的容器映像與 `MeterUsage`操作整合，並收到容器啟動`ThrottlingException`時 以外的例外狀況，您應該終止容器，以防止未經授權的使用。

以外的例外僅在對 的初始呼叫中`ThrottlingException`擲回`MeterUsage`。來自相同 Amazon ECS 任務或 Amazon EKS Pod 或 AgentCore 執行期端點的後續呼叫不會擲回 `CustomerNotSubscribedException`，即使客戶在任務或 Pod 仍在執行時取消訂閱。這些客戶在取消訂閱並追蹤其用量後，仍需支付執行中容器的費用。

如需 常見錯誤的詳細說明，請參閱 *AWS Marketplace Metering Service API 參考*中的 [MeterUsage](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html)`MeterUsage`。每個 AWS SDK 程式設計語言都有一組錯誤處理準則，如需其他資訊，請參閱這些準則。

## （選用） 廠商計量標記
<a name="container-vendor-metered-tagging"></a>

廠商計量標記可協助獨立軟體廠商 (ISVs) 為買方提供更精細的軟體用量洞察，並協助他們執行成本分配。

**注意**  
Amazon Bedrock AgentCore 產品的計量請求不支援廠商計量標記。

您有多種方法可以標記買方的軟體用量。其中一個是先詢問您的買方，他們想要在成本分配中看到什麼。然後，您可以將用量分割到您追蹤買方帳戶的屬性。屬性的範例包括 `AccountId`、`Cost Centers`、 `Business Unit`和您產品的其他相關中繼資料。這些屬性會以標籤的形式公開給買方。使用標籤，買方可以在帳單 AWS 主控台 ([https://console.aws.amazon.com/costmanagement/](https://console.aws.amazon.com/costmanagement/)：//) 中檢視依標籤值分割為用量的成本。廠商計量標記不會變更您報告的價格、維度或總用量。它可讓您的客戶依適合您產品的類別檢視其成本。

在常見的使用案例中，買方使用 訂閱您的產品 AWS 帳戶。買方也有許多與相同產品訂閱相關聯的使用者。您可以使用索引鍵為 的標籤建立用量配置`AccountId`，然後將用量配置給每個使用者。在此情況下，買方可以在帳單和成本管理主控台中啟用`AccountId`標籤，並分析個別使用者用量。

### 賣方體驗
<a name="container-vendor-metered-tag-seller"></a>

賣方可以使用相同的標籤集彙總資源的計量記錄，而不是彙總所有資源的用量。例如，賣方可以建構包含不同儲存`UsageAllocations`貯體的計量記錄。每個儲存貯體代表一組標籤`UsageQuantity`的 ，例如 `AccountId`和 `BusinessUnit`。

在下圖中，**資源 1** 具有一組唯一的 `AccountId` 和 `BusinessUnit`標籤，並在**計量記錄中**顯示為單一項目。

**資源 2** 和**資源 3** 都有相同的`AccountId`標籤 `2222`和相同的`BusinessUnit`標籤 `Operations`。因此，它們會合併為**計量記錄中**的單一`UsageAllocations`項目。

![\[顯示廠商計量標籤如何結合用量資料的圖表。具有不同 AccountIds和 BusinessUnits 的三個資源 （資源 1、2 和 3) 會合併為單一計量記錄，並依 AccountId 和 BusinessUnit 分組 UsageAllocations，再傳送至 AWS Marketplace Metering Service。\]](http://docs.aws.amazon.com/zh_tw/marketplace/latest/userguide/images/seller-vendor-meter-tag.png)


賣方也可以將沒有標籤的資源合併為`UsageAllocation`具有配置用量數量的單一資源，並將其做為 中的其中一個項目傳送`UsageAllocations`。

限制包括：
+ 標籤數量 – 5
+ 大小 `UsageAllocations`（基數） – 2，500

驗證包括：
+ 標籤索引鍵和值允許的字元 – a-zA-Z0-9\$1 -=.\$1：\$1/@
+ 跨`UsageAllocation`清單的標籤上限 – 5
+ 兩個 `UsageAllocations` 不能有相同的標籤 （也就是標籤索引鍵和值的相同組合）。如果是這種情況，他們必須使用相同的 `UsageAllocation`。
+ `AllocatedUsageQuantity` 的 總和`UsageAllocation`必須等於 `UsageQuantity`，即彙總用量。

### 買方體驗
<a name="container-vendor-metered-tag-buyer"></a>

下表顯示買方啟用 `AccountId`和`BusinessUnit`廠商標籤後買方體驗的範例。

在此範例中，買方可以在其**成本用量報告中看到配置的用量**。廠商計量的標籤使用字首 `“aws:marketplace:isv”`。買方可以在帳單和成本管理、**成本分配標籤**、 **AWS產生的成本分配標籤**下啟用它們。

**成本用量報告**的第一列和最後一列與賣方傳送到計量服務的內容相關 （如[賣方體驗](#container-vendor-metered-tag-seller)範例所示）。


**成本用量報告 （簡化）**  

| ProductCode  | 買方 | UsageDimension | UsageQuantity | `aws:marketplace:isv:AccountId ` | `aws:marketplace:isv:BusinessUnit` | 
| --- | --- | --- | --- | --- | --- | 
| xyz | 111122223333 | 網路：每個 (GB) 已檢查  | 70 | 2222 | 作業 | 
| xyz | 111122223333 | 網路：每個 (GB) 已檢查  | 30 | 3333 | 財務 | 
| xyz | 111122223333 | 網路：每個 (GB) 已檢查  | 20 | 4444 | IT | 
| xyz | 111122223333 | 網路：每個 (GB) 已檢查  | 20 | 5555 | Marketing | 
| xyz | 111122223333 | 網路：每個 (GB) 已檢查  | 30 | 1111 | Marketing | 

如需程式碼範例，請參閱「[`MeterUsage` 具有用量配置標記的程式碼範例 （選用）](#container-meterusage-code-example)」。

## 程式碼範例
<a name="container-meter-code-example"></a>

以下程式碼範例可協助您將容器產品與發佈和維護產品所需的 AWS Marketplace APIs 整合。

### `MeterUsage` 具有用量配置標記的程式碼範例 （選用）
<a name="container-meterusage-code-example"></a>

下列程式碼範例與具有耗用定價模型的容器產品相關。Python 範例會傳送含有適當用量分配標籤的計量記錄給 AWS Marketplace ，以向您的客戶收取pay-as-you-go。

```
# NOTE: Your application will need to aggregate usage for the 
#       customer for the hour and set the quantity as seen below. 
# AWS Marketplace can only accept records for up to an hour in the past. 
#
# productCode is supplied after the AWS Marketplace Ops team has 
# published the product to limited

# Import AWS Python SDK
import boto3
import time

usageRecord = [
    { 
        "AllocatedUsageQuantity": 2, 
        "Tags": 
            [ 
                { "Key": "BusinessUnit", "Value": "IT" },
                { "Key": "AccountId", "Value": "123456789" },
            ]

    },
    { 
        "AllocatedUsageQuantity": 1, 
        "Tags": 
            [ 
                { "Key": "BusinessUnit", "Value": "Finance" },
                { "Key": "AccountId", "Value": "987654321" },
            ]

    }
]

marketplaceClient = boto3.client("meteringmarketplace")

response = marketplaceClient.meter_usage(
    ProductCode="testProduct",
    Timestamp=int(time.time()),
    UsageDimension="Dimension1",
    UsageQuantity=3,
    DryRun=False,
    UsageAllocations=usageRecord 
)
```

如需 的詳細資訊`MeterUsage`，請參閱《 *AWS Marketplace Metering Service API 參考*》中的 [MeterUsage](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html)。

### 回應範例
<a name="container-meterusage-code-response"></a>

```
{ "MeteringRecordId": "string" }
```

# 使用自訂計量與 AWS Marketplace Metering Service 和 整合您的容器產品 適用於 Java 的 AWS SDK
<a name="java-integration-example-meterusage"></a>

AWS Marketplace 容器產品可以對每個產品最多 24 個不同的定價維度進行自訂計量。若要啟用自訂計量，您可以將容器產品與 AWS Marketplace Metering Service 整合。您可以使用 [https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_MeterUsage.html) API 操作，為該用量定義自己的定價單位和自訂計量到 AWS 進行計費。下列範例概述使用 適用於 Java 的 AWS SDK 與 [AWS Marketplace Metering Service](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html) `MeterUsage`操作整合的實作。

如需完整詳細資訊，請參閱 [`MeterUsage` Java 範例](#meterusage-java-example)。無論語言為何，都適用下列許多步驟。

**範例： AWS Marketplace Metering Service 整合**

1. 登入 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/tour)。

1. 從**資產**中，選擇**容器**以開始建立新的容器產品。建立產品會產生產品的產品代碼，以與您的容器映像整合。如需設定 AWS Identity and Access Management (IAM) 許可的詳細資訊，請參閱 [AWS Marketplace 計量和權利 API 許可](iam-user-policy-for-aws-marketplace-actions.md)。

1.  下載公有 [AWS Java 開發套件](https://aws.amazon.com/sdk-for-java/)。
**重要**  
 若要從 Amazon Elastic Kubernetes Service (Amazon EKS) 呼叫計量 API 操作[，您必須使用支援的 AWS SDK](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html)，並在執行 Kubernetes 1.13 或更新版本的 Amazon EKS 叢集上執行。

1. 每個維度用量每小時從任務或 Pod 呼叫一次 `MeterUsage`操作。API 操作接受 `Dimension`、 `Resource`和 唯一組合的一個計量記錄`Hour`。資源可以是 Amazon Elastic Container Service (Amazon ECS) 任務或 Amazon EKS Pod。

   ```
   {
       "ProductCode" : "string", // (required)
       "UsageDimension" : "string", // (required)
       "UsageQuantity":  int, // (optional) Default is 0. Acceptable value from [0, 2147483647 (INT_MAX)]
       "Timestamp": Date, // (required) Timestamp in UTC. Value can be one hour in the past.
       "UsageAllocations": List<UsageAllocation> // (optional) UsageAllocations across 1 or more tags.
   }
   ```
**注意**  
連接到 時，可能會看到暫時性問題 AWS Marketplace Metering Service。 AWS Marketplace 強烈建議在指數退避的情況下，實作重試長達 30 分鐘，以避免短期中斷或網路問題。

1. 重建容器映像的新版本，其中包含`MeterUsage`呼叫、標記容器，並將其推送至與 Amazon ECS 或 Amazon EKS 相容的任何 Docker 登錄檔，例如 Amazon Elastic Container Registry (Amazon ECR)。如果您使用的是 Amazon ECR，請確定啟動 Amazon ECS 任務或 Amazon EKS Pod 的帳戶具有 Amazon ECR 儲存庫的許可。否則，操作會失敗。

1. 建立 [IAM](https://aws.amazon.com/iam/) 角色，授予容器呼叫 的許可`MeterUsage`，如下列程式碼範例所定義。您必須在 Amazon ECS 任務或 Amazon EKS Pod 定義的[任務角色](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_role_arn)參數中提供此 AWS Identity and Access Management (IAM) 角色。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Action": [
                   "aws-marketplace:MeterUsage"
                   ],
                   "Effect": "Allow",
                   "Resource": "*"
           }
       ]
   }
   ```

------

1. 建立 Amazon ECS 任務或 Amazon EKS Pod 定義，參考與 整合的容器， AWS Marketplace 並參考您在步驟 6 中建立的 IAM 角色。如果您想要查看記錄，請在任務定義中啟用 AWS CloudTrail 記錄。

1. 建立 Amazon ECS 或 Amazon EKS 叢集來執行您的任務或 Pod。如需建立 Amazon ECS 叢集的詳細資訊，請參閱《*Amazon Elastic Container Service 開發人員指南*》中的[建立叢集](https://docs.aws.amazon.com/AmazonECS/latest/userguide/create_cluster.html)。如需建立 Amazon EKS 叢集 （使用 Kubernetes 1.1.3.x 版或更新版本） 的詳細資訊，請參閱[建立 Amazon EKS 叢集](https://docs.aws.amazon.com/eks/latest/userguide/create_cluster.html)。

1. 設定 Amazon ECS 或 Amazon EKS 叢集，並在 us-east-1 AWS Region 中啟動您在步驟 8 中建立的 Amazon ECS 任務定義或 Amazon EKS Pod。只有在此測試程序期間，在產品上線之前，您必須使用此區域。

1. 當您從 取得`MeterUsage`針對產品發佈的每個維度的有效回應時，您可以開始建立容器產品。如有疑問，請聯絡[AWS Marketplace 賣方營運](https://aws.amazon.com/marketplace/management/contact-us/)團隊。

## `MeterUsage` Java 範例
<a name="meterusage-java-example"></a>

下列程式碼範例使用 適用於 Java 的 AWS SDK 和 AWS Marketplace Metering Service 來呼叫 `MeterUsage`操作。

下列程式碼範例在沒有 的情況下呼叫 `MeterUsage`操作`UsageAllocations`。

```
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMetering;
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMeteringClientBuilder;
import com.amazonaws.services.marketplacemetering.model.MeterUsageRequest;
import com.amazonaws.services.marketplacemetering.model.MeterUsageResult;

import java.util.Date;

public class MeterUsage {
    private static final String PRODUCT_CODE = ".......";
    private final AWSMarketplaceMetering awsMarketplaceMetering;

    public MeterUsage() {
        awsMarketplaceMetering = AWSMarketplaceMeteringClientBuilder.standard().build();
    }

    /**
     * Submits metering record for a FCP Dimension. The API accepts 1 metering record per dimension
     * for a given buyer's resource for a given timestamp hour. Ex. If a buyer is running 10 tasks,
     * the API will accepts 1 call to MeterUsage in an hour for a given dimension for each running task.
     *
     * @param dimension - FCP dimension name provided during the publishing of the product.
     * @param quantity - FCP dimension consumption value for the hour.
     * @param timestamp - Timestamp, in UTC, for which the usage is being reported.
     *                  Timestamp cant be more than 1 hour in the past.
     *                  Make sure the timestamp value is not before the start of the software usage.
     */
    public void callMeterUsage(String dimension, int quantity, Date timestamp) {
        MeterUsageRequest meterUsageRequest = new MeterUsageRequest()
                .withProductCode(PRODUCT_CODE)
                .withUsageDimension(dimension)
                .withUsageQuantity(quantity)
                .withTimestamp(timestamp);
        MeterUsageResult meterUsageResult = awsMarketplaceMetering.meterUsage(meterUsageRequest);
    }
}
```

下列程式碼範例使用 呼叫 `MeterUsage`操作`UsageAllocations`。

```
private static String callMeterUsageWithAllocationsByTag(AWSMarketplaceMetering marketplaceMetering) {
        // Tag Keys for the product
        String tagKey1 = "Key1";
        String tagKey2 = "Key2";
        String tagKey3 = "Key3";

        // 1st Usage Allocation bucket which has two Tags [{Key1, Key1Value1},{Key2, Key2Value1}]
        List<Tag> tagsForUsageAllocation1 = Arrays.asList(new Tag().withKey(tagKey1).withValue("Key1Value1"),
                new Tag().withKey(tagKey2).withValue("Key2Value1"));
        UsageAllocation usageAllocation1 = new UsageAllocation()
                .withTags(tagsForUsageAllocation1)
                .withAllocatedUsageQuantity(20);

        // 2nd Usage Allocation bucket which has two Tags [{Key1, Key1Value2},{Key2, Key2Value1}]
        List<Tag> tagsForUsageAllocation2 = Arrays.asList(new Tag().withKey(tagKey1).withValue("Key1Value2"),
                new Tag().withKey(tagKey2).withValue("Key2Value1"));
        UsageAllocation usageAllocation2 = new UsageAllocation()
                .withTags(tagsForUsageAllocation2)
                .withAllocatedUsageQuantity(20);

        // 3rd Usage Allocation bucket which has two Tags [{Key1, Key1Value2},{Key2, Key2Value2},{Key3, Key3Value1}]
        List<Tag> tagsForUsageAllocation3 = Arrays.asList(new Tag().withKey(tagKey1).withValue("Key1Value2"),
                new Tag().withKey(tagKey2).withValue("Key2Value2"),
                new Tag().withKey(tagKey3).withValue("Key3Value1"));
        UsageAllocation usageAllocation3 = new UsageAllocation()
                .withTags(tagsForUsageAllocation3)
                .withAllocatedUsageQuantity(15);

        // 4th Usage Allocation bucket with no tags
        UsageAllocation usageAllocation4 = new UsageAllocation()
                .withAllocatedUsageQuantity(15);

        List<UsageAllocation> usageAllocationList = Arrays.asList(usageAllocation1,
                usageAllocation2,
                usageAllocation3,
                usageAllocation4);

        MeterUsageRequest meterUsageRequest = new MeterUsageRequest()
                .withProductCode("TestProductCode")
                .withUsageDimension("Dimension1")
                .withTimestamp(new Date())
                //UsageQuantity value must match with sum of all AllocatedUsageQuantity
                .withUsageQuantity(70)
                .withUsageAllocations(usageAllocationList);

        MeterUsageResult meterUsageResult;
        try {
            meterUsageResult = marketplaceMetering.meterUsage(meterUsageRequest);
        } catch (Exception e) {
            // Log Error
            throw e;
        }

        return meterUsageResult.getMeteringRecordId();
    }
```

# 使用 的容器產品的合約定價 AWS License Manager
<a name="container-license-manager-integration"></a>

對於具有合約定價的容器型產品，您可以使用 AWS License Manager 將授權與產品建立關聯。 AWS License Manager 是一種授權管理工具，可讓您的應用程式追蹤和更新客戶購買的授權 （也稱為權利）。本節提供如何將產品與 整合的相關資訊 AWS License Manager。整合完成後，您可以在其上發佈您的產品清單 AWS Marketplace。

如果您要將 License Manager 與適用於 Amazon EKS Anywhere、Amazon ECS Anywhere、Amazon Elastic Compute Cloud (Amazon EC2) 或內部部署基礎設施 AWS Marketplace 的 for Containers Anywhere 產品整合，請遵循 中的指示[將 AWS Marketplace for Containers Anywhere 與 License Manager 整合](container-anywhere-license-manager-integration.md)。

如需詳細資訊 AWS License Manager，請參閱 [AWS License Manager 使用者指南](https://docs.aws.amazon.com/license-manager/latest/userguide/license-manager.html)和 *AWS CLI 命令參考*的 [AWS License Manager](https://docs.aws.amazon.com/cli/latest/reference/license-manager/index.html)一節。

如需將 AWS License Manager 與容器產品與合約定價整合的詳細資訊，請參閱 [與賣方研討會的前期付款實驗室整合](https://catalog.workshops.aws/mpseller/en-US/container/integrate-contract)。 *AWS Marketplace *

**Topics**
+ [容器產品的合約定價](#container-contracts)
+ [授權模型](#container-LM-license-models)
+ [AWS License Manager 整合先決條件](#container-LM-prereqs)
+ [將容器產品與 License Manager 整合](#container-integrate-with-LM)
+ [License Manager API 操作](#container-LM-API-calls)
+ [授權續約和升級](#container-LM-lic-renew-upgrade)
+ [將 AWS Marketplace for Containers Anywhere 與 License Manager 整合](container-anywhere-license-manager-integration.md)

## 容器產品的合約定價
<a name="container-contracts"></a>

對於具有合約定價的容器型產品， 會根據您與客戶之間的合約，預先依您定義的付款排程向您的客戶 AWS Marketplace 收費。之後，他們有權使用這些資源。

若要設定定價，請選擇您提供給客戶的一或多個合約持續時間。您可以為每個合約期間輸入不同的價格。您的選項為 1 個月、12 個月、24 個月和 36 個月的持續時間。對於私有優惠，您可以指定自訂持續時間，以月為單位 （最多 60 個月）。

選擇最能描述您產品定價的類別。定價類別會顯示在 AWS Marketplace 網站上的客戶。您可以選擇**頻寬** (GB/s、MB/s)、**資料** (GB、MB、TB)、**主機**、**請求**、**層**或**使用者**。如果沒有任何預先定義的類別符合您的需求，您可以選擇更通用的 **Units** 類別。

優惠最多可新增 24 個維度。


**範例：資料儲存應用程式**  

|   | 1 個月價格 | 12 個月價格  | 24 個月價格  | P36-month價格  | 
| --- | --- | --- | --- | --- | 
|  未加密的資料 (GB)  |  \$11.50/GB  |  \$116.00/GB  |  \$130.00/GB  |  \$160.00/GB  | 
|  加密的資料 (GB)  |  1.55 美元/GB  |  \$116.60/GB  |  31.20 USD/GB  |  \$161.20/GB  | 


**範例：日誌監控產品**  

|   | 1 個月價格 | 12 個月價格  | 24 個月價格 | 36 個月價格 | 
| --- | --- | --- | --- | --- | 
|  基本 （監控 10 個主機、監控 5 個容器）  |  100 美元  |  1，000 美元  | 2000 美元  | 4000 美元 | 
|  標準 （監控 20 個主機、監控 10 個容器）  |  \$1200  |  2000 美元  | 4000 美元  | 8000 美元 | 
|  Pro （監控 40 個主機、監控 20 個容器）  |  400 美元  |  4000 美元  | 8000 美元  | 16，000 美元 | 
|  每小時監控的其他主機  | 10 美元  | 100 美元  |  \$1200 | 400 美元 | 
|  每小時監控的其他容器  | 10 美元  | 100 美元  |  \$1200 | 400 美元 | 

**注意**  
價格可以是下列持續時間：1 個月、12 個月、24 個月或 36 個月。您可以選擇為您的產品提供一或多個選項。每個維度的持續時間必須相同。  

**Example**  
例如，在您有 `ReadOnlyUsers`和 `AdminUsers`維度的情況下，如果您為 ReadOnlyUsers 提供每年價格，您`AdminUsers`也必須為 提供每年價格。


### 自動續約
<a name="ami-contracts-automatic-renewals"></a>

 當客戶 AWS Marketplace 使用容器合約購買您的產品時，他們可以同意自動續約合約條款。客戶每個月或 1、2 或 3 年繼續支付權利。

客戶可以隨時修改續約設定。如需詳細資訊，請參閱《 *AWS Marketplace 買方指南*》中的[修改現有合約](https://docs.aws.amazon.com/marketplace/latest/buyerguide/buyer-container-contracts.html#modify-existing-contract)。

## 授權模型
<a name="container-LM-license-models"></a>

AWS Marketplace 與 整合 AWS License Manager 支援兩種授權模型：
+ [可設定的授權模型](#container-LM-config-lic-model)
+ [分層授權模型](#container-LM-tiered-lic-model)

### 可設定的授權模型
<a name="container-LM-config-lic-model"></a>

可設定授權模型 （也稱為可量化授權模型） 會在買方取得授權後，授予買方特定數量的資源。

您可以設定定價維度和每個單價。然後，買方可以選擇他們想要購買的資源數量。

**Example 定價維度和每單位價格的**  
您可以設定定價維度 （例如資料備份） 和每單位價格 （例如 \$130/單位）。  
買方可以選擇購買 5、10 或 20 個單位。  
您的產品會追蹤和測量用量，以測量消耗的資源數量。

使用組態模型時，會以下列兩種方式之一計算權利：
+ [繪製授權](#container-floating-lic)
+ [浮動授權](#container-floating-lic) 

#### 下調授權
<a name="container-drawndown-lic"></a>

 授權是從使用時允許的授權數量集區中提取。該權利會永久簽出，且無法傳回授權集區。

**Example 處理有限數量的資料**  
使用者有權處理 500 GB 的資料。隨著他們繼續處理資料，數量會從 500 GB 的集區中抽取，直到所有 500 GB 授權都用盡為止。

對於提取授權，您可以使用 `CheckoutLicense` API 操作來查看使用的授權單位 （權限）。

**Example 的備份到 Amazon S3 的單位數/年**  
您有一個儲存產品，允許將資料備份至 Amazon Simple Storage Service 最多 1，024 個單位，為期一年。您可以使用多個 Amazon EC2 執行個體啟動您的應用程式。您的應用程式具有追蹤和彙總資料的機制。您的軟體會在每次備份時以產品 ID 呼叫 `CheckoutLicense` API 操作，或以固定間隔更新耗用的數量。  
在此範例中，您的軟體會呼叫 `CheckoutLicense` API 操作來檢查 10 個單位的資料。當總容量達到客戶購買的備份限制時，API 呼叫會失敗。

**請求**

```
linux-machine ~]$ aws license-manager checkout-license\
--product-sku "2205b290-19e6-4c76-9eea-377d6bf7la47" \
--checkout-type "PERPETUAL" \
--key-fingerprint "aws:294406891311:AWS/Marketplace:issuer-fingerprint" \
--entitlements "Name=DataConsumption, Value=l0, Unit=Count" \
--client-token "AKIAIOSFODNN7EXAMPLE"
```

**回應**

```
{"CheckoutType": "PERPETUAL",
"EntitlementsAllowed": [{
"Name": "IntermediateTier",
"Units": "None"
}],
"Expiration": "2021-04-22Tl9:02:36",
"IssuedAt": "2021-04-22Tl8:02:36",
"LicenseArn": "arn:aws:license-manager::294406891311:license:l-16bf01b...",
"LicenseConsumptionToken": "AKIAIOSFODNN7EXAMPLE"
}
```

#### 浮動授權
<a name="container-floating-lic"></a>

 授權在使用後會傳回至允許授權數量的集區。

對於浮動授權，應用程式會在使用資源時，使用 `CheckoutLicense` API 操作從權利集區簽出權利。`CheckoutLicense` API 操作的回應包含授權使用字符，這是結帳的唯一識別符。授權使用字符可用來對已簽出的權限執行其他動作，例如將它們簽入授權或延長簽出。

若要將權利檢查回集區，請在不再使用資源時使用 `CheckInLicense` API 操作。

```
aws license-manager check-in-license --license-consumption-token "f1603b3c1f574b7284db84..."
```

如果無法簽入權利 （如果應用程式當機），權利會在 60 分鐘後自動簽入集區。如果資源使用時間超過 60 分鐘，最佳實務是使用 `ExtendLicenseConsumption` API 操作，在資源使用期間，保持從集區中檢查權利。

```
aws license-manager extend-license-consumption --license-consumption-token "f1603b3c1f574b7284..."
```

**Example 來自固定上限的使用者數量**  
使用者有權在應用程式上同時存取 500 名使用者。當使用者登入和登出時，會繪製使用者並傳回 500 名使用者的集區。不過，應用程式無法從集區中提取超過 500 個使用者，因為 500 個同時使用者是固定的上限。

對於浮動權利，您可以使用 `CheckInLicense` API 操作將授權單位傳回權利集區。

**Example 一年的並行使用者數量**  
您的產品會根據並行使用者數量定價。客戶為 10 個使用者購買授權一年。客戶提供 AWS Identity and Access Management (IAM) 許可來啟動軟體。當使用者登入時，您的應用程式會呼叫 `CheckoutLicense` API 操作，將數量減少 1。當使用者登出時，應用程式會呼叫 `CheckInLicense` API 操作，將該授權傳回至集區。如果您不呼叫 `CheckInLicense`，授權單位會在 1 小時後自動簽入。

**注意**  
在下列請求中， `key-fingerprint` 不是預留位置值，而是將發佈所有授權的指紋實際值。

**請求**

```
aws license-manager checkout-license\
--product-sku "2205b290-19e6-4c76-9eea-377d6bf7la47" \
--checkout-type "PROVISIONAL" \
--key-fingerprint "aws:294406891311:AWS/Marketplace:issuer-fingerprint" \
--entitlements "Name=ReadOnlyUSers, Value=l0, Unit=Count" \
--client-token "AKIAIOSFODNN7EXAMPLE"
```

**回應**

```
{
  "CheckoutType": "PROVISIONAL",
  "EntitlementsAllowed": [
    {
      "Name": "ReadOnlyUsers", 
      "Count": 10,
      "Units": "Count",
      "Value": "Enabled"
    }
},
  "Expiration": "2021-04-22Tl9:02: 36",
  "IssuedAt": "2021-04-22Tl8:02:36",
  "LicenseArn": "arn:aws:license-manager::294406891311:license:l-16bf01b...",
  "LicenseConsumptionToken": "AKIAIOSFODNN7EXAMPLE"
}
```

### 分層授權模型
<a name="container-LM-tiered-lic-model"></a>

在買方取得授權之後，分層授權模型會授予買方特定層級或層級的應用程式功能。

您可以為您的產品建立方案，例如 Basic、Intermediate 和 Premium。然後，買方會選取其中一個預先定義的層。

應用程式不需要追蹤或計量應用程式的用量。

使用分層授權模型時，不會計算權利，而是表示客戶購買的服務層級。

如果您想要同時提供綁定功能，最好使用 層。

**Example 基本、中級和高級方案**  
客戶可以為軟體的三個可能方案之一簽署合約：基本、中級或高級。每個方案都有自己的定價。您的軟體可以透過叫用 `CheckoutLicense` API 操作並在請求中指定所有可能的層來識別客戶已註冊的層。  
請求的回應包含與客戶已取得的方案對應的權利。根據此資訊，軟體可以佈建適當的客戶體驗。

#### 請求
<a name="container-LM-tiered-request"></a>

```
linux-machine  ~]$ aws  license-manager   checkout-license\
--product-sku  "2205b290-19e6-4c76-9eea-377d6bf7la47"  \
--checkout-type  "PROVISIONAL"  \
--key-fingerprint  "aws:294406891311:AWS/Marketplace:issuer-fingerprint" \
--entitlements  "Name=BasicTier,  Unit=None"   "Name=IntermediateTier,  Unit=None"	\ "Name=PremiumTier, Unit=None"
```

#### 回應
<a name="container-LM-tiered-response"></a>

```
{
  "CheckoutType": "PROVISIONAL",
  "EntitlementsAllowed": [
    {
      "Name": "IntermediateTier", 
      "Units": "None"
    }
},
  "Expiration": "2021-04-22Tl9:02:36",
  "IssuedAt": "2021-04-22Tl8:02:36",
  "LicenseArn": "arn:aws:license-manager::294406891311:license:l-16bf01b...",
  "LicenseConsumptionToken": "AKIAIOSFODNN7EXAMPLE"
}
```

## AWS License Manager 整合先決條件
<a name="container-LM-prereqs"></a>

在發佈產品之前，您必須執行下列動作：

1. 在 中建立新的容器產品 AWS Marketplace 管理入口網站，並記下其產品代碼。

   如需詳細資訊，請參閱[概觀：建立容器產品](container-product-getting-started.md#create-container-product)。

1. 針對執行應用程式的 任務或 Pod，使用 IAM 角色搭配呼叫 `CheckoutLicense`、 `ExtendLicenseConsumption`和 `CheckInLicense` API 操作所需的 IAM 許可。

   必要的 IAM 許可詳述於下列 IAM 政策中。

------
#### [ JSON ]

****  

   ```
   {
      "Version":"2012-10-17",		 	 	 
      "Statement":[
         {
            "Sid":"VisualEditorO",
            "Effect":"Allow",
            "Action":[
               "license-manager:CheckoutLicense",
               "license-manager:GetLicense",
               "license-manager:CheckInLicense",
               "license-manager:ExtendLicenseConsumption",
               "license-manager:ListReceivedLicenses"
            ],
            "Resource":"*"
         }
      ]
   }
   ```

------

1. 使用您定義的所有定價維度的記錄對 `RegisterUsage` API 操作進行測試呼叫。

## 將容器產品與 License Manager 整合
<a name="container-integrate-with-LM"></a>

**將您的容器型產品與 License Manager 整合**

1. 設定 IAM 許可以呼叫 License Manager。如需詳細資訊，請參閱[AWS License Manager 整合先決條件](#container-LM-prereqs)。

1. 下載 AWS SDK。
**注意**  
當您的容器在 Amazon EC2 執行個體、Amazon ECS 任務或 Amazon EKS Pod 中執行時，請勿在 software. AWS credentials 中設定 AWS 登入資料，系統會在執行時間自動取得買方的登入資料。

1. 將授權檢查新增至您的產品。

   您的產品可以在應執行授權檢查的位置呼叫 `CheckoutLicense` API 操作。若要檢查授權，您的產品必須知道：

   1. 授權的信任發行者 (AWS Marketplace)

   1. 應用程式的產品 SKU （產品 ID)

   1. 檢查此應用程式的權利

   API 呼叫會根據您設定的定價授權類型而有所不同。

1. 發佈您的產品清單 AWS Marketplace。

## License Manager API 操作
<a name="container-LM-API-calls"></a>

若要管理存放在客戶 License Manager 帳戶中的授權，您的軟體可以使用下列 API 操作：
+ `GetLicense` – 軟體可查詢的 API。它會擷取已購買授權的狀態 （即已過期或即將過期），並傳送狀態通知給客戶。
+ `CheckoutLicense` – 探索使用者已購買的授權。當使用者已取用一些授權數量時，您也可以使用 `CheckoutLicense` API 操作來更新授權數量。使用 `CheckoutLicense`，您可以繼續檢查客戶使用的授權數量。當客戶耗盡所有授權時，此呼叫會傳回錯誤。如需執行 的建議節奏資訊`CheckoutLicense`，請參閱 [授權續約和升級](#container-LM-lic-renew-upgrade)。
+ `ExtendLicenseConsumption` – 在浮動維度的情況下，當軟體簽出授權時，授權會在 60 分鐘後自動返回集區。如果您想要延長授權保持簽出的時間，請使用 `ExtendLicenseConsumption` API 操作將授權再延長 60 分鐘。
+ `CheckInLicense` – 如果是浮動維度，當您想要將授權傳回權利集區時，請使用 `CheckInLicense` API 操作。
+ `ListReceivedLicenses` API – 列出買方購買的授權。

## 授權續約和升級
<a name="container-LM-lic-renew-upgrade"></a>

客戶可以在 上續約或升級其授權 AWS Marketplace 管理入口網站。進行額外的購買後， AWS Marketplace 會產生反映新權利的授權新版本。您的軟體會使用相同的 API 操作讀取新的權利。在 License Manager 整合方面，您不需要採取任何不同的動作來處理續約和升級。

由於授權續約、升級、取消等，我們建議您的產品在使用產品時定期呼叫 `CheckoutLicense` API 操作。透過定期使用 `CheckoutLicense` API 操作，產品可以偵測權利的變更，例如升級和過期。

建議您每 15 分鐘執行一次 `CheckoutLicense` API 呼叫。

# 將 AWS Marketplace for Containers Anywhere 與 License Manager 整合
<a name="container-anywhere-license-manager-integration"></a>

身為 AWS Marketplace 賣方，您可以 AWS License Manager 整合適用於 Amazon EKS Anywhere、Amazon ECS Anywhere、Amazon EC2 或內部部署基礎設施的 AWS Marketplace for Containers Anywhere 產品。以下各節提供此整合的說明。

如需與 License Manager 整合的一般資訊 AWS Marketplace，包括可用的授權模型，請參閱 [使用 的容器產品的合約定價 AWS License Manager](container-license-manager-integration.md)。如需 的詳細資訊 AWS License Manager，請參閱 [AWS License Manager 使用者指南](https://docs.aws.amazon.com/license-manager/latest/userguide/license-manager.html)和 *AWS CLI 命令參考*的 [AWS License Manager](https://docs.aws.amazon.com/cli/latest/reference/license-manager/index.html)一節。

**Topics**
+ [將 AWS Marketplace for Containers Anywhere 產品與 License Manager 整合](#containers-anywhere-integrate-with-LM)
+ [在本機測試 License Manager 整合](#container-testing-LM-integration-locally)
+ [在 Amazon EKS 上測試 License Manager 整合](#container-testing-LM-integration-EKS)
+ [使用 License Manager 浮動授權權利](#container-LM-floating-license)
+ [與現場部署的 License Manager 整合的最佳實務](#container-LM-best-practices-on-prem)
+ [`LicenseManagerCredentialsProvider` - Java 實作](#container-license-manager-cred-provider-java)
+ [`LicenseManagerCredentialsProvider` - `Golang`實作](#container-license-manager-cred-provider-golang)

## 將 AWS Marketplace for Containers Anywhere 產品與 License Manager 整合
<a name="containers-anywhere-integrate-with-LM"></a>

使用以下指示將 AWS Marketplace for Containers Anywhere 產品與 整合 AWS License Manager。

**將您的 AWS Marketplace for Containers Anywhere 產品與 License Manager 整合**

1. 開啟 Web 瀏覽器並登入 [AWS Marketplace 管理入口網站](https://aws.amazon.com/marketplace/management/)。

1. 執行下列步驟，為您的容器產品建立產品 ID。在後續步驟中，您將在容器映像中使用此 ID 進行授權檢查。

   1. 從選單列中，展開**資產**，然後選擇**容器**。

   1. 輸入產品面向客戶的名稱，然後選擇**建立**。您可以稍後變更此名稱。

   1. 記下**產品 ID**。您將在建立或更新產品定價詳細資訊時使用它。
**提示**  
如果您遺失產品 ID，您可以從**資產**功能表中 AWS Marketplace 管理入口網站 選擇**容器**，在 中找到它。**Containers** 頁面會顯示您的產品清單及其相關聯的產品 IDs。

1. 下載最新的公有 AWS SDK，然後將其安裝在您的容器應用程式中。您可以在在 [AWS 上建置的工具](https://aws.amazon.com/tools/)中找到您偏好 AWS SDK 的安裝指示。
**注意**  
若要從 Amazon EKS Anywhere 或 未提供的 Kubernetes 叢集呼叫 License Manager API 操作 AWS，您必須使用支援的 AWS SDK。若要檢視支援的 AWS SDKs 清單，請參閱[使用支援的 AWS SDK](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html)。

1. 使用自訂登入資料提供者建立 AWS License Manager 用戶端，以便為部署在 上的容器應用程式 AWS 以及內部部署提供登入資料。如需自訂登入資料提供者的完整原始碼`LicenseCredentialProvider`，請參閱下列章節：
   + [`LicenseManagerCredentialsProvider` - Java 實作](#container-license-manager-cred-provider-java)
   + [`LicenseManagerCredentialsProvider` - `Golang`實作](#container-license-manager-cred-provider-golang)

    `LicenseCredentialsProvider` 透過新增 來擴展 AWS SDK 的預設登入資料提供者鏈，以供內部部署使用`LicenseManagerTokenCredentialsProvider`。這透過在內部部署環境中使用 License Manager OIDC 發行的身分字符來提供憑證。您必須在應用程式 classpath `LicenseCredentialsProvider`中包含 的原始碼。
**注意**  
延伸 `DefaultCredentialsProvider`可讓相同的容器應用程式在內部部署環境中執行 AWS 和 時取得登入資料。如果容器應用程式已使用自訂登入資料提供者鏈而非預設鏈，也可以透過將 `LicenseManagerTokenCredentialsProvider`新增至自訂鏈來延伸。

   下列程式碼片段是使用 Java 建立 AWS License Manager 用戶端的範例。

   ```
   LicenseManagerClientBuilder clientBuilder = LicenseManagerClient.builder().credentialsProvider(LicenseCredentialsProvider.create());
   ```

1. 使用產品方案中每個付費容器映像的 `aws license-manager checkout-license`命令來呼叫 `CheckoutLicense` API 操作。這會檢查買方是否有權為您的應用程式使用授權。如果買方有權使用應用程式， 會`CheckoutLicense`成功並傳回請求的權限及其值。如果買方無權使用應用程式， 會`CheckoutLicense`擲回例外狀況。

   呼叫 `CheckoutLicense` API 操作時需要下列參數：
   + `CheckoutType` – 有效值為 `PROVISIONAL`或 `PERPETUAL`：
     + 當已從集區中耗盡已簽出的權限數量`PERPETUAL`時，請使用 。

       範例：買方有權處理 500 GB 的資料。隨著他們繼續處理資料，數量會從 500 GB 的集區中消耗。
     + `PROVISIONAL` 用於浮動授權權利，其中權利會從集區中簽出，並在使用後傳回。

       範例：使用者有權在應用程式上同時存取 500 名使用者。當使用者登入或登出時，系統會將使用者繪製或傳回至 500 名使用者的集區。若要進一步了解浮動授權權利，請參閱 [使用 License Manager 浮動授權權利](#container-LM-floating-license)。
   + `ClientToken` – 唯一且區分大小寫的識別符。我們建議針對每個唯一請求使用隨機 UUID。
   + `Entitlements` – 要簽出的權限清單。
     + 針對功能權利，提供 `Name`和 `Unit` 屬性，如下所示。

       ```
       {
         "Name": "<Entitlement_Name>",
         "Unit": "None"
       }
       ```
     + 針對計數權利，提供 `Name`、 `Unit`和 `Count` 屬性，如下所示。

       ```
       {
         "Name": "<Entitlement_Name>",
         "Unit": "<Entitlement_Unit>",
         "Value": <Desired_Count>
       }
       ```
   + `KeyFingerprint` – 所發行授權的金鑰指紋 AWS Marketplace 為 `aws:294406891311:AWS/Marketplace:issuer-fingerprint`。使用此金鑰指紋可確保授權是由 發出 AWS Marketplace ，而不是由不可靠的實體發出。
   + `ProductSKU` – 上一個步驟 AWS Marketplace 管理入口網站 中在 上產生的產品 ID。

   下列程式碼片段是使用 進行 `CheckoutLicense` API 操作的呼叫範例 AWS CLI。

   ```
   aws license-manager checkout-license \
   --product-sku "2205b290-19e6-4c76-9eea-377d6bf71a47" \
   --checkout-type "PROVISIONAL" \
   --client-token "79464194dca9429698cc774587a603a1" \
   --entitlements "Name=AWS::Marketplace::Usage/Drawdown/DataConsumption, Value=10, Unit=Gigabytes" \
   --key-fingerprint "aws:294406891311:AWS/Marketplace:issuer-fingerprint"
   ```
**注意**  
若要檢查授權，容器應用程式需要傳出網路存取權才能使用 License Manager。部署在內部部署的應用程式可能會遇到不可靠或緩慢的傳出網路存取。呼叫 License Manager 時，這些應用程式應包含足夠的重試次數。如需詳細資訊，請參閱[與現場部署的 License Manager 整合的最佳實務](#container-LM-best-practices-on-prem)。

1. 定期呼叫 `CheckoutLicense` API 操作，以識別因續約、升級或取消 而導致客戶授權的任何變更 AWS Marketplace。節奏取決於應用程式。我們建議您每天檢查一次授權，以自動收取變更，而無需任何買方介入。

   部署於內部部署的應用程式可能具有不可靠的傳出網路存取權，以定期檢查授權。在這種情況下，應用程式應使用快取的授權以獲得足夠的彈性。如需詳細資訊，請參閱[與現場部署的 License Manager 整合的最佳實務](#container-LM-best-practices-on-prem)。

1. 將`CheckoutLicense`呼叫與容器應用程式整合之後，請建置具有變更的 Docker 容器映像新版本。

1. 更新應用程式的 Helm Chart 以接受 Kubernetes 秘密作為選用輸入，其中包含使用 License Manager APIs組態。組態秘密將包含 License Manager 發行的身分字符和 角色，該 AWS Identity and Access Management 角色將由先前描述的自訂登入資料提供者使用，以取得在現場部署容器應用程式時呼叫 License Manager APIs 的 AWS 登入資料。此外，將 新增 AWS 區域 為預設值為 的輸入`us-east-1`。

   現場部署容器應用程式的買方可以透過容器產品的 AWS Marketplace 買方體驗來建立 Kubernetes 秘密。提供 Kubernetes 秘密名稱做為`helm install`命令的輸入。組態秘密的設定格式如下。

   ```
   apiVersion: v1
   kind: Secret
   metadata:
     name: aws-marketplace-license-config
   type: Opaque
   stringData:
     license_token: <token_value> // License Manager issued JWT token
     iam_role: <role_arn> // AWS Identity and Access Management role to assume with license token
   ```

1. 針對與 整合的容器映像，更新 Helm Chart 中的應用程式部署範本 AWS License Manager ，以包含下列項目：
   + Pod 的服務帳戶 – 在 Amazon EKS 上的 Helm 部署需要 服務帳戶。它用於透過在容器映像上設定服務帳戶的 IAM 角色來取得呼叫 License Manager API 操作的許可。如需服務帳戶的 IAM 角色詳細資訊，請參閱[服務帳戶的 IAM 角色](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)。
   + 內部部署的授權存取 – 需要授權組態秘密，才能提供登入資料和適當的許可，以在內部部署環境中呼叫 Helm 部署的 License Manager API 操作。買方將從 AWS Marketplace 買方體驗產生授權秘密並提供給 Helm。

   下列程式碼片段是具有服務帳戶、授權組態和映像提取秘密的範例部署規格。

   ```
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: example-app
   spec:
     replicas: 1
     selector:
       matchLabels:
         app: example-app
     template:
       metadata:
         labels:
           app: example-app
   spec:
         // Service account for pod
         serviceAccountName: {{ .Values.serviceAccountName }}
         containers:
           - name: example-app
             image: example-app
             ports:
               - containerPort: 8001
   // Add the following conditional attributes
   {{ - if .Values.awsmp.licenseConfigSecretName }}
             //Mount the license volume to the container image
             volumeMounts:
               - name: awsmp-product-license
                 mountPath: "/var/run/secrets/product-license"
             //Add following environment variable to container for credential
   provider
             env:
               - name: AWS_WEB_IDENTITY_REFRESH_TOKEN_FILE
                 value: "/var/run/secrets/product-license/license_token"
               - name: AWS_ROLE_ARN
                   valueFrom:
                       secretKeyRef:
                       name: {{ .Values.aws.licenseConfigSecretName }}
                       key: iam_role
         //Mount the license secret as a volume to the pod
         volumes:
           - name: awsmp-product-license
             secret:
               secretName: {{ .Values.aws.licenseConfigSecretName }}
               optional: true
   {{ - end }}
   ```
**注意**  
授權組態秘密是選用的。買方只會將 值用於內部部署。對於 AWS 部署，部署規格必須包含 License Manager 整合映像的服務帳戶。

1. 透過執行以下章節中的步驟，在本機和 Amazon EKS 上測試 License Manager 整合：

   1. [在本機測試 License Manager 整合](#container-testing-LM-integration-locally)

   1. [在 Amazon EKS 上測試 License Manager 整合](#container-testing-LM-integration-EKS)

1. 在現場部署 AWS 和現場部署成功驗證 License Manager 整合之後，您可以依照中的步驟建立容器產品清單[概觀：建立容器產品](container-product-getting-started.md#create-container-product)。

## 在本機測試 License Manager 整合
<a name="container-testing-LM-integration-locally"></a>

您可以使用 minikube 或任何其他設定來測試本機任何 Kubernetes 叢集上的 License Manager 整合。確定 Kubernetes 叢集具有傳出網際網路存取權，以呼叫 License Manager API 操作。

**在本機測試 License Manager 整合**

1. 在具有所需權限的測試賣方帳戶中建立測試授權。若要設定測試授權，請參閱 *AWS License Manager API 參考*中的 [CreateLicense](https://docs.aws.amazon.com/license-manager/latest/APIReference/API_CreateLicense.html)。或者，使用以下指令碼來建立測試授權，然後建立授權給測試買方帳戶以取用授權。下列指令碼使用測試賣方帳戶登入資料。

   ```
   read -p 'AWS Account for test buyer: ' TEST_BUYER_ACCOUNT_ID
   read -p 'License entitlements: ' ENTITLEMENTS
   
   # TEST_SELLER_ACCOUNT_ID="109876543210"
   # ENTITLEMENTS="{\"Name\": \"ByData\",\"MaxCount\": 1000,\"Overage\":true,\"Unit\": \"Gigabits\",\"AllowCheckIn\": true}"
   
   # Create License
   
   NOW=$(date +"%Y-%m-%dT00:00:00+00:00")
   
   PRODUCT_NAME="My awesome product"
   PRODUCT_SKU="c97b7825-44c4-4f42-b025-12baa4c171e0"
   
   LICENSE_BENEFICIARY=" arn:aws:iam::$TEST_BUYER_ACCOUNT_ID:root "
   LICENSE_ISSUER_NAME="test-seller"
   LICENSE_NAME="test-seller-license"
   
   CLIENT_TOKEN="b3920968-a94f-4547-af07-3dd232319367"
   CONSUMPTION_TTL=180
   CONSUMPTION_RENEW_TYPE="None"
   
   HOME_REGION="us-east-1"
   
   LICENSE_ARN=$(aws license-manager create-license --license-name "$LICENSE_NAME" --product-name "$PRODUCT_NAME" --product-sku "$PRODUCT_SKU" --issuer Name="$LICENSE_ISSUER_NAME" --home-region "$HOME_REGION" --validity Begin="$NOW" --entitlements "$ENTITLEMENTS" --beneficiary "$LICENSE_BENEFICIARY" --consumption-configuration RenewType="$CONSUMPTION_RENEW_TYPE",ProvisionalConfiguration={MaxTimeToLiveInMinutes=$CONSUMPTION_TTL} --client-token "$CLIENT_TOKEN" | jq -r ".LicenseArn" )
   
   echo "License arn: $LICENSE_ARN"
   
   # Create Grant
   
   GRANT_TOKEN="e9a14140-4fca-4219-8230-57511a6ea6"
   GRANT_NAME="test-grant"
   
   GRANT_ARN=$(aws license-manager create-grant --grant-name "$GRANT_NAME" --license-arn "$LICENSE_ARN" --principals "$LICENSE_BENEFICIARY" --home-region "$HOME_REGION" --client-token "$GRANT_TOKEN" --allowed-operations "CheckoutLicense" "CheckInLicense" "ExtendConsumptionLicense" "CreateToken" | jq -r ".GrantArn")
   
   echo "Grant arn: $GRANT_ARN"
   ```

1. 使用先前定義的秘密格式，使用授權字符和 IAM 角色建立 Kubernetes 秘密。使用 License Manager `CreateToken` API 操作來產生授權字符。然後，使用 IAM `CreateRole` API 操作來建立具有許可和信任政策的 IAM 角色。請參閱下列指令碼中的範例。下列指令碼使用測試買方帳戶登入資料。

   ```
   read -p 'AWS Account for test license: ' TEST_ACCOUNT_ID
   read -p 'License Arn' LICENSE_ARN
   # Create IAM Role
   ROLE_NAME="AWSLicenseManagerConsumptionTestRole"
   ROLE_DESCRIPTION="Role to test AWS License Manager integration on-prem"
   ROLE_POLICY_ARN="arn:aws:iam::aws:policy/service-role/AWSLicenseManagerConsumptionPolicy"
   ROLE_TRUST_POLICY="{\"Version\": \"2012-10-17\",\"Statement\": [{ \"Effect\":\"Allow\", \"Principal\": { \"Federated\": \"openid-license-manager.amazonaws.com\" }, \"Action\": \"sts:AssumeRoleWithWebIdentity\",\"Condition\": { \"ForAnyValue:StringLike\": { \"openid-license-manager.amazonaws.com:amr\": \"aws:license-manager:token-issuer-account-id:${TEST_ACCOUNT_ID}\" }}}]}"
   ROLE_SESSION_DURATION=3600
   
   ROLE_ARN=$(aws iam create-role --role-name "$ROLE_NAME" --description "$ROLE_DESCRIPTION" --assume-role-policy-document "$ROLE_TRUST_POLICY" --max-session-duration $ROLE_SESSION_DURATION | jq ".Role" | jq -r ".Arn")
   
   aws iam attach-role-policy --role-name "$ROLE_NAME" --policy-arn "$ROLE_POLICY_ARN"
   
   echo "Role arn: $ROLE_ARN"
   
   # Create Token
   CLIENT_TOKEN="b3920968-a94f-4547-af07-3dd232319367"
   
   TOKEN=$(aws license-manager create-token --license-arn $LICENSE_ARN --role-arns $ROLE_ARN --client-token $CLIENT_TOKEN | jq '.Token')
   
   echo "License access token: $TOKEN"c
   ```

1. 設定在外部託管的任何 Kubernetes 叢集 AWS。使用它來測試容器應用程式是否可以從 以外的環境連線至 AWS License Manager API， AWS 並且自訂登入資料提供者已與應用程式充分整合。

1. 將先前產生的授權字符和 IAM 角色部署到本機 Kubernetes 叢集。

   ```
   kubectl create secret generic "awsmp-license-access-config" \
   --from-literal=license_token=${TOKEN} \
   --from-literal=iam_role=${ROLE_ARN}
   ```

1. 透過 Helm 使用秘密名稱做為輸入來部署應用程式，並確認應用程式可以呼叫 License Manager API 操作來執行權利檢查。如需 Helm 和部署規格變更，請參閱 中的步驟 9[將 AWS Marketplace for Containers Anywhere 產品與 License Manager 整合](#containers-anywhere-integrate-with-LM)。

## 在 Amazon EKS 上測試 License Manager 整合
<a name="container-testing-LM-integration-EKS"></a>

您也可以在 Amazon EKS 上測試 License Manager 整合。測試以確保應用程式可以在沒有授權組態秘密的情況下呼叫 License Manager API 操作。此外，請確定服務帳戶可用來設定服務帳戶的 IAM 角色 (IRSA)，並提供應用程式相關登入資料。

**在 Amazon EKS 上測試 License Manager 整合**

1. 在具有所需權利的測試賣方帳戶中建立測試授權。請參閱 [CreateLicense API 參考](https://docs.aws.amazon.com/license-manager/latest/APIReference/API_CreateLicense.html)以設定您的測試授權，或使用下列指令碼建立一個授權，並建立授權給測試買方帳戶以取用授權。下列指令碼使用測試賣方帳戶登入資料。

   ```
   read -p 'AWS Account for test buyer: ' TEST_BUYER_ACCOUNT_ID
   read -p 'License entitlements: ' ENTITLEMENTS
   
   # TEST_SELLER_ACCOUNT_ID="109876543210"
   # ENTITLEMENTS="{\"Name\": \"ByData\",\"MaxCount\": 1000,\"Overage\": true,\"Unit\": \"Gigabits\",\"AllowCheckIn\": true}"
   
   # Create License
   
   NOW=$(date +"%Y-%m-%dT00:00:00+00:00")
   
   PRODUCT_NAME="My awesome product"
   PRODUCT_SKU="c97b7825-44c4-4f42-b025-12baa4c171e0"
   
   LICENSE_BENEFICIARY=" arn:aws:iam::$TEST_BUYER_ACCOUNT_ID:root "
   LICENSE_ISSUER_NAME="test-seller"
   LICENSE_NAME="test-seller-license"
   
   CLIENT_TOKEN="b3920968-a94f-4547-af07-3dd232319367"
   CONSUMPTION_TTL=180
   CONSUMPTION_RENEW_TYPE="None"
   
   HOME_REGION="us-east-1"
   
   LICENSE_ARN=$(aws license-manager create-license --license-name "$LICENSE_NAME" --product-name "$PRODUCT_NAME" --product-sku "$PRODUCT_SKU" --issuer Name="$LICENSE_ISSUER_NAME" --home-region "$HOME_REGION" --validity Begin="$NOW" --entitlements "$ENTITLEMENTS" --beneficiary "$LICENSE_BENEFICIARY" --consumption-configuration RenewType="$CONSUMPTION_RENEW_TYPE",ProvisionalConfiguration={MaxTimeToLiveInMinutes=$CONSUMPTION_TTL} --client-token "$CLIENT_TOKEN" | jq -r ".LicenseArn" )
   
   echo "License arn: $LICENSE_ARN"
   
   # Create Grant
   
   GRANT_TOKEN="e9a14140-4fca-4219-8230-57511a6ea6"
   GRANT_NAME="test-grant"
   
   GRANT_ARN=$(aws license-manager create-grant --grant-name "$GRANT_NAME" --license-arn "$LICENSE_ARN" --principals "$LICENSE_BENEFICIARY" --home-region "$HOME_REGION" --client-token "$GRANT_TOKEN" --allowed-operations "CheckoutLicense" "CheckInLicense" "ExtendConsumptionLicense" "CreateToken" | jq -r ".GrantArn")
   
   echo "Grant arn: $GRANT_ARN"
   ```

1. 建立所需組態的測試 Amazon EKS 叢集，或執行下列命令以使用預設組態。

   ```
   aws ec2 create-key-pair --region us-west-2 --key-name eks-key-pair
   ```

   ```
   eksctl create cluster \
   --name awsmp-eks-test-example \
   --region us-west-2 \
   --with-oidc \
   --ssh-access \
   --ssh-public-key eks-key-pair
   ```

1. 為現有叢集建立服務帳戶，並將其與 IAM 角色建立關聯。下列命令會使用 建立 IAM 角色`AWSLicenseManagerConsumptionPolicy`。然後，命令會將它連接到 Amazon EKS 叢集`test_sa`的服務帳戶，其中應部署 License Manager 整合映像。因此，服務帳戶可以取得適當的登入資料來呼叫 License Manager API 操作。

   ```
   eksctl create iamserviceaccount \
   --name test_sa \
   --namespace test_namespace \
   --cluster awsmp-eks-test-example \
   --attach-policy-arn "arn:aws:iam::aws:policy/service-role/AWSLicenseManagerConsumptionPolicy" \
   --approve \
   --override-existing-serviceaccounts
   ```

1. 在 IAM 角色與上一個命令相關聯的服務帳戶中，透過 Helm 部署應用程式。確認應用程式可以呼叫 License Manager API 操作來執行權利檢查。

## 使用 License Manager 浮動授權權利
<a name="container-LM-floating-license"></a>

使用浮動授權時，當使用者登入應用程式時，會從可用授權集區中提取授權。當使用者登出時，授權會新增回可用的授權集區。

對於浮動授權，應用程式會使用 `CheckoutLicense` API 操作，在使用資源時從權利集區簽出權利。`CheckoutLicense` API 操作的回應包含授權使用字符，這是結帳的唯一識別符。授權使用字符可以對已簽出的權限執行其他動作，例如將它們簽回授權集區或延長簽出。

當資源不再使用時，應用程式會使用 `CheckInLicense` API 操作將權利檢查回集區。

```
aws license-manager check-in-license \
--license-consumption-token "f1603b3c1f574b7284db84a9e771ee12"
```

如果將授權檢查回集區失敗，例如，如果應用程式在操作期間當機，則會在 60 分鐘後自動將權利檢查回集區。因此，如果資源的使用時間超過 60 分鐘，最佳實務是將權利保留在集區之外。若要這樣做，只要資源正在使用，請使用 `ExtendLicenseConsumption` API 操作。

```
aws license-manager extend-license-consumption \
--license-consumption-token "f1603b3c1f574b7284db84a9e771ee12"
```

## 與現場部署的 License Manager 整合的最佳實務
<a name="container-LM-best-practices-on-prem"></a>

內部部署環境中的容器應用程式部署可能會遇到不可靠的傳出網路存取。使用下列最佳實務來新增彈性，以避免因網際網路連線能力不佳造成潛在問題而導致買方的服務中斷：
+ **充分重試** – 暫時性網路問題可能會讓您的應用程式無法連線到 AWS License Manager。實作重試最多 30 分鐘，並呈指數退避。這有助於避免短期中斷或網路問題。
+ **避免硬性限制** – 部署在連線叢集中的應用程式可以定期檢查授權，以識別因升級或續約而產生的任何變更。透過不可靠的傳出存取，應用程式可能無法識別這些變更。盡可能避免由於無法透過 License Manager 檢查授權而導致買方的服務中斷。當授權過期且無法檢查授權是否有效時，應用程式可以恢復免費試用或開放原始碼的體驗。
+ **通知客戶** – 使用快取的授權時，授權的任何變更 （包括續約或升級） 都不會自動反映在執行中的工作負載上。通知您的客戶 （他們必須暫時允許傳出存取應用程式，以便應用程式可以更新其快取的授權。例如，透過應用程式本身或文件通知客戶。同樣地，當回復到一組較低的功能時，請通知客戶其權利已耗盡或授權已過期。然後，他們可以選擇升級或續約。

## `LicenseManagerCredentialsProvider` - Java 實作
<a name="container-license-manager-cred-provider-java"></a>

`LicenseCredentialsProvider` 透過新增 來擴展 AWS SDK 的預設登入資料提供者鏈，以供內部部署使用`LicenseManagerTokenCredentialsProvider`。

**`LicenseCredentialsProvider`**

```
package com.amazon.awsmp.license;

import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.auth.credentials.internal.LazyAwsCredentialsProvider;
import software.amazon.awssdk.utils.SdkAutoCloseable;

public class LicenseCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable {
    private static final LicenseCredentialsProvider CREDENTIALS_PROVIDER = new LicenseCredentialsProvider();
    private final LazyAwsCredentialsProvider providerChain;

    private LicenseCredentialsProvider() {
        this.providerChain = createChain();
    }

    public static LicenseCredentialsProvider create() {
        return CREDENTIALS_PROVIDER;
    }

    @Override
    public AwsCredentials resolveCredentials() {
        return this.providerChain.resolveCredentials();
    }

    @Override
    public void close() {
        this.providerChain.close();
    }

    private LazyAwsCredentialsProvider createChain() {
        return LazyAwsCredentialsProvider.create(() -> {
            AwsCredentialsProvider[] credentialsProviders = new AwsCredentialsProvider[]{
                    DefaultCredentialsProvider.create(),
                    LicenseManagerTokenCredentialsProvider.create()};

            return AwsCredentialsProviderChain.builder().reuseLastProviderEnabled(true)
                    .credentialsProviders(credentialsProviders).build();
        });
    }
}
```

**`LicenseManagerTokenCredentialsProvider`**

`LicenseManagerTokenCredentialsProvider` 在內部部署環境中使用 License Manager OIDC 發行的身分字符來提供登入資料。您必須在應用程式 classpath `LicenseCredentialsProvider`中包含 的原始碼。

```
package com.amazon.awsmp.license;

import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.core.retry.RetryPolicyContext;
import software.amazon.awssdk.core.retry.conditions.OrRetryCondition;
import software.amazon.awssdk.core.retry.conditions.RetryCondition;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain;
import software.amazon.awssdk.services.licensemanager.LicenseManagerClient;
import software.amazon.awssdk.services.licensemanager.model.GetAccessTokenRequest;
import software.amazon.awssdk.services.licensemanager.model.GetAccessTokenResponse;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.auth.StsAssumeRoleWithWebIdentityCredentialsProvider;
import software.amazon.awssdk.services.sts.model.AssumeRoleWithWebIdentityRequest;
import software.amazon.awssdk.services.sts.model.IdpCommunicationErrorException;
import software.amazon.awssdk.utils.IoUtils;
import software.amazon.awssdk.utils.SdkAutoCloseable;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.awssdk.utils.SystemSetting;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.function.Supplier;

public class LicenseManagerTokenCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable {

    private final StsAssumeRoleWithWebIdentityCredentialsProvider credentialsProvider;
    private final RuntimeException loadException;

    private Path licenseAccessTokenFile;
    private String roleArn;
    private String roleSessionName;
    private StsClient stsClient;
    private LicenseManagerClient lmClient;

    public static LicenseManagerTokenCredentialsProvider create() {
        return new Builder().build();
    }

    @Override
    public AwsCredentials resolveCredentials() {
        if (this.loadException != null) {
            throw this.loadException;
        }
        return this.credentialsProvider.resolveCredentials();
    }

    @Override
    public void close() {
        IoUtils.closeQuietly(this.credentialsProvider, null);
        IoUtils.closeQuietly(this.stsClient, null);
        IoUtils.closeIfCloseable(this.lmClient, null);
    }

    private LicenseManagerTokenCredentialsProvider(Builder builder) {
        StsAssumeRoleWithWebIdentityCredentialsProvider credentialsProvider = null;
        RuntimeException loadException = null;

        try {
            this.licenseAccessTokenFile = Paths.get(StringUtils.trim(LicenseSystemSetting.AWS_WEB_IDENTITY_REFRESH_TOKEN_FILE.getStringValueOrThrow()));
            this.roleArn = SdkSystemSetting.AWS_ROLE_ARN.getStringValueOrThrow();
            this.roleSessionName = SdkSystemSetting.AWS_ROLE_SESSION_NAME.getStringValue().orElse("aws-sdk-java-" + System.currentTimeMillis());
            this.stsClient = builder.stsClient != null ? builder.stsClient : StsClientFactory.create();
            this.lmClient = builder.lmClient != null ? builder.lmClient : LicenseManagerClientFactory.create();

            AssumeRoleWithWebIdentityRequest request = AssumeRoleWithWebIdentityRequest.builder()
                    .roleArn(this.roleArn).roleSessionName(this.roleSessionName).build();

            Supplier<AssumeRoleWithWebIdentityRequest> supplier = new AssumeRoleRequestSupplier(request,
                    this.licenseAccessTokenFile, this.lmClient);

            credentialsProvider = StsAssumeRoleWithWebIdentityCredentialsProvider.builder()
                    .stsClient(this.stsClient).refreshRequest(supplier).build();
        } catch (RuntimeException ex) {
            loadException = ex;
        }

        this.credentialsProvider = credentialsProvider;
        this.loadException = loadException;
    }

    public static final class Builder {
        private Path licenseAccessTokenFile;
        private String roleArn;
        private String roleSessionName;
        private StsClient stsClient;
        private LicenseManagerClient lmClient;

        public LicenseManagerTokenCredentialsProvider build() {
            return new LicenseManagerTokenCredentialsProvider(this);
        }

        public LicenseManagerTokenCredentialsProvider.Builder licenseAccessTokenFile(Path licenseAccessTokenFile) {
            this.licenseAccessTokenFile = licenseAccessTokenFile;
            return this;
        }

        public LicenseManagerTokenCredentialsProvider.Builder roleArn(String roleArn) {
            this.roleArn = roleArn;
            return this;
        }

        public LicenseManagerTokenCredentialsProvider.Builder roleSessionName(String roleSessionName) {
            this.roleSessionName = roleSessionName;
            return this;
        }

        public LicenseManagerTokenCredentialsProvider.Builder stsClient(StsClient stsClient) {
            this.stsClient = stsClient;
            return this;
        }

        public LicenseManagerTokenCredentialsProvider.Builder lmClient(LicenseManagerClient lmClient) {
            this.lmClient = lmClient;
            return this;
        }
    }

    private static final class AssumeRoleRequestSupplier implements Supplier {
        private final LicenseManagerClient lmClient;
        private final AssumeRoleWithWebIdentityRequest request;
        private final Path webIdentityRefreshTokenFile;

        AssumeRoleRequestSupplier(final AssumeRoleWithWebIdentityRequest request,
                                                 final Path webIdentityRefreshTokenFile,
                                                 final LicenseManagerClient lmClient) {
            this.lmClient = lmClient;
            this.request = request;
            this.webIdentityRefreshTokenFile = webIdentityRefreshTokenFile;
        }

        public AssumeRoleWithWebIdentityRequest get() {
            return this.request.toBuilder()
                    .webIdentityToken(getIdentityToken())
                    .build();
        }

        private String getIdentityToken() {
            return refreshIdToken(readRefreshToken(this.webIdentityRefreshTokenFile));
        }

        private String readRefreshToken(Path file) {
            try (InputStream webIdentityRefreshTokenStream = Files.newInputStream(file)) {
                return IoUtils.toUtf8String(webIdentityRefreshTokenStream);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        private String refreshIdToken(String licenseRefreshToken) {
            final GetAccessTokenRequest request = GetAccessTokenRequest.builder()
                    .token(licenseRefreshToken)
                    .build();

            GetAccessTokenResponse response = this.lmClient.getAccessToken(request);
            return response.accessToken();
        }
    }

    private static final class LicenseManagerClientFactory {
        private static final Duration DEFAULT_API_TIMEOUT = Duration.ofSeconds(30);
        private static final Duration DEFAULT_API_ATTEMPT_TIMEOUT = Duration.ofSeconds(10);

        public static LicenseManagerClient create() {
            return getLicenseManagerClient();
        }

        private static LicenseManagerClient getLicenseManagerClient() {
            ClientOverrideConfiguration configuration = ClientOverrideConfiguration.builder()
                    .apiCallTimeout(DEFAULT_API_TIMEOUT)
                    .apiCallAttemptTimeout(DEFAULT_API_ATTEMPT_TIMEOUT)
                    .build();

            LicenseManagerClient client = LicenseManagerClient.builder()
                    .region(configureLicenseManagerRegion())
                    .credentialsProvider(AnonymousCredentialsProvider.create())
                    .overrideConfiguration(configuration).build();
            return client;
        }

        private static Region configureLicenseManagerRegion() {
            Region defaultRegion = Region.US_EAST_1;

            Region region;
            try {
                region = (new DefaultAwsRegionProviderChain()).getRegion();
            } catch (RuntimeException ex) {
                region = defaultRegion;
            }
            return region;
        }
    }

    private static final class StsClientFactory {
        private static final Duration DEFAULT_API_TIMEOUT = Duration.ofSeconds(30);
        private static final Duration DEFAULT_API_ATTEMPT_TIMEOUT = Duration.ofSeconds(10);

        public static StsClient create() {
            return getStsClient();
        }

        private static StsClient getStsClient() {
            OrRetryCondition retryCondition = OrRetryCondition.create(new StsRetryCondition(),
                    RetryCondition.defaultRetryCondition());

            ClientOverrideConfiguration configuration = ClientOverrideConfiguration.builder()
                    .apiCallTimeout(DEFAULT_API_TIMEOUT)
                    .apiCallAttemptTimeout(DEFAULT_API_ATTEMPT_TIMEOUT)
                    .retryPolicy(r -> r.retryCondition(retryCondition))
                    .build();

            return StsClient.builder()
                    .region(configureStsRegion())
                    .credentialsProvider(AnonymousCredentialsProvider.create())
                    .overrideConfiguration(configuration).build();
        }

        private static Region configureStsRegion() {
            Region defaultRegion = Region.US_EAST_1;
            Region stsRegion;
            try {
                stsRegion = (new DefaultAwsRegionProviderChain()).getRegion();
            } catch (RuntimeException ex) {
                stsRegion = defaultRegion;
            }
            return stsRegion;
        }

        private static final class StsRetryCondition implements RetryCondition {
            public boolean shouldRetry(RetryPolicyContext context) {
                return context.exception() instanceof IdpCommunicationErrorException;
            }
        }
    }

    private enum LicenseSystemSetting implements SystemSetting {
        AWS_WEB_IDENTITY_REFRESH_TOKEN_FILE("aws.webIdentityRefreshTokenFile");

        private String systemProperty;
        private String defaultValue = null;

        LicenseSystemSetting(String systemProperty) {
            this.systemProperty = systemProperty;
        }

        @Override
        public String property() {
            return this.systemProperty;
        }

        @Override
        public String environmentVariable() {
            return this.name();
        }

        @Override
        public String defaultValue() {
            return this.defaultValue;
        }
    }
}
```

## `LicenseManagerCredentialsProvider` - `Golang`實作
<a name="container-license-manager-cred-provider-golang"></a>

**`LicenseCredentialsProvider`**

`LicenseCredentialsProvider` 透過新增 來擴展 AWS SDK 的預設登入資料提供者鏈，以供內部部署使用`LicenseManagerTokenCredentialsProvider`。

```
package lib

import (
	"context"
	"fmt"
	"sync"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
)

// LicenseCredentialsProvider is the custom credential provider that can retrieve valid temporary aws credentials
type LicenseCredentialsProvider struct {
	fallBackProvider   aws.CredentialsProvider
	mux                sync.RWMutex
	licenseCredentials aws.Credentials
	err                error
}

// NewLicenseCredentialsProvider method will create a LicenseCredentialProvider Object which contains valid temporary aws credentials
func NewLicenseCredentialsProvider() (*LicenseCredentialsProvider, error) {
	licenseCredentialProvider := &LicenseCredentialsProvider{}
	fallBackProvider, err := createCredentialProvider()
	if err != nil {
		return licenseCredentialProvider, fmt.Errorf("failed to create LicenseCredentialsProvider, %w", err)
	}
	licenseCredentialProvider.fallBackProvider = fallBackProvider
	return licenseCredentialProvider, nil
}

// Retrieve method will retrieve temporary aws credentials from the credential provider
func (l *LicenseCredentialsProvider) Retrieve(ctx context.Context) (aws.Credentials, error) {
	l.mux.RLock()
	defer l.mux.RUnlock()
	l.licenseCredentials, l.err = l.fallBackProvider.Retrieve(ctx)
	return l.licenseCredentials, l.err
}

func createCredentialProvider() (aws.CredentialsProvider, error) {
	// LoadDefaultConfig will examine all "default" credential providers
	ctx := context.TODO()
	cfg, err := config.LoadDefaultConfig(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to create FallBackProvider, %w", err)
	}

	var useFallbackProvider bool
	if cfg.Credentials != nil {
		if _, err := cfg.Credentials.Retrieve(ctx); err != nil {
			// If the "default" credentials provider cannot retrieve credentials, enable fallback to customCredentialsProvider.
			useFallbackProvider = true
		}
	} else {
		useFallbackProvider = true
	}

	if useFallbackProvider {
		customProvider, err := newLicenseManagerTokenCredentialsProvider()
		if err != nil {
			return cfg.Credentials, fmt.Errorf("failed to create fallBackProvider, %w", err)
		}
		// wrap up customProvider with CredentialsCache to enable caching
		cfg.Credentials = aws.NewCredentialsCache(customProvider)
	}
	return cfg.Credentials, nil
}
```

**`LicenseManagerTokenCredentialsProvider`**

`LicenseManagerTokenCredentialsProvider` 在內部部署環境中使用 License Manager OIDC 發行的身分字符來提供登入資料。您必須在應用程式 classpath `LicenseCredentialsProvider`中包含 的原始碼。

```
package lib

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"sync"
	"time"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/sts"
)

const awsRefreshTokenFilePathEnvVar = "AWS_LICENSE_ACCESS_FILE"

// licenseManagerTokenCredentialsProvider defines and contains StsAssumeRoleWithWebIdentityProvider
type licenseManagerTokenCredentialsProvider struct {
	stsCredentialProvider *stsAssumeRoleWithWebIdentityProvider
	mux                   sync.RWMutex
	licenseCredentials    aws.Credentials
	err                   error
}

// Retrieve method will retrieve credentials from credential provider.
// Make this method public to make this provider satisfies CredentialProvider interface
func (a *licenseManagerTokenCredentialsProvider) Retrieve(ctx context.Context) (aws.Credentials, error) {
	a.mux.RLock()
	defer a.mux.RUnlock()
	a.licenseCredentials, a.err = a.stsCredentialProvider.Retrieve(ctx)
	return a.licenseCredentials, a.err
}

// newLicenseManagerTokenCredentialsProvider will create and return a LicenseManagerTokenCredentialsProvider Object which wraps up stsAssumeRoleWithWebIdentityProvider
func newLicenseManagerTokenCredentialsProvider() (*licenseManagerTokenCredentialsProvider, error) {
	// 1. Retrieve variables From yaml environment
	envConfig, err := config.NewEnvConfig()
	if err != nil {
		return &licenseManagerTokenCredentialsProvider{}, fmt.Errorf("failed to create LicenseManagerTokenCredentialsProvider, %w", err)
	}
	roleArn := envConfig.RoleARN
	var roleSessionName string
	if envConfig.RoleSessionName == "" {
		roleSessionName = fmt.Sprintf("aws-sdk-go-v2-%v", time.Now().UnixNano())
	} else {
		roleSessionName = envConfig.RoleSessionName
	}
	tokenFilePath := os.Getenv(awsRefreshTokenFilePathEnvVar)
	b, err := ioutil.ReadFile(tokenFilePath)
	if err != nil {
		return &licenseManagerTokenCredentialsProvider{}, fmt.Errorf("failed to create LicenseManagerTokenCredentialsProvider, %w", err)
	}
	refreshToken := aws.String(string(b))

	// 2. Create stsClient
	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		return &licenseManagerTokenCredentialsProvider{}, fmt.Errorf("failed to create LicenseManagerTokenCredentialsProvider, %w", err)
	}
	stsClient := sts.NewFromConfig(cfg, func(o *sts.Options) {
		o.Region = configureStsClientRegion(cfg.Region)
		o.Credentials = aws.AnonymousCredentials{}
	})

	// 3. Configure StsAssumeRoleWithWebIdentityProvider
	stsCredentialProvider := newStsAssumeRoleWithWebIdentityProvider(stsClient, roleArn, roleSessionName, refreshToken)

	// 4. Build and return
	return &licenseManagerTokenCredentialsProvider{
		stsCredentialProvider: stsCredentialProvider,
	}, nil
}

func configureStsClientRegion(configRegion string) string {
	defaultRegion := "us-east-1"
	if configRegion == "" {
		return defaultRegion
	} else {
		return configRegion
	}
}
```

# 容器產品的 Amazon SNS 通知
<a name="container-notification"></a>

若要接收通知，您可以訂閱產品建立期間 AWS Marketplace 提供給您的 Amazon Simple Notification Service (Amazon SNS) 主題。這些主題會針對您產品的客戶訂閱提供變更通知。例如，您可以使用這些通知來了解客戶何時接受私有優惠。

**注意**  
在產品建立過程中，會為您的產品建立 Amazon SNS 主題。若要訂閱通知，您需要 Amazon SNS 主題的 Amazon Resource Name (ARN) （例如 `arn:aws:sns:us-east-1:123456789012:aws-mp-subscription-notification-PRODUCTCODE`)。ARN 不適用於伺服器產品的賣方入口網站。請聯絡 [AWS Marketplace 操作團隊](https://aws.amazon.com/marketplace/management/contact-us)以請求 ARN。

下列 Amazon SNS 主題適用於容器產品：
+ [Amazon SNS 主題： `aws-mp-subscription-notification`](#container-sns-subscription-message-body) – 本主題會在買方訂閱或取消訂閱產品時通知您。這適用於每小時定價模型，包括長期每小時和每小時。

## Amazon SNS 主題： `aws-mp-subscription-notification`
<a name="container-sns-subscription-message-body"></a>

`aws-mp-subscription-notification` 主題中的每個訊息都有下列格式。

```
{
    "action": "<action-name>",
    "customer-identifier": " X01EXAMPLEX",
    "product-code": "n0123EXAMPLEXXXXXXXXXXXX",
    "offer-identifier": "offer-abcexample123"
}
```

*<action-name>* 會根據通知而有所不同。可能的動作包括：
+ `subscribe-success`
+ `subscribe-fail`
+ `unsubscribe-pending`
+ `unsubscribe-success`

只有在動作為 `subscribe-success`或 時， `offer-identifier`才會包含在通知中`subscribe-fail`。當動作為 `unsubscribe-pending`或 時，它不會包含在通知中`unsubscribe-success`。對於 2024 年 1 月之前建立的優惠，此識別符僅包含在私有優惠的通知中。對於 2024 年 1 月及更新版本建立的優惠，此識別符會包含在所有優惠的通知中，包括私有優惠和公有優惠。

如需優惠類型的資訊，請參閱 [DescribeEntity API](https://docs.aws.amazon.com//marketplace/latest/APIReference/work-with-private-offers.html#describe-entity) 的回應或協議[續約儀表板中的協議](https://docs.aws.amazon.com//marketplace/latest/userguide/agreements-renewals-dashboard.html)優惠可見性。

**注意**  
 對於 [DescribeEntity API](https://docs.aws.amazon.com//marketplace/latest/APIReference/work-with-private-offers.html#describe-entity)，如果您 AWS 帳戶 在以該優惠規則為目標的面向帳戶中找到 ，則這是私有優惠。如果 AWS 帳戶 帳戶中沒有以該優惠規則為目標的面向為目標的 ，則這是公開優惠。

## 訂閱 Amazon SQS 佇列至 Amazon SNS 主題
<a name="subscribing-sqs-queue-to-sns-topic"></a>

我們建議訂閱 Amazon SQS 佇列至提供的 SNS 主題。如需建立 SQS 佇列和訂閱主題佇列的詳細說明，請參閱《[Amazon Simple Notification Service 開發人員指南》中的訂閱 Amazon SQS 佇列至 Amazon SNS 主題](https://docs.aws.amazon.com/sns/latest/dg/subscribe-sqs-queue-to-sns-topic.html)。 **

**注意**  
您只能從 AWS 帳戶 用來銷售產品的 訂閱 AWS Marketplace SNS 主題。不過，您可以將訊息轉送到不同的 帳戶。如需詳細資訊，請參閱[《Amazon Simple Notification Service 開發人員指南》中的將 Amazon SNS 訊息傳送至不同帳戶中的 Amazon SQS 佇列](https://docs.aws.amazon.com/sns/latest/dg/sns-send-message-to-sqs-cross-account.html)。 **

### 輪詢 SQS 佇列以取得通知
<a name="polling-the-sqs-for-notifications"></a>

將 SQS 佇列訂閱 SNS 主題後，訊息會儲存在 SQS 中。您必須定義持續輪詢佇列、尋找訊息並相應地處理它們的服務。