1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「Dockerはわかるけど…」から卒業!AWSでコンテナを動かすための30日集中講座 - Day 25: サーバーレスコンテナ:AWS Fargateの真価と活用事例

Last updated at Posted at 2025-08-23

Day 25: サーバーレスコンテナ:AWS Fargateの真価と活用事例 🚀

皆さん、こんにちは!30日集中講座、Day 25へようこそ。

第3週では、Kubernetesを使ったコンテナオーケストレーションを学び、Day 21の最終演習で本番環境レベルのEKSデプロイメントを成功させました。これで、皆さんはコンテナ環境の構築・運用に関する高度なスキルを身につけたと言えるでしょう。

今日は、再びAWSのFargateに焦点を当てます。Day 11でECSとEKSの実行環境としてFargateを簡単に紹介しましたが、今回はその「サーバーレス」という真価と、実際のビジネスでの活用事例を深く掘り下げていきます。

そしてさらに、4章からは、単なる概念説明ではなく、実際の本番環境で使える エンタープライズレベルのFargateアーキテクチャ について、具体的なコード例として紹介しています。


1. AWS Fargateの真価:サーバー管理からの完全な解放

Fargateは、コンテナを実行するための基盤である仮想サーバー(EC2インスタンス)の管理を完全にAWSに任せる、サーバーレスコンテナの実行環境です。

  • 従来のコンテナ運用(ECS on EC2):
    • 開発者や運用者がEC2インスタンスをプロビジョニングし、OSのパッチ適用、スケーリング、セキュリティ設定などを手動で行う必要があります。これはコンテナ管理とは別に、インフラ管理という大きな運用負荷を伴います。
  • Fargateのコンテナ運用(ECS on Fargate):
    • 開発者は、コンテナイメージと、必要なCPU・メモリリソースを指定するだけです。
    • AWSが、裏側で最適なサーバーを自動で選択し、起動・管理します。

Fargateの真価は、この「インフラ管理のレイヤーを完全に抽象化する」ことにあります。これにより、開発者はインフラの煩雑さから解放され、アプリケーション開発そのものに集中できるようになるのです。


2. Fargateのメリットとデメリット

メリット

  1. 運用負荷の最小化: サーバーのパッチ適用やスケーリングといったインフラ管理が不要になります。
  2. 高いセキュリティ: AWSがホストOSのセキュリティを管理するため、脆弱性対応の運用負荷が軽減されます。
  3. シンプルで素早いデプロイ: 必要なコンテナリソースを指定するだけで、迅速にアプリケーションをデプロイできます。
  4. 従量課金: コンテナが実行された時間分だけ課金されるため、使った分だけ支払う明朗会計です。

デメリット

  1. カスタマイズ性の制限: ホストOSへのアクセスができないため、特定のツールをインストールしたり、OSレベルの調整をしたりすることはできません。
  2. コスト: 低稼働率の常時稼働アプリケーションや、リザーブドインスタンスを活用できる大規模システムでは、EC2に比べてコストが割高になる場合があります。

3. AWS Fargateの活用事例

Fargateは、そのシンプルさとスケーラビリティから、多くのユースケースで活用されています。

ユースケース1: WebアプリケーションとAPIサーバー

  • なぜFargateが適しているのか: 予測が難しいトラフィック変動に対して、インフラ管理の手間をかけずに自動でスケーリングできます。多くのスタートアップやSaaS企業が、開発スピードを優先するためにFargateを好んで利用します。

ユースケース2: バッチ処理とジョブ

  • なぜFargateが適しているのか: データ処理やレポート生成といった一時的なバッチジョブを実行するのに最適です。必要な時にだけコンテナを起動し、処理が完了したら自動で停止するため、無駄なコストが発生しません。AWS Step FunctionsやCloudWatch Eventsと組み合わせて、バッチ処理を自動化できます。

ユースケース3: 開発・テスト環境

  • なぜFargateが適しているのか: 開発者ごとに独立した環境を簡単にプロビジョニングできます。手動でEC2インスタンスを管理する必要がなく、開発者は素早くテスト環境を立ち上げ、コストも使った分だけ支払うため効率的です。

4. Fargateアーキテクチャの設計原則

マイクロサービスアーキテクチャでのFargate活用

本番環境では、Fargateを単独で使うのではなく、複数のAWSサービスと組み合わせた堅牢なアーキテクチャを構築します。

Fargate選択の判断基準

Fargateが最適なケース

  • スタートアップから中規模企業(〜100コンテナ)
  • 予測困難なトラフィック変動
  • 開発チームの運用負荷最小化が優先
  • コンプライアンス要件でホストOS管理を避けたい場合

EC2が適しているケース

  • 大規模で安定したワークロード(100+コンテナ)
  • GPUや特殊なハードウェアが必要
  • ホストOSレベルのカスタマイズが必要
  • コスト最適化が最優先

5. 本番レベルのFargate設定

高可用性を考慮したECS on Fargate設定

