通过AWS和CloudFormation自动分配IPv6地址

4

是否有办法在自动缩放组+启动配置中将IPv6地址自动分配给EC2实例?

VPC和子网都已设置为IPv6。手动创建的实例可以正常工作。 我也可以手动分配它们,但似乎找不到在CloudFormation中执行此操作的方法。

2个回答

3
当前状态是,CloudFormation对IPv6的支持是可行的。虽然不太好用也不完整,但您可以使用它来构建堆栈——我必须使用2个自定义资源:
- 第一个是通用资源,我在其他地方也使用它,并在此处重复使用,以解决缺失功能的问题,即从VPC的/56自动提供的网络构建子网/64 CIDR块。 - 另一个我必须添加特别是为了解决EC2 API中的错误,CloudFormation正确使用。
以下是我的设置:

1. 将IPv6 CIDR块添加到您的VPC:

VPCipv6:
  Type: "AWS::EC2::VPCCidrBlock"
  Properties:
    VpcId: !Ref VPC
    AmazonProvidedIpv6CidrBlock: true

2. 提取网络前缀以创建/64子网:

如此答案所解释的那样。

VPCipv6Prefix:
  Type: Custom::Variable
  Properties:
    ServiceToken: !GetAtt [ IdentityFunc, Arn ]
    Value: !Select [ 0, !Split [ "00::/", !Select [ 0, !GetAtt VPC.Ipv6CidrBlocks ] ] ]
IdentityFunc是Lambda中为"自定义变量"实现的"恒等函数",就像这个答案所描述的那样。与链接中的答案不同的是,我直接在同一堆栈中实现该函数,因此更易于维护。点击此处查看要点

3. 将IPv6默认路由添加到您的Internet网关:

RouteInternet6:
  Type: "AWS::EC2::Route"
  Properties:
    RouteTableId: !Ref RouteTableMain
    DestinationIpv6CidrBlock: "::/0"
    GatewayId: !Ref IGWPublicNet
  DependsOn:
    - IGWNetAttachment

IGWNetAttachment 是对堆栈中定义的 AWS::EC2::VPCGatewayAttachment 的引用。如果您不等待它,路由可能无法正确设置。

4. 在您的子网中添加一个 IPv6 CIDR 块:

SubnetA:
  Type: AWS::EC2::Subnet
  Properties:
    AvailabilityZone: !Select [ 0, !GetAZs { Ref: "AWS::Region" } ]
    CidrBlock: 172.20.0.0/24
    MapPublicIpOnLaunch: true
    # The following does not work if MapPublicIpOnLaunch because of EC2 bug
    ## AssignIpv6AddressOnCreation: true 
    Ipv6CidrBlock: !Sub "${VPCipv6Prefix.Value}00::/64"
    VpcId:
      Ref: VPC

关于“AssignIpv6AddressOnCreation” 这一部分被注释掉——通常你就是这么做的,但是 EC2 API 中有一个 bug 阻止了它的工作——并非 CloudFormation 的问题。在AWS 论坛中记录了此问题以及解决方案,下面我将呈现这个解决方案。
5. 通过另一个 lambda 修复“AssignIpv6AddressOnCreation”的问题:
这是 lambda 的设置:
IPv6WorkaroundRole:
  Type: AWS::IAM::Role
  Properties:
    AssumeRolePolicyDocument:
      Version: '2012-10-17'
      Statement:
      - Effect: Allow
        Principal:
          Service:
          - lambda.amazonaws.com
        Action:
        - sts:AssumeRole
    Path: "/"
    Policies:
      - PolicyName: !Sub "ipv6-fix-logs-${AWS::StackName}"
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Effect: Allow
            Action:
            - logs:CreateLogGroup
            - logs:CreateLogStream
            - logs:PutLogEvents
            Resource: arn:aws:logs:*:*:*
      - PolicyName: !Sub "ipv6-fix-modify-${AWS::StackName}"
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Effect: Allow
            Action:
            - ec2:ModifySubnetAttribute
            Resource: "*"

IPv6WorkaroundLambda:
  Type: AWS::Lambda::Function
  Properties:
    Handler: "index.lambda_handler"
    Code: #import cfnresponse below required to send respose back to CFN
      ZipFile:
        Fn::Sub: |
          import cfnresponse
          import boto3

          def lambda_handler(event, context):
              if event['RequestType'] is 'Delete':
                cfnresponse.send(event, context, cfnresponse.SUCCESS)
                return

              responseValue = event['ResourceProperties']['SubnetId']
              ec2 = boto3.client('ec2', region_name='${AWS::Region}')
              ec2.modify_subnet_attribute(AssignIpv6AddressOnCreation={
                                              'Value': True
                                            },
                                            SubnetId=responseValue)
              responseData = {}
              responseData['SubnetId'] = responseValue
              cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
    Runtime: python2.7
    Role: !GetAtt IPv6WorkaroundRole.Arn
    Timeout: 30

这是如何使用它的:

IPv6WorkaroundSubnetA:
  Type: Custom::SubnetModify
  Properties:
    ServiceToken: !GetAtt IPv6WorkaroundLambda.Arn
    SubnetId: !Ref SubnetA

这个调用与自动缩放组一起完成设置,但很不可能失败 - 我运行了几十次,它从未出现过在第一个实例启动之前无法正确设置字段的问题。

感谢@Guss。我仍然认为这是2020年末的一个问题。 - Matt Rowles

1
我遇到了一个非常类似的问题,并与AWS支持团队进行了交流。目前情况是CloudFormation中的IPv6支持非常有限。
最终我们为许多IPv6特定的事情创建了自定义资源。我们有一个自定义资源,它可以:
  • 在子网上启用IPv6分配
  • 创建出口网关
  • 添加出口网关的路由(内置的Route资源指向EIGW时会“无法稳定”)
自定义资源只是执行“原始”API调用的Lambda函数和授予Lambda足够权限执行该API调用的IAM角色。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接