Deletion policies
When we create our stack, we need to make sure that mission-critical resources are protected from accidental deletion.
In some cases, this is enabled by EnableTerminationProtection for services such as EC2 and RDS. S3 buckets, when filled with objects, will fail to delete because they have to be emptied first.
Deletion policies allow you to mitigate this risk within CloudFormation. In addition, deletion policies give you a few more features in addition to basic termination protection.
For example, say that you have created a testing stack that you don't need once the testing phase is finished, but you need the dump of the database (which is actually a snapshot of the RDS instance). Sometimes, you don't want to recreate the same data structure, or the database already has important data that you want to move to the production environment.
Let's see whether deletion policies can help us:
Resources:
VeryImportantDb:
Type: AWS::RDS::Instance
DeletionPolicy: Snapshot
Properties:
# Here you set properties for your RDS instance.
What will happen when we remove this resource from the template or delete the stack is that CloudFormation will signal RDS to take a final snapshot of the instance and then delete it.
Important note
The deletion policy snapshot is not available for every single resource. At the time of writing, the supported resources are AWS::EC2::Volume, AWS::ElastiCache::CacheCluster, AWS::ElastiCache::ReplicationGroup, AWS::Neptune::DBCluster, AWS::RDS::DBCluster, and AWS::RDS::DBInstance, AWS::Redshift::Cluster.
Bear that in mind when you design your infrastructure.
Another situation is when we want to retain some of the resources when we delete the stack. Here, we use the deletion policy called Retain:
Resources:
EvenMoreImportantDb:
Type: AWS::RDS::Instance
DeletionPolicy: Retain
Properties:
# Here you set properties for your RDS instance.
In case of deletion, what will happen is that this DB instance will be removed from CloudFormation's state, but the resource itself will stay in our account.
Another deletion policy is, obviously, Delete, which is a default policy for all the resources in the template. If we do not specify any deletion policy for the resource, it will be deleted from the stack or with the stack.
Unfortunately, deletion policies cannot be combined with Conditions, since they only allow the storing of String values. What do we need to do if we want different deletion policies for different conditions?
Well, this will require us to declare the same resource multiple times, but with different logical name, condition, and deletion policies.
We don't have to worry about resource duplication, if we set up conditions properly:
Parameters:
Environment:
Type: String
AllowedValued: [ "dev", "test", "prod" ]
Default: "dev"
Conditions:
ProdEnv: !Equals [ !Ref Environment, "prod" ]
TestEnv: !Equals [ !Ref Environment, "test" ]
DevEnv: !Equals [ !Ref Environment, "dev" ]
Then, our Resource section would look like the following:
Resources:
ProdDatabase:
Condition: ProdEnv
Type: AWS::RDS::DBInstance
DeletionPolicy: Retain
Properties:
# Properties for production database
TestDatabase:
Condition: TestEnv
Type: AWS::RDS::DBInstance
DeletionPolicy: Snapshot
Properties:
# Properties for test database
DevDatabase:
Condition: DevEnv
Type: AWS::RDS::DBInstance
DeletionPolicy: Delete
Properties:
# Properties for dev database
This introduces extra complexity for our template but makes it more universal.
Protecting your data is important, so always make sure that you use deletion policies for storage services, such as databases, and storage backends, such as S3 buckets or EBS volumes.
Now that we know how to mitigate the risk of data loss, let's move on to the next topic.