本番環境でFargateを使用する場合、高可用性、セキュリティ、運用性を考慮した設定が必要です。以下は、エンタープライズレベルで使用できるタスク定義の詳細な設定例です。

{
  // タスク定義の基本情報
  // タスク定義のファミリー名。リビジョン管理の基準となる識別子
  "family": "production-web-app",
  
  // Fargateでは必須の設定。各タスクが独自のENI(Elastic Network Interface)を持ち
  // VPC内で独立したネットワークセキュリティを実現
  "networkMode": "awsvpc",
  
  // このタスク定義がFargateでのみ実行可能であることを明示
  // EC2での実行を防ぎ、予期しない動作を回避
  "requiresCompatibilities": ["FARGATE"],
  
  // リソース設定
  // CPU単位(1024 = 1 vCPU)。Fargateでは事前定義された値のみ使用可能
  // 選択肢: 256, 512, 1024, 2048, 4096
  "cpu": "1024",
  
  // メモリ容量(MB単位)。CPUとメモリの組み合わせには制約がある
  // 1 vCPUの場合: 2GB, 3GB, 4GB, 5GB, 6GB, 7GB, 8GBから選択
  "memory": "2048",
  
  // IAMロール設定
  // ECSサービスがタスクを起動するために必要な権限
  // ECRからのイメージプル、CloudWatchログ出力、Secrets Manager連携などで使用
  "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
  
  // アプリケーションコード内でAWSサービスにアクセスするための権限
  // S3、RDS、SQSなどへのアクセス権限をここで制御
  "taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
  
  "containerDefinitions": [
    {
      // コンテナの基本設定
      // コンテナ名。サービス定義やロードバランサー設定で参照される重要な識別子
      "name": "web-app",
      
      // ECRレジストリのイメージURI。本番環境では「latest」以外の具体的なタグ使用を強く推奨
      // 例: ":v1.2.3"  ":sha-abcd1234" など
      "image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/web-app:latest",
      
      // このコンテナが停止した場合、タスク全体を停止する設定
      // ウェブアプリのメインコンテナでは通常true
      "essential": true,
      
      // ネットワーク設定
      "portMappings": [
        {
          // コンテナが内部で使用するポート番号
          // アプリケーションのリスンポートと一致させる
          "containerPort": 3000,
          // プロトコル指定(tcp/udp)。HTTPアプリケーションではtcp
          "protocol": "tcp"
        }
      ],
      
      // ヘルスチェック設定
      // ELBヘルスチェックとは別のアプリケーションレベルヘルスチェック
      // より詳細な健康状態を監視可能
      "healthCheck": {
        "command": [
          "CMD-SHELL",
          "curl -f http://localhost:3000/health || exit 1"
        ],
        // チェック間隔(秒)本番環境では30秒が標準的
        "interval": 30,
        // タイムアウト時間(秒)レスポンスが遅い場合は延長
        "timeout": 5,
        // 連続失敗許容回数。3回失敗で異常と判定
        "retries": 3,
        // 初回チェックまでの猶予時間。アプリ起動時間を考慮
        "startPeriod": 60
      },
      
      // ログ設定
      // CloudWatch Logsへのログ出力設定
      // 集中ログ管理とモニタリングの基盤
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          // ロググループ名(事前作成必要)
          "awslogs-group": "/ecs/production-web-app",
          // ログを保存するリージョン
          "awslogs-region": "ap-northeast-1",
          // ログストリーム名の接頭辞
          "awslogs-stream-prefix": "ecs"
        }
      },
      
      // セキュリティ設定
      // AWS Secrets Managerから機密情報を安全に注入
      // 平文での機密情報保存を回避するセキュリティベストプラクティス
      "secrets": [
        {
          // コンテナ内での環境変数名
          "name": "DB_PASSWORD",
          // Secrets ManagerのARN。自動ローテーション機能も利用可能
          "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/db-password"
        },
        {
          "name": "JWT_SECRET",
          "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/jwt-secret"
        }
      ],
      
      // 環境変数設定
      // 平文の環境変数(機密情報は絶対に含めない)
      // 設定値や非機密なメタデータに使用
      "environment": [
        {
          "name": "NODE_ENV",
          "value": "production"
        },
        {
          "name": "DB_HOST",
          "value": "prod-cluster.cluster-xyz.ap-northeast-1.rds.amazonaws.com"
        }
      ]
    }
  ]
}

Terraform による Infrastructure as Code

本番環境のFargateデプロイメントでは、Infrastructure as Codeが必須です。以下のTerraform設定は、高可用性とセキュリティを考慮したエンタープライズレベルの構成です。

# terraform/fargate.tf

# ECSクラスタの作成
resource "aws_ecs_cluster" "main" {
  // クラスタ名。環境間で一意である必要があり、リソース識別の基準となる
  name = "production-cluster"

  setting {
    name  = "containerInsights"
    // Container Insightsを有効化してメトリクス詳細監視を実現
    // CPU、メモリ、ネットワーク、ストレージメトリクスを自動収集
    value = "enabled"
  }

  // リソース管理とコスト配分のためのタグ付けは運用上必須
  // 後々のコスト分析や権限管理で重要な役割を果たす
  tags = {
    Environment = "production"
    Project     = "web-app"
  }
}

