【问题标题】:CloudFormation GUI Parameter OverrideCloudFormation GUI 参数覆盖
【发布时间】:2020-11-03 02:46:19
【问题描述】:

我有一个带有 2 个参数的 CloudFormation 模板。一个用于 EC2 名称,第二个用于 URL。 UserData 启动后会在 EC2 上卷曲必要的 URL。此 URL 会根据用户的需要而更改。我添加了标签以确保 CloudFormation 正在接受更改。当我通过 GUI 进行更新时,两个标签都会更新。但是,UserData 的 curl 中的 URL 没有。我正在尝试创建有关如何通过 CloudFormation GUI 更新此模板的说明。是否可以通过 GUI 在 URL 参数的 UserData 部分中完成参数覆盖?这是我的 CloudFormation 模板的 sn-p。

{
"Parameters":{
    "ArtifactURL" : {
        "Type" : "String",
        "Default" : "https://stuff.war",
        "Description": "Enter the Artifact's URL to be installed on this EC2.  Default is the latest stuff"
    },
    "EC2Name" : {
        "Type" : "String",
        "Default" : "MyCloudFormationInstance"
    }
},
"Resources" : {
    "MyCloudFormationInstance" : {
        "Type" : "AWS::EC2::Instance",
        "Properties" : {
            "AvailabilityZone" : "...",
            "ImageId" : "...",
            "SecurityGroupIds" :[ "..." ],
            "KeyName" : "...",
            "Tags" : [
                {
                    "Key" : "Name",
                    "Value" : { "Ref": "EC2Name"}
                },
                {
                    "Key" : "Url",
                    "Value" : { "Ref": "ArtifactURL"}
                }
            ],
            "IamInstanceProfile" : "...",
            "InstanceType" : "t2.micro",
            "UserData" : {"Fn::Base64": {"Fn::Join" : ["", [
                "#!/bin/bash","\n",
                "warlink=\"", { "Ref": "ArtifactURL" },"\"\n",
                "echo \"warlink: $warlink\" > myFile.txt","\n",
                "\n","curl \"$warlink\" -O","\n",

【问题讨论】:

    标签: amazon-web-services amazon-cloudformation


    【解决方案1】:

    我在这里做一些假设:

    • 我假设您的目标是更新 CloudFormation 参数 ArtifactURL 应该使实例下载 新的 URL;
    • 另外,我假设您没有直接验证 UserData 是否已更新,但您间接通过注意到未下载新 URL 来验证它并认为原因是 UserData 没有更新。

    如果这些假设无效,请在问题中说明您的最终目标是什么以及您观察到的具体内容。

    UserData 脚本中的ArtifactURL 很可能正在更新——这正是 CloudFormation 应该如何工作的。您可能观察到新的 URL 没有被下载,这是完全不同的和预期的。

    EC2 实例支持修改其 UserData,而 CloudFormation 支持进行该更改。但是,默认情况下,在大多数 AMI 中,操作系统(特别是 cloud-init 包)被配置为 仅运行 UserData 脚本 once-per-instance(而不是once-per-boot)。

    这意味着,默认情况下,对 UserData 脚本所做的更改不会执行

    如果您查看资源类型 AWS::EC2::Instance 的 CloudFormation 文档,您会发现 TagsUserData 属性都可以更新而无需替换。具体来说,Tags 的更新完全没有任何中断,而UserData 则以 Stop -> Start 循环进行更新。当实例重新启动时,cloud-init 包会验证它之前已经为 该实例执行过一次 UserData,因此它不会再次执行它——不管它是否已被修改。 p>

    所以,你需要的是 在UserData被修改时触发重新执行。

    有多种方法可以实现这一目标。由于您使用的是 CloudFormation,我建议您使用 cfn-hup

    cfn-hup 帮助程序是一个守护程序,它检测资源元数据的变化并在检测到变化时运行用户指定的操作。

    此工具专门用于检测 UserData 中的更改并重新运行它们。链接的文档页面中有一个示例,您还可以通过搜索 cfn-hup 找到很多其他示例。

    最后要注意的是,还有其他几种方法可以实现相同的目标(如果修改了 UserData 脚本,或者每次启动等都重新执行它们)。另一个不错的选择是了解更多关于cloud-init 并修改其配置。始终确保您阅读的选项已记录在案并受到您正在使用的基础架构或软件的支持(例如,您会发现很多地方建议您可以删除锁定文件以强制重新执行 UserData,但是这是个坏建议)。

    【讨论】:

    • 感谢您的帮助。抱歉,花了这么长时间才回复,但正如您所说,找到正确和完整的信息需要一段时间。我知道我有一点弗兰肯斯坦剧本,但它有效。我让它与 cfn-init 和 cfn-hup 一起工作。
    【解决方案2】:

    这是编辑后的最终代码

        {
    "Parameters":{
        "ArtifactURL" : {
            "Type" : "String",
            "Default" : "https://stuff.war",
            "Description": "Enter the Artifact's URL"
        },
        "EC2Name" : {
            "Type" : "String",
            "Default" : "MyCloudFormationInstance"
        }
    },
    "Resources" : {
        "WaitHandle" : { 
            "Type" : "AWS::CloudFormation::WaitConditionHandle"
         },
        "MyCloudFormationInstance" : {
            "Type" : "AWS::EC2::Instance",
            "Metadata" : {
                "ArtifactURL": { "Ref": "ArtifactURL"},
                "AWS::CloudFormation::Init" : {
                    "configSets": {
                        "myconfigs" : ["config-cfn-hup","install-artifact"]
                    },
                    "install-artifact" : {
                        "commands": {
                            "1-run-script" : {
                                "command" : { "Fn::Join" : [ "", [
                                    "/bin/bash /etc/downloadandinstallfile.sh"
                                ]]}
                            }
                        }
                    },
                    "config-cfn-hup" : {
                        "files" : {
                            "/etc/downloadandinstallfile.sh" : {
                                "content" : { "Fn::Join" : ["", [
                                    "#!/bin/bash","\n",
                                    "warlink=\"", { "Ref": "ArtifactURL" },"\"\n",
                                    "echo \"warlink: $warlink\" > myFile.txt","\n",
                                    "\n","curl \"$warlink\" -O","\n"]]},
                                "mode" : "000777",
                                "owner" : "root",
                                "group" : "root"
                            },
                            "/etc/cfn/cfn-hup.conf" : {
                                "content" : { "Fn::Join" : ["", [
                                    "[main]\n",
                                    "stack=", { "Ref" : "AWS::StackId" }, "\n",
                                    "region=", { "Ref" : "AWS::Region" }, "\n",
                                    "interval=1\n"
                                ]]},
                                "mode"  : "000400",
                                "owner" : "root",
                                "group" : "root"
                            },
                            "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : {
                                "content" : { "Fn::Join" : ["", [
                                    "[cfn-auto-reloader-hook]\n",
                                    "triggers=post.update\n",
                                    "path=Resources.MyCloudFormationInstance.Metadata.AWS::CloudFormation::Init\n",
                                    "action=cfn-init -v --configsets myconfigs --stack ", { "Ref" : "AWS::StackId" }, " --resource MyCloudFormationInstance ", " --region ", { "Ref" : "AWS::Region"},"\n",
                                    "runas=root\n"
                                ]]}
                            },
                            "/etc/systemd/system/cfn-hup.service" : {
                                "content" : { "Fn::Join" : ["", [
                                    "[Unit]\n",
                                    "Description=CloudFormation helper daemon\n",
                                    "\n",
                                    "[Service]\n",
                                    "ExecStart=/bin/cfn-hup\n",
                                    "Restart=always\n",
                                    "Type=simple\n",
                                    "\n",
                                    "[Install]\n",
                                    "WantedBy=multi-user.target"
                                ]]}
                            }
                        },
                        "commands" : {
                            "01-install-set" : {
                                "command" : { "Fn::Join" : [ "", [
                                    "set -xe\n"
                                ]]}
                            },
                            "02-daemon-reload" : {
                                "command" : { "Fn::Join" : [ "", [
                                    "systemctl daemon-reload"
                                ]]}
                            },
                            "03-enable-service" : {
                                "command" : { "Fn::Join" : [ "", [
                                    "systemctl enable cfn-hup.service\n"
                                ]]}
                            },
                            "04-start-service" : {
                                "command" : { "Fn::Join" : [ "", [
                                    "service cfn-hup.service start\n"
                                ]]}
                            }
                        }
                    }
                }
            },
            "Properties" : {
                "AvailabilityZone" : "xxxxxxxx",
                "ImageId" : "xxxxxxxxxx",
                "SecurityGroupIds" :[ "xxxxxxx" ],
                "KeyName" : "xxx.pem",
                "Tags" : [
                    {
                        "Key" : "Name",
                        "Value" : { "Ref": "EC2Name"}
                    },
                    {
                        "Key" : "Url",
                        "Value" : { "Ref": "NexusArtifactURL"}
                    }
                ],
                "IamInstanceProfile" : "ec2LoggingRole",
                "InstanceType" : "t2.micro",
                "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
                    "#!/bin/bash -v\n",
                    "# Function to return error code to the wait handle\n",
                    "function handle_error\n",
                    "{\n",
                    " cfn-signal -e 1 -r \"$1\" '", { "Ref" : "WaitHandle"}, "'\n",
                    " exit 1\n",
                    "}\n",
    
                    "yum update -y \n",
                    "pip3 install pystache\n",
                    "pip3 install argparse\n",
                    "pip3 install python-daemon\n",
                    "pip3 install requests\n",
                    "curl -sSL https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz -O\n",
                    "# tar -xpf aws-cfn-bootstrap-latest.tar.gz -C /opt\n",
                    "# cd /opt/aws-cfn-bootstrap-1.4/\n",
                    "# sudo python setup.py build\n",
                    "# sudo python setup.py install\n",
                    "easy_install aws-cfn-bootstrap-latest.tar.gz\n",
                    "#ln -s /usr/init/redhat/cfn-hup /etc/init.d/cfn-hup\n",
                    "#chmod 775 /usr/init/redhat/cfn-hup\n",
                    "#cd /opt\n",
                    "#mkdir aws\n",
                    "#cd aws\n",
                    "#mkdir bin\n",
                    "#ln -s /usr/bin/cfn-hup /opt/aws/bin/cfn-hup\n",
                    
                    "sudo cfn-init -v -c myconfigs -s ", { "Ref" : "AWS::StackId" }, " -r MyCloudFormationInstance ", " --region ", { "Ref" : "AWS::Region" }, " || handle_error 'Failed to run cfn-init'\n",
    
                    "# Return success\n",
    
                    "cfn-signal -e 0 -r \"Stack Complete\" '", { "Ref" : "WaitHandle" }, "'\n"
                    ]]}
                }
            }
        }
    },
    "Outputs":{
        "InstanceID" : {
            "Description" : "The Instance ID",
            "Value": { "Ref" : "MyCloudFormationInstance" }
        },
        "PublicIp" : {
            "Description" : "Instance's Public Ip",
            "Value" : { "Fn::GetAtt" : [ "MyCloudFormationInstance", "PublicIp"]}
        },
        "SSHLogin" : {
            "Description" : "SSH command to log into your instance",
            "Value" : {"Fn::Join" : ["", ["ssh -i \"xxx.pem\" ec2-user@", {"Fn::GetAtt": ["MyCloudFormationInstance","PublicDnsName"]}]]}
        }
    }}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-05
      相关资源
      最近更新 更多