내용으로 건너뛰기

AWS CloudFormation을 사용하여 AWS PrivateLink 엔드포인트가 있는 Amazon EC2에 DataSync 에이전트를 자동으로 배포하려면 어떻게 해야 합니까?

4분 분량
0

AWS CloudFormation을 사용하여 AWS PrivateLink 엔드포인트가 있는 프라이빗 서브넷의 Amazon Elastic Compute Cloud(Amazon EC2)에 AWS DataSync 에이전트를 생성하려고 합니다.

해결 방법

AWS CloudFormation을 사용하면 AWS PrivateLink 엔드포인트를 통해 Amazon EC2 인스턴스에서 실행되는 DataSync 에이전트를 자동으로 생성하고 활성화할 수 있습니다.

Lambda 함수를 사용하여 DataSync 에이전트의 활성화 키를 검색하는 사용자 지정 리소스를 사용하는 YAML 템플릿을 사용하십시오. 다음 YAML 코드를 복사한 후 AWS CloudFormation 템플릿으로 저장하십시오.

AWSTemplateFormatVersion: '2010-09-09'  
Description: >-  
  This CloudFormation template deploys an EC2 instance with the AWS DataSync  
  agent AMI.  

Metadata:  
  AWS::CloudFormation::Interface:  
    ParameterGroups:  
    - Label:  
        default: Deploy DataSync agent on Amazon EC2 via PrivateLink VPC endpoint  
      Parameters:  
      - InstanceType  
      - ImageId  
      - SubnetId  
      - VpcId  
    ParameterLabels:  
      InstanceType:  
        default: Agent EC2 Instance Size  
      SubnetId:  
        default: Select your Subnet  
      VpcId:  
        default: Select your VPC Contains Above Subnet  
      ImageId:  
        default: Agent Image (Keep default - Do NOT change)  

Parameters:  
  InstanceType:  
    Description: Instance type for the DataSync agent EC2 instance  
    Type: String  
    Default: m5.2xlarge  
    AllowedValues:  
      - m5.2xlarge  
      - m5.4xlarge  
    ConstraintDescription: must be a valid EC2 instance type.  

  ImageId:  
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>  
    Default: /aws/service/datasync/ami  

  SubnetId:  
    Type: AWS::EC2::Subnet::Id  
    Description: The subnet where to deploy the instance  

  VpcId:   
    Type: AWS::EC2::VPC::Id  
    Description: Select the VPC containing the subnet selected above.  