# ECSサービスの設定
resource "aws_ecs_service" "web_app" {
  name            = "web-app-service"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.web_app.arn
  
  // 通常時に実行する健全なタスク数
  // 高可用性のため最低2、推奨は3以上(異なるAZに分散)
  desired_count   = 3
  
  // サーバーレスモードでの実行を明示的に指定
  // EC2起動タイプとの混同を防ぐ
  launch_type     = "FARGATE"

  # ネットワーク設定
  network_configuration {
    // プライベートサブネットでの実行でセキュリティを向上
    // NAT Gatewayを通じて外部通信を行い、直接のインターネットアクセスを制限
    subnets         = var.private_subnet_ids
    
    // ネットワークレベルのファイアウォール設定
    // 最小権限の原則に従い、必要な通信のみ許可
    security_groups = [aws_security_group.ecs_tasks.id]
  }

  # ロードバランサー統合
  load_balancer {
    // ALBのターゲットグループに自動登録
    // タスクの起動/停止時の自動登録/除外を実現
    target_group_arn = aws_lb_target_group.web_app.arn
    
    // タスク定義内のコンテナ名と完全に一致させる必要がある
    container_name   = "web-app"
    
    // トラフィックを転送するコンテナのポート番号
    container_port   = 3000
  }

  # デプロイメント設定
  deployment_configuration {
    // デプロイ時の最大インスタンス数(通常の2倍まで)
    // ローリングデプロイ時のBlue-Green的な動作を可能にする
    maximum_percent         = 200
    
    // デプロイ時の最小健全インスタンス数(通常の50%以上)
    // サービス継続性とデプロイ速度のバランスを調整
    minimum_healthy_percent = 50
  }

  # Terraform管理の例外設定
  lifecycle {
    // Auto Scalingによるdesired_count変更をTerraform管理外とする
    // 手動スケーリングやAuto Scalingとの競合を防ぐ
    ignore_changes = [desired_count]
  }

  // ALBリスナー作成完了後にサービス作成を開始
  // 依存関係を明示してデプロイ順序を制御
  depends_on = [aws_lb_listener.web_app]
}

# Application Load Balancer設定
resource "aws_lb" "main" {
  name               = "production-alb"
  
  // false: インターネット向け、true: VPC内部のみ
  // パブリックAPIの場合はfalse、内部サービス間通信ではtrue
  internal           = false
  
  // Layer 7ロードバランサー(HTTP/HTTPS対応)
  // パス、ヘッダーベースのルーティングが可能
  load_balancer_type = "application"
  
  security_groups    = [aws_security_group.alb.id]
  
  // パブリックサブネットに配置してインターネット通信を受け入れ
  subnets           = var.public_subnet_ids

  // 本番環境では誤削除防止機能を有効化
  // Terraformでの削除時は事前にfalseに変更が必要
  enable_deletion_protection = true

  tags = {
    Environment = "production"
  }
}

# ターゲットグループ設定
resource "aws_lb_target_group" "web_app" {
  name        = "web-app-tg"
  port        = 3000
  protocol    = "HTTP"
  vpc_id      = var.vpc_id
  
  // Fargateでは「ip」タイプを使用(EC2では「instance」)
  // awsvpcネットワークモードとの組み合わせで動作
  target_type = "ip"

  # ヘルスチェック設定の詳細
  health_check {
    enabled             = true
    
    // 連続成功2回で健全と判定(迅速な復旧)
    healthy_threshold   = 2
    
    // 連続失敗2回で異常と判定(迅速な検知)
    unhealthy_threshold = 2
    
    // ヘルスチェックのタイムアウト時間
    timeout             = 5
    
    // ヘルスチェック実行間隔
    interval            = 30
    
    // アプリケーションのヘルスチェックエンドポイント
    path                = "/health"
    
    // 正常レスポンスとするHTTPステータスコード
    matcher             = "200"
    
    // 上記設定により、最短1分でヘルス状態の変化を検知可能
  }
}

# Auto Scaling設定詳細
resource "aws_appautoscaling_target" "ecs_target" {
  // 最大インスタンス数(コスト制御の上限)
  // トラフィック急増時のコスト暴走を防ぐ重要な設定
  max_capacity       = 10
  
  // 最小インスタンス数(高可用性確保)
  // 障害時や低負荷時でも基本的なサービス継続性を保証
  min_capacity       = 3
  
  // スケーリング対象のECSサービス識別子
  // クラスタ名とサービス名を組み合わせた一意識別子
  resource_id        = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.web_app.name}"
  
  // スケールする対象の次元(タスク数)
  // ECSサービスの場合は常にDesiredCount
  scalable_dimension = "ecs:service:DesiredCount"
  
  // AWSサービスのネームスペース識別子
  service_namespace  = "ecs"
}

