{"id":4231,"date":"2021-04-04T18:01:09","date_gmt":"2021-04-04T16:01:09","guid":{"rendered":"http:\/\/miro.borodziuk.eu\/?p=4231"},"modified":"2021-06-24T21:46:19","modified_gmt":"2021-06-24T19:46:19","slug":"cloudformation-4","status":"publish","type":"post","link":"http:\/\/miro.borodziuk.eu\/index.php\/2021\/04\/04\/cloudformation-4\/","title":{"rendered":"CloudFormation &#8211; 4"},"content":{"rendered":"<p><!--more--><\/p>\n<p><span style=\"color: #3366ff;\">Rollbacks on failures<\/span><\/p>\n<ul>\n<li>Stack Creation Fails: (CreateStack API)\n<ul>\n<li>Default everything rolls back (gets deleted). We can look at the log OnFailure=ROLLBACK<\/li>\n<li>Troubleshoot: Option to disable rollback and manually troubleshoot OnFailure=DO_NOTHING<\/li>\n<li>Delete: get rid of the stack entirely, do not keep anything OnFailure DELETE<\/li>\n<\/ul>\n<\/li>\n<li>Stack Update Fails: (UpdateStack API)\n<ul>\n<li>The stack automatically rolls back to the previous known working state<\/li>\n<li>Ability to see in the log what happened and error messages<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Let&#8217;s use the same template file:<\/p>\n<pre class=\"lang:default decode:true\">---\r\nParameters:\r\n  SSHKey:\r\n    Type: AWS::EC2::KeyPair::KeyName\r\n    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance\r\n\r\nResources:\r\n  MyInstance:\r\n    Type: AWS::EC2::Instance\r\n    Properties:\r\n      AvailabilityZone: eu-central-1a\r\n      ImageId: ami-00a205cb8e06c3c4e\r\n      InstanceType: t2.micro\r\n      KeyName: !Ref SSHKey\r\n      SecurityGroups:\r\n        - !Ref SSHSecurityGroup\r\n      # we install our web server with user data\r\n      UserData: \r\n        Fn::Base64:\r\n          !Sub |\r\n            #!\/bin\/bash -xe\r\n            # Get the latest CloudFormation package\r\n            yum update -y aws-cfn-bootstrap\r\n            # Start cfn-init\r\n            \/opt\/aws\/bin\/cfn-init -s ${AWS::StackId} -r MyInstance --region ${AWS::Region}\r\n            # Start cfn-signal to the wait condition\r\n            \/opt\/aws\/bin\/cfn-signal -e $? --stack ${AWS::StackId} --resource SampleWaitCondition --region ${AWS::Region}\r\n    Metadata:\r\n      Comment: Install a simple Apache HTTP page\r\n      AWS::CloudFormation::Init:\r\n        config:\r\n          packages:\r\n            yum:\r\n              httpd: []\r\n          files:\r\n            \"\/var\/www\/html\/index.html\":\r\n              content: |\r\n                &lt;h1&gt;Hello World from EC2 instance!&lt;\/h1&gt;\r\n                &lt;p&gt;This was created using cfn-init&lt;\/p&gt;\r\n              mode: '000644'\r\n          commands:\r\n            hello:\r\n              command: \"echo 'boom' &amp;&amp; exit 1\"\r\n          services:\r\n            sysvinit:\r\n              httpd:\r\n                enabled: 'true'\r\n                ensureRunning: 'true'\r\n\r\n  SampleWaitCondition:\r\n    CreationPolicy:\r\n      ResourceSignal:\r\n        Timeout: PT1M\r\n        Count: 1\r\n    Type: AWS::CloudFormation::WaitCondition\r\n\r\n  # our EC2 security group\r\n  SSHSecurityGroup:\r\n    Type: AWS::EC2::SecurityGroup\r\n    Properties:\r\n      GroupDescription: SSH and HTTP\r\n      SecurityGroupIngress:\r\n      - CidrIp: 0.0.0.0\/0\r\n        FromPort: 22\r\n        IpProtocol: tcp\r\n        ToPort: 22\r\n      - CidrIp: 0.0.0.0\/0\r\n        FromPort: 80\r\n        IpProtocol: tcp\r\n        ToPort: 80\r\n\r\n<\/pre>\n<p>Now we can create a stack<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4235 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation049.jpg\" alt=\"\" width=\"684\" height=\"481\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation049.jpg 684w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation049-300x211.jpg 300w\" sizes=\"(max-width: 684px) 100vw, 684px\" \/><\/p>\n<p>but with different option:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4237\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation050-1.jpg\" alt=\"\" width=\"665\" height=\"796\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation050-1.jpg 665w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation050-1-251x300.jpg 251w\" sizes=\"(max-width: 665px) 100vw, 665px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4239\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation051.jpg\" alt=\"\" width=\"683\" height=\"404\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation051.jpg 683w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation051-300x177.jpg 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p>This time we still f<span title=\"Failed to receive 1 resource signal(s) within the specified duration\">ailed to receive 1 resource signal(s) <\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-4242 size-full aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation052-1.jpg\" alt=\"\" width=\"1048\" height=\"598\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation052-1.jpg 1048w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation052-1-300x171.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation052-1-1024x584.jpg 1024w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation052-1-768x438.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>But stack wasn&#8217;t rolled back.<\/p>\n<p>When we connect to the created EC2 instance we can see the reason of an error:<\/p>\n<pre class=\"lang:default decode:true\">[ec2-user@ip-172-31-31-182 ~]$ sudo \/var\/log\/cfn-init.log\r\nsudo: \/var\/log\/cfn-init.log: command not found\r\n[ec2-user@ip-172-31-31-182 ~]$ sudo cat \/var\/log\/cfn-init.log\r\n2021-06-01 16:41:35,941 [INFO] -----------------------Starting build-----------------------\r\n2021-06-01 16:41:35,942 [INFO] Running configSets: default\r\n2021-06-01 16:41:35,943 [INFO] Running configSet default\r\n2021-06-01 16:41:35,944 [INFO] Running config config\r\n2021-06-01 16:41:47,932 [INFO] Yum installed ['httpd']\r\n2021-06-01 16:41:47,947 [ERROR] Command hello (echo 'boom' &amp;&amp; exit 1) failed\r\n2021-06-01 16:41:47,947 [ERROR] Error encountered during build of config: Command hello failed\r\nTraceback (most recent call last):\r\n  File \"\/usr\/lib\/python3.7\/site-packages\/cfnbootstrap\/construction.py\", line 573, in run_config\r\n    CloudFormationCarpenter(config, self._auth_config).build(worklog)\r\n  File \"\/usr\/lib\/python3.7\/site-packages\/cfnbootstrap\/construction.py\", line 273, in build\r\n    self._config.commands)\r\n  File \"\/usr\/lib\/python3.7\/site-packages\/cfnbootstrap\/command_tool.py\", line 127, in apply\r\n    raise ToolError(u\"Command %s failed\" % name)\r\ncfnbootstrap.construction_errors.ToolError: Command hello failed\r\n2021-06-01 16:41:47,947 [ERROR] -----------------------BUILD FAILED!------------------------\r\n2021-06-01 16:41:47,947 [ERROR] Unhandled exception during build: Command hello failed\r\nTraceback (most recent call last):\r\n  File \"\/opt\/aws\/bin\/cfn-init\", line 176, in &lt;module&gt;\r\n    worklog.build(metadata, configSets)\r\n  File \"\/usr\/lib\/python3.7\/site-packages\/cfnbootstrap\/construction.py\", line 135, in build\r\n    Contractor(metadata).build(configSets, self)\r\n  File \"\/usr\/lib\/python3.7\/site-packages\/cfnbootstrap\/construction.py\", line 561, in build\r\n    self.run_config(config, worklog)\r\n  File \"\/usr\/lib\/python3.7\/site-packages\/cfnbootstrap\/construction.py\", line 573, in run_config\r\n    CloudFormationCarpenter(config, self._auth_config).build(worklog)\r\n  File \"\/usr\/lib\/python3.7\/site-packages\/cfnbootstrap\/construction.py\", line 273, in build\r\n    self._config.commands)\r\n  File \"\/usr\/lib\/python3.7\/site-packages\/cfnbootstrap\/command_tool.py\", line 127, in apply\r\n    raise ToolError(u\"Command %s failed\" % name)\r\ncfnbootstrap.construction_errors.ToolError: Command hello failed<\/pre>\n<p>For troubleshooting we need not to rollback on failure.<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Nested stacks<\/span><\/p>\n<ul>\n<li>Nested stacks are stacks as part of other stacks<\/li>\n<li>They allow you to isolate repeated patterns \/ common components in separate stacks and call them from other stacks<\/li>\n<li>Example:\n<ul>\n<li>Load Balancer configuration that is re-used<\/li>\n<li>Security Group that is re-used<\/li>\n<\/ul>\n<\/li>\n<li>Nested stacks are considered best practice<\/li>\n<li>To update a nested stack, always update the parent (root stack)<\/li>\n<\/ul>\n<p>Consider such a cloudformation template:<\/p>\n<pre class=\"lang:default decode:true\">Parameters:\r\n  SSHKey:\r\n    Type: AWS::EC2::KeyPair::KeyName\r\n    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance\r\n  \r\nResources:\r\n  myStack:\r\n    Type: AWS::CloudFormation::Stack\r\n    Properties:\r\n      TemplateURL: https:\/\/s3.amazonaws.com\/cloudformation-templates-us-east-1\/LAMP_Single_Instance.template\r\n      Parameters:\r\n        KeyName: !Ref SSHKey\r\n        DBName: \"mydb\"\r\n        DBUser: \"user\"\r\n        DBPassword: \"pass\"\r\n        DBRootPassword: \"passroot\"\r\n        InstanceType: t2.micro\r\n        SSHLocation: \"0.0.0.0\/0\"\r\n\r\nOutputs:\r\n  StackRef:\r\n    Value: !Ref myStack\r\n  OutputFromNestedStack:\r\n    Value: !GetAtt myStack.Outputs.WebsiteURL<\/pre>\n<p>As we see to TemplateURL is attached to this yaml. The URL of the attached template is<\/p>\n<p><a href=\"https:\/\/s3.amazonaws.com\/cloudformation-templates-us-east-1\/LAMP_Single_Instance.template\" target=\"_blank\" rel=\"noopener\">https:\/\/s3.amazonaws.com\/cloudformation-templates-us-east-1\/LAMP_Single_Instance.template<\/a><\/p>\n<p>Let&#8217;s crete a stack:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4252 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation054-1.jpg\" alt=\"\" width=\"664\" height=\"503\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation054-1.jpg 664w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation054-1-300x227.jpg 300w\" sizes=\"(max-width: 664px) 100vw, 664px\" \/><\/p>\n<p><code>Nest -&gt; Next<\/code><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4253 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation055.jpg\" alt=\"\" width=\"655\" height=\"416\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation055.jpg 655w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation055-300x191.jpg 300w\" sizes=\"(max-width: 655px) 100vw, 655px\" \/><\/p>\n<p><code>Create stack<\/code><\/p>\n<p>Now we have two stack created:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4255 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation056.jpg\" alt=\"\" width=\"1031\" height=\"423\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation056.jpg 1031w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation056-300x123.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation056-1024x420.jpg 1024w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation056-768x315.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>If we go to the output of the nested stack we have the url of created LAMP website:<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4257 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation058-1.jpg\" alt=\"\" width=\"848\" height=\"393\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation058-1.jpg 848w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation058-1-300x139.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation058-1-768x356.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4260\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation060.jpg\" alt=\"\" width=\"806\" height=\"742\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation060.jpg 806w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation060-300x276.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation060-768x707.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>If we want to delete two stacks we need to delete the parent stack:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4258 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation059.jpg\" alt=\"\" width=\"1010\" height=\"541\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation059.jpg 1010w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation059-300x161.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation059-768x411.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">ChangeSets<\/span><\/p>\n<ul>\n<li>When you update a stack, you need to know what changes before it happens for greater confidence<\/li>\n<li>ChangeSets won&#8217;t say if the update will be successful<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4262\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation062.jpg\" alt=\"\" width=\"1367\" height=\"443\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation062.jpg 1367w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation062-300x97.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation062-1024x332.jpg 1024w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation062-768x249.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>At the begining we will create simple stack<\/p>\n<pre class=\"lang:default decode:true \">---\r\nResources:\r\n  MyEC2Instance:\r\n    Type: AWS::EC2::Instance\r\n    Properties:\r\n      AvailabilityZone: eu-central-1a\r\n      ImageId: ami-00a205cb8e06c3c4e\r\n      InstanceType: t2.micro\r\n<\/pre>\n<p><code><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4264 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation063.jpg\" alt=\"\" width=\"711\" height=\"487\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation063.jpg 711w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation063-300x205.jpg 300w\" sizes=\"(max-width: 711px) 100vw, 711px\" \/><\/code><\/p>\n<p><code>Next -&gt; Next -&gt; Create stack<\/code><\/p>\n<p>Now let&#8217;s create change set for created stack. We will use such a tamplate<\/p>\n<pre class=\"lang:default decode:true\">---\r\nParameters:\r\n  SecurityGroupDescription:\r\n    Description: Security Group Description\r\n    Type: String\r\n\r\nResources:\r\n  MyEC2Instance:\r\n    Type: AWS::EC2::Instance\r\n    Properties:\r\n      AvailabilityZone: eu-central-1a\r\n      ImageId: ami-00a205cb8e06c3c4e\r\n      InstanceType: t2.micro\r\n      SecurityGroups:\r\n        - !Ref SSHSecurityGroup\r\n        - !Ref ServerSecurityGroup\r\n\r\n  # an elastic IP for our instance\r\n  MyEIP:\r\n    Type: AWS::EC2::EIP\r\n    Properties:\r\n      InstanceId: !Ref MyEC2Instance\r\n\r\n  # our EC2 security group\r\n  SSHSecurityGroup:\r\n    Type: AWS::EC2::SecurityGroup\r\n    Properties:\r\n      GroupDescription: Enable SSH access via port 22\r\n      SecurityGroupIngress:\r\n      - CidrIp: 0.0.0.0\/0\r\n        FromPort: 22\r\n        IpProtocol: tcp\r\n        ToPort: 22\r\n\r\n  # our second EC2 security group\r\n  ServerSecurityGroup:\r\n    Type: AWS::EC2::SecurityGroup\r\n    Properties:\r\n      GroupDescription: !Ref SecurityGroupDescription\r\n      SecurityGroupIngress:\r\n      - IpProtocol: tcp\r\n        FromPort: 80\r\n        ToPort: 80\r\n        CidrIp: 0.0.0.0\/0\r\n      - IpProtocol: tcp\r\n        FromPort: 22\r\n        ToPort: 22\r\n        CidrIp: 192.168.1.1\/32\r\n<\/pre>\n<p><code>CloudFormation -&gt; Stacks -&gt; StackCsDemo -&gt; Create change set<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4267\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation065.jpg\" alt=\"\" width=\"702\" height=\"693\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation065.jpg 702w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation065-300x296.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation065-100x100.jpg 100w\" sizes=\"(max-width: 702px) 100vw, 702px\" \/><\/p>\n<p><code>Next -&gt; Next -&gt; Create change set -&gt; Create change set<\/code><\/p>\n<p>Change set has not\u00a0 been created yet.<\/p>\n<p>We can see every changes that will be created in our stack:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4270 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation066-1.jpg\" alt=\"\" width=\"896\" height=\"421\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation066-1.jpg 896w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation066-1-300x141.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation066-1-768x361.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>You can delete or execute the change set.<\/p>\n<p>Let&#8217;s execute the change set.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4274 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation067.jpg\" alt=\"\" width=\"779\" height=\"722\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation067.jpg 779w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation067-300x278.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation067-768x712.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Retaining Data on Deletes<\/span><\/p>\n<ul>\n<li>You can put a DeletionPolicy on any resource to control what happens when the CloudFormation template is deleted<\/li>\n<li><code>DeletionPolicy=Retain<\/code>:\n<ul>\n<li>Specify on resources to preserve \/ backup in case of CloudFormation deletes<\/li>\n<li>To keep a resource, specify Retain (works for any resource \/ nested stack)<\/li>\n<\/ul>\n<\/li>\n<li><code>DeletionPolicy=Snapshot<\/code>:\n<ul>\n<li>EBSVolume, ElastiCache Cluster, ElastiCache ReplicationGroup<\/li>\n<li>RDS DBlnstance, RDS DBCluster, Redshift Cluster<\/li>\n<\/ul>\n<\/li>\n<li><code>DeletePolicy=Delete<\/code> (default behavior):\n<ul>\n<li>Note: for <code>AWS::RDS::DBCluster<\/code> resources, the default policy is <code>Snapshot<\/code><\/li>\n<li>Note: to delete an S3 bucket, you need to first empty the bucket of its content<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Consider such a yaml template:<\/p>\n<pre class=\"lang:default decode:true\">---\r\nResources:\r\n  MySG:\r\n    Type: AWS::EC2::SecurityGroup\r\n    DeletionPolicy: Retain\r\n    Properties:\r\n      GroupDescription: Enable SSH access via port 22\r\n      SecurityGroupIngress:\r\n      - CidrIp: 0.0.0.0\/0\r\n        FromPort: 22\r\n        IpProtocol: tcp\r\n        ToPort: 22\r\n\r\n  MyEBS:\r\n    Type: AWS::EC2::Volume\r\n    DeletionPolicy: Snapshot\r\n    Properties:\r\n      AvailabilityZone: eu-central-1a\r\n      Size: 1\r\n      VolumeType: gp2<\/pre>\n<p>Let&#8217;s go and create a stack:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4277 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation069.jpg\" alt=\"\" width=\"683\" height=\"750\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation069.jpg 683w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation069-273x300.jpg 273w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/p>\n<p><code>Next-&gt;<\/code><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4278 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation070.jpg\" alt=\"\" width=\"702\" height=\"486\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation070.jpg 702w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation070-300x208.jpg 300w\" sizes=\"(max-width: 702px) 100vw, 702px\" \/><\/p>\n<p><code>Next -&gt; Next -&gt; Create stack<\/code><\/p>\n<p>We have created EBS volume and Security Group.<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4281 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation071-1.jpg\" alt=\"\" width=\"757\" height=\"408\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation071-1.jpg 757w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation071-1-300x162.jpg 300w\" sizes=\"(max-width: 706px) 89vw, (max-width: 767px) 82vw, 740px\" \/><\/p>\n<p>Now, let&#8217;s delete the stack. As we see the Security Group MySG has not been deleted.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4283 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation071-2.jpg\" alt=\"\" width=\"851\" height=\"565\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation071-2.jpg 851w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation071-2-300x199.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation071-2-768x510.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>EBS volume has been deleted but the snapshot of the volume has been taken.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4284 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation073.jpg\" alt=\"\" width=\"861\" height=\"193\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation073.jpg 861w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation073-300x67.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation073-768x172.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Termination Protection on Stacks<\/span><\/p>\n<ul>\n<li>To prevent accidental deletes of CloudFormation templates, use Termination Protection<\/li>\n<\/ul>\n<p>Let&#8217;s see this quickly. First we create a simple stack:<\/p>\n<pre class=\"lang:default decode:true\">---\r\nResources:\r\n  MyEC2Instance:\r\n    Type: AWS::EC2::Instance\r\n    Properties:\r\n      AvailabilityZone: eu-central-1a\r\n      ImageId: ami-00a205cb8e06c3c4e\r\n      InstanceType: t2.micro\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4290 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation075.jpg\" alt=\"\" width=\"718\" height=\"530\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation075.jpg 718w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation075-300x221.jpg 300w\" sizes=\"(max-width: 718px) 100vw, 718px\" \/><\/p>\n<p>Now let&#8217;s enable the termination protection:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4291 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation076.jpg\" alt=\"\" width=\"802\" height=\"263\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation076.jpg 802w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation076-300x98.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation076-768x252.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/> <img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4292 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation077.jpg\" alt=\"\" width=\"581\" height=\"224\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation077.jpg 581w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation077-300x116.jpg 300w\" sizes=\"(max-width: 581px) 100vw, 581px\" \/><\/p>\n<p>After we enable the termination protection we can not delete the stack:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4293 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation078.jpg\" alt=\"\" width=\"576\" height=\"215\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation078.jpg 576w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation078-300x112.jpg 300w\" sizes=\"(max-width: 576px) 100vw, 576px\" \/><\/p>\n<p>As it is mentioned to delete the stack we need to disable termination policy.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":4248,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[89],"tags":[],"_links":{"self":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/4231"}],"collection":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/comments?post=4231"}],"version-history":[{"count":31,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/4231\/revisions"}],"predecessor-version":[{"id":4294,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/4231\/revisions\/4294"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media\/4248"}],"wp:attachment":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media?parent=4231"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/categories?post=4231"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/tags?post=4231"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}