

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# を使用してカスタム属性で AWS Cloud Map サービス検出を使用する方法について説明します。 AWS CLI
<a name="tutorial-microservices-cli"></a>

このチュートリアルでは、カスタム属性で AWS Cloud Map サービス検出を使用する方法を示します。カスタム属性を使用してリソースを動的に検出 AWS Cloud Map するために を使用するマイクロサービスアプリケーションを作成します。アプリケーションは、DynamoDB テーブルとの間でデータを書き込み、読み取る 2 つの Lambda 関数で構成され、すべてのリソースが登録されています AWS Cloud Map。

チュートリアル AWS マネジメントコンソール のバージョンについては、「」を参照してください[カスタム属性で AWS Cloud Map サービス検出を使用する方法について説明します。](tutorial-microservices.md)。

## 前提条件
<a name="prerequisites"></a>

このチュートリアルを開始する前に、「」の手順を完了してください[を使用するように をセットアップする AWS Cloud Map](setting-up-cloud-map.md)。

## AWS Cloud Map 名前空間を作成する
<a name="create-an-aws-cloud-map-namespace"></a>

名前空間は、アプリケーションのサービスをグループ化するために使用されるコンストラクトです。このステップでは、 AWS Cloud Map API コールを通じてリソースを検出できるようにする名前空間を作成します。

1. 次のコマンドを実行して、HTTP 名前空間を作成します。

   ```
   aws servicediscovery create-http-namespace \
     --name cloudmap-tutorial \
     --creator-request-id cloudmap-tutorial-request
   ```

   コマンドはオペレーション ID を返します。オペレーションのステータスは、次のコマンドで確認できます。

   ```
   aws servicediscovery get-operation \
     --operation-id operation-id
   ```

1. 名前空間が作成されたら、後続のコマンドで使用する ID を取得できます。

   ```
   aws servicediscovery list-namespaces \
     --query "Namespaces[?Name=='cloudmap-tutorial'].Id" \
     --output text
   ```

1. 後で使用するために、名前空間 ID を変数に保存します。

   ```
   NAMESPACE_ID=$(aws servicediscovery list-namespaces \
     --query "Namespaces[?Name=='cloudmap-tutorial'].Id" \
     --output text)
   ```

## DynamoDB テーブルを作成する
<a name="create-a-dynamodb-table"></a>

次に、アプリケーションのデータを保存する DynamoDB テーブルを作成します。

1. 次のコマンドを実行してテーブルを作成します。

   ```
   aws dynamodb create-table \
     --table-name cloudmap \
     --attribute-definitions AttributeName=id,AttributeType=S \
     --key-schema AttributeName=id,KeyType=HASH \
     --billing-mode PAY_PER_REQUEST
   ```

1. テーブルがアクティブになるまで待ってから次に進みます。

   ```
   aws dynamodb wait table-exists --table-name cloudmap
   ```

   このコマンドは、テーブルが完全に作成され、使用できる状態になるまで待機します。

## AWS Cloud Map データサービスを作成し、DynamoDB テーブルを登録する
<a name="create-an-aws-cloud-map-data-service-and-register-the-dynamodb-table"></a>

次に、名前空間にサービスを作成して、データストレージリソースを表します。

1. 次のコマンドを実行して、データストレージリソース AWS Cloud Map のサービスを作成します。

   ```
   aws servicediscovery create-service \
     --name data-service \
     --namespace-id $NAMESPACE_ID \
     --creator-request-id data-service-request
   ```

1. データサービスのサービス ID を取得します。

   ```
   DATA_SERVICE_ID=$(aws servicediscovery list-services \
     --query "Services[?Name=='data-service'].Id" \
     --output text)
   ```

1. DynamoDB テーブルをサービスインスタンスとして、テーブル名を指定するカスタム属性に登録します。

   ```
   aws servicediscovery register-instance \
     --service-id $DATA_SERVICE_ID \
     --instance-id data-instance \
     --attributes tablename=cloudmap
   ```

   カスタム属性`tablename=cloudmap`を使用すると、他の のサービスが DynamoDB テーブル名を動的に検出できます。

## Lambda 関数の IAM ロールを作成する
<a name="create-an-iam-role-for-lambda-functions"></a>

Lambda 関数がリソースへのアクセス AWS に使用する IAM ロールを作成します。

1. 次の JSON を使用して、IAM ロールの信頼ポリシードキュメントを作成します。

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": "lambda.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

------

1. 次のコマンドを実行して、信頼ポリシーを使用して IAM ロールを作成します。

   ```
   aws iam create-role \
     --role-name cloudmap-tutorial-role \
     --assume-role-policy-document file://lambda-trust-policy.json
   ```

1. 次の JSON を使用して、最小特権のアクセス許可を持つカスタム IAM ポリシーのファイルを作成します。

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": [
           "logs:CreateLogGroup",
           "logs:CreateLogStream",
           "logs:PutLogEvents"
         ],
         "Resource": "arn:aws:logs:*:*:*"
       },
       {
         "Effect": "Allow",
         "Action": [
           "servicediscovery:DiscoverInstances"
         ],
         "Resource": "*"
       },
       {
         "Effect": "Allow",
         "Action": [
           "dynamodb:PutItem",
           "dynamodb:Scan"
         ],
         "Resource": "arn:aws:dynamodb:*:*:table/cloudmap"
       }
     ]
   }
   ```

------

1. ポリシーを作成して IAM ロールにアタッチします。

   ```
   aws iam create-policy \
     --policy-name CloudMapTutorialPolicy \
     --policy-document file://cloudmap-policy.json
   
   POLICY_ARN=$(aws iam list-policies \
     --query "Policies[?PolicyName=='CloudMapTutorialPolicy'].Arn" \
     --output text)
   
   aws iam attach-role-policy \
     --role-name cloudmap-tutorial-role \
     --policy-arn $POLICY_ARN
   
   aws iam attach-role-policy \
     --role-name cloudmap-tutorial-role \
     --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
   ```

## Lambda 関数を作成してデータを書き込む
<a name="create-the-lambda-function-to-write-data"></a>

DynamoDB テーブルにデータを書き込む Lambda 関数を作成するには、次の手順に従います。

1. 書き込み関数の Python ファイルを作成します。

   ```
   cat > writefunction.py << EOF
   import json
   import boto3
   import random
   
   def lambda_handler(event, context):
       try:
           serviceclient = boto3.client('servicediscovery')
           
           response = serviceclient.discover_instances(
               NamespaceName='cloudmap-tutorial',
               ServiceName='data-service')
           
           if not response.get("Instances"):
               return {
                   'statusCode': 500,
                   'body': json.dumps({"error": "No instances found"})
               }
               
           tablename = response["Instances"][0]["Attributes"].get("tablename")
           if not tablename:
               return {
                   'statusCode': 500,
                   'body': json.dumps({"error": "Table name attribute not found"})
               }
              
           dynamodbclient = boto3.resource('dynamodb')
              
           table = dynamodbclient.Table(tablename)
           
           # Validate input
           if not isinstance(event, str):
               return {
                   'statusCode': 400,
                   'body': json.dumps({"error": "Input must be a string"})
               }
              
           response = table.put_item(
               Item={ 'id': str(random.randint(1,100)), 'todo': event })
              
           return {
               'statusCode': 200,
               'body': json.dumps(response)
           }
       except Exception as e:
           return {
               'statusCode': 500,
               'body': json.dumps({"error": str(e)})
           }
   EOF
   ```

   この関数は AWS Cloud Map 、 を使用してカスタム属性から DynamoDB テーブル名を検出し、テーブルにデータを書き込みます。

1. Lambda 関数をパッケージ化してデプロイします。

   ```
   zip writefunction.zip writefunction.py
   
   ROLE_ARN=$(aws iam get-role --role-name cloudmap-tutorial-role \
     --query 'Role.Arn' --output text)
   
   aws lambda create-function \
     --function-name writefunction \
     --runtime python3.12 \
     --role $ROLE_ARN \
     --handler writefunction.lambda_handler \
     --zip-file fileb://writefunction.zip \
     --architectures x86_64
   ```

1. 関数のタイムアウトを更新して、タイムアウトエラーを回避します。

   ```
   aws lambda update-function-configuration \
     --function-name writefunction \
     --timeout 5
   ```

## AWS Cloud Map アプリケーションサービスを作成し、Lambda 書き込み関数を登録する
<a name="create-an-aws-cloud-map-app-service-and-register-the-lambda-write-function"></a>

名前空間にアプリケーション関数を表す別のサービスを作成するには、次の手順に従います。

1. アプリケーション関数のサービスを作成します。

   ```
   aws servicediscovery create-service \
     --name app-service \
     --namespace-id $NAMESPACE_ID \
     --creator-request-id app-service-request
   ```

1. アプリサービスのサービス ID を取得します。

   ```
   APP_SERVICE_ID=$(aws servicediscovery list-services \
     --query "Services[?Name=='app-service'].Id" \
     --output text)
   ```

1. Lambda 書き込み関数をカスタム属性を持つサービスインスタンスとして登録します。

   ```
   aws servicediscovery register-instance \
     --service-id $APP_SERVICE_ID \
     --instance-id write-instance \
     --attributes action=write,functionname=writefunction
   ```

   カスタム属性`action=write`と `functionname=writefunction`は、クライアントがその目的に基づいてこの関数を検出できるようにします。

## Lambda 関数を作成してデータを読み取る
<a name="create-the-lambda-function-to-read-data"></a>

DynamoDB テーブルからデータを読み取る Lambda 関数を作成するには、次の手順に従います。

1. 読み取り関数の Python ファイルを作成します。

   ```
   cat > readfunction.py << EOF
   import json
   import boto3
   
   def lambda_handler(event, context):
       try:
           serviceclient = boto3.client('servicediscovery')
   
           response = serviceclient.discover_instances(
               NamespaceName='cloudmap-tutorial', 
               ServiceName='data-service')
           
           if not response.get("Instances"):
               return {
                   'statusCode': 500,
                   'body': json.dumps({"error": "No instances found"})
               }
               
           tablename = response["Instances"][0]["Attributes"].get("tablename")
           if not tablename:
               return {
                   'statusCode': 500,
                   'body': json.dumps({"error": "Table name attribute not found"})
               }
              
           dynamodbclient = boto3.resource('dynamodb')
              
           table = dynamodbclient.Table(tablename)
           
           # Use pagination for larger tables
           response = table.scan(
               Select='ALL_ATTRIBUTES',
               Limit=50  # Limit results for demonstration purposes
           )
           
           # For production, you would implement pagination like this:
           # items = []
           # while 'LastEvaluatedKey' in response:
           #     items.extend(response['Items'])
           #     response = table.scan(
           #         Select='ALL_ATTRIBUTES',
           #         ExclusiveStartKey=response['LastEvaluatedKey']
           #     )
           # items.extend(response['Items'])
   
           return {
               'statusCode': 200,
               'body': json.dumps(response)
           }
       except Exception as e:
           return {
               'statusCode': 500,
               'body': json.dumps({"error": str(e)})
           }
   EOF
   ```

   この関数は、 AWS Cloud Map を使用して DynamoDB テーブル名を検出し、テーブルからデータを読み取ります。これには、エラー処理とページ分割コメントが含まれます。

1. Lambda 関数をパッケージ化してデプロイします。

   ```
   zip readfunction.zip readfunction.py
   
   aws lambda create-function \
     --function-name readfunction \
     --runtime python3.12 \
     --role $ROLE_ARN \
     --handler readfunction.lambda_handler \
     --zip-file fileb://readfunction.zip \
     --architectures x86_64
   ```

1. 関数のタイムアウトを更新します。

   ```
   aws lambda update-function-configuration \
     --function-name readfunction \
     --timeout 5
   ```

## Lambda 読み取り関数をサービスインスタンスとして登録する
<a name="register-the-lambda-read-function-as-a-service-instance"></a>

Lambda 読み取り関数をアプリケーションサービス内の別のサービスインスタンスとして登録するには、次の手順に従います。

```
aws servicediscovery register-instance \
  --service-id $APP_SERVICE_ID \
  --instance-id read-instance \
  --attributes action=read,functionname=readfunction
```

カスタム属性`action=read`と `functionname=readfunction`は、クライアントがその目的に基づいてこの関数を検出できるようにします。

## クライアントアプリケーションを作成して実行する
<a name="create-and-run-client-applications"></a>

書き込み関数を検出して呼び出す AWS Cloud Map ために が使用する Python クライアントアプリケーションを作成するには、次の手順に従います。

1. 書き込みクライアントアプリケーション用の Python ファイルを作成します。

   ```
   cat > writeclient.py << EOF
   import boto3
   import json
   
   try:
       serviceclient = boto3.client('servicediscovery')
   
       print("Discovering write function...")
       response = serviceclient.discover_instances(
           NamespaceName='cloudmap-tutorial', 
           ServiceName='app-service', 
           QueryParameters={ 'action': 'write' }
       )
   
       if not response.get("Instances"):
           print("Error: No instances found")
           exit(1)
           
       functionname = response["Instances"][0]["Attributes"].get("functionname")
       if not functionname:
           print("Error: Function name attribute not found")
           exit(1)
           
       print(f"Found function: {functionname}")
   
       lambdaclient = boto3.client('lambda')
   
       print("Invoking Lambda function...")
       resp = lambdaclient.invoke(
           FunctionName=functionname, 
           Payload='"This is a test data"'
       )
   
       payload = resp["Payload"].read()
       print(f"Response: {payload.decode('utf-8')}")
       
   except Exception as e:
       print(f"Error: {str(e)}")
   EOF
   ```

   このクライアントは、 `QueryParameters`オプションを使用して、 `action=write` 属性を持つサービスインスタンスを検索します。

1. 読み取りクライアントアプリケーションの Python ファイルを作成します。

   ```
   cat > readclient.py << EOF
   import boto3
   import json
   
   try:
       serviceclient = boto3.client('servicediscovery')
   
       print("Discovering read function...")
       response = serviceclient.discover_instances(
           NamespaceName='cloudmap-tutorial', 
           ServiceName='app-service', 
           QueryParameters={ 'action': 'read' }
       )
   
       if not response.get("Instances"):
           print("Error: No instances found")
           exit(1)
           
       functionname = response["Instances"][0]["Attributes"].get("functionname")
       if not functionname:
           print("Error: Function name attribute not found")
           exit(1)
           
       print(f"Found function: {functionname}")
   
       lambdaclient = boto3.client('lambda')
   
       print("Invoking Lambda function...")
       resp = lambdaclient.invoke(
           FunctionName=functionname, 
           InvocationType='RequestResponse'
       )
   
       payload = resp["Payload"].read()
       print(f"Response: {payload.decode('utf-8')}")
       
   except Exception as e:
       print(f"Error: {str(e)}")
   EOF
   ```

1. 書き込みクライアントを実行して、DynamoDB テーブルにデータを追加します。

   ```
   python3 writeclient.py
   ```

   出力には、HTTP ステータスコード 200 で成功したレスポンスが表示されます。

1. 読み取りクライアントを実行して、DynamoDB テーブルからデータを取得します。

   ```
   python3 readclient.py
   ```

   出力には、ランダムに生成された ID や「これはテストデータです」値など、テーブルに書き込まれたデータが表示されます。

## リソースをクリーンアップする
<a name="clean-up-resources"></a>

チュートリアルが終了したら、追加料金が発生しないようにリソースをクリーンアップします。

1. まず、次のコマンドを実行してサービスインスタンスの登録を解除します。

   ```
   aws servicediscovery deregister-instance \
     --service-id $APP_SERVICE_ID \
     --instance-id read-instance
   
   aws servicediscovery deregister-instance \
     --service-id $APP_SERVICE_ID \
     --instance-id write-instance
   
   aws servicediscovery deregister-instance \
     --service-id $DATA_SERVICE_ID \
     --instance-id data-instance
   ```

1. 次のコマンドを実行して、サービスを削除します。

   ```
   aws servicediscovery delete-service \
     --id $APP_SERVICE_ID
   
   aws servicediscovery delete-service \
     --id $DATA_SERVICE_ID
   ```

1. 次のコマンドを実行して、名前空間を削除します。

   ```
   aws servicediscovery delete-namespace \
     --id $NAMESPACE_ID
   ```

1. 次のコマンドを実行して、Lambda 関数を削除します。

   ```
   aws lambda delete-function --function-name writefunction
   aws lambda delete-function --function-name readfunction
   ```

1. 次のコマンドを実行して、IAM ロールとポリシーを削除します。

   ```
   aws iam detach-role-policy \
     --role-name cloudmap-tutorial-role \
     --policy-arn $POLICY_ARN
   
   aws iam detach-role-policy \
     --role-name cloudmap-tutorial-role \
     --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
   
   aws iam delete-policy \
     --policy-arn $POLICY_ARN
   
   aws iam delete-role --role-name cloudmap-tutorial-role
   ```

1. 次のコマンドを実行して、DynamoDB テーブルを削除します。

   ```
   aws dynamodb delete-table --table-name cloudmap
   ```

1. 次のコマンドを実行して、一時ファイルをクリーンアップします。

   ```
   rm -f lambda-trust-policy.json cloudmap-policy.json writefunction.py readfunction.py writefunction.zip readfunction.zip writeclient.py readclient.py
   ```