

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

# 在 Amazon OpenSearch Service 中建置多租戶無伺服器架構
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service"></a>

*Tabby Ward 和 Nisha Gambhir，Amazon Web Services*

## 摘要
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-summary"></a>

Amazon OpenSearch Service 是一種受管服務，可讓您輕鬆部署、操作和擴展 Elasticsearch，這是熱門的開放原始碼搜尋和分析引擎。OpenSearch Service 提供任意文字搜尋，以及近乎即時的串流資料擷取和儀表板，例如日誌和指標。

軟體即服務 (SaaS) 供應商經常使用 OpenSearch Service 來處理各種使用案例，例如以可擴展且安全的方式獲得客戶洞見，同時降低複雜性和停機時間。

 在多租戶環境中使用 OpenSearch Service 引入了一系列的考量，會影響 SaaS 解決方案的分割、隔離、部署和管理。SaaS 提供者必須考慮如何使用不斷轉移的工作負載，有效地擴展其 Elasticsearch 叢集。他們還需要考慮分層和嘈雜的鄰國條件如何影響其分割模型。

此模式會檢閱用來代表和隔離具有 Elasticsearch 建構的租戶資料的模型。此外，模式著重於簡單的無伺服器參考架構作為範例，以示範 在多租戶環境中使用 OpenSearch Service 進行索引和搜尋。它會實作集區資料分割模型，在所有租用戶之間共用相同的索引，同時維持租用戶的資料隔離。此模式使用下列 AWS 服務：Amazon API Gateway AWS Lambda、Amazon Simple Storage Service (Amazon S3) 和 OpenSearch Service。

如需集區模型和其他資料分割模型的詳細資訊，請參閱[其他資訊](#build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-additional)一節。

## 先決條件和限制
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-prereqs"></a>

**先決條件**
+ 作用中 AWS 帳戶
+ [AWS Command Line Interface (AWS CLI) 2.x 版](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html)，在 macOS、Linux 或 Windows 上安裝和設定
+ [Python 3.9 版](https://www.python.org/downloads/release/python-3921/)
+ [pip3](https://pip.pypa.io/en/stable/) – Python 原始程式碼以要部署在 Lambda 函數中的 .zip 檔案提供。如果您想要在本機使用或自訂程式碼，請依照下列步驟開發和重新編譯原始程式碼：

  1. 在與 Python 指令碼相同的目錄中執行下列命令來產生 `requirements.txt` 檔案： `pip3 freeze > requirements.txt`

  1. 安裝相依性： `pip3 install -r requirements.txt`

**限制**
+ 此程式碼以 Python 執行，目前不支援其他程式設計語言。 
+ 範例應用程式不包含 AWS 跨區域或災難復原 (DR) 支援。 
+ 此模式僅供示範之用。它不適用於生產環境。

## Architecture
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-architecture"></a>

下圖說明此模式的高階架構。架構包含下列項目：
+ Lambda 索引和查詢內容 
+ OpenSearch Service 執行搜尋 
+ API Gateway 提供與 使用者的 API 互動
+ Amazon S3 存放原始 （非索引） 資料
+ Amazon CloudWatch 監控日誌
+ AWS Identity and Access Management (IAM) 以建立租戶角色和政策

![高階多租戶無伺服器架構。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/1a8501e7-0776-4aca-aed3-28e3ada1d15d.png)


**自動化和擴展**

為了簡化，模式會使用 AWS CLI 來佈建基礎設施和部署範例程式碼。您可以建立 CloudFormation 範本或 AWS Cloud Development Kit (AWS CDK) 指令碼來自動化模式。

## 工具
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-tools"></a>

**AWS 服務**
+ [AWS CLI](https://aws.amazon.com/cli/) 是統一的工具，可讓您在命令列 Shell 中使用命令來管理 AWS 服務 和資源。
+ [Lambda](https://aws.amazon.com/lambda/) 是一種運算服務，可讓您執行程式碼，而無需佈建或管理伺服器。Lambda 只有在需要時才會執行程式碼，可自動從每天數項請求擴展成每秒數千項請求。
+ [API Gateway](https://aws.amazon.com/api-gateway/) 是 ， AWS 服務 用於建立、發佈、維護、監控和保護任何規模的 REST、HTTP 和 WebSocket APIs。
+ [Amazon S3](https://aws.amazon.com/s3/) 是一種物件儲存服務，可讓您隨時從 Web 上的任何位置存放和擷取任意數量的資訊。
+ [OpenSearch Service](https://aws.amazon.com/opensearch-service/) 是一項全受管服務，可讓您以經濟實惠的方式大規模部署、保護和執行 Elasticsearch。

**Code**

附件提供此模式的範例檔案。其中包含：
+ `index_lambda_package.zip` – 使用集區模型為 OpenSearch Service 中的資料編製索引的 Lambda 函數。
+ `search_lambda_package.zip` – 在 OpenSearch Service 中搜尋資料的 Lambda 函數。
+ `Tenant-1-data` – Tenant-1 的原始 （非索引） 資料範例。
+ `Tenant-2-data` – Tenant-2 的原始 （非索引） 資料範例。

**重要**  
此模式中的故事包括針對 Unix、Linux 和 macOS 格式化的 AWS CLI 命令範例。用於 Windows 時，請以插入號 (^) 取代每一行結尾處的 Unix 接續字元斜線 (\\)。

**注意**  
在 AWS CLI 命令中，將角括號 (<>) 內的所有值取代為正確的值。

## 史詩
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-epics"></a>

### 建立和設定 S3 儲存貯體
<a name="create-and-configure-an-s3-bucket"></a>


| 任務 | 說明 | 所需的技能 | 
| --- | --- | --- | 
| 建立 S3 儲存貯體。 | 在 中建立 S3 儲存貯體 AWS 區域。此儲存貯體會保留範例應用程式的非索引租用戶資料。請確定 S3 儲存貯體的名稱是全域唯一的，因為命名空間是由所有 共用 AWS 帳戶。<br />若要建立 S3 儲存貯體，您可以使用 AWS CLI [create-bucket](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/create-bucket.html) 命令，如下所示：<pre>aws s3api create-bucket \<br />  --bucket <tenantrawdata> \<br />  --region <your-AWS-Region></pre><br />其中 `tenantrawdata`是 S3 儲存貯體名稱。（您可以使用遵循儲存[貯體命名準則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)的任何唯一名稱。) | 雲端架構師、雲端管理員 | 

### 建立和設定 Elasticsearch 叢集
<a name="create-and-configure-an-elasticsearch-cluster"></a>


| 任務 | 說明 | 所需的技能 | 
| --- | --- | --- | 
| 建立 OpenSearch Service 網域 | 執行 AWS CLI [create-elasticsearch-domain](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/es/create-elasticsearch-domain.html) 命令來建立 OpenSearch Service 網域：<pre>aws es create-elasticsearch-domain \<br />  --domain-name vpc-cli-example \<br />  --elasticsearch-version 7.10 \<br />  --elasticsearch-cluster-config InstanceType=t3.medium.elasticsearch,InstanceCount=1 \<br />  --ebs-options EBSEnabled=true,VolumeType=gp2,VolumeSize=10 \<br />  --domain-endpoint-options "{\"EnforceHTTPS\": true}" \<br />  --encryption-at-rest-options "{\"Enabled\": true}" \<br />  --node-to-node-encryption-options "{\"Enabled\": true}" \<br />  --advanced-security-options "{\"Enabled\": true, \"InternalUserDatabaseEnabled\": true, \<br />    \"MasterUserOptions\": {\"MasterUserName\": \"KibanaUser\", \<br />    \"MasterUserPassword\": \"NewKibanaPassword@123\"}}" \<br />  --vpc-options "{\"SubnetIds\": [\"<subnet-id>\"], \"SecurityGroupIds\": [\"<sg-id>\"]}" \<br />  --access-policies "{\"Version\": \"2012-10-17\", \"Statement\": [ { \"Effect\": \"Allow\", \ <br />    \"Principal\": {\"AWS\": \"*\" }, \"Action\":\"es:*\", \<br />    \"Resource\": \"arn:aws:es:<region>:<account-id>:domain\/vpc-cli-example\/*\" } ] }"</pre><br />執行個體計數設定為 1，因為網域用於測試目的。您需要使用 `advanced-security-options` 參數啟用精細存取控制，因為在建立網域之後無法變更詳細資訊。 <br />此命令會建立主要使用者名稱 (`KibanaUser`) 和密碼，您可用來登入 Kibana 主控台。<br />由於網域是虛擬私有雲端 (VPC) 的一部分，因此您必須指定要使用的存取政策，以確保可以連接 Elasticsearch 執行個體。<br />如需詳細資訊，請參閱 AWS 文件中的在 [VPC 內啟動 Amazon OpenSearch Service 網域](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html)。 | 雲端架構師、雲端管理員 | 
| 設定堡壘主機。 | 將 Amazon Elastic Compute Cloud (Amazon EC2) Windows 執行個體設定為堡壘主機，以存取 Kibana 主控台。Elasticsearch 安全群組必須允許來自 Amazon EC2 安全群組的流量。如需說明，請參閱部落格文章[使用堡壘伺服器控制 EC2 執行個體的網路存取](https://aws.amazon.com/blogs/security/controlling-network-access-to-ec2-instances-using-a-bastion-server/)。<br />當堡壘主機已設定，且您有與執行個體相關聯的安全群組可用時，請使用 AWS CLI [authorize-security-group-ingress](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/authorize-security-group-ingress.html) 命令將許可新增至 Elasticsearch 安全群組，以允許來自 Amazon EC2 （堡壘主機） 安全群組的連接埠 443。<pre>aws ec2 authorize-security-group-ingress \<br />  --group-id <SecurityGroupIdfElasticSearch> \ <br />  --protocol tcp \<br />  --port 443 \<br />  --source-group <SecurityGroupIdfBashionHostEC2></pre> | 雲端架構師、雲端管理員 | 

### 建立和設定 Lambda 索引函數
<a name="create-and-configure-the-lam-index-function"></a>


| 任務 | 說明 | 所需的技能 | 
| --- | --- | --- | 
| 建立 Lambda 執行角色。 | 執行 AWS CLI [createe-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) 命令，以授予 Lambda 索引函數對 AWS 服務 和 資源的存取權：<pre>aws iam create-role \<br />  --role-name index-lambda-role \<br />  --assume-role-policy-document file://lambda_assume_role.json</pre><br />其中 `lambda_assume_role.json`是將`AssumeRole`許可授予 Lambda 函數的 JSON 文件，如下所示：<pre>{<br />     "Version": "2012-10-17",		 	 	 <br />     "Statement": [<br />         {<br />             "Effect": "Allow",<br />             "Principal": {<br />                 "Service": "lambda.amazonaws.com"<br />               },<br />             "Action": "sts:AssumeRole"<br />         }<br />     ]<br /> }</pre> | 雲端架構師、雲端管理員 | 
| 將受管政策連接至 Lambda 角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將受管政策連接至上一個步驟中建立的角色。這兩個政策提供角色建立彈性網路介面和將日誌寫入 CloudWatch Logs 的許可。<pre>aws iam attach-role-policy \<br />  --role-name index-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole<br /><br />aws iam attach-role-policy \<br />  --role-name index-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole </pre> | 雲端架構師、雲端管理員 | 
| 建立政策以授予 Lambda 索引函數讀取 S3 物件的許可。 | 對 執行 AWS CLI [createe-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) 命令，授予 Lambda 索引函數讀取 S3 儲存貯體中物件的`s3:GetObject`許可：<pre>aws iam create-policy \<br />  --policy-name s3-permission-policy \<br />  --policy-document file://s3-policy.json</pre><br />檔案`s3-policy.json`是如下所示的 JSON 文件，授予`s3:GetObject`許可以允許對 S3 物件的讀取存取。如果您在建立 S3 儲存貯體時使用不同的名稱，請在 `Resource `區段中提供正確的儲存貯體名稱：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />           "Effect": "Allow",<br />           "Action": "s3:GetObject",<br />           "Resource": "arn:aws:s3:::<tenantrawdata>/*"<br />        }<br />    ]<br />}</pre> | 雲端架構師、雲端管理員 | 
| 將 Amazon S3 許可政策連接至 Lambda 執行角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將您在上一個步驟中建立的 Amazon S3 許可政策連接至 Lambda 執行角色：<pre>aws iam attach-role-policy \<br />  --role-name index-lambda-role \<br />  --policy-arn <PolicyARN></pre><br />其中 `PolicyARN`是 Amazon S3 許可政策的 Amazon Resource Name (ARN)。您可以從上一個命令的輸出取得此值。 | 雲端架構師、雲端管理員 | 
| 建立 Lambda 索引函數。 | 執行 AWS CLI [createe-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) 命令來建立 Lambda 索引函數，這會存取 OpenSearch Service：<pre>aws lambda create-function \<br />  --function-name index-lambda-function \<br />  --zip-file fileb://index_lambda_package.zip \<br />  --handler lambda_index.lambda_handler \<br />  --runtime python3.9 \<br />  --role "arn:aws:iam::account-id:role/index-lambda-role" \<br />  --timeout 30 \<br />  --vpc-config "{\"SubnetIds\": [\"<subnet-id1\>", \"<subnet-id2>\"], \<br />    \"SecurityGroupIds\": [\"<sg-1>\"]}"</pre> | 雲端架構師、雲端管理員 | 
| 允許 Amazon S3 呼叫 Lambda 索引函數。 | 執行 AWS CLI [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html) 命令，為 Amazon S3 提供呼叫 Lambda 索引函數的許可：<pre>aws lambda add-permission \<br />  --function-name index-lambda-function \<br />  --statement-id s3-permissions \<br />  --action lambda:InvokeFunction \<br />  --principal s3.amazonaws.com \<br />  --source-arn "arn:aws:s3:::<tenantrawdata>" \<br />  --source-account "<account-id>" </pre> | 雲端架構師、雲端管理員 | 
| 為 Amazon S3 事件新增 Lambda 觸發條件。 | 執行 AWS CLI [put-bucket-notification-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-notification-configuration.html) 命令，以在偵測到 Amazon S3 `ObjectCreated`事件時傳送 通知至 Lambda 索引函數。索引函數會在物件上傳到 S3 儲存貯體時執行。 <pre>aws s3api put-bucket-notification-configuration \<br />  --bucket <tenantrawdata> \<br />  --notification-configuration file://s3-trigger.json</pre><br />檔案`s3-trigger.json`是目前資料夾中的 JSON 文件，會在 Amazon S3 `ObjectCreated`事件發生時將資源政策新增至 Lambda 函數。 | 雲端架構師、雲端管理員 | 

### 建立和設定 Lambda 搜尋函數
<a name="create-and-configure-the-lam-search-function"></a>


| 任務 | 說明 | 所需的技能 | 
| --- | --- | --- | 
| 建立 Lambda 執行角色。 | 執行 AWS CLI [createe-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) 命令，授予 Lambda 搜尋函數對 AWS 服務 和 資源的存取權：<pre>aws iam create-role \<br />  --role-name search-lambda-role \<br />  --assume-role-policy-document file://lambda_assume_role.json</pre><br />其中 `lambda_assume_role.json` 是目前資料夾中的 JSON 文件，授予 Lambda 函數`AssumeRole`許可，如下所示：<pre>{<br />     "Version": "2012-10-17",		 	 	 <br />     "Statement": [<br />         {<br />             "Effect": "Allow",<br />             "Principal": {<br />                 "Service": "lambda.amazonaws.com"<br />               },<br />             "Action": "sts:AssumeRole"<br />         }<br />     ]<br /> }</pre> | 雲端架構師、雲端管理員 | 
| 將受管政策連接至 Lambda 角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將受管政策連接至上一個步驟中建立的角色。這兩個政策提供角色建立彈性網路介面和將日誌寫入 CloudWatch Logs 的許可。<pre>aws iam attach-role-policy \<br />  --role-name search-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole<br /><br />aws iam attach-role-policy \<br />  --role-name search-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole </pre> | 雲端架構師、雲端管理員 | 
| 建立 Lambda 搜尋函數。 | 執行 AWS CLI [createe-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) 命令來建立 Lambda 搜尋函數，這會存取 OpenSearch Service：<pre>aws lambda create-function \<br />  --function-name search-lambda-function \<br />  --zip-file fileb://search_lambda_package.zip \<br />  --handler lambda_search.lambda_handler \<br />  --runtime python3.9 \<br />  --role "arn:aws:iam::account-id:role/search-lambda-role" \<br />  --timeout 30 \<br />  --vpc-config "{\"SubnetIds\": [\"<subnet-id1\>", \"<subnet-id2>\"], \<br />    \"SecurityGroupIds\": [\"<sg-1>\"]}"</pre> | 雲端架構師、雲端管理員 | 

### 建立和設定租戶角色
<a name="create-and-configure-tenant-roles"></a>


| 任務 | 說明 | 所需的技能 | 
| --- | --- | --- | 
| 建立租戶 IAM 角色。 | 執行 the AWS CLI [create-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) 命令來建立兩個租戶角色，用於測試搜尋功能：<pre>aws iam create-role \<br />  --role-name Tenant-1-role \<br />  --assume-role-policy-document file://assume-role-policy.json</pre><pre>aws iam create-role \<br />  --role-name Tenant-2-role \<br />  --assume-role-policy-document file://assume-role-policy.json</pre><br />檔案`assume-role-policy.json`是目前資料夾中的 JSON 文件，可將`AssumeRole`許可授予 Lambda 執行角色：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Principal": {<br />                 "AWS": "<Lambda execution role for index function>",<br />                 "AWS": "<Lambda execution role for search function>"<br />             },<br />            "Action": "sts:AssumeRole"<br />        }<br />    ]<br />}</pre> | 雲端架構師、雲端管理員 | 
| 建立租戶 IAM 政策。 | 執行 AWS CLI [createe-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) 命令來建立租用戶政策，以授予對 Elasticsearch 操作的存取權：<pre>aws iam create-policy \<br />  --policy-name tenant-policy \<br />  --policy-document file://policy.json</pre><br />檔案`policy.json`是目前資料夾中的 JSON 文件，可授予 Elasticsearch 的許可：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Action": [<br />                "es:ESHttpDelete",<br />                "es:ESHttpGet",<br />                "es:ESHttpHead",<br />                "es:ESHttpPost",<br />                "es:ESHttpPut",<br />                "es:ESHttpPatch"<br />            ],<br />            "Resource": [<br />                "<ARN of Elasticsearch domain created earlier>"<br />            ]<br />        }<br />    ]<br />}</pre> | 雲端架構師、雲端管理員 | 
| 將租戶 IAM 政策連接至租戶角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將租用戶 IAM 政策連接至您在先前步驟中建立的兩個租用戶角色：<pre>aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/tenant-policy \<br />  --role-name Tenant-1-role<br /><br />aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/tenant-policy \<br />  --role-name Tenant-2-role</pre><br />政策 ARN 來自上一個步驟的輸出。 | 雲端架構師、雲端管理員 | 
| 建立 IAM 政策，授予 Lambda 擔任角色的許可。 | 執行 the AWS CLI [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) 命令，為 Lambda 建立政策以擔任租戶角色：<pre>aws iam create-policy \<br />  --policy-name assume-tenant-role-policy \<br />  --policy-document file://lambda_policy.json</pre><br />檔案`lambda_policy.json`是目前資料夾中的 JSON 文件，授予 許可`AssumeRole`：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />       {<br />            "Effect": "Allow",<br />            "Action":  "sts:AssumeRole",<br />            "Resource": "<ARN of tenant role created earlier>"<br />       }<br />    ]<br />}</pre><br />對於 `Resource`，您可以使用萬用字元來避免為每個租用戶建立新的政策。 | 雲端架構師、雲端管理員 | 
| 建立 IAM 政策，以授予 Lambda 索引角色存取 Amazon S3 的許可。 | 執行 the AWS CLI [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) 命令，授予 Lambda 索引角色存取 S3 儲存貯體中物件的許可：<pre>aws iam create-policy \<br />  --policy-name s3-permission-policy \<br />  --policy-document file://s3_lambda_policy.json</pre><br />檔案`s3_lambda_policy.json`是目前資料夾中的下列 JSON 政策文件：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Action": "s3:GetObject",<br />            "Resource": "arn:aws:s3:::tenantrawdata/*"<br />        }<br />    ]<br />}</pre> | 雲端架構師、雲端管理員 | 
| 將政策連接至 Lambda 執行角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將上一個步驟中建立的政策連接至您先前建立的 Lambda 索引和搜尋執行角色：<pre>aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/assume-tenant-role-policy \<br />  --role-name index-lambda-role<br /><br />aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/assume-tenant-role-policy \<br />  --role-name search-lambda-role<br /><br />aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/s3-permission-policy \<br />  --role-name index-lambda-role</pre><br />政策 ARN 來自上一個步驟的輸出。 | 雲端架構師、雲端管理員 | 

### 建立和設定搜尋 API
<a name="create-and-configure-a-search-api"></a>


| 任務 | 說明 | 所需的技能 | 
| --- | --- | --- | 
| 在 API Gateway 中建立 REST API。 | 執行 AWS CLI [create-rest-api](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/create-rest-api.html) 命令來建立 REST API 資源：<pre>aws apigateway create-rest-api \<br />  --name Test-Api \<br />  --endpoint-configuration "{ \"types\": [\"REGIONAL\"] }"</pre><br />對於端點組態類型，您可以指定 `EDGE`，而不是`REGIONAL`使用節點，而不是特定節點 AWS 區域。<br />請注意命令輸出中 `id` 欄位的值。這是您將在後續命令中使用的 API ID。 | 雲端架構師、雲端管理員 | 
| 建立搜尋 API 的資源。 | 搜尋 API 資源會以資源名稱 啟動 Lambda 搜尋函數`search`。（您不需要為 Lambda 索引函數建立 API，因為它會在物件上傳至 S3 儲存貯體時自動執行。)[See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html) | 雲端架構師、雲端管理員 | 
| 建立搜尋 API 的 GET 方法。 | 執行 AWS CLI [put-method](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/put-method.html) 命令來建立搜尋 API `GET `的方法：<pre>aws apigateway put-method \<br />  --rest-api-id <API-ID> \<br />  --resource-id <ID from the previous command output> \<br />  --http-method GET \<br />  --authorization-type "NONE" \<br />  --no-api-key-required</pre><br />針對 `resource-id`，指定來自 `create-resource`命令輸出的 ID。 | 雲端架構師、雲端管理員 | 
| 建立搜尋 API 的方法回應。 | 執行 AWS CLI [put-method-response](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/put-method-response.html) 命令，為搜尋 API 新增方法回應：<pre>aws apigateway put-method-response \<br />  --rest-api-id <API-ID> \<br />  --resource-id  <ID from the create-resource command output> \<br />  --http-method GET \<br />  --status-code 200 \<br />  --response-models "{\"application/json\": \"Empty\"}"</pre><br />針對 `resource-id`，指定先前`create-resource`命令輸出的 ID。 | 雲端架構師、雲端管理員 | 
| 設定搜尋 API 的代理 Lambda 整合。 | 執行 AWS CLI [put-integration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/put-integration.html) 命令來設定與 Lambda 搜尋函數的整合：<pre>aws apigateway put-integration \<br />  --rest-api-id <API-ID> \<br />  --resource-id  <ID from the create-resource command output> \<br />  --http-method GET \<br />  --type AWS_PROXY \<br />  --integration-http-method GET \<br />  --uri arn:aws:apigateway:region:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account-id>:function:<function-name>/invocations</pre><br />針對 `resource-id`，指定先前`create-resource`命令的 ID。 | 雲端架構師、雲端管理員 | 
| 授予 API Gateway 呼叫 Lambda 搜尋函數的許可。 | 執行 AWS CLI [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html) 命令，給予 API Gateway 使用搜尋函數的許可：<pre>aws lambda add-permission \<br />  --function-name <function-name> \<br />  --statement-id apigateway-get \<br />  --action lambda:InvokeFunction \<br />  --principal apigateway.amazonaws.com \<br />  --source-arn "arn:aws:execute-api:<region>:<account-id>:api-id/*/GET/search</pre><br />如果您使用不同的 API 資源名稱而非 ，請變更`source-arn`路徑`search`。 | 雲端架構師、雲端管理員 | 
| 部署搜尋 API。 | 執行 the AWS CLI [create-deployment](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/create-deployment.html) 命令來建立名為 的階段資源`dev`：<pre>aws apigateway create-deployment \<br />  --rest-api-id <API-ID> \<br />  --stage-name dev</pre><br />如果您更新 API，您可以使用相同的 AWS CLI 命令將其重新部署到相同的階段。 | 雲端架構師、雲端管理員 | 

### 建立和設定 Kibana 角色
<a name="create-and-configure-kibana-roles"></a>


| 任務 | 說明 | 所需的技能 | 
| --- | --- | --- | 
| 登入 Kibana 主控台。 | [See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html) | 雲端架構師、雲端管理員 | 
| 建立和設定 Kibana 角色。 | 若要提供資料隔離並確保一個租用戶無法擷取另一個租用戶的資料，您需要使用文件安全，這允許租用戶僅存取包含其租用戶 ID 的文件。[See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html) | 雲端架構師、雲端管理員 | 
| 將使用者映射至角色。 | [See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html)我們建議您在租戶加入時自動建立租戶和 Kibana 角色。 | 雲端架構師、雲端管理員 | 
| 建立租用戶資料索引。 | 在導覽窗格的**管理**下，選擇**開發工具**，然後執行下列命令。此命令會建立`tenant-data`索引來定義 `TenantId` 屬性的映射。<pre>PUT /tenant-data<br />{<br />  "mappings": {<br />    "properties": {<br />      "TenantId": { "type": "keyword"}<br />    }<br />  }<br />}</pre> | 雲端架構師、雲端管理員 | 

### 為 Amazon S3 和 建立 VPC 端點 AWS STS
<a name="create-vpc-endpoints-for-s3-and-sts"></a>


| 任務 | 說明 | 所需的技能 | 
| --- | --- | --- | 
| 建立 Amazon S3 的 VPC 端點。 | 執行 AWS CLI [create-vpc-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/create-vpc-endpoint.html) 命令，為 Amazon S3 建立 VPC 端點。端點可讓 VPC 中的 Lambda 索引函數存取 Amazon S3。<pre>aws ec2 create-vpc-endpoint \<br />  --vpc-id <VPC-ID> \<br />  --service-name com.amazonaws.us-east-1.s3 \<br />  --route-table-ids <route-table-ID></pre><br />針對 `vpc-id`，指定您用於 Lambda 索引函數的 VPC。對於 `service-name`，請使用 Amazon S3 端點的正確 URL。針對 `route-table-ids`，指定與 VPC 端點相關聯的路由表。 | 雲端架構師、雲端管理員 | 
| 為 建立 VPC 端點 AWS STS。 | 執行 AWS CLI [create-vpc-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/create-vpc-endpoint.html) 命令來建立 AWS Security Token Service () 的 VPC 端點AWS STS。端點可讓 VPC 中的 Lambda 索引和搜尋函數存取 AWS STS。函數在擔任 IAM 角色 AWS STS 時使用。<pre>aws ec2 create-vpc-endpoint \<br />  --vpc-id <VPC-ID> \<br />  --vpc-endpoint-type Interface \<br />  --service-name com.amazonaws.us-east-1.sts \<br />  --subnet-id <subnet-ID> \<br />  --security-group-id <security-group-ID></pre><br />針對 `vpc-id`，指定您用於 Lambda 索引和搜尋函數的 VPC。針對 `subnet-id`，提供應建立此端點的子網路。針對 `security-group-id`，指定要與此端點建立關聯的安全群組。（它可以與 Lambda 使用的安全群組相同。) | 雲端架構師、雲端管理員 | 

### 測試多租戶和資料隔離
<a name="test-multi-tenancy-and-data-isolation"></a>


| 任務 | 說明 | 所需的技能 | 
| --- | --- | --- | 
| 更新索引和搜尋函數的 Python 檔案。 | [See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html)您可以從 OpenSearch Service 主控台的**概觀 **索引標籤取得 Elasticsearch 端點。 OpenSearch 其格式為 `<AWS-Region>.es.amazonaws.com`。 | 雲端架構師、應用程式開發人員 | 
| 更新 Lambda 程式碼。 | 使用 AWS CLI [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令，使用您對 Python 檔案所做的變更來更新 Lambda 程式碼：<pre>aws lambda update-function-code \<br />  --function-name index-lambda-function \<br />  --zip-file fileb://index_lambda_package.zip<br /><br />aws lambda update-function-code \<br />  --function-name search-lambda-function \<br />  --zip-file fileb://search_lambda_package.zip</pre> | 雲端架構師、應用程式開發人員 | 
| 將原始資料上傳至 S3 儲存貯體。 | 使用 the AWS CLI [cp](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/cp.html) 命令將Tenant-1 和Tenant-2 物件的資料上傳至儲存`tenantrawdata`貯體 （指定您為此目的建立的 S3 儲存貯體名稱）：<pre>aws s3 cp tenant-1-data s3://tenantrawdata<br />aws s3 cp tenant-2-data s3://tenantrawdata</pre><br />S3 儲存貯體設定為在上傳資料時執行 Lambda 索引函數，以便在 Elasticsearch 中編製文件索引。 | 雲端架構師、雲端管理員 | 
| 從 Kibana 主控台搜尋資料。 | 在 Kibana 主控台上執行下列查詢：<pre>GET tenant-data/_search</pre><br />此查詢會顯示在 Elasticsearch 中編製索引的所有文件。在此情況下，您應該會看到Tenant-1 和Tenant-2 的兩份個別文件。 | 雲端架構師、雲端管理員 | 
| 從 API Gateway 測試搜尋 API。 | [See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html)如需畫面圖例，請參閱[其他資訊](#build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-additional)一節。 | 雲端架構師、應用程式開發人員 | 
| 清除資源。 | 清除您建立的所有資源，以防止您的 帳戶產生額外費用。 | AWS DevOps、雲端架構師、雲端管理員 | 

## 相關資源
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-resources"></a>
+ [適用於 Python (Boto) 的 AWS SDK](https://aws.amazon.com/sdk-for-python/)
+ [AWS Lambda 文件](https://docs.aws.amazon.com/lambda/)
+ [API Gateway 文件](https://docs.aws.amazon.com/apigateway/)
+ [Amazon S3 文件](https://docs.aws.amazon.com/s3/)
+ [Amazon OpenSearch Service 文件](https://docs.aws.amazon.com/elasticsearch-service/)
  + [Amazon OpenSearch Service 中的精細存取控制](https://docs.amazonaws.cn/en_us/elasticsearch-service/latest/developerguide/fgac.html)
  + [使用 Amazon OpenSearch Service 建立搜尋應用程式](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/search-example.html)
  + [在 VPC 中啟動 Amazon OpenSearch Service 網域](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html)

## 其他資訊
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-additional"></a>

**資料分割模型**

多租戶系統中使用三種常見的資料分割模型：孤立、集區和混合。您選擇的模型取決於您環境的合規、雜訊鄰近、操作和隔離需求。

*Silo 模型*

在孤島模型中，每個租用戶的資料會存放在不同的儲存區域中，其中不會混合租用戶資料。您可以使用兩種方法來使用 OpenSearch Service 實作孤立模型：每個租用戶的網域和每個租用戶的索引。
+ **每個租用戶的網域** – 您可以為每個租用戶使用單獨的 OpenSearch Service 網域 （與 Elasticsearch 叢集同義）。將每個租用戶放置在自己的網域中，可提供與在獨立建構中擁有資料相關聯的所有優點。不過，這種方法帶來了管理和敏捷性的挑戰。其分散式性質使彙整和評估租戶的運作狀態和活動更加困難。這是一個昂貴的選項，要求每個 OpenSearch Service 網域至少擁有三個主節點和兩個資料節點供生產工作負載使用。

![多租戶無伺服器架構的每個租戶的網域孤島模型。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/c2195f82-e5ed-40bb-b76a-3b0210bf1254.png)


 
+ **每個租用戶的索引** – 您可以將租用戶資料放在 OpenSearch Service 叢集中的個別索引中。透過此方法，您可以在建立和命名索引時使用租用戶識別符，方法是在索引名稱前面加上租用戶識別符。每個租用戶的索引方法可協助您實現孤立目標，而無需為每個租用戶引入完全獨立的叢集。不過，如果索引數量增加，您可能會遇到記憶體壓力，因為這種方法需要更多的碎片，主節點必須處理更多的配置和重新平衡。

![多租用戶無伺服器架構的每個租用戶孤島模型索引。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/354a9463-25bb-422b-84de-d4875a7c8ea2.png)


 

**孤立模型中的隔離** – 在孤立模型中，您可以使用 IAM 政策來隔離存放每個租戶資料的網域或索引。這些政策可防止一個租用戶存取另一個租用戶的資料。若要實作孤立隔離模型，您可以建立以資源為基礎的政策，以控制對租戶資源的存取。這通常是網域存取政策，指定委託人可以在網域的子資源上執行哪些動作，包括 Elasticsearch 索引和 APIs。透過 IAM 身分型政策，您可以在 OpenSearch Service 中的網域、索引或 APIs上指定*允許**或拒絕*的動作。IAM 政策的`Action` 元素說明政策允許或拒絕的特定動作，而 `Principal `元素指定受影響的帳戶、使用者或角色。

下列範例政策僅授予Tenant-1 對`tenant-1`網域上子資源的完整存取權 （如 所指定`es:*`)。`Resource` 元素`/*`中的結尾表示此政策適用於網域的子資源，而非網域本身。當此政策生效時，租用戶不得在現有網域上建立新網域或修改設定。

```
{
   "Version": "2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::<aws-account-id>:user/Tenant-1"
         },
         "Action": "es:*",
         "Resource": "arn:aws:es:<Region>:<account-id>:domain/tenant-1/*"
      }
   ]
}
```

若要實作每個索引孤島模型的租用戶，您需要修改此範例政策，透過指定索引名稱，進一步將Tenant-1 限制為指定的索引或索引。下列範例政策會將Tenant-1 限制為`tenant-index-1`索引。 

```
{
   "Version": "2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::123456789012:user/Tenant-1"
         },
         "Action": "es:*",
         "Resource": "arn:aws:es:<Region>:<account-id>:domain/test-domain/tenant-index-1/*"
      }
   ]
}
```

*集區模型*

在集區模型中，所有租用戶資料都會存放在相同網域內的索引中。租用戶識別符包含在資料 （文件） 中，並用作分割區索引鍵，因此您可以判斷哪些資料屬於哪個租用戶。此模型可減少管理開銷。操作和管理集區索引比管理多個索引更簡單且更有效率。不過，由於租戶資料在相同的索引中混合，您會失去孤立模型提供的自然租戶隔離。這種方法也可能會因為雜訊鄰近效果而降低效能。

![多租戶無伺服器架構的集區模型。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/c2c3bb0f-6ccd-47a7-ab67-e7f3f8c7f289.png)


 

**集區模型中的租戶隔離** – 一般而言，在集區模型中實作租戶隔離具有挑戰性。與孤立模型搭配使用的 IAM 機制不允許您根據存放在文件中的租用戶 ID 來描述隔離。

另一種方法是使用 Open Distro for Elasticsearch 提供的[精細存取控制](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/fgac.html) (FGAC) 支援。FGAC 可讓您在索引、文件或欄位層級控制許可。在每個請求中，FGAC 會評估使用者登入資料，並對使用者進行身分驗證或拒絕存取。如果 FGAC 驗證使用者，它會擷取對應至該使用者的所有角色，並使用完整的許可集來判斷如何處理請求。 

若要在集區模型中實現所需的隔離，您可以使用[文件層級安全性](https://opendistro.github.io/for-elasticsearch-docs/docs/security/access-control/document-level-security/)，這可讓您將角色限制為索引中的文件子集。下列範例角色會將查詢限制為Tenant-1。透過將此角色套用至Tenant-1，您可以實現必要的隔離。 

```
{
   "bool": {
     "must": {
       "match": {
         "tenantId": "Tenant-1"
       }
     }
   }
 }
```

*混合模型*

混合模型在相同環境中 使用孤立和集區模型的 組合，為每個租用戶層 （例如免費、標準和高級層） 提供獨特的體驗。每個層遵循與集區模型中使用的相同安全性描述檔。

 

![適用於多租戶無伺服器架構的混合模型。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/e7def98a-38ef-435a-9881-7e95ae4d4940.png)


**混合模型中的租用戶隔離** – 在混合模型中，您遵循與集區模型相同的安全性設定檔，其中在文件層級使用 FGAC 安全模型提供租用戶隔離。雖然此策略簡化了叢集管理並提供敏捷性，但它會使架構的其他層面複雜化。例如，您的程式碼需要額外的複雜性，才能判斷哪個模型與每個租用戶相關聯。您也必須確保單一租用戶查詢不會讓整個網域飽和，並降低其他租用戶的體驗。 

**在 API Gateway 中測試**

*Tenant-1 查詢的測試時段*

![Tenant-1 查詢的測試時段。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/a6757d3f-977a-4ecc-90cb-83ab7f1c3588.png)


*Tenant-2 查詢的測試時段*

 

![Tenant-2 查詢的測試時段。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/31bfd656-33ca-4750-b6e6-da4d703c2071.png)


## 附件
<a name="attachments-750196bb-03f6-4b6e-92cd-eb7141602547"></a>

若要存取與本文件相關聯的其他內容，請下載並解壓縮下列檔案： [attachment.zip](samples/p-attach/750196bb-03f6-4b6e-92cd-eb7141602547/attachments/attachment.zip)