Skip to content

AWS ECS Fargate ResourceInitializationError: プライベートレジストリ認証エラーの解決方法

AWS ECS Fargate でプライベートリポジトリを使用する際に、「ResourceInitializationError: unable to pull secrets or registry auth」エラーが発生する問題とその解決方法について解説します。

問題の概要

ECS Fargate platform version 1.4.0 以降で、プライベートコンテナリポジトリの認証やシークレットの取得に失敗し、以下のエラーが発生します:

ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to get registry auth from asm: service call has been retried 1 time(s): asm fetching secret from the service for <secretname>: RequestError: ...

このエラーは、ECSタスクがAWS Secrets ManagerやECRへのアクセスに必要なネットワーク接続を確立できない場合に発生します。

根本原因

AWS従業員の回答によると、この問題はFargate platform version 1.3.0から1.4.0への変更に起因しています:

  • バージョン1.3.0以前: Fargateタスクは2つのネットワークインターフェースを使用
    • 1つはアプリケーション通信、ログ、コンテナイメージ取得用
    • もう1つはECR認証情報とシークレット取得用のプラットフォーム専用
  • バージョン1.4.0以降: 単一のネットワークインターフェースに統合
    • すべてのトラフィックが顧客VPC内を通るよう変更
    • VPCフローログで監視可能、ネットワークレベルの制御が可能に

この変更により、ネットワーク制御の柔軟性は向上しましたが、ユーザーはVPC内でECRやSecrets Managerへのネットワークパスを適切に設定する責任を負うことになりました。

解決方法

以下のいずれかの方法で問題を解決できます。

方法1: パブリックサブネットでの実行

パブリックサブネットでタスクを実行し、パブリックIPアドレスを割り当てます:

WARNING

セキュリティ上の理由から、本番環境では慎重に検討してください。

  1. ECSサービス設定で「Auto-assign public IP」を「ENABLED」に設定
  2. インターネットゲートウェイ経由でECRおよびSecrets Managerにアクセス

方法2: NATゲートウェイの使用

プライベートサブネットでタスクを実行し、NATゲートウェイを経由して外部接続を許可します:

json
// プライベートサブネットのルートテーブル
Destination: 0.0.0.0/0
Target: nat-{NATゲートウェイID}
json
// アウトバウンドルール
Type: All traffic
Protocol: All
Port: All
Destination: 0.0.0.0/0

方法3: VPCエンドポイントの設定(推奨)

プライベートサブネットでタスクを実行し、VPCエンドポイントを使用してAWSサービスにアクセスします。これが最も安全で推奨される方法です。

必要なVPCエンドポイント

サービスエンドポイント名
ECR APIcom.amazonaws.<region>.ecr.api
ECR DKRcom.amazonaws.<region>.ecr.dkr
S3com.amazonaws.<region>.s3 (ゲートウェイエンドポイント)
CloudWatch Logscom.amazonaws.<region>.logs
Secrets Managercom.amazonaws.<region>.secretsmanager
KMScom.amazonaws.<region>.kms

セキュリティグループ設定

VPCエンドポイント用のセキュリティグループを作成し、インバウンドルールを設定します:

json
Type: HTTPS
Protocol: TCP
Port: 443
Source: <ECSサービスにアタッチされたセキュリティグループ>
terraform
resource "aws_security_group" "vpc_endpoint_sg" {
  name        = "vpc-endpoint-sg"
  description = "Security group for VPC endpoints"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    security_groups = [aws_security_group.ecs_service.id]
  }
}

IAM権限の確認

ECSタスク実行ロールに以下の権限が付与されていることを確認してください:

json
{
  "Effect": "Allow",
  "Action": [
    "ecr:GetAuthorizationToken",
    "ecr:BatchGetImage",
    "ecr:GetDownloadUrlForLayer",
    "logs:CreateLogStream",
    "logs:PutLogEvents",
    "secretsmanager:GetSecretValue"
  ],
  "Resource": "*"
}
json
{
  "Effect": "Allow",
  "Principal": {
    "Service": "ecs-tasks.amazonaws.com"
  },
  "Action": "sts:AssumeRole"
}

シークレットARNの形式確認

Secrets Managerを使用する場合、シークレットARNの形式を確認してください:

json
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "MY_SECRET",
      "valueFrom": "arn:aws:secretsmanager:<region>:<account>:secret:<secret_name>:MY_SECRET"
    }]
  }]
}
json
{
  "containerDefinitions": [{
    "secrets": [{
      "name": "MY_SECRET",
      "valueFrom": "arn:aws:secretsmanager:<region>:<account>:secret:<secret_name>:MY_SECRET::"
    }]
  }]
}

