

# AWS CLI を使用した Amazon ECS Service Connect の設定
<a name="create-service-connect"></a>

AWS CLI で Service Connect を使用する Fargate タスクで Amazon ECS サービスを作成できます。

**注記**  
デュアルスタックサービスエンドポイントを使用することで、IPv4 と IPv6 の両方を介して AWS CLI、SDK、および Amazon ECS API から Amazon ECS とやり取りできます。詳細については、「[Amazon ECS デュアルスタックエンドポイントの使用](dual-stack-endpoint.md)」を参照してください。

## 前提条件
<a name="create-service-connect-prereqs"></a>

Service Connect の前提条件は次のとおりです。
+ AWS CLI の最新バージョンがインストールされ、設定されていることを確認します。詳細については、「[AWS CLIの最新バージョンのインストールまたは更新](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)」を参照してください。
+ IAM ユーザーに [AmazonECS\$1FullAccess](security-iam-awsmanpol.md#security-iam-awsmanpol-AmazonECS_FullAccess) IAM ポリシー例で指定されている必要なアクセス権限があること。
+ VPC、サブネット、ルートテーブルおよびセキュリティグループが使用できるように作成されています。詳細については、「[仮想プライベートクラウドを作成する](get-set-up-for-amazon-ecs.md#create-a-vpc)」を参照してください。
+ `ecsTaskExecutionRole` という名前のタスク実行ロールがあり、`AmazonECSTaskExecutionRolePolicy` 管理ポリシーがそのロールにアタッチされています。このロールにより、Fargate は NGINX アプリケーションログと Service Connect プロキシログを Amazon CloudWatch Logs に書き込むことができます。詳細については、「[タスク実行 ロールの作成](task_execution_IAM_role.md#create-task-execution-role)」を参照してください。

## ステップ 1: クラスターを作成する
<a name="create-service-connect-cluster"></a>

次の手順に従って Amazon ECS クラスターと名前空間を作成します。

**Amazon ECS クラスターと AWS Cloud Map 名前空間を作成するには**

1. `tutorial` という名前の Amazon ECS クラスターを作成して使用します。パラメータ `--service-connect-defaults` は、クラスターのデフォルト名前空間を設定します。この出力の例では、`service-connect` という名前の AWS Cloud Map 名前空間はこのアカウントおよび AWS リージョンには存在しないため、名前空間は Amazon ECS によって作成されています。名前空間はアカウント内の AWS Cloud Map で作成され、他のすべての名前空間でも表示されるため、目的を示す名前を使用します。

   ```
   aws ecs create-cluster --cluster-name tutorial --service-connect-defaults namespace=service-connect
   ```

   出力:

   ```
   {
       "cluster": {
           "clusterArn": "arn:aws:ecs:us-west-2:123456789012:cluster/tutorial",
           "clusterName": "tutorial",
           "serviceConnectDefaults": {
               "namespace": "arn:aws:servicediscovery:us-west-2:123456789012:namespace/ns-EXAMPLE"
           },
           "status": "PROVISIONING",
           "registeredContainerInstancesCount": 0,
           "runningTasksCount": 0,
           "pendingTasksCount": 0,
           "activeServicesCount": 0,
           "statistics": [],
           "tags": [],
           "settings": [
               {
                   "name": "containerInsights",
                   "value": "disabled"
               }
           ],
           "capacityProviders": [],
           "defaultCapacityProviderStrategy": [],
           "attachments": [
               {
                   "id": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
                   "type": "sc",
                   "status": "ATTACHING",
                   "details": []
               }
           ],
           "attachmentsStatus": "UPDATE_IN_PROGRESS"
       }
   }
   }
   ```

1. クラスターが作成されていることを確認します。

   ```
   aws ecs describe-clusters --clusters tutorial
   ```

   出力:

   ```
   {
       "clusters": [
           {
               "clusterArn": "arn:aws:ecs:us-west-2:123456789012:cluster/tutorial",
               "clusterName": "tutorial",
               "serviceConnectDefaults": {
                   "namespace": "arn:aws:servicediscovery:us-west-2:123456789012:namespace/ns-EXAMPLE"
               },
               "status": "ACTIVE",
               "registeredContainerInstancesCount": 0,
               "runningTasksCount": 0,
               "pendingTasksCount": 0,
               "activeServicesCount": 0,
               "statistics": [],
               "tags": [],
               "settings": [],
               "capacityProviders": [],
               "defaultCapacityProviderStrategy": []
           }
       ],
       "failures": []
   }
   ```

1. (オプション) 名前空間が AWS Cloud Map で作成されていることを確認します。これは AWS Cloud Map で作成されているため、AWS マネジメントコンソールまたは通常の AWS CLI 構成を使用できます。

   例えば、以下の AWS CLI を使用します。

   ```
   aws servicediscovery get-namespace --id ns-EXAMPLE
   ```

   出力:

   ```
   {
       "Namespace": {
           "Id": "ns-EXAMPLE",
           "Arn": "arn:aws:servicediscovery:us-west-2:123456789012:namespace/ns-EXAMPLE",
           "Name": "service-connect",
           "Type": "HTTP",
           "Properties": {
               "DnsProperties": {
                   "SOA": {}
               },
               "HttpProperties": {
                   "HttpName": "service-connect"
               }
           },
           "CreateDate": 1661749852.422,
           "CreatorRequestId": "service-connect"
       }
   }
   ```

## ステップ 2: サーバー用のサービスを作成する
<a name="create-service-connect-nginx-server"></a>

Service Connect 機能は、Amazon ECS 上の複数のアプリケーションを相互接続することを目的としています。これらのアプリケーションの少なくとも 1 つは、接続するウェブサービスを提供する必要があります。このステップでは、以下を作成します。
+ 未修正の公式 NGINX コンテナイメージを使用し、Service Connect 設定を含むタスク定義。
+ このサービスへのトラフィック用にサービス検出とサービスメッシュプロキシを提供するために Service Connect を設定する Amazon ECS サービス定義。この構成では、クラスター構成からデフォルトの名前空間を再利用することで、各サービスに対して行うサービス構成の量を減らします。
+ Amazon ECS サービス。タスク定義を使用して 1 つのタスクを実行し、Service Connect プロキシ用の追加コンテナを挿入します。プロキシは、タスク定義のコンテナポートマッピングからポートをリッスンします。Amazon ECS で実行されているクライアントアプリケーションで、クライアントタスクのプロキシは、タスク定義ポート名、サービス検出名またはサービスクライアントエイリアス名、およびクライアントエイリアスからのポート番号へのアウトバウンド接続をリッスンします。

**Service Connect を使用してウェブサービスを作成するには**

1. Fargate と互換性があり、`awsvpc` ネットワークモードを使用するタスク定義を登録します。以下の手順に従ってください。

   1. 次のタスク定義の内容で、`service-connect-nginx.json` というファイルを作成します。

      このタスク定義は、ポートマッピングに `name` および `appProtocol` パラメータを追加することによって Service Connect を構成します。複数のポートが使用されている場合、ポート名によりサービス構成でこのポートをより識別しやすくなります。また、ポート名は、名前空間内の他のアプリケーションが使用する検出可能な名前としてもデフォルトで使用されています。

      サービスでは ECS Exec が有効になっているため、タスク定義にはタスク IAM ロールが含まれています。
**重要**  
このタスク定義では、`logConfiguration` を使用して `stdout` および `stderr` から Amazon CloudWatch Logs に nginx 出力を送信します。このタスク実行ロールには、CloudWatch Logs ロググループを作成するために必要な追加の権限はありません。AWS マネジメントコンソールまたは AWS CLI を使用して、CloudWatch Logs にロググループを作成します。nginx ログを CloudWatch Logs に送信したくない場合、`logConfiguration` を削除できます。  
タスク実行ロールの AWS アカウント ID を AWS アカウント ID に置き換えます。

      ```
      {
          "family": "service-connect-nginx",
          "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
          "taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
          "networkMode": "awsvpc",
          "containerDefinitions": [
              {
              "name": "webserver",
              "image": "public.ecr.aws/docker/library/nginx:latest",
              "cpu": 100,
              "portMappings": [
                  {
                      "name": "nginx",
                      "containerPort": 80,
                      "protocol": "tcp", 
                      "appProtocol": "http"
                  }
              ],
              "essential": true,
              "logConfiguration": {
                  "logDriver": "awslogs",
                  "options": {
                      "awslogs-group": "/ecs/service-connect-nginx",
                      "awslogs-region": "region", 
                      "awslogs-stream-prefix": "nginx"
                  }
              }
              }
          ],
          "cpu": "256",
          "memory": "512"
      }
      ```

   1. 次の `service-connect-nginx.json` ファイルを使用して、タスク定義を登録します。

      ```
      aws ecs register-task-definition --cli-input-json file://service-connect-nginx.json
      ```

1. サービスを作成します。

   1. 作成する Amazon ECS サービスの内容で、`service-connect-nginx-service.json` という名前のファイルを作成します。この例では、前のステップで作成したタスク定義を使用します。このタスク定義の例では `awsvpc` ネットワークモードを使用しているため、`awsvpcConfiguration` が必要となります。

      ECS サービスを作成する際に、Fargate と、Service Connect をサポートする `LATEST` プラットフォームバージョンを指定します。`securityGroups` および `subnets` は、Amazon ECS を使用するための要件を満たしている VPC に属している必要があります。Amazon VPC コンソールからセキュリティグループとサブネット ID を取得できます。

      このサービスは、`serviceConnectConfiguration` パラメータを追加して Service Connect を設定します。クラスターにはデフォルトの名前空間が設定されているため、名前空間は必要ありません。名前空間内の ECS で実行されているクライアントアプリケーションは、`portName` および `clientAliases` のポートを使用してこのサービスに接続します。例えば、nginx はルートロケーション `/` にウェルカムページを提供しているため、`http://nginx:80/` を使用してこのサービスにアクセスできます。Amazon ECS で実行されていない、または同じ名前空間にない外部アプリケーションは、タスクの IP アドレスとタスク定義のポート番号を使用して、Service Connect プロキシ経由でこのアプリケーションにアクセスできます。ご使用の `tls` 設定に合わせて、`awsPcaAuthorityArn`、`kmsKey` および IAM ロールの `roleArn` に対する証明書 `arn` を追加します。

      このサービスは、`logConfiguration` を使用して `stdout` および `stderr` から Amazon CloudWatch Logs にサービス接続プロキシの出力を送信します。このタスク実行ロールには、CloudWatch Logs ロググループを作成するために必要な追加の権限はありません。AWS マネジメントコンソールまたは AWS CLI を使用して、CloudWatch Logs にロググループを作成します。このロググループを作成し、CloudWatch Logs にプロキシログを保存することをお勧めします。プロキシログを CloudWatch Logs に送信したくない場合、`logConfiguration` を削除できます。

      ```
      {
          "cluster": "tutorial",
          "deploymentConfiguration": {
              "maximumPercent": 200,
              "minimumHealthyPercent": 0
          },
          "deploymentController": {
              "type": "ECS"
          },
          "desiredCount": 1,
          "enableECSManagedTags": true,
          "enableExecuteCommand": true,
          "launchType": "FARGATE",
          "networkConfiguration": {
              "awsvpcConfiguration": {
                  "assignPublicIp": "ENABLED",
                  "securityGroups": [
                      "sg-EXAMPLE"
                  ],
                  "subnets": [
                      "subnet-EXAMPLE",
                      "subnet-EXAMPLE",
                      "subnet-EXAMPLE"
                  ]
                 }
          },
          "platformVersion": "LATEST",
          "propagateTags": "SERVICE",
          "serviceName": "service-connect-nginx-service",
          "serviceConnectConfiguration": {
              "enabled": true,
              "services": [
                  {
                      "portName": "nginx",
                      "clientAliases": [
                          {
                              "port": 80
                          }
                      ],
                      "tls": {
                         "issuerCertificateAuthority": {
                            "awsPcaAuthorityArn": "certificateArn"
                         }, 
                         "kmsKey": "kmsKey", 
                         "roleArn": "iamRoleArn"
                      }
                  }
              ],
              "logConfiguration": {
                  "logDriver": "awslogs",
                  "options": {
                      "awslogs-group": "/ecs/service-connect-proxy",
                      "awslogs-region": "region",
                      "awslogs-stream-prefix": "service-connect-proxy"
                  }
              }
          },
          "taskDefinition": "service-connect-nginx"
      }
      ```

   1. 次の `service-connect-nginx-service.json` のファイルを使用して、サービスを作成します。

      ```
      aws ecs create-service --cluster tutorial --cli-input-json file://service-connect-nginx-service.json
      ```

      出力:

      ```
      {
          "service": {
              "serviceArn": "arn:aws:ecs:us-west-2:123456789012:service/tutorial/service-connect-nginx-service",
              "serviceName": "service-connect-nginx-service",
              "clusterArn": "arn:aws:ecs:us-west-2:123456789012:cluster/tutorial",
              "loadBalancers": [],
              "serviceRegistries": [],
              "status": "ACTIVE",
              "desiredCount": 1,
              "runningCount": 0,
              "pendingCount": 0,
              "launchType": "FARGATE",
              "platformVersion": "LATEST",
              "platformFamily": "Linux",
              "taskDefinition": "arn:aws:ecs:us-west-2:123456789012:task-definition/service-connect-nginx:1",
              "deploymentConfiguration": {
                  "deploymentCircuitBreaker": {
                      "enable": false,
                      "rollback": false
                  },
                  "maximumPercent": 200,
                  "minimumHealthyPercent": 0
              },
              "deployments": [
                  {
                      "id": "ecs-svc/3763308422771520962",
                      "status": "PRIMARY",
                      "taskDefinition": "arn:aws:ecs:us-west-2:123456789012:task-definition/service-connect-nginx:1",
                      "desiredCount": 1,
                      "pendingCount": 0,
                      "runningCount": 0,
                      "failedTasks": 0,
                      "createdAt": 1661210032.602,
                      "updatedAt": 1661210032.602,
                      "launchType": "FARGATE",
                      "platformVersion": "1.4.0",
                      "platformFamily": "Linux",
                      "networkConfiguration": {
                          "awsvpcConfiguration": {
                              "assignPublicIp": "ENABLED",
                              "securityGroups": [
                                  "sg-EXAMPLE"
                              ],
                              "subnets": [
                                  "subnet-EXAMPLEf",
                                  "subnet-EXAMPLE",
                                  "subnet-EXAMPLE"
                              ]
                          }
                      },
                      "rolloutState": "IN_PROGRESS",
                      "rolloutStateReason": "ECS deployment ecs-svc/3763308422771520962 in progress.",
                      "failedLaunchTaskCount": 0,
                      "replacedTaskCount": 0,
                      "serviceConnectConfiguration": {
                          "enabled": true,
                          "namespace": "service-connect",
                          "services": [
                              {
                                  "portName": "nginx",
                                  "clientAliases": [
                                      {
                                          "port": 80
                                      }
                                  ]
                              }
                          ],
                          "logConfiguration": {
                              "logDriver": "awslogs",
                              "options": {
                                  "awslogs-group": "/ecs/service-connect-proxy",
                                  "awslogs-region": "us-west-2",
                                  "awslogs-stream-prefix": "service-connect-proxy"
                              },
                              "secretOptions": []
                          }
                      },
                      "serviceConnectResources": [
                          {
                              "discoveryName": "nginx",
                              "discoveryArn": "arn:aws:servicediscovery:us-west-2:123456789012:service/srv-EXAMPLE"
                          }
                      ]
                  }
              ],
              "roleArn": "arn:aws:iam::123456789012:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS",
              "version": 0,
              "events": [],
              "createdAt": 1661210032.602,
              "placementConstraints": [],
              "placementStrategy": [],
              "networkConfiguration": {
                  "awsvpcConfiguration": {
                      "assignPublicIp": "ENABLED",
                      "securityGroups": [
                          "sg-EXAMPLE"
                      ],
                      "subnets": [
                          "subnet-EXAMPLE",
                          "subnet-EXAMPLE",
                          "subnet-EXAMPLE"
                      ]
                  }
              },
              "schedulingStrategy": "REPLICA",
              "enableECSManagedTags": true,
              "propagateTags": "SERVICE",
              "enableExecuteCommand": true
          }
      }
      ```

      指定した `serviceConnectConfiguration` は、出力の最初の*デプロイ*内に表示されます。タスクに変更を加える必要がある方法で ECS サービスを変更すると、Amazon ECS によって新しいデプロイが作成されます。

## ステップ 3: 接続できることを確認する
<a name="create-service-connect-verify"></a>

Service Connect が設定され動作していることを確認するには、次の手順に従って外部アプリケーションからウェブサービスに接続します。次に、Service Connect プロキシが作成した CloudWatch にある追加のメトリクスを確認します。

**外部アプリケーションからウェブサービスに接続するには**
+ タスク IP アドレスを使用して、タスク IP アドレスとコンテナポートに接続する

  AWS CLI を使用して `aws ecs list-tasks --cluster tutorial` を使用したタスク ID を取得します。

  サブネットとセキュリティグループがタスク定義のポート上のパブリックインターネットからのトラフィックを許可している場合、コンピュータからパブリック IP に接続できます。ただし、パブリック IP は「describe-tasks」からは利用できないため、手順として、Amazon EC2 AWS マネジメントコンソールまたは AWS CLI に移動して Elastic Network Interface の詳細を取得する必要があります。

  この例では、同じ VPC 内の Amazon EC2 インスタンスはタスクのプライベート IP を使用します。アプリケーションは nginx ですが、`server: envoy` ヘッダーには Service Connect プロキシが使用されていることが表示されます。Service Connect プロキシはタスク定義のコンテナポートをリッスンしています。

  ```
  $ curl -v 10.0.19.50:80/
  *   Trying 10.0.19.50:80...
  * Connected to 10.0.19.50 (10.0.19.50) port 80 (#0)
  > GET / HTTP/1.1
  > Host: 10.0.19.50
  > User-Agent: curl/7.79.1
  > Accept: */*
  >
  * Mark bundle as not supporting multiuse
  < HTTP/1.1 200 OK
  < server: envoy
  < date: Tue, 23 Aug 2022 03:53:06 GMT
  < content-type: text/html
  < content-length: 612
  < last-modified: Tue, 16 Apr 2019 13:08:19 GMT
  < etag: "5cb5d3c3-264"
  < accept-ranges: bytes
  < x-envoy-upstream-service-time: 0
  <
  <!DOCTYPE html>
  <html>
  <head>
  <title>Welcome to nginx!</title>
  <style>
      body {
          width: 35em;
          margin: 0 auto;
          font-family: Tahoma, Verdana, Arial, sans-serif;
      }
  </style>
  </head>
  <body>
  <h1>Welcome to nginx!</h1>
  <p>If you see this page, the nginx web server is successfully installed and
  working. Further configuration is required.</p>
  
  <p>For online documentation and support please refer to
  <a href="http://nginx.org/">nginx.org</a>.<br/>
  Commercial support is available at
  <a href="http://nginx.com/">nginx.com</a>.</p>
  
  <p><em>Thank you for using nginx.</em></p>
  </body>
  </html>
  ```

**Service Connect メトリクスを表示するには**  
Service Connect プロキシは、アプリケーション (HTTP、HTTP2、gRPC、または TCP 接続) メトリクスを CloudWatch メトリクス内に作成します。CloudWatch コンソールを使用する場合、Amazon ECS 名前空間にある **[DiscoveryName]**、(**[DiscoveryName, ServiceName, ClusterName]**)、**[TargetDiscoveryName]**、および (**[TargetDiscoveryName, ServiceName, ClusterName]**) という追加のメトリクスディメンションを確認します。これらのメトリクスおよびディメンションの詳細については、「Amazon CloudWatch Logs ユーザーガイド」の「[利用可能なメトリクスを表示する](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/viewing_metrics_with_cloudwatch.html)」を参照してください。