CloudFormation/EC2-访问模板中的 EC2 实例的 IP 地址?

CloudFormation/EC2-访问模板中的 EC2 实例的 IP 地址?

我正在尝试定义一个 Cassandra 节点集群,以及一些其他实例(一些中间件和应用服务器)。我希望能够将 Cassandra 节点的(内部)IP 地址添加到中间件的配置中,并将第一个 Cassandra 节点的 IP 添加到其他节点的配置中,作为种子节点。我可以完全从模板内部实现这一点吗?(在 AMI 中调用脚本是可以的,但集中配置或平台未提供的任何类型的远程数据库则不行)

谢谢! 安德拉斯

编辑:我忘了提到我还需要使用实例的 IP 来更新相关的安全组。

答案1

在对 AWS 文档进行一番挖掘之后,我发现你可以引用在同一模板中创建的资源的属性,只要它们 a) 在你的引用之前定义 b) 不指向正在创建的资源(没有循环依赖)

b) 意味着要找出 EC2 节点自己的 IP,我确实必须调用 ceejayoz 上面提到的 aws URL

这是我对 Cassandra 节点实例资源的定义。请注意,我在配置文件中放置了标记,以便能够安全地插入正确的值,但您始终可以恢复为简单地替换默认值(例如,将“initial_token: 0”替换为“initial_token: 123”)。

    "Cas1" : {

        "Type" : "AWS::EC2::Instance",
        "Metadata" : {
            "AWS::CloudFormation::Init" : {
                "config" : {
                    "packages" : {
                        "yum" : {
                            "opscenter-free" : [],
                            "pyOpenSSL" : []
                        }
                    }
                },

                "services" : {
                    "sysvinit" : {
                        "cassandra" : {
                            "enabled" : "true",
                            "ensureRunning" : "true"
                        },
                        "opscenterd" : {
                            "enabled" : "true",
                            "ensureRunning" : "true"
                        }
                    }
                }
            }
        },

        "Properties" : {
            "SecurityGroups" : [ { "Ref" : "CommonSecurityGroup" }, { "Ref" : "OpsCenterSecurityGroup" } ],
            "KeyName" : { "Ref" : "KeyName" },
            "InstanceType" : { "Ref" : "CassandraInstanceType" },
            "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "CassandraInstanceType" }, "Arch" ] } ] },
            "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
            "#!/bin/bash -v\n",

            "MY_IP=`(curl http://169.254.169.254/latest/meta-data/local-ipv4)`\n",
            "sed -i 's/REPLACE_WITH_TOKEN/0/g' /etc/cassandra/conf/cassandra.yaml\n",
            "sed -i 's/REPLACE_WITH_MY_IP/'$MY_IP'/g' /etc/cassandra/conf/cassandra.yaml\n",
            "sed -i 's/REPLACE_WITH_SEED_IP/'$MY_IP'/g' /etc/cassandra/conf/cassandra.yaml\n",
            "sed -i 's/REPLACE_WITH_MAX_HEAP_SIZE/8G/g' /etc/cassandra/conf/cassandra-env.sh\n",
            "sed -i 's/REPLACE_WITH_HEAP_NEWSIZE/4G/g' /etc/cassandra/conf/cassandra-env.sh\n",

            "yum update -y aws-cfn-bootstrap\n",

            "/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackName" }, " -r Cas1 ",
            "    --access-key ",  { "Ref" : "HostKeys" },
            "    --secret-key ", {"Fn::GetAtt": ["HostKeys", "SecretAccessKey"]},
            "    --region ", { "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-init'\n",

            "sed -i 's/127.0.0.1/'$MY_IP'/g' /etc/opscenter/opscenterd.conf\n",
            "sed -i 's/#passwd_file/passwd_file/g' /etc/opscenter/opscenterd.conf\n",
            "echo 'xxx:xxx:admin' > /etc/opscenter/.passwd\n",

            "rm -fR /var/lib/cassandra/data\n",
            "rm -fR /var/lib/cassandra/commitlog\n",
            "mkdir /var/lib/cassandra/data\n",
            "mkdir /var/lib/cassandra/commitlog\n",
            "chown -R cassandra:cassandra /var/lib/cassandra\n",

            "service cassandra start\n",
            "service opscenterd start\n"

            ]]}}
        }

    },

后续节点的配置相同,除了行

            "sed -i 's/REPLACE_WITH_SEED_IP/'$MY_IP'/g' /etc/cassandra/conf/cassandra.yaml\n",

