DFE on AWS -- Teardown
Provisioning is in aws.md. Running the cluster is in aws-operations.md.
Lifecycle tags
tags.lifecycle: ephemeral(tyre-kick, provision-test-destroy) is the one governance tag that changes what gets built and not just what gets labelled. It sets the secret recovery windows on the deployment's own secrets and the Kafka SCRAM credential to 0 days instead of 30. It sets redpanda-cloud'sallow_deletionto true instead of the vendor's own default refusal. So a tyre-kick deployment tears down cleanly, anything else keeps the vendor's normal deletion protection, and nobody has to remember a per-resource flag.- The tag also decides what a destroy keeps. An ephemeral deployment's KMS key is scheduled for deletion (7 days) and its ClickHouse object-store, CloudTrail and session-log buckets go with their objects. Any other deployment keeps the key and all three buckets, each with its policy, encryption and lifecycle, because tofu forgets them and doesn't delete them. A bare
tofu destroythen ends withDestroy was successful but left behind forgotten instancesunless you pass-suppress-forget-errors.dfe-ops teardown --with-terraformpasses it on a persistent deployment only, read from the root'sretained_on_destroyoutput, and its last lines name every address it kept. Delete the buckets once nothing needs what they hold, then schedule the key's deletion. - Every
dfe-opscommand against an ephemeral dial opens with one stderr line. It gives the resolvedcompute_bucketfromsizing/resolved.yaml(a T-shirt bucket, never a rate) and how long the cluster has been up. Deployment age comes from the root'scluster_created_atoutput. A dial with no cluster behind it reports the age as unavailable. Neither reading may fail the command. - A managed node group gets a launch template when the registry cache writes a node script. Adding one to an existing node group replaces the group.
Tearing down
- Start teardown as soon as your last check passes. The managed Kafka cluster takes longest to create and to delete, so it goes down first. When you're testing, batch your checks into one full cloud cycle and don't run one per finding (cloud-cycle.md).
bootstrap/destroy.shdeletes the node pools' Application,karpenter-pools-<cluster>found by its name, once the load balancers are released. It keeps Karpenter itself until every NodeClaim is gone (up to 600s), because a node left running holds its subnets through its network interfaces andtofu destroyfails on them. On a test run its last step terminates any node a Karpenter pool launched for that run and cluster.- The dfe-hyperdx store keeps its volumes (reclaim policy
Retain) while it runs. Once the DocumentDB operator has gone,bootstrap/destroy.shsets the volumes labelleddocumentdb.io/cluster=dfe-documentdb,documentdb.io/namespace=cnpgtoDelete, so the EBS CSI driver deletes each one with its disk. Atofu destroyrun without it first leaves those disks behind. - Tear down with
tofu destroyinterraform/environments/aws, and delete the Kubernetes workloads first. Anything that made a load balancer, a volume or a DNS record did so through a controller, andtofu destroydoesn't know about it. - An untargeted
tofu destroyon an MSK dial fails withClient configuration missinguntil the Redpanda credentials are in the environment. The root declaresprovider "redpanda", and OpenTofu configures every provider the configuration requires whether or not the dial selects it. That provider's client resolvesREDPANDA_CLIENT_IDandREDPANDA_CLIENT_SECRETor fails. Until the root stops requiring it, export those two with any value for the run, or destroy by target. Don't reach for-exclude, because it can't be combined with-target.
Rebuilding a persistent deployment under the same name
A persistent destroy leaves the key and the three buckets in the account, so an apply under the same dial name fails creating them (BucketAlreadyOwnedByYou). Import them first, from terraform/environments/aws, so the new deployment takes over the kept data and doesn't start beside it. The key and each bucket are in the kept lines the teardown printed. The key's ID is its ARN after key/, and a bucket's name is its ARN after arn:aws:s3:::.
| Address | Import ID |
|---|---|
module.cluster.aws_kms_key.retained[0] | the key's ID |
module.cluster.module.clickhouse_object_store.<resource>.retained[0] | the ClickHouse bucket's name |
module.cloudtrail_bucket[0].<resource>.retained[0] | the CloudTrail bucket's name (only with cloudtrail.enabled) |
module.toolbox_session_logs.<resource>.retained[0] | the session-log bucket's name |
<resource> is each of aws_s3_bucket, aws_s3_bucket_public_access_block, aws_s3_bucket_ownership_controls, aws_s3_bucket_policy, aws_s3_bucket_server_side_encryption_configuration and aws_s3_bucket_lifecycle_configuration, all imported by the bucket's name, plus aws_s3_bucket_versioning on the CloudTrail and session-log buckets. For example:
tofu import 'module.cluster.aws_kms_key.retained[0]' 00000000-0000-0000-0000-000000000000
tofu import 'module.toolbox_session_logs.aws_s3_bucket.retained[0]' dfe-toolbox-session-logs
Then tofu plan shows the imported resources unchanged and everything else to create. The key's alias is recreated, pointing at the imported key.
Sweeping what is left
- Run
scripts/cloud_sweep.py --region <region>read-only to see what's left. Add--exclude-bucket <state bucket>so the state store is never a candidate. Only add--deleteonce you've read the listing. --deleterequires--account <12-digit>, checked againstaws sts get-caller-identitybefore anything is touched. It refuses on a mismatch or a missing--account, the same guard both tofu roots already carry against running in the wrong account. It also prints the full eligible list and asks for a typedyesbefore deleting anything.--yesskips that prompt for a CI run.--include-untaggedwidens the sweep to every resource the listers found, tagged or not, which turns--deleteinto a region-wide wipe of the account (--exclude-bucketis the one exemption). Without it,--deleteonly removes resources carrying the tag filter. The AWS account defaults are never listed or touched: the default VPC and everything that comes with it, and AWS-managed KMS aliases.--expiredselects resources whosedfe-e2erun tag carries anexpires-atpast--grace(default 1h), plus any non-default security group with no run tag inside a VPC so selected. EKS creates its cluster security group untagged and outside tofu state, and the VPC can't be deleted while it stands. Unattended runs and their reaper are in cloud-cycle.md.