-
Notifications
You must be signed in to change notification settings - Fork 0
Terraform layout
Three stacks, three states, three lifetimes.
terraform/azure/ the machine that hosts the cloud
terraform/openstack/ what lives inside the cloud
terraform/kubernetes/ the k3s experiment
The reflex is to put everything in one folder. Splitting them was decided on one question: what happens if this is destroyed by mistake?
| Stack | Rebuild cost | Changes |
|---|---|---|
azure |
an hour, DevStack has to be reinstalled | rarely |
openstack |
thirty seconds | constantly |
kubernetes |
a few minutes | it is an experiment |
A single state would mean one wrong terraform destroy wipes the host along
with the instance you meant to remove. Separate states keep the blast radius
proportional to what you are working on.
The second reason is that they do not even talk to the same API: azure calls
Azure, the other two call your own OpenStack.
Three tests, in order:
Does it differ between two people running this? Subscription, resource group, region, SSH key path. Those are variables with a default only when a wrong value is harmless.
Is it a security decision? allowed_ssh_cidr has no default. A default
would be a silent choice made for the user, and the tempting default is
0.0.0.0/0. Terraform refusing to run is the correct behaviour here.
Would a change force a rebuild? VM size, image, flavor. Worth exposing, so adapting to a different subscription is a value change and not a code edit.
Everything else stays hardcoded. A variable nobody will ever change is noise.
data "azurerm_resource_group" "lab" {
name = var.resource_group_name
}The resource group already exists and belongs to the school. data reads it,
resource would claim ownership, and a terraform destroy would then try to
delete a group shared with the whole class.
The rule: describe with resource only what you are willing to destroy.
Outputs are not decoration, they are how the next tool gets its input:
-
public_ipandprivate_ipfeed the Ansible inventory -
floating_ipfeeds the SSH command at the end of the demo -
instance_nameexists so the demo can name the instance instead of guessing
Whenever a value has to be copied by hand from one step to the next, that value should have been an output.
resource "openstack_networking_floatingip_associate_v2" "vm" {
floating_ip = openstack_networking_floatingip_v2.vm.address
port_id = data.openstack_networking_port_v2.vm.id
}Referencing another resource is what builds the graph. depends_on is a last
resort, for the rare case where the link is real but invisible to Terraform.
The same idea powers the k3s node: the floating IP is created first because its address is referenced inside the cloud-init that configures the API server certificate.
-
List what already exists and what you are creating. The first group is
data, the second isresource - Group by lifetime. Things destroyed together belong in the same state
- Look for the hand copied values. Each one is a missing output
- Look for the dangerous defaults. Each one is a variable that should have none
-
Read the provider documentation for the resource, not a blog post.
Providers change: v3 of the OpenStack provider dropped
openstack_compute_floatingip_associate_v2, and only the registry said so