引用种子(第一个)节点的 IP 地址

            "sed -i 's/REPLACE_WITH_SEED_IP/", { "Fn::GetAtt" : ["Cas1", "PrivateIp"] }, "/g' /etc/cassandra/conf/cassandra.yaml\n",

至于将实例 IP 添加到安全组,这似乎是不必要的,您只需创建一个组并向其中添加 Ingress 资源,并在其中引用该组作为源

    "CommonSecurityGroup" : {
        "Type" : "AWS::EC2::SecurityGroup",
        "Properties" : {
            "GroupDescription" : "Enables",
            "SecurityGroupIngress" : [ {
                "IpProtocol" : "tcp",
                "FromPort" : "22",
                "ToPort" : "22",
                "CidrIp" : "0.0.0.0/0"
            } ]
        }
    },

    "OpsCenterSecurityGroup" : {
        "Type" : "AWS::EC2::SecurityGroup",
        "Properties" : {
            "GroupDescription" : "Enables",
            "SecurityGroupIngress" : [ {
                "IpProtocol" : "tcp",
                "FromPort" : "8888",
                "ToPort" : "8888",
                "CidrIp" : "0.0.0.0/0"
            },
            "SecurityGroupIngress" : [ {
                "IpProtocol" : "tcp",
                "FromPort" : "61620",
                "ToPort" : "61621",
                "SourceSecurityGroupName" : { "Ref": "CommonSecurityGroup" }
            } ]
        }
    },

    "CassandraThriftIngress" : {
        "Type" : "AWS::EC2::SecurityGroupIngress",
        "Properties" : {
            "GroupName": { "Ref": "CommonSecurityGroup" },
            "IpProtocol" : "tcp",
            "FromPort" : "9160",
            "ToPort" : "9160",
            "SourceSecurityGroupName" : { "Ref": "CommonSecurityGroup" }
        }
    },

    "CassandraData" : {
        "Type" : "AWS::EC2::SecurityGroupIngress",
        "Properties" : {
            "GroupName": { "Ref": "CommonSecurityGroup" },
            "IpProtocol" : "tcp",
            "FromPort" : "7000",
            "ToPort" : "7001",
            "SourceSecurityGroupName" : { "Ref": "CommonSecurityGroup" }
        }
    },

    "CassandraJMX" : {
        "Type" : "AWS::EC2::SecurityGroupIngress",
        "Properties" : {
            "GroupName": { "Ref": "CommonSecurityGroup" },
            "IpProtocol" : "tcp",
            "FromPort" : "7199",
            "ToPort" : "7199",
            "SourceSecurityGroupName" : { "Ref": "OpsCenterSecurityGroup" }
        }
    },

答案2

可以调用 AMI 中的脚本

如果是这样,您只需要 cURL 和 EC2 的内部元数据服务。从实例中:

curl http://169.254.169.254/latest/meta-data/local-ipv4

还有一大堆其他可用的元数据http://169.254.169.254/latest/meta-data/——主机名、安全组、实例 ID 等。

答案3

是的,您可以完全在模板内完成此操作。下面是模板的“资源”部分,其中定义了三个实例:两个 Cassandra 实例和一个中间件实例。

第二个 Cassandra 实例接收第一个 Cassandra 实例的 IP 作为用户数据。中间件实例接收两个 Cassandra 实例的 IP,也将其作为用户数据。

两个 Cassandra 实例都添加到“cassandra-nodes”安全组中。我没有包含此定义,但在片段部分。您不需要手动将其 IP 添加到 SG,只需在描述实例时引用它即可。

"Resources" : {
    "CassOneInstance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : "ami-123",
        "InstanceType": "c1.medium",
        "SecurityGroups" : [ "cassandra-nodes" ]
      }
    },
    "CassTwoInstance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : "ami-123",
        "InstanceType": "c1.medium",
        "SecurityGroups" : [ "cassandra-nodes" ],
        "UserData" : { 
            "Fn::Base64" : { 
                "Fn::Join" : [ ":", [ 
                    { "Fn::GetAtt" : [ "CaseOneInstance", "PrivateIP" ] }
                ] 
            }
         },
      }
    },
    "MiddleWareInstance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : "ami-123",
        "InstanceType": "c1.medium",
        "UserData" : { 
            "Fn::Base64" : { 
                "Fn::Join" : [ ":", [ 
                    { "Fn::GetAtt" : [ "CaseOneInstance", "PrivateIp" ] },
                    { "Fn::GetAtt" : [ "CaseTwoInstance", "PrivateIp" ] }
                ]
            }
         },
      }
    }
}

相关内容