如何通过AWS CloudFormation模板动态配置EC2私网IP为安全组入站规则?
解决CloudFormation中动态将EC2实例IP分配给安全组入站规则的问题
问题场景
尝试使用AWS CloudFormation模板启动MyEC2Instance1和MyEC2Instance2两个EC2实例,并创建仅允许MyEC2Instance2访问的安全组,但模板执行时报错:
CIDR block {{MyEC2Instance2.PrivateIpAddresses[0]}}/32 is malformed (Service: AmazonEC2; Status Code: 400; Error Code: InvalidParameterValue; Request ID: dd12c2d9-fe00-481d-b267-d6ad355ab2b0; Proxy: null)
原CloudFormation模板
AWSTemplateFormatVersion: '2010-09-09' Parameters: SourceAccountId: Type: String Description: "AWS Account ID where the AMIs are shared from" SourceAmis: Type: List<String> Description: "List of shared encrypted AMI IDs" VpcId: Type: String Description: "VPC ID where the security groups will be created." Resources: MyEC2Instance1: Type: 'AWS::EC2::Instance' Properties: ImageId: !Select [0, !Ref SourceAmis] # Select the first AMI from the list InstanceType: t2.micro KeyName: New_Test_PIM SubnetId: subnet-xxxxxxxxxxxx Tags: - Key: Name Value: "Test_1_EC2" MyEC2Instance2: Type: 'AWS::EC2::Instance' Properties: ImageId: !Select [1, !Ref SourceAmis] # Select the second AMI from the list InstanceType: t2.micro KeyName: New_Test_PIM SubnetId: subnet-xxxxxxxxxxxxx Tags: - Key: Name Value: "Test_2_EC2" MyEIP: Type: 'AWS::EC2::EIP' MySecurityGroup: Type: 'AWS::EC2::SecurityGroup' DependsOn: MyEC2Instance2 Properties: GroupDescription: "Allow traffic from MyEC2Instance2s private IP" VpcId: !Ref "VpcId" MySecurityGroupIngress: Type: 'AWS::EC2::SecurityGroupIngress' DependsOn: MySecurityGroup Properties: GroupId: !GetAtt MySecurityGroup.GroupId IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Sub "{{MyEC2Instance2.PrivateIpAddresses[0]}}/32" Description: "Inbound Rule 1"
错误原因
- 私有IP引用语法错误:对于单网络接口的EC2实例,CloudFormation提供的私有IP属性是
PrivateIp,而非PrivateIpAddresses[0] - !Sub语法错误:使用
!Sub时,变量引用只需用${资源名.属性名}格式,不需要额外嵌套双大括号{{}}
解决方案
方案一:修正IP引用语法
直接修改MySecurityGroupIngress中的CidrIp字段,使用正确的属性和!Sub语法:
MySecurityGroupIngress: Type: 'AWS::EC2::SecurityGroupIngress' DependsOn: MySecurityGroup Properties: GroupId: !GetAtt MySecurityGroup.GroupId IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Sub "${MyEC2Instance2.PrivateIp}/32" Description: "Inbound Rule 1"
方案二:推荐用安全组替代IP(更灵活)
通过安全组之间的授权代替固定IP,即使实例重启导致私有IP变化,规则依然有效:
- 给
MyEC2Instance2分配专属安全组
MyEC2Instance2: Type: 'AWS::EC2::Instance' Properties: ImageId: !Select [1, !Ref SourceAmis] InstanceType: t2.micro KeyName: New_Test_PIM SubnetId: subnet-xxxxxxxxxxxxx SecurityGroups: [!Ref MyEC2Instance2SG] Tags: - Key: Name Value: "Test_2_EC2" MyEC2Instance2SG: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: "Security group for MyEC2Instance2" VpcId: !Ref VpcId
- 修改入站规则,引用安全组ID代替CIDR
MySecurityGroupIngress: Type: 'AWS::EC2::SecurityGroupIngress' DependsOn: MySecurityGroup Properties: GroupId: !GetAtt MySecurityGroup.GroupId IpProtocol: tcp FromPort: 22 ToPort: 22 SourceSecurityGroupId: !Ref MyEC2Instance2SG Description: "Inbound Rule 1"
内容的提问来源于stack exchange,提问作者CodingNinja
相关产品推荐
相关产品推荐

