Skip to content

Kom i gang med Terraform

Denne veiledningen setter opp en minimal Frostmoln-konfigurasjon med Terraform.

1. Konfigurer leverandøren

Opprett main.tf:

hcl
terraform {
  required_providers {
    frostmoln = {
      source = "frostmoln/frostmoln"
    }
  }
}

provider "frostmoln" {
  # Legitimasjon leses fra leverandørargumenter eller miljøvariabler.
  # Generer en API-nøkkel i portalen under Settings -> API Keys.
}

Oppgi API-nøkkelen din via miljøet slik at den holder seg utenfor kildekontroll:

bash
export FROSTMOLN_API_KEY=fmk_...

Velge en tenant

Som standard håndterer leverandøren ressurser i kontoens standard-tenant. For å rette mot en annen tenant, sett tenant_id på leverandøren — eller miljøvariabelen FROSTMOLN_TENANT_ID:

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

Å rette mot en annen tenant enn standarden krever en fm CLI- / OIDC-økt (fm auth login) der brukeren tilhører flere tenanter — en API-nøkkel er bundet til én enkelt tenant. Én tenant per leverandørinstans; for å håndtere mer enn én tenant i samme konfigurasjon, deklarer en andre leverandør med et alias. Ikke pek tenant_id om på en leverandør som allerede håndterer ressurser — bruk en egen leverandør med alias (og terraform state mv), ellers prøver Terraform å opprette dem på nytt i den nye tenanten.

2. Definer ressurser

Den minste konfigurasjonen som faktisk gir deg en maskin du kan logge inn på, er et VPC, en gateway for det, et subnett, en sikkerhetsgruppe, en SSH-nøkkel og selve instansen. Legg dette til i 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
}

Noen ting i den konfigurasjonen er verdt å kjenne til før du kjører den.

  • Et VPC har ingen vei ut til internett før en gateway er deklarert for det.frostmoln_vpc har bevisst ikke noe konnektivitetsargument — i Terraform er konnektivitetsvalget tilstedeværelsen eller fraværet av frostmoln_gateway. Et VPC uten gateway er isolert i begge retninger, og fordi plattformens DNS og tilkoblingen til administrerte tjenester nås over samme vei, kan instanser i det heller ikke slå opp navn. Det er den vanligste grunnen til at en første terraform apply ser ut til å lykkes, og cloud-init deretter feiler på hver pakke den prøver å installere. Se Gateway.
  • image_id og flavor_id tar ID-er, ikke visningsnavn. En flavors ID er SKU-en dens, så gp1.small kan skrives direkte — se hvilke som tilbys med fm compute flavor list, eller les dem i Terraform med datakildene frostmoln_flavor / frostmoln_flavors. Images identifiseres med UUID, så slå opp ett på navn med datakilden frostmoln_image som over.
  • security_groups avgjør hva som kan nå inn. Utelat den, eller sett den til [], og instansen faller tilbake på tenantens default-gruppe, som tillater all utgående trafikk, men bare slipper inn innkommende trafikk fra instanser i samme gruppe — altså ingenting fra internett, ikke engang SSH. En gruppe du lager selv starter på samme måte: utgående tillatt, ingen innkommende regler i det hele tatt, så den innkommende trafikken du vil ha må skrives ut slik frostmoln_security_group_rule.ssh gjør over.
  • ssh_key_names tar nøkkelnavn. frostmoln_ssh_key identifiseres av navnet sitt innenfor en tenant, så frostmoln_ssh_key.laptop.name er verdien som skal sendes inn. Terraforms file() utvider ikke ~ på egen hånd — pakk stien inn i pathexpand() som over, eller oppgi en absolutt sti.
  • zone er valgfri. Utelat den, så velger plattformen en tilgjengelighetssone og lagrer den i tilstanden. Hold subnettet og instansen i samme sone.

3. Bruk

bash
terraform init
terraform plan
terraform apply

Terraform sporer tilstand, så påfølgende apply-kjøringer endrer bare det som er forskjellig.

4. Riv det ned

terraform destroy fjerner ressursene igjen, med tre bevisste stopp på veien:

  • Gatewayen nekter å bli ødelagt til konfigurasjonen sier at tapet av tilkobling er tilsiktet. Legg til acknowledge_connectivity_loss = truefrostmoln_gateway.main, kjør terraform apply på det, og riv så ned — og sett linjen tilbake først neste gang du trenger den, siden en gjenglemt true avvæpner vernet for resten av ressursens levetid.
  • Gatewayen nekter også så lenge offentlige IP-er i VPC-en fortsatt avhenger av den. depends_on over ordner det for den ene adressen i denne konfigurasjonen, men enhver annen offentlig IP i samme VPC — en lastbalanserers, eller en denne konfigurasjonen ikke administrerer — må kobles fra først. Se Offentlige IPer.
  • Å ødelegge frostmoln_public_ip frigjør adressen for godt. Den går tilbake til en delt pool og deles ut til den neste som spør, så en adresse som er publisert i DNS eller ligger i noens tillatelsesliste er verdt å beskytte med Terraforms egen lifecycle { prevent_destroy = true }.

Relatert