Skip to content

Kom godt i gang med Terraform ​

Denne guide sætter en minimal Frostmoln-konfiguration op med Terraform.

1. Konfigurer udbyderen ​

Opret main.tf:

hcl
terraform {
  required_providers {
    frostmoln = {
      source = "registry.terraform.io/frostmoln/frostmoln"
    }
  }
}

provider "frostmoln" {
  # Legitimationsoplysninger læses fra udbyderargumenter eller miljøvariabler.
  # Generer en API-nøgle i portalen under Settings -> API Keys.
}

Bruger du OpenTofu? Behold den fuldt kvalificerede kildeadresse — se noten i oversigten over udbyderen.

Angiv din API-nøgle via miljøet, så den holdes uden for versionsstyringen:

bash
export FROSTMOLN_API_KEY=fmk_...

Valg af tenant ​

Som standard administrerer udbyderen ressourcer i din kontos standard-tenant. For at målrette mod en anden tenant sætter du tenant_id på udbyderen — eller miljøvariablen FROSTMOLN_TENANT_ID:

hcl
provider "frostmoln" {
  tenant_id = "00000000-0000-0000-0000-000000000000"
}

At målrette mod en anden tenant end din standard-tenant kræver en fm CLI- / OIDC-session (fm auth login), hvis bruger hører til flere tenants — en API-nøgle er bundet til én enkelt tenant. Én tenant pr. udbyderinstans; for at administrere mere end én tenant i den samme konfiguration deklarerer du endnu en udbyder med et alias. Peg ikke tenant_id et nyt sted hen på en udbyder, der allerede administrerer ressourcer — brug en separat udbyder med alias (og terraform state mv), ellers forsøger Terraform at genskabe dem i den nye tenant.

2. Definer ressourcer ​

Den mindste konfiguration, der rent faktisk giver dig en maskine, du kan logge ind på, er et VPC, en gateway til det, et subnet, en sikkerhedsgruppe, en SSH-nøgle og selve instansen. Tilføj dette til main.tf:

hcl
resource "frostmoln_vpc" "main" {
  name = "tf-vpc"
  cidr = "10.0.0.0/16"
}

# A VPC is an isolated network until a gateway is declared for it: no outbound
# internet and no platform DNS. Leave this out and the instance below still
# boots, but cloud-init cannot reach anything and name resolution fails.
resource "frostmoln_gateway" "main" {
  vpc_id = frostmoln_vpc.main.id
  mode   = "public_ip"
}

resource "frostmoln_subnet" "main" {
  name   = "tf-subnet"
  vpc_id = frostmoln_vpc.main.id
  cidr   = "10.0.1.0/24"
  zone   = "falkenberg"
}

resource "frostmoln_security_group" "web" {
  name   = "tf-web"
  vpc_id = frostmoln_vpc.main.id
}

resource "frostmoln_security_group_rule" "ssh" {
  security_group_id = frostmoln_security_group.web.id
  direction         = "ingress"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_cidr       = "203.0.113.4/32" # your own address, not 0.0.0.0/0
  description       = "SSH from the office"
}

resource "frostmoln_ssh_key" "laptop" {
  name       = "my-laptop"
  public_key = file(pathexpand("~/.ssh/id_ed25519.pub"))
}

data "frostmoln_image" "ubuntu" {
  name = "ubuntu-24.04"
}

resource "frostmoln_instance" "web" {
  name      = "tf-web"
  image_id  = data.frostmoln_image.ubuntu.id
  flavor_id = "gp1.small"
  zone      = "falkenberg"
  vpc_id    = frostmoln_vpc.main.id
  subnet_id = frostmoln_subnet.main.id

  security_groups = [frostmoln_security_group.web.id]
  ssh_key_names   = [frostmoln_ssh_key.laptop.name]
}