トラブルシューティングツール

AWS Systems Managerの自動化実行機能を使用して問題を診断できます:

  1. AWS Systems Managerコンソールにアクセス
  2. AutomationExecute automationを選択
  3. 実行ドキュメント名でAWSSupport-TroubleshootECSTaskFailedToStartを検索
  4. 必要なパラメータを入力して実行

このツールは、以下の問題を自動的に診断します:

  • 欠落しているVPCエンドポイント
  • セキュリティグループの設定ミス
  • IAM権限の問題
  • イメージプールの失敗

Terraform設定例

以下は、適切に設定されたVPCとエンドポイントのTerraform設定例です:

Terraform設定例
terraform
variable "name" {
  description = "プロジェクト名"
  type        = string
}

variable "environment" {
  description = "環境名"
  type        = string
}

variable "aws_region" {
  description = "AWSリージョン"
  type        = string
}

data "aws_availability_zones" "available" {}

locals {
  num_availability_zones = 3
  availability_zones = slice(data.aws_availability_zones.available.names, 0, local.num_availability_zones)
  public_cidrs = [for n in range(1, local.num_availability_zones + 1): "10.0.${n}.0/24"]
  private_cidrs = [for n in range(local.num_availability_zones + 1, local.num_availability_zones * 2 + 1): "10.0.${n}.0/24"]
}

resource "aws_vpc" "this" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "${var.name}-${var.environment}"
  }
}

resource "aws_subnet" "private" {
  count             = local.num_availability_zones
  availability_zone = element(local.availability_zones, count.index)
  cidr_block        = element(local.private_cidrs, count.index)
  vpc_id            = aws_vpc.this.id

  tags = {
    Name = "${var.name}-${var.environment}-private-${count.index + 1}"
  }
}

resource "aws_vpc_endpoint" "ecr_dkr" {
  private_dns_enabled = true
  service_name        = "com.amazonaws.${var.aws_region}.ecr.dkr"
  vpc_endpoint_type   = "Interface"
  vpc_id              = aws_vpc.this.id

  security_group_ids = [aws_security_group.this.id]
  subnet_ids         = aws_subnet.private[*].id

  tags = {
    Name = "${var.name}-${var.environment}-privatelink-ecr-dkr"
  }
}

resource "aws_vpc_endpoint" "ecr_api" {
  private_dns_enabled = true
  service_name        = "com.amazonaws.${var.aws_region}.ecr.api"
  vpc_endpoint_type   = "Interface"
  vpc_id              = aws_vpc.this.id

  security_group_ids = [aws_security_group.this.id]
  subnet_ids         = aws_subnet.private[*].id

  tags = {
    Name = "${var.name}-${var.environment}-privatelink-ecr-api"
  }
}

resource "aws_vpc_endpoint" "cloudwatch" {
  private_dns_enabled = true
  service_name        = "com.amazonaws.${var.aws_region}.logs"
  vpc_endpoint_type   = "Interface"
  vpc_id              = aws_vpc.this.id

  security_group_ids = [aws_security_group.this.id]
  subnet_ids         = aws_subnet.private[*].id

  tags = {
    Name = "${var.name}-${var.environment}-privatelink-cloudwatch"
  }
}

resource "aws_vpc_endpoint" "s3_gateway" {
  service_name      = "com.amazonaws.${var.aws_region}.s3"
  vpc_endpoint_type = "Gateway"
  vpc_id            = aws_vpc.this.id

  route_table_ids = [aws_default_route_table.this.id]

  tags = {
    Name = "${var.name}-${var.environment}-privatelink-s3-gateway"
  }
}

まとめ

ECS Fargate platform version 1.4.0以降では、ネットワークアーキテクチャの変更により、プライベートサブネットでタスクを実行する場合は適切なVPCエンドポイントの設定が必須です。最も安全で推奨される解決方法は、VPCエンドポイントを使用してAWSサービスにアクセスする方法です。

問題が発生した場合は、以下の順序で確認することをおすすめします:

  1. VPCエンドポイントの設定とセキュリティグループ
  2. IAM実行ロールの権限
  3. シークレットARNの形式
  4. サブネットのルートテーブル設定
  5. AWSのトラブルシューティングツールの実行

これらの設定を適切に行うことで、ResourceInitializationErrorを解決し、安定したECS Fargate環境を構築できます。