# Auto Scalingポリシー
resource "aws_appautoscaling_policy" "ecs_cpu_policy" {
  name               = "cpu-scaling-policy"
  
  // ターゲット追跡スケーリング(指定値を維持する方式)
  // シンプルかつ効果的で、ほとんどのケースで推奨される方式
  policy_type        = "TargetTrackingScaling"
  
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      // AWSが事前定義したCPU使用率メトリクス
      // カスタムメトリクスよりも信頼性が高く、設定も簡単
      predefined_metric_type = "ECSServiceAverageCPUUtilization"
    }
    
    // 目標CPU使用率(70%を維持)
    // 50-80%が一般的、トラフィックパターンに応じて調整
    // scale_out_cooldown、scale_in_cooldownは自動設定される
    target_value = 70.0
  }
}

6. パフォーマンス最適化とコスト管理

コスト最適化戦略

Spot容量プロバイダーの活用(開発環境)

開発・テスト環境では、コスト削減のためにFargate Spotを使用することができます。本番環境に比べて高可用性要件が低い場合に有効です。

# コスト削減のためのSpot容量プロバイダー
resource "aws_ecs_capacity_provider" "fargate_spot" {
  name = "FARGATE_SPOT"

  fargate_capacity_provider {
    auto_scaling_group_provider {
      auto_scaling_group_arn = aws_autoscaling_group.ecs_asg.arn
    }
  }
}

# 開発環境でのSpot利用サービス
resource "aws_ecs_service" "dev_app" {
  name    = "dev-app-service"
  cluster = aws_ecs_cluster.dev.id
  
  # Spot容量プロバイダーを使用してコストを最大70%削減
  capacity_provider_strategy {
    capacity_provider = "FARGATE_SPOT"
    weight           = 1
  }
  
  # 開発環境では単一インスタンス
  desired_count = 1
}

7. 高度なFargateパターン

バッチ処理の最適化

AWS Batch + Fargateによるスケーラブルなデータ処理

大規模なバッチ処理やデータ変換タスクでは、AWS BatchとFargateを組み合わせることで、効率的でコスト効果の高いソリューションを構築できます。

# batch-processor.py
import boto3
import json
import time

class FargateDataProcessor:
    """
    Fargateを使用したデータ処理ジョブの管理クラス
    AWS Batchと連携して大規模なデータ処理を効率的に実行
    """
    def __init__(self):
        self.batch_client = boto3.client('batch')
        self.s3_client = boto3.client('s3')
    
    def submit_processing_job(self, input_data, job_queue, job_definition):
        """
        大規模データ処理ジョブの投入
        
        Args:
            input_data: 処理対象データの情報(S3バケット、キーなど)
            job_queue: AWS Batchのジョブキュー名
            job_definition: 使用するジョブ定義
        
        Returns:
            str: 投入されたジョブのID
        """
        job_name = f"data-processing-{int(time.time())}"
        
        response = self.batch_client.submit_job(
            jobName=job_name,
            jobQueue=job_queue,
            jobDefinition=job_definition,
            parameters={
                'inputBucket': input_data['bucket'],
                'inputKey': input_data['key'],
                'outputBucket': input_data['output_bucket']
            }
        )
        
        return response['jobId']
    
    def monitor_job_progress(self, job_id):
        """
        ジョブ進行状況の監視
        
        Args:
            job_id: 監視対象のジョブID
        
        Returns:
            dict: ジョブの現在状況(ステータス、進行率、ログ情報など)
        """
        response = self.batch_client.describe_jobs(jobs=[job_id])
        job = response['jobs'][0]
        
        return {
            'status': job['status'],
            'progress': job.get('progress', 0),
            'start_time': job.get('startedAt'),
            'logs': job.get('logStreamName')
        }

# AWS Batchジョブ定義(Terraform)
resource "aws_batch_job_definition" "fargate_processor" {
  name = "fargate-data-processor"
  type = "container"
  
  # Fargateプラットフォームの指定
  platform_capabilities = ["FARGATE"]
  
  # コンテナ設定の詳細
  container_properties = jsonencode({
    # データ処理用のカスタムイメージ
    image = "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/data-processor:latest"
    
    # Fargateプラットフォーム設定
    fargatePlatformConfiguration = {
      platformVersion = "LATEST"
    }
    
    # リソース要件(データ処理に適したサイズ)
    resourceRequirements = [
      {
        type  = "VCPU"
        value = "4"
      },
      {
        type  = "MEMORY"
        value = "8192"
      }
    ]
    
    # AWS サービスアクセス用のロール
    jobRoleArn = aws_iam_role.batch_execution_role.arn
    
    # 環境変数設定
    environment = [
      {
        name  = "AWS_DEFAULT_REGION"
        value = "ap-northeast-1"
      }
    ]
  })
}

Blue-Greenデプロイメントの実装

