【问题标题】:Is there a way to get a volume unmounted when I call CloudFormation delete-stack?当我调用 CloudFormation 删除堆栈时,有没有办法卸载卷?
【发布时间】:2013-12-19 19:45:18
【问题描述】:

我正在使用 CloudFormation 创建我的环境。堆栈的一部分包括从快照创建卷,将其与 EC2 实例关联,然后挂载它。

"Resources" : {
    "EBSData" : {
        "Type" : "AWS::EC2::Volume",
     ...snip...
    },

    "MountPoint" : {
        "Type" : "AWS::EC2::VolumeAttachment",
     ...snip...
    },

    "myTestInstance" : {
        "Type" : "AWS::EC2::Instance",
     ...snip...
    }
 },

当我尝试调用 delete-stack 时,它失败了,因为该卷仍然挂载:

  "StackStatusReason": "The following resource(s) failed to delete: [EBSData, MountPoint].", 
  "CreationTime": "2013-12-03T13:40:58.646Z", 
  "StackName": "myTestStack", 
  "StackStatus": "DELETE_FAILED", 
  "DisableRollback": false

第二次调用 delete-stack 成功,因为实例已经被销毁了。

cloudformation delete-stack 调用的运行实例中是否有任何挂钩,我可以在其中卸载卷?还有其他方法吗?

【问题讨论】:

  • 我几乎有同样的问题。我正在创建在创建 EC2 实例时挂载的新卷,但是当我删除时,删除流程会在尝试删除实例之前尝试删除这些卷。卷无法删除,但实例成功。除非因为实例已经消失而再次调用 delete,否则整体状态将失败。

标签: amazon-web-services amazon-ec2 amazon-cloudformation


【解决方案1】:

为了使这项工作正常进行,我必须更改连接音量的方式。除了使用AWS::EC2::VolumeAttachment,您还可以在该实例的属性中指定要附加到该实例的 EBS 卷:

"Resources" : {
    "EBSData" : {
        "Type" : "AWS::EC2::Volume",
     ...snip...
    },

    "myTestInstance" : {
        "Type" : "AWS::EC2::Instance",
        "Properties": {
            "Volumes": [ { "VolumeId": { "Ref": "EBSData" }, "Device": "<device mount point>" }]
        ...snip...
        },
     ...snip...
    }
 },

以这种方式附加卷似乎会使 CloudFormation 以正确的顺序删除实例和卷。即在删除卷之前关闭实例。

确保EBSData 不使用对myTestInstance 的任何引用,否则您将获得循环依赖。

【讨论】:

  • 没有太多关于此的文档,但您的答案似乎是当前的最佳实践,并且确实解决了问题。谢谢!
  • herebedragons:您创建的卷需要与 EC2 实例位于同一可用区中,但是事先无法知道,因此您需要在卷中添加 Fn:GetAtt: [myTestInstance, AvailabilityZone],但这当然引入了我们需要避免的循环依赖
  • @lsh 我在从实例中获取 AvailabilityZone 时遇到了同样的循环依赖问题。你找到解决办法了吗?
  • 您需要使用 AWS::EC2::VolumeAttachment 将 ec2 实例与卷相关联并在那里指定可用区。要点在这里:gist.github.com/lsh-0/a6304893e7f97c9f7ac4
  • eck 抱歉,这没什么意义。希望要点能解决问题。
【解决方案2】:

我通过“DependsOn”资源属性找到了我的问题here 的答案。

基本上,这能够解决我的问题(在对您问题的评论中描述):

"Resources" : {
    "EBSData" : {
        "Type" : "AWS::EC2::Volume",
        "DependsOn": "myTestInstance",
     ...snip...
    },
    "MountPoint" : {
        "Type" : "AWS::EC2::VolumeAttachment",
     ...snip...
    },

    "myTestInstance" : {
        "Type" : "AWS::EC2::Instance",
     ...snip...
    }
 },

注意在 Volume 资源中添加了 "DependsOn": "myTestInstance"。由于 VolumeAttachment 资源为 Volume 内置了“DependsOn”,所以一切都应该很好。

附加说明:这还没有经过测试,但是一旦测试就会更新。

【讨论】:

  • 我相信这是在云形成并行时引入的错误。最初,很多这些东西是顺序的,并且使其并行引入了竞争条件。几个月前它就消失了,在它变得痛苦之前,所以我们从来没有真正彻底地测试过它,让我从“我相信”到“它是”。
  • 有人成功测试过解决方案吗?我遇到了完全相同的问题,如上所述尝试了 DependsOn,但堆栈删除仍然失败。
【解决方案3】:

CloudFormation 没有做什么,它无法撤消:您的卷是由您安装的(使用 CloudInit 通过 UserData 或其他方式),而 CloudFormation 不知道如何撤消此操作。因此,堆栈删除被停止,因为设备保持安装状态,并且卷处于“忙碌状态”。

recommended way 是使用 CloudFormation CustomRessource 来声明挂载点:

"ExampleVolumeMount" : {
    "Type" : "Custom::VolumeMount",
    "Version" : "1.0",
    "DependsOn" : ["VolumeAttachment", "ExampleWaitCondition"],
    "Properties" : {
        "ServiceToken" : { "Fn::GetAtt" : ["CustomResourcePipeline", "Outputs.CustomResourceTopicARN"] },
        "Device" : "/dev/xvdh",
        "MountPoint" : "/mnt/disk",
        "FsType" : "ext3",
        "Format" : "true"
    }
},

它使用由子模板创建的 ServiceToken:https://s3.amazonaws.com/cloudformation-examples/cr-backend-substack-template.template,其中包含一个 SQS 队列和一个 SNS 主题。

您可以在AWSlabs github account 上查看完整的示例和脚本。

【讨论】:

    猜你喜欢
    • 2021-10-26
    • 1970-01-01
    • 2019-09-01
    • 2018-04-04
    • 2017-10-27
    • 1970-01-01
    • 2017-02-21
    • 2018-11-23
    • 1970-01-01
    相关资源
    最近更新 更多