# An address of its own, so you can reach the instance from outside. The
# depends_on is what makes `terraform destroy` work: a gateway refuses to be
# removed while public IPs in its VPC still point at it, and without this edge
# nothing tells Terraform to release the address before the gateway.
resource "frostmoln_public_ip" "web" {
  instance_id = frostmoln_instance.web.id

  depends_on = [frostmoln_gateway.main]
}

output "web_address" {
  value = frostmoln_public_ip.web.address
}

Et par ting derinde er værd at kende, før du kører den.

  • Et VPC har ingen vej ud til internettet, før der er deklareret en gateway for det. frostmoln_vpc har med vilje ikke noget konnektivitetsargument — i Terraform er valget af konnektivitet tilstedeværelsen eller fraværet af frostmoln_gateway. Et VPC uden en gateway er isoleret i begge retninger, og fordi platformens DNS og forbindelsen til administrerede tjenester nås ad samme vej, kan instanser i det heller ikke slå navne op. Det er den sædvanlige årsag til, at en første terraform apply ser ud til at være lykkedes, hvorefter cloud-init fejler på hver eneste pakke, den forsøger at installere. Se Gateway.
  • image_id og flavor_id tager ID'er, ikke visningsnavne. En flavors ID er dens SKU, så gp1.small kan skrives bogstaveligt — se hvad der tilbydes med fm compute flavor list, eller læs det i Terraform med datakilderne frostmoln_flavor / frostmoln_flavors. Images identificeres med UUID, så slå et op på navn med datakilden frostmoln_image som ovenfor.
  • security_groups afgør, hvad der kan nå ind. Udelad den, eller sæt den til [], så falder instansen tilbage på tenantens default-gruppe, som tillader al udgående trafik, men kun lukker indgående trafik ind fra instanser i den samme gruppe — altså intet fra internettet, heller ikke SSH. En gruppe, du selv opretter, starter på samme måde: udgående tilladt, slet ingen indgående regler, så den indgående trafik, du ønsker, skal skrives ud, som frostmoln_security_group_rule.ssh gør ovenfor.
  • ssh_key_names tager nøglenavne. frostmoln_ssh_key identificeres ved sit navn inden for en tenant, så frostmoln_ssh_key.laptop.name er den værdi, du skal sende med. Terraforms file() udvider ikke ~ af sig selv — pak stien ind i pathexpand() som ovenfor, eller angiv en absolut sti.
  • zone er valgfri. Udelad den, så vælger platformen en tilgængelighedszone og gemmer den i tilstanden. Hold subnettet og instansen i den samme zone.

3. Anvend ​

bash
terraform init
terraform plan
terraform apply

Terraform holder styr på tilstanden, så efterfølgende apply-kørsler kun ændrer det, der afviger.

4. Riv det ned ​

terraform destroy fjerner ressourcerne igen, med tre bevidste stop på vejen:

  • Gatewayen nægter at blive destrueret, indtil konfigurationen siger, at tabet af konnektivitet er tilsigtet. Tilføj acknowledge_connectivity_loss = true til frostmoln_gateway.main, kør terraform apply på det, og riv derefter ned — og sæt først linjen tilbage, næste gang du får brug for den, eftersom et efterladt true afvæbner beskyttelsen i hele ressourcens levetid.
  • Gatewayen nægter også, så længe offentlige IP-adresser i dens VPC stadig afhænger af den. depends_on ovenfor klarer det for den ene adresse i denne konfiguration, men enhver anden offentlig IP-adresse i det samme VPC — en lastbalancers, eller en som denne konfiguration ikke administrerer — skal frakobles først. Se Offentlige IP-adresser.
  • At destruere frostmoln_public_ip frigiver adressen for bestandigt. Den vender tilbage til en delt pulje og udstedes igen til den næste, der beder om en, så en adresse, der er offentliggjort i DNS eller står på nogens tilladelsesliste, er værd at beskytte med Terraforms egen lifecycle { prevent_destroy = true }.

Relateret ​