本番環境でのゼロダウンタイムデプロイメントを実現するため、CodeDeployと連携したBlue-Greenデプロイメントを設定します。

# CodeDeploy設定(codedeploy-config.yml)
# Blue-Greenデプロイメントでゼロダウンタイム更新を実現
version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        # デプロイ対象のタスク定義(動的に更新される)
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          # ロードバランサー統合設定
          ContainerName: "web-app"
          ContainerPort: 3000
        # 最新プラットフォームバージョンを使用
        PlatformVersion: "LATEST"

# デプロイメントライフサイクルフック
Hooks:
  - BeforeInstall:
      # アプリケーション停止前の処理(キャッシュクリア、ログ保存など)
      - location: scripts/stop_application.sh
        timeout: 300
        
  - ApplicationStart:
      # 新しいバージョンのアプリケーション開始処理
      - location: scripts/start_application.sh
        timeout: 300
        
  - ApplicationStop:
      # デプロイメント完了後の検証処理
      - location: scripts/validate_deployment.sh
        timeout: 300
#!/bin/bash
# scripts/validate_deployment.sh
# デプロイメント後の自動検証スクリプト

# ヘルスチェック実行によるデプロイメント検証
HEALTH_CHECK_URL="http://your-alb.amazonaws.com/health"
MAX_ATTEMPTS=30
ATTEMPT=1

echo "🔍 Starting deployment validation..."

while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
    # ヘルスチェックエンドポイントにリクエスト送信
    HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" $HEALTH_CHECK_URL)
    
    if [ $HTTP_CODE -eq 200 ]; then
        echo "✅ Deployment validation successful (HTTP $HTTP_CODE)"
        
        # 追加の機能テスト実行
        echo "🧪 Running functional tests..."
        
        # API エンドポイントの動作確認
        API_RESPONSE=$(curl -s -w "%{http_code}" "$HEALTH_CHECK_URL/api/status")
        if [[ $API_RESPONSE == *"200" ]]; then
            echo "✅ API endpoints responding correctly"
        else
            echo "❌ API validation failed"
            exit 1
        fi
        
        # データベース接続確認
        DB_RESPONSE=$(curl -s -w "%{http_code}" "$HEALTH_CHECK_URL/db/health")
        if [[ $DB_RESPONSE == *"200" ]]; then
            echo "✅ Database connectivity verified"
        else
            echo "❌ Database connection failed"
            exit 1
        fi
        
        echo "🎉 All validation checks passed!"
        exit 0
    fi
    
    echo "⏳ Attempt $ATTEMPT/$MAX_ATTEMPTS: HTTP $HTTP_CODE (waiting for service to be ready...)"
    sleep 10
    ((ATTEMPT++))
done

echo "❌ Deployment validation failed after $MAX_ATTEMPTS attempts"
echo "🔧 Check CloudWatch logs for detailed error information"
exit 1

8. モニタリングとObservability

カスタムメトリクスでの詳細監視

Fargateアプリケーションでは、標準的なCPU/メモリメトリクスだけでなく、アプリケーション固有のメトリクスを監視することが重要です。

# fargate-monitoring.py
import boto3
import psutil
import time
import redis
import json
from datetime import datetime

class FargateMonitor:
    """
    Fargate アプリケーション専用の監視クラス
    CloudWatch カスタムメトリクスでビジネスメトリクスを追跡
    """
    def __init__(self):
        self.cloudwatch = boto3.client('cloudwatch')
        self.namespace = 'Custom/Fargate/Application'
        self.redis_client = redis.Redis(host='your-redis-cluster.cache.amazonaws.com')
    
    def publish_custom_metrics(self, service_name):
        """
        アプリケーション固有のメトリクスを送信
        
        Args:
            service_name: 監視対象のサービス名
        """
        
        # アプリケーションレベルのメトリクス収集
        active_connections = self.get_active_connections()
        queue_depth = self.get_queue_depth()
        cache_hit_ratio = self.get_cache_hit_ratio()
        response_time_p95 = self.get_response_time_percentile(95)
        
        # CloudWatchメトリクスデータの構築
        metrics_data = [
            {
                'MetricName': 'ActiveConnections',
                'Value': active_connections,
                'Unit': 'Count',
                'Dimensions': [
                    {'Name': 'ServiceName', 'Value': service_name},
                    {'Name': 'Environment', 'Value': 'production'}
                ]
            },
            {
                'MetricName': 'QueueDepth',
                'Value': queue_depth,
                'Unit': 'Count',
                'Dimensions': [
                    {'Name': 'ServiceName', 'Value': service_name}
                ]
            },
            {
                'MetricName': 'CacheHitRatio',
                'Value': cache_hit_ratio,
                'Unit': 'Percent',
                'Dimensions': [
                    {'Name': 'ServiceName', 'Value': service_name}
                ]
            },
            {
                'MetricName': 'ResponseTime95thPercentile',
                'Value': response_time_p95,
                'Unit': 'Milliseconds',
                'Dimensions': [
                    {'Name': 'ServiceName', 'Value': service_name}
                ]
            }
        ]
        
        # CloudWatchにメトリクス送信
        self.cloudwatch.put_metric_data(
            Namespace=self.namespace,
            MetricData=metrics_data
        )
    
    def get_active_connections(self):
        """アクティブネットワーク接続数を取得"""
        connections = psutil.net_connections(kind='inet')
        active_connections = [conn for conn in connections if conn.status == 'ESTABLISHED']
        return len(active_connections)
    
    def get_queue_depth(self):
        """Redis/SQSキューの深さを取得"""
        try:
            # SQS キューの深さ監視例
            sqs = boto3.client('sqs')
            response = sqs.get_queue_attributes(
                QueueUrl='https://sqs.ap-northeast-1.amazonaws.com/123456789012/processing-queue',
                AttributeNames=['ApproximateNumberOfMessages']
            )
            return int(response['Attributes']['ApproximateNumberOfMessages'])
        except Exception as e:
            print(f"Error getting queue depth: {e}")
            return 0
    
    def get_cache_hit_ratio(self):
        """Redisキャッシュヒット率を計算"""
        try:
            info = self.redis_client.info('stats')
            hits = info['keyspace_hits']
            misses = info['keyspace_misses']
            
            if hits + misses == 0:
                return 0
            
            hit_ratio = (hits / (hits + misses)) * 100
            return round(hit_ratio, 2)
        except Exception as e:
            print(f"Error calculating cache hit ratio: {e}")
            return 0
    
    def get_response_time_percentile(self, percentile):
        """アプリケーションレスポンス時間のパーセンタイル取得"""
        # 実際の実装では、アプリケーション内で測定したレスポンス時間を
        # Redis や データベースから取得することが多い
        return 45.7  # サンプル値(ミリ秒)

