在CloudFormation中为EMR主节点专用IP地址创建A记录

时间:2019-03-27 20:07:55

标签: amazon-web-services amazon-cloudformation amazon-emr amazon-route53

我想知道是否有一种方法可以在CloudFormation配置中声明一个AWS::Route53::RecordSet,该配置指向一个EMR群集上主节点的私有IP地址,该地址也是在相同配置中定义的? / p>

CloudFormation脚本应该是不言自明的:

  rVPC:
    Type: AWS::EC2::VPC
    # ... 

  rMyEMRCluster:
    Type: AWS::EMR::Cluster
    # ...

  rPrivateHostedZone:
    Type: AWS::Route53::HostedZone
    Properties:
      Name: "example.com"
      VPCs:
        - VPCId: !Ref rVPC
          VPCRegion: ${AWS::Region}

  rMyRecordSet:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref rPrivateHostedZone
      Name: !Sub "sub.example.com"
      Region: ${AWS::Region}
      Type: A
      ResourceRecords:
        # TODO: How can I do something like this:
        # - GetAtt rMyEMRCluster.MasterNodePrivateIpAddress

3 个答案:

答案 0 :(得分:1)

不太。

唯一可用的返回值是MasterPublicDNS。但是,这应该解析为主节点的IP地址。

请参阅AWS::EMR::Cluster - AWS CloudFormation返回值部分。

答案 1 :(得分:0)

您可以尝试为此使用自定义资源。它可以使用emr:ListInstances来获取IP,然后可以在Route 53资源中使用该结果。

我还没有尝试过,但是像下面这样的东西应该可以工作。如果EMR需要花费一些时间来创建主节点,而CloudFormation尚未等待,则可能需要在其中添加一些延迟。

Resources:
  DescribeClusterRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: DescribeCluster
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Action: elasticmapreduce:ListInstances
                Effect: Allow
                Resource: "*"
  GetClusterPrivateIP:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.6
      Handler: index.handler
      Role: !Sub ${DescribeClusterRole.Arn}
      Timeout: 60
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import traceback

          def handler(event, context):
            try:
              response = boto3.client('emr').list_instances(
                  ClusterId=event['ResourceProperties']['ClusterId'],
                  InstanceGroupTypes=['MASTER'],
              )

              ip = response['Instances'][0]['PrivateIpAddress']

              cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, ip)
            except:
              traceback.print_last()
              cfnresponse.send(event, context, cfnresponse.FAIL, {}, "ok")
  MasterIp:
    Type: Custom::EmrMasterIp
    Properties:
      ServiceToken: !Sub ${GetClusterPrivateIP.Arn}
      ClusterId: !Ref rMyEMRCluster
  rMyRecordSet:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref rPrivateHostedZone
      Name: !Sub "sub.example.com"
      Region: ${AWS::Region}
      Type: A
      ResourceRecords:
        !Ref MasterIp

答案 2 :(得分:0)

如果可以从您的本地网络解析MasterPublicDNS。通常不是。因此,您必须将MasterPublicDNS转换为IP地址,您可以像下面这样

#ResourceRecords: # - !GetAtt rMyEMRCluster.MasterPublicDNS # convert ip-10-11-12-13.ec2.internal to 10.11.12.13 ResourceRecords: - !Join - '.' - - !Select - 1 - !Split - "-" - !Select [0, !Split [".ec2.internal", !GetAtt rMyEMRCluster.MasterPublicDNS]] - !Select - 2 - !Split - "-" - !Select [0, !Split [".ec2.internal", !GetAtt rMyEMRCluster.MasterPublicDNS]] - !Select - 3 - !Split - "-" - !Select [0, !Split [".ec2.internal", !GetAtt rMyEMRCluster.MasterPublicDNS]] - !Select - 4 - !Split - "-" - !Select [0, !Split [".ec2.internal", !GetAtt rMyEMRCluster.MasterPublicDNS]]