了解如何使用 搭配自訂屬性使用 AWS Cloud Map 服務探索 AWS CLI - AWS Cloud Map

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

了解如何使用 搭配自訂屬性使用 AWS Cloud Map 服務探索 AWS CLI

本教學課程示範如何搭配自訂屬性使用 AWS Cloud Map 服務探索。您將建立使用 的微服務應用程式, AWS Cloud Map 以使用自訂屬性動態探索資源。應用程式由兩個 Lambda 函數組成,這些函數會將資料寫入 DynamoDB 資料表並從中讀取,並在其中註冊所有資源 AWS Cloud Map。

如需教學課程的 AWS Management Console 版本,請參閱 了解如何搭配自訂屬性使用 AWS Cloud Map 服務探索

先決條件

開始本教學課程之前,請先完成 中的步驟設定 以使用 AWS Cloud Map

建立 AWS Cloud Map 命名空間

命名空間是用來將應用程式服務分組的建構。在此步驟中,您將建立一個命名空間,允許透過 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
  2. 建立命名空間後,您可以擷取其 ID 以用於後續命令:

    aws servicediscovery list-namespaces \ --query "Namespaces[?Name=='cloudmap-tutorial'].Id" \ --output text
  3. 將命名空間 ID 存放在變數中以供日後使用:

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

建立 DynamoDB 資料表

接著,建立 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
  2. 等待資料表變成作用中,再繼續:

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

    此命令會等到資料表完全建立且可供使用。

建立 AWS Cloud Map 資料服務並註冊 DynamoDB 資料表

現在,在您的命名空間中建立服務來代表資料儲存資源:

  1. 執行下列命令來建立資料儲存資源 AWS Cloud Map 的服務:

    aws servicediscovery create-service \ --name data-service \ --namespace-id $NAMESPACE_ID \ --creator-request-id data-service-request
  2. 取得資料服務的服務 ID:

    DATA_SERVICE_ID=$(aws servicediscovery list-services \ --query "Services[?Name=='data-service'].Id" \ --output text)
  3. 使用指定資料表名稱的自訂屬性,將 DynamoDB 資料表註冊為服務執行個體:

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

    自訂屬性tablename=cloudmap可讓其他 服務動態探索 DynamoDB 資料表名稱。

為 Lambda 函數建立 IAM 角色

建立 Lambda 函數用來存取 AWS 資源的 IAM 角色:

  1. 建立 IAM 角色的信任政策文件:

    cat > lambda-trust-policy.json << EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOF
  2. 執行下列命令,使用信任政策建立 IAM 角色:

    aws iam create-role \ --role-name cloudmap-tutorial-role \ --assume-role-policy-document file://lambda-trust-policy.json
  3. 為具有最低權限許可的自訂 IAM 政策建立 檔案:

    cat > cloudmap-policy.json << EOF { "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" } ] } EOF
  4. 建立政策並將其連接至 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 函數以寫入資料

若要建立將資料寫入 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 資料表名稱,然後將資料寫入資料表。

  2. 封裝和部署 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
  3. 更新函數逾時以避免逾時錯誤:

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

建立 AWS Cloud Map 應用程式服務並註冊 Lambda 寫入函數

若要在命名空間中建立其他服務來代表應用程式函數,請依照下列步驟執行:

  1. 為應用程式函數建立服務:

    aws servicediscovery create-service \ --name app-service \ --namespace-id $NAMESPACE_ID \ --creator-request-id app-service-request
  2. 取得應用程式服務的服務 ID:

    APP_SERVICE_ID=$(aws servicediscovery list-services \ --query "Services[?Name=='app-service'].Id" \ --output text)
  3. 使用自訂屬性將 Lambda 寫入函數註冊為服務執行個體:

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

    自訂屬性action=write,並functionname=writefunction允許用戶端根據其用途探索此函數。

建立 Lambda 函數以讀取資料

若要建立從 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 資料表名稱,然後從資料表讀取資料。它包含錯誤處理和分頁註解。

  2. 封裝和部署 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
  3. 更新函數逾時:

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

將 Lambda 讀取函數註冊為服務執行個體

若要將 Lambda 讀取函數註冊為應用程式服務中的另一個服務執行個體,請遵循下列步驟:

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

自訂屬性action=read,並functionname=readfunction允許用戶端根據其用途探索此函數。

建立和執行用戶端應用程式

若要建立 Python 用戶端應用程式,以使用 AWS Cloud Map 來探索和叫用寫入函數,請遵循下列步驟:

  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 屬性的服務執行個體。

  2. 為讀取用戶端應用程式建立 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
  3. 執行寫入用戶端,將資料新增至 DynamoDB 資料表:

    python3 writeclient.py

    輸出應會顯示 HTTP 狀態碼為 200 的成功回應。

  4. 執行讀取用戶端以從 DynamoDB 資料表擷取資料:

    python3 readclient.py

    輸出應會顯示寫入資料表的資料,包括隨機產生的 ID 和「這是測試資料」值。

清除資源

完成教學課程後,請清除資源以避免產生額外費用。

  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
  2. 執行下列命令來刪除服務:

    aws servicediscovery delete-service \ --id $APP_SERVICE_ID aws servicediscovery delete-service \ --id $DATA_SERVICE_ID
  3. 執行下列命令來刪除命名空間:

    aws servicediscovery delete-namespace \ --id $NAMESPACE_ID
  4. 執行下列命令來刪除 Lambda 函數:

    aws lambda delete-function --function-name writefunction aws lambda delete-function --function-name readfunction
  5. 執行下列命令來刪除 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
  6. 執行下列命令來刪除 DynamoDB 資料表:

    aws dynamodb delete-table --table-name cloudmap
  7. 執行下列命令來清除暫存檔案:

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