# 監視スクリプトの定期実行
if __name__ == "__main__":
    monitor = FargateMonitor()
    
    while True:
        try:
            monitor.publish_custom_metrics('web-app-service')
            print(f"✅ Metrics published at {datetime.now()}")
        except Exception as e:
            print(f"❌ Error publishing metrics: {e}")
        
        # 60秒間隔でメトリクス送信
        time.sleep(60)

分散トレーシングの実装

マイクロサービスアーキテクチャでは、複数のサービス間でのリクエスト追跡が重要です。AWS X-Rayを使用した分散トレーシングを実装します。

// app.js - X-Rayトレーシング
const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const express = require('express');
const mysql = require('mysql2/promise');

const app = express();

// X-Ray分散トレーシングミドルウェアの設定
// 全てのHTTPリクエストを自動的にトレース
app.use(AWSXRay.express.openSegment('fargate-web-app'));

// データベース接続プール(X-Ray監視対象)
const dbPool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

app.get('/api/users/:id', async (req, res) => {
  const segment = AWSXRay.getSegment();
  
  try {
    // データベースアクセスをトレース対象として追加
    const subsegment = segment.addNewSubsegment('database-query');
    subsegment.addAnnotation('user_id', req.params.id);
    subsegment.addAnnotation('query_type', 'SELECT');
    
    // データベースクエリ実行
    const startTime = Date.now();
    const [rows] = await dbPool.execute(
      'SELECT id, name, email, created_at FROM users WHERE id = ?',
      [req.params.id]
    );
    const queryTime = Date.now() - startTime;
    
    // パフォーマンスメタデータの追加
    subsegment.addMetadata('query_performance', {
      execution_time_ms: queryTime,
      rows_returned: rows.length
    });
    
    subsegment.close();
    
    if (rows.length === 0) {
      // ユーザーが見つからない場合のトレース情報
      segment.addAnnotation('result', 'user_not_found');
      return res.status(404).json({ error: 'User not found' });
    }
    
    // 外部API呼び出しのトレース
    const externalApiSegment = segment.addNewSubsegment('external-api-call');
    externalApiSegment.addAnnotation('api_endpoint', 'user-preferences');
    
    try {
      // 外部サービス連携(例:ユーザー設定取得)
      const preferencesResponse = await fetch(`http://preferences-service/api/users/${req.params.id}/preferences`, {
        headers: {
          'Authorization': `Bearer ${process.env.API_TOKEN}`
        }
      });
      
      const preferences = await preferencesResponse.json();
      externalApiSegment.addMetadata('preferences_data', preferences);
      
    } catch (apiError) {
      // 外部API呼び出し失敗時のエラートレース
      externalApiSegment.addError(apiError);
      console.warn('Failed to fetch user preferences:', apiError.message);
    } finally {
      externalApiSegment.close();
    }
    
    // 成功レスポンスのトレース情報
    segment.addAnnotation('result', 'success');
    segment.addMetadata('response_data', {
      user_id: rows[0].id,
      response_size: JSON.stringify(rows[0]).length
    });
    
    res.json({
      user: rows[0],
      preferences: preferences || null
    });
    
  } catch (error) {
    // エラー情報をトレースに追加
    segment.addError(error);
    segment.addAnnotation('error_type', error.name);
    
    console.error('Database query failed:', error);
    res.status(500).json({ error: 'Internal Server Error' });
  }
});

// ヘルスチェックエンドポイント
app.get('/health', (req, res) => {
  const segment = AWSXRay.getSegment();
  segment.addAnnotation('endpoint', 'health_check');
  
  // アプリケーションの健康状態チェック
  const healthStatus = {
    status: 'healthy',
    timestamp: new Date().toISOString(),
    version: process.env.APP_VERSION || '1.0.0',
    uptime: process.uptime()
  };
  
  res.json(healthStatus);
});

// X-Rayセグメント終了ミドルウェア
app.use(AWSXRay.express.closeSegment());

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`🚀 Fargate application listening on port ${port}`);
  console.log(`📊 X-Ray tracing enabled for distributed monitoring`);
});

9. セキュリティと運用の実践

Fargateにおけるゼロトラストアーキテクチャ

本番環境では、最小権限の原則とゼロトラストセキュリティモデルに基づいた設定が必要です。

# security-enhanced-task-definition.yml
# セキュリティ強化されたFargateタスク定義
family: secure-fargate-app
networkMode: awsvpc
requiresCompatibilities:
  - FARGATE
cpu: '1024'
memory: '2048'

containerDefinitions:
  - name: app
    image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/secure-app:latest
    
    # セキュリティ強化設定
    # 非rootユーザーでの実行(セキュリティベストプラクティス)
    user: "1001:1001"
    
    # ルートファイルシステムを読み取り専用に設定
    # アプリケーションの改ざんを防止
    readonlyRootFilesystem: true
    
    # 最小権限の原則に基づくLinux Capabilitiesの設定
    linuxParameters:
      capabilities:
        # 全ての権限を削除
        drop:
          - ALL
        # 必要最小限の権限のみ付与(例:ネットワークバインド)
        add:
          - NET_BIND_SERVICE
    
    # セキュアなログ設定(機密情報フィルタリング対応)
    logConfiguration:
      logDriver: awslogs
      options:
        awslogs-group: "/fargate/secure-app"
        awslogs-region: "ap-northeast-1"
        awslogs-stream-prefix: "secure"
    
    # アプリケーション健康監視
    healthCheck:
      command:
        - CMD-SHELL
        - "curl -f http://localhost:8080/health || exit 1"
      interval: 30
      timeout: 5
      retries: 3
    
    # 非機密環境変数(機密情報は絶対に含めない)
    environment:
      - name: NODE_ENV
        value: production
      - name: LOG_LEVEL
        value: info
      - name: CORS_ORIGIN
        value: "https://app.example.com"
    
    # AWS Secrets Managerによる機密情報管理
    # 自動ローテーション機能で定期的なパスワード更新も可能
    secrets:
      - name: DB_PASSWORD
        valueFrom: arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/database-password
      - name: JWT_SECRET
        valueFrom: arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/jwt-secret
      - name: REDIS_AUTH_TOKEN
        valueFrom: arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/redis-token
      - name: EXTERNAL_API_KEY
        valueFrom: arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/external-api-key

10. 災害復旧とビジネス継続性

マルチリージョン対応Fargateアーキテクチャ

事業継続性を確保するため、複数のAWSリージョンにまたがるFargateアーキテクチャを構築します。

# multi-region-fargate.tf
# マルチリージョン災害復旧対応のFargate設定

# AWSプロバイダー設定(プライマリリージョン)
provider "aws" {
  alias  = "primary"
  region = "ap-northeast-1"  # 東京リージョン
}

# AWSプロバイダー設定(災害復旧リージョン)
provider "aws" {
  alias  = "disaster_recovery"
  region = "us-west-2"       # オレゴンリージョン
}

# プライマリリージョンのFargateサービス
module "primary_fargate" {
  source = "./modules/fargate-service"
  
  providers = {
    aws = aws.primary
  }
  
  region           = "ap-northeast-1"
  environment     = "production"
  service_name    = "web-app"
  
  # 通常時は3つのタスクで運用
  desired_count   = 3
  
  # プライマリデータベースエンドポイント
  database_endpoint = aws_db_instance.primary.endpoint
  
  # プライマリリージョン固有の設定
  enable_auto_scaling = true
  max_capacity       = 10
  min_capacity       = 3
}

# 災害復旧リージョンのFargateサービス
module "dr_fargate" {
  source = "./modules/fargate-service"
  
  providers = {
    aws = aws.disaster_recovery
  }
  
  region           = "us-west-2"
  environment     = "dr"
  service_name    = "web-app"
  
  # 通常時は停止状態(コスト削減)
  desired_count   = 0
  
  # 災害復旧用のリードレプリカデータベース
  database_endpoint = aws_db_instance.replica.endpoint
  
  # DR環境での設定
  enable_auto_scaling = true
  max_capacity       = 5   # プライマリより小規模
  min_capacity       = 0   # 通常時は停止
}

# Route 53による自動フェイルオーバー設定
resource "aws_route53_record" "primary" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "api.example.com"
  type    = "A"
  
  # プライマリレコードとして設定
  set_identifier = "primary"
  
  # フェイルオーバールーティングポリシー
  failover_routing_policy {
    type = "PRIMARY"
  }
  
  # ALBエイリアス設定
  alias {
    name                   = module.primary_fargate.alb_dns_name
    zone_id               = module.primary_fargate.alb_zone_id
    # ヘルスチェックによる自動フェイルオーバー
    evaluate_target_health = true
  }
  
  # ヘルスチェック関連付け
  health_check_id = aws_route53_health_check.primary.id
}

# セカンダリ(災害復旧)レコード
resource "aws_route53_record" "secondary" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "api.example.com"
  type    = "A"
  
  set_identifier = "secondary"
  
  failover_routing_policy {
    type = "SECONDARY"
  }
  
  alias {
    name                   = module.dr_fargate.alb_dns_name
    zone_id               = module.dr_fargate.alb_zone_id
    evaluate_target_health = true
  }
}

# プライマリリージョンのヘルスチェック
resource "aws_route53_health_check" "primary" {
  fqdn                            = module.primary_fargate.alb_dns_name
  port                           = 443
  type                           = "HTTPS"
  resource_path                  = "/health"
  failure_threshold              = "3"
  request_interval               = "30"
  
  # ヘルスチェック失敗時の通知設定
  cloudwatch_alarm_name          = "primary-region-health-alarm"
  cloudwatch_alarm_namespace     = "AWS/Route53"
  
  tags = {
    Name = "Primary Region Health Check"
    Environment = "production"
  }
}

# 災害復旧時の自動スケールアップ設定
resource "aws_cloudwatch_metric_alarm" "primary_down" {
  alarm_name          = "primary-region-down"
  comparison_operator = "LessThanThreshold"
  evaluation_periods  = "2"
  metric_name         = "HealthCheckStatus"
  namespace           = "AWS/Route53"
  period              = "60"
  statistic           = "Minimum"
  threshold           = "1"
  alarm_description   = "This metric monitors primary region health"
  
  # プライマリダウン時のアクション
  alarm_actions = [
    aws_sns_topic.disaster_recovery_alerts.arn,
    # Lambda関数でDRリージョンのスケールアップをトリガー
    aws_lambda_function.dr_scale_up.arn
  ]
}

11. まとめ:Fargateによるモダンアプリケーションアーキテクチャ

Fargateアーキテクチャの成熟度レベル

レベル1: 基本的なFargateデプロイ

  • 単一サービスのFargateデプロイ
  • ALBとの統合
  • 基本的なAuto Scaling設定

レベル2: プロダクション対応

  • マルチAZ配置による高可用性
  • セキュリティ強化設定(非rootユーザー、最小権限)
  • カスタムメトリクス監視
  • Blue-Greenデプロイメント

レベル3: エンタープライズ対応

  • マルチリージョン災害復旧
  • ゼロトラストセキュリティアーキテクチャ
  • 分散トレーシング(AWS X-Ray)
  • 自動化されたコスト最適化

次世代のコンテナアーキテクチャ

Fargateは単なる実行環境ではなく、開発者体験の革命です。インフラの複雑性から解放された開発チームは、ビジネス価値の創出に集中できるようになります。

Fargateがもたらす変革:

  1. 運用負荷の劇的削減: サーバー管理、パッチ適用、キャパシティプランニングからの解放
  2. 開発速度の向上: インフラ準備時間の短縮により、アイデアから本番までの期間を大幅に短縮
  3. コスト効率: 使用した分だけの従量課金により、無駄なリソースコストを削減
  4. スケーラビリティ: トラフィック変動に対する自動的かつ迅速な対応

このサーバーレスな考え方は、コンテナのメリットを最大限に引き出し、開発チーム全体の生産性を向上させる上で非常に重要です。

実践的な次のステップ:

  1. 既存システムのFargate移行評価:現在のEC2ベースのコンテナアプリケーションでFargateに適したワークロードを特定
  2. 段階的移行戦略:開発環境→ステージング環境→本番環境の順で徐々にFargateを導入
  3. 監視・運用体制の整備:CloudWatchメトリクス、X-Ray、ログ集約システムの構築
  4. セキュリティポリシーの策定:ゼロトラストアーキテクチャに基づくセキュリティガイドラインの作成

次回の予告

Day 26: 総合演習 - マルチサービス・コンテナアプリケーションの構築

明日は、これまで学んだFargate、ECS、EKSの知識を総合して、実際のマルチサービス・コンテナアプリケーションを一から構築する実践的な演習を行います。フロントエンド、バックエンドAPI、データベース、キューイングシステムを含む完全なエコシステムを、現代的なベストプラクティスに従って構築していきます。

それでは、また明日お会いしましょう!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?