如何在 Cloudformation 模板中将 EIP 分配给 VPC 的 Autoscaling Group

Posted

技术标签:

【中文标题】如何在 Cloudformation 模板中将 EIP 分配给 VPC 的 Autoscaling Group【英文标题】:How to assign EIP to Autoscaling Group of VPC in Cloudformation template 【发布时间】:2016-04-23 07:22:24 【问题描述】:

我想将我保留的弹性 IP(ec2 经典 ip)之一分配给 VPC 中的 Autoscaling 组。使用 AWS Cli 我将 ip 移动到 vpc:

$ aws ec2 move-address-to-vpc --public-ip 23.23.23.23

并在 aws concole 中看到,此 IP 已传递给 VPC。 并在资源中 Cloudformation 模板中 AutoscalingGroup 的标签中分配:

"Process": 
        "Type" : "AWS::AutoScaling::AutoScalingGroup",
        "Properties": 
            "LaunchConfigurationName": "Ref": "PreprocessorLC",
            "LoadBalancerNames": ["Ref": "ProcessELB"],
            "VPCZoneIdentifier" : [ "Fn::Join" : [",", [  "Ref" : "PublicSubnet1",  "Ref" : "PublicSubnet2" ]]],
            "AvailabilityZones": "Ref": "AZs",
            "MinSize" : "1",
            "MaxSize" : "1",
            "HealthCheckGracePeriod": 300,
            "Tags" : [
                "Key": "Name", "Value": "Fn::Join": ["", ["Ref": "Env", "-Process"]], "PropagateAtLaunch": true,
                "Key": "WorkersScalingGroup", "Value": "Fn::Join": ["", ["Offering-", "Ref": "Env",  "-Process-Worker"]], "PropagateAtLaunch": true,
                "Key": "EIP", "Value": "Ref": "ProcessIP", "PropagateAtLaunch": true,
                "Key": "Environment", "Value": "Ref": "Env", "PropagateAtLaunch": true
            ]
        
    

并在参数中添加了“ProcessIP”的值:

"ProcessIP":
            "Description": "DEV: 23.23.23.23",
            "Type": "String",
            "Default": "23.23.23.23",
            "AllowedValues": ["23.23.23.23"]

而且它不起作用。仍然获得随机IP。 如果有人可以告诉我哪里错了,或者应该添加什么使它起作用?

谢谢!

【问题讨论】:

【参考方案1】:

您需要明确地将弹性 IP 地址与所需的 EC2 实例相关联。您可以在启动时在用户数据脚本中执行此操作,也可以通过其他脚本或配置管理在外部执行此操作。

PropagateAtLaunch 只是将标签从 Auto Scaling 组传播到由于 Auto Scaling 操作而启动的任何实例。我不知道有什么魔法会导致标记的弹性 IP 地址与启动的实例相关联。

查看更多关于使用 EIP here 编写启动时脚本的讨论和示例。

【讨论】:

如果没有 VPC,将其放入标签中可以正常工作。你知道这个特定问题的任何“脚本或配置管理”示例吗? 顺便说一下,我很想知道这在 EC2 Classic 中有效。我以前没见过。你确定那里大概没有脚本。 我们就这样工作了半年多。我确定,因为我写的) 我没有怀疑你;我只是没见过这个。例如,我没有看到任何与“PropagateAtLaunch”和“EIP”相关的文档表明它将导致启动的实例与该 EIP 关联。如果 Auto Scaling 启动多个实例,我也看不出这将如何工作(最后启动的实例会“赢得”EIP 吗?)如果你有任何文档,请指点我。谢谢。 AWS 文档很糟糕。在启动时传播您在参数中输入的 EIP,显然是针对我的,没有任何示例。在这里您可以看到其他示例:docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/… 并且仅适用于第一个实例。【参考方案2】:

这是简单的 bash 脚本:

#!/bin/sh
# Region in Which instance is running
EC2_REGION='us-east-1'
AWS_ACCESS_KEY='xxxxxxxxxxxx'
AWS_SECRET_ACCESS_KEY='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

#Instance ID captured through Instance meta data
InstanceID=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id`

#Elastic IP captured through the EIP instance tag
Elastic_IP=`/opt/aws/apitools/ec2/bin/ec2-describe-tags -O $AWS_ACCESS_KEY -W $AWS_SECRET_ACCESS_KEY --filter resource-id=$InstanceID --filter key='EIP' | cut -f5`
Allocate_ID=`/opt/aws/apitools/ec2/bin/ec2-describe-tags -O $AWS_ACCESS_KEY -W $AWS_SECRET_ACCESS_KEY --filter resource-id=$InstanceID --filter key="AllocationID" | cut -f5`

#Assigning Elastic IP to Instance
aws ec2 associate-address --instance-id $InstanceID --allocation-id $Allocate_ID

【讨论】:

这里的 aws 论坛上有一个类似方法的讨论forums.aws.amazon.com/message.jspa?messageID=498761【参考方案3】:

就我而言,我需要保留一组未分配的 EIP,并在它们启动时将它们随机分配给 EC2。这样我就始终知道我的服务器将使用我可以在其他地方列入白名单的特定 IP 列表。

如果您创建多个名为“prod-pool”的 EIP,则可以使用此脚本。

apt install -y jq awscli
ALLOCATION_ID=`aws ec2 describe-addresses --filters="Name=tag:Name,Values=prod-pool" | jq -r '.Addresses[] | "\(.InstanceId) \(.AllocationId)"' | grep null | awk 'print $2' | xargs shuf -n1 -e`

if [ ! -z $ALLOCATION_ID ]; then
    aws ec2 associate-address --instance-id $INSTANCE_ID --allocation-id $ALLOCATION_ID --allow-reassociation
fi

您可以将此策略附加到您的 IAM 用户


  "Version": "2012-10-17",
  "Statement": [
    
      "Sid": "AllowEIPAttachment",
      "Effect": "Allow",
      "Resource": [
        "*"
      ],
      "Action": [
        "ec2:AssociateAddress",
        "ec2:DisassociateAddress"
      ]
    
  ]

【讨论】:

这是较新的,因此没有声誉,但恕我直言,这是最好的,因为它使用了保持凭据不公开的能力,并且很容易在许多自动化情况下应用。跨度> 这看起来很棒。但是它怎么知道关联免费 IP 而没有占用一个呢? @Nir 发生grep null 只选择了一个没有分配AllocationId 的IP【参考方案4】:

我创建了一个 AWS Lambda 函数,它会自动将池中的弹性 IP 地址绑定到自动扩展组的实例。这减少了在实例的引导脚本中获取 EIP 地址的需要。有关完整的说明,请查看 https://binx.io/blog/2019/09/02/how-to-dynamically-bind-elastic-ip-addresses-to-an-auto-scaling-group/

【讨论】:

以上是关于如何在 Cloudformation 模板中将 EIP 分配给 VPC 的 Autoscaling Group的主要内容,如果未能解决你的问题,请参考以下文章

如何在 CloudFormation 中将字符串列表作为参数传递?

我可以在参数部分 AWS CloudFormation 模板中将标签定义为参数吗

在 CloudFormation 中将 Cognito 验证类型设置为链接

在 cloudformation 中将标签作为参数传递

Cloudformation 模板验证

如何在 Cloudformation 模板/CDK 中添加 AWS IoT 配置模板