如何針對將環境變數傳遞到 Amazon ECS 任務時的問題進行疑難排解?
上次更新日期:2022 年 4 月 14 日
我想要針對將環境變數傳遞到 Amazon Elastic Container Service (Amazon ECS) 任務時的問題進行疑難排解。
簡短描述
您可以通過以下方式之一在 Amazon ECS 任務內傳遞環境變數:
- 在 Amazon Simple Storage Service (Amazon S3) 儲存貯體內以 environmentFiles 物件的形式傳遞變數。
- 在 AWS Systems Manager Parameter Store 內存放變數。
- 在 ECS 任務定義中存放變數。
- 在 AWS Secrets Manager 內存放變數。
注意:為求安全,最佳實務是使用 Parameter Store 或 Secrets Manager 以環境變數的形式存放敏感資料。
通過上述方法之一來傳遞環境變數時,您可能會收到以下錯誤:
參數存放區:
Fetching secret data from SSM Parameter Store in region: AccessDeniedException: User: arn:aws:sts::123456789:assumed-role/ecsExecutionRole/f512996041234a63ac354214 is not authorized to perform: ssm:GetParameters on resource: arn:aws:ssm:ap-south-1:12345678:parameter/status code: 400, request id: e46b40ee-0a38-46da-aedd-05f23a41e861 (從區域中的 SSM 參數存放擷取密碼資料:AccessDeniedException:使用者:arn:aws:sts::123456789:assumed-role/ecsExecutionRole/f512996041234a63ac354214 沒有權限執行:ssm:GetParameters 於資源:arn:aws:ssm:ap-south-1:12345678:parameter/狀態代碼:400,要求 ID:e46b40ee-0a38-46da-aedd-05f23a41e861)
-或-
ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve secrets from ssm: service call has been retried 5 time(s): RequestCanceled (ResourceInitializationError:無法提取密碼或登錄檔授權:執行資源擷取失敗:無法從 SSM 擷取密碼:已重試 5 次服務呼叫:RequestCanceled)
Secrets Manager:
ResourceInitializationError error
-或-
Amazon Elastic Compute Cloud (Amazon EC2) 上出現 AccessDenied 錯誤
若要解決這些錯誤,請參閱如何對 Amazon ECS 中的 AWS Secrets Manager 機密相關問題進行疑難排解?
Amazon S3:
ResourceInitializationError: failed to download env files: file download command: non empty error stream (ResourceInitializationError:無法下載 env 檔案:檔案下載命令:非空白錯誤串流)
由於以下原因,當您將環境變數傳遞到 Amazon ECS 任務時,您可能會遇到問題:
- Amazon ECS 任務執行角色沒有所需的 AWS Identity and Management (IAM) 許可。
- 網路設定存在問題。
- 應用程式無法讀取環境變數。
- 容器定義中的變數格式不正確。
- 環境變數未自動重新整理。
解決方案
Amazon ECS 任務執行角色沒有所需的 IAM 許可
如果您在 Parameter Store 或 Secrets Manage 內使用環境變數,則請檢閱 AWS CloudTrail 事件中是否有以下任一 API 呼叫:
GetParameters (若為 Parameter Store)
-或-
GetSecretValue (若為 Secrets Manager)
如果您在 CloudTrail 事件中發現任務執行角色有 AccessDenied 錯誤,請以手動方式將所需許可以內嵌政策的形式新增到 ECS 任務執行 IAM 角色。您也可以建立客戶管理的政策,並將該政策新增到 ECS 任務執行角色。
如果您使用的是 Secrets Manager,請將以下許可納入到任務執行角色:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"kms:Decrypt"
],
"Resource": [
"arn:aws:secretsmanager:example-region:11112222333344445555:secret:example-secret",
"arn:aws:kms:example-region:1111222233334444:key/example-key-id"
]
}
]
}
如果您使用的是 Parameter Store,請將以下許可納入到任務執行角色:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameters",
"secretsmanager:GetSecretValue",
"kms:Decrypt"
],
"Resource": [
"arn:aws:ssm:example-region:1111222233334444:parameter/example-parameter",
"arn:aws:secretsmanager:example-region:1111222233334444:secret:example-secret",
"arn:aws:kms:example-region:1111222233334444:key/example-key-id"
]
}
]
}
若要使用 S3 儲存貯體來以 .env 檔案的形式存放環境變數,請以手動方式將以下許可以內嵌政策的形式新增到任務執行角色:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::example-bucket/example-folder/example-env-file"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::example-bucket"
]
}
]
}
網路設定存在問題
如果 ECS 任務位於私有子網路,請驗證以下事項:
- 確定任務或服務的安全群組在連接埠 443 上允許輸出流量。
- 如果您使用的是 VPC 端點,請確定網路 ACL 在連接埠 443 上允許輸出流量。
- 使用 telnet 命令來驗證能否與 Systems Manager/Secrets Manager 和 Amazon S3 端點建立連線。
- 如果您使用的是 NAT 閘道,請確定任務有通往 NAT 閘道的預設路由。
- 確定您已為任務定義 VPC 端點。如果已定義 VPC 端點,則請確定有 Secrets Manager/Systems Manager Parameter Store 和 S3 所需的 VPC 端點。
- 如果您使用的是 VPC 端點,請確定以下事項:
- VPC 端點的安全群組在連接埠 443 上允許來自任務或服務的輸出流量。
- VPC 端點與正確的 VPC 關聯。
- VPC 屬性 enableDnsHostnames 和 enableDnsSupport 已開啟。
如果 ECS 任務位於公有子網路,請驗證以下事項:
- 確定任務已啟用公有 IP 地址。
- 確定 VPC 的安全群組在連接埠 443 上具有對外存取網際網路的權限。
- 確定網路 ACL 組態允許所有流量在子網路與網際網路之間流動。
應用程式無法讀取環境變數
若要檢查任務容器內所填入的環境變數是否正確,請執行以下操作:
- 列出容器內公開的所有環境變數。
- 驗證此清單是否包含您在 S3 的任務定義或 .env 檔案中定義的環境變數。
如果您使用的是 Amazon EC2 或 AWS Fargate 啟動類型,則最佳實務是使用 ECS Exec 功能。您可以使用此功能在 Amazon EC2 執行個體或 Fargate 中執行命令,或將 Shell 放到在 Amazon EC2 執行個體或 Fargate 上執行的容器。在啟用此功能後,請執行以下命令來與容器互動。
aws ecs execute-command --cluster example-cluster \
--task example-task-id \
--container example-container \
--interactive \
--command "/bin/sh"
如果您使用的是 Amazon EC2 啟動類型,則也可以使用 Docker exec 命令來與容器互動。在這種情況下,請執行以下操作:
連線到任務執行所在的容器執行個體。然後,執行以下 Docker 命令以尋找任務容器的容器 ID。
docker container ps
執行以下命令來與容器互動:
docker exec -it example-container-id bash
注意:請根據容器的預設 Shell 來選取 Shell。
在與容器建立連線後,請於容器上執行 env 命令以取得完整的環境變數清單。檢閱此清單以確定您在任務定義或 .env 檔案中定義的環境變數是否存在。
容器定義中的變數格式不正確
在容器定義內定義環境變數時,請務必要將環境變數定義為 KeyValuePair 物件,類似以下內容:
"environment": [{
"name": "foo",
"value": "bar"
}]
在 .env 檔案中定義環境變數時,也請務必使用此格式。
環境變數未自動重新整理
在 .env 檔案中更新環境變數時,該變數不會在執行中的容器內自動重新整理。
若要在任務中注入更新後的環境變數值,請通過執行以下命令來更新服務:
aws ecs update-service --cluster example-cluster --service example-service --force-new-deployment
如果在容器定義中使用環境變數,則必須建立新的任務定義才能重新整理更新後的環境變數。使用這個新的任務定義時,您可以建立新的任務或更新 ECS 服務。
aws ecs update-service --cluster example-cluster --service example-service --task-definition <family:revision>
注意:
在將環境變數傳遞到任務時,請記住以下事項:
- 如果容器定義中有使用 environment 參數所指定的環境變數,則其優先順序會高於環境檔案內所包含的變數。
- 如果指定了多個環境檔案,且這些檔案包含相同的變數,則會以進入順序處理這些檔案。系統會使用變數的第一個值,並忽略重複變數的後續值。最佳實務是使用唯一的變數名稱。
- 如果將環境檔案指定為容器覆寫,則會使用該檔案。容器定義中所指定的任何其他環境檔案則會被忽略。
- 環境變數可用於檔案 /proc/1/environ 中容器內的 PID 1 程序。如果容器正在執行多個程序或 init 程序 (例如包裝函式指令碼、啟動指令碼或 supervisord),則環境變數無法供非 PID 1 程序使用。