Resources:  
  NewKeyPair:  
    Type: 'AWS::EC2::KeyPair'  
    Properties:  
      KeyName: !Sub "ssh-key-cfn-stack-${AWS::StackName}"  

  DataSyncAgentInstance:  
    Type: AWS::EC2::Instance  
    Properties:  
      ImageId: !Ref ImageId  
      InstanceType: !Ref InstanceType  
      SubnetId: !Ref SubnetId  
      SecurityGroupIds:  
        - !Ref DataSyncAgentSecurityGroup  
      KeyName: !Ref NewKeyPair  
      Tags:  
        - Key: "Name"  
          Value: !Ref 'AWS::StackName'  

  DataSyncAgentSecurityGroup:  
    Type: AWS::EC2::SecurityGroup  
    Properties:  
      GroupDescription: Enable SSH access and DataSync agent communication  
      SecurityGroupIngress:  
        - IpProtocol: tcp  
          FromPort: 80  
          ToPort: 80  
          CidrIp: 0.0.0.0/0  
      VpcId: !Ref VpcId  

  DsInterfaceEndpoint:  
    Type: 'AWS::EC2::VPCEndpoint'  
    Properties:  
      VpcEndpointType: 'Interface'  
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.datasync'  
      VpcId: !Ref VpcId  
      SubnetIds:   
        - !Ref SubnetId  
      SecurityGroupIds:  
        - !Ref DsVpceSecurityGroup  

  DsVpceSecurityGroup:  
    Type: 'AWS::EC2::SecurityGroup'  
    Properties:  
      GroupDescription: 'Allow control traffic from agent'  
      VpcId: !Ref VpcId  
      SecurityGroupIngress:  
        - IpProtocol: tcp  
          FromPort: 443  
          ToPort: 443  
          CidrIp: !Sub "${DataSyncAgentInstance.PrivateIp}/32"  
        - IpProtocol: tcp  
          FromPort: 1024  
          ToPort: 1064  
          CidrIp: !Sub "${DataSyncAgentInstance.PrivateIp}/32"  
        - IpProtocol: tcp  
          FromPort: 22  
          ToPort: 22  
          CidrIp: !Sub "${DataSyncAgentInstance.PrivateIp}/32"  

  LambdaActivator:  
      Type: AWS::Lambda::Function  
      DependsOn: DsInterfaceEndpoint  
      Properties:  
        FunctionName: !Ref 'AWS::StackName'  
        Description: 'Lambda function to get the activation key'  
        VpcConfig:   
          SecurityGroupIds:  
            - !Ref DataSyncAgentSecurityGroup  
          SubnetIds:  
            - !Ref SubnetId  
        Environment:  
          Variables:  
            DsDnsEntryList: !Select [1, !Split [':', !Select [0, !GetAtt DsInterfaceEndpoint.DnsEntries]]]  
        Code:  
          ZipFile: !Sub |  
            import boto3, json, urllib.request, socket, time, os  
            import cfnresponse  

            print('Loading function')  
            def handler(event, context):  
                print('EVENT:')  
                print(event)  
                responseData = {}  
                try:  
                    if event['RequestType'] == "Create":  
                        agentIp = "${DataSyncAgentInstance.PrivateIp}"  
                        awsRegion = "${AWS::Region}"  
                        VpceDnsName = os.environ['DsDnsEntryList']  
                        VpceIp = socket.gethostbyname(VpceDnsName)  

                        print("Agent IP: " + agentIp)  
                        print("AWS Region: " + awsRegion)  
                        print("VPC Endpoint DNS Name: " + VpceDnsName)  
                        print("VPC IP: " + VpceIp)  

                        activateUrl = "http://" + agentIp + "/?gatewayType=SYNC&activationRegion=" + awsRegion + "&privateLinkEndpoint=" + VpceIp + "&endpointType=PRIVATE_LINK&no_redirect"  
                        print(activateUrl)  

                        time.sleep(30)  
                        print("Sending URL for Getting activation key")  
                        res = urllib.request.urlopen(urllib.request.Request(  
                            url=activateUrl,  
                            method='GET'),  
                            timeout=600)  

                        print("HTTP Response :" + str(res.status) + " " + res.reason)  
                        activationKey = res.read().decode('utf-8')  

                        responseData['Data'] = activationKey  

                    elif event['RequestType'] == "Delete":  
                        print("Lambda is being deleted by the CloudFormation stack!!")  

                    else:  
                        print("Should not perform actions!!")  

                    cfnresponse.send(event, context, cfnresponse.SUCCESS,   
                            responseData, 'cfn-customresource-id')  

                    return {  
                      'body': json.dumps('Execution completed!')  
                    }  

                except Exception as e:  
                    print(e)  
                    cfnresponse.send(event, context, cfnresponse.FAILED,   
                            responseData, 'cfn-customresource-id')  
                    raise e  

        Handler: index.handler  
        Role: !GetAtt FunctionIamRole.Arn  
        Runtime: python3.12  
        Timeout: 300  

  ActivatorInvoker:  
    DependsOn:  
      - LambdaActivator  
      - DataSyncAgentInstance  
    Type: AWS::CloudFormation::CustomResource  
    Properties:  
      ServiceToken: !GetAtt LambdaActivator.Arn  

  FunctionIamRole:  
    Type: AWS::IAM::Role  
    Properties:  
      AssumeRolePolicyDocument:  
        Version: '2012-10-17'  
        Statement:  
          - Effect: Allow  
            Principal:  
              Service:  
                - lambda.amazonaws.com  
            Action:  
              - 'sts:AssumeRole'  
      ManagedPolicyArns:  
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"  
      Policies:   
        - PolicyName: !Sub "ec2-permissions-lambda-${AWS::StackName}"  
          PolicyDocument:  
            Version: '2012-10-17'  
            Statement:  
              - Effect: Allow  
                Action:  
                  - ec2:CreateNetworkInterface  
                  - ec2:DeleteNetworkInterface  
                  - ec2:DescribeNetworkInterfaces  
                Resource: "*"  

  ActiveAgent:  
    Type: AWS::DataSync::Agent  
    Properties:  
      ActivationKey: !GetAtt ActivatorInvoker.Data  
      AgentName: !Sub "datasync-agent-created-from-cfn-${AWS::StackName}"  
      VpcEndpointId: !GetAtt DsInterfaceEndpoint.Id  
      SecurityGroupArns:  
        - !Sub "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group/${DsVpceSecurityGroup}"  
      SubnetArns:  
        - !Sub "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${SubnetId}"  

Outputs:  
  KeyPairId:  
    Description: KeyPairId of the newly created SSH Key to connect the EC2 (you can download the key under Parameter Store, a capability of AWS Systems Manager)  
    Value: !GetAtt NewKeyPair.KeyPairId  

  PrivateIp:  
    Description: PrivateIp of the newly created EC2 instance  
    Value: !GetAtt DataSyncAgentInstance.PrivateIp  

  ActivationKey:  
    Description: Agent Activation Key  
    Value: !GetAtt ActivatorInvoker.Data

AWS CloudFormation 콘솔을 사용하여 AWS CloudFormation 스택을 생성하십시오. 스택 생성 페이지의 사전 조건 - 템플릿 준비에서 기존 템플릿 선택을 선택합니다. 템플릿 지정에서 템플릿 파일 업로드를 선택한 다음, 저장한 템플릿을 선택합니다.

참고: 파라미터 섹션에서 지정한 프라이빗 서브넷은 Amazon Virtual Private Cloud(VPC) 게이트웨이 엔드포인트를 통해 Amazon Simple Storage Service(Amazon S3) 서비스에 액세스할 수 있어야 합니다.

AWS 공식업데이트됨 일 년 전
댓글 없음

관련 콘텐츠