Files
alva/infra/terraform/README.md
T
Claude 19796bec70 Terraform blir enda vägen, och backup ett obligatoriskt val
Kustomize- och Argo CD-vägen är borttagen. Den beskrev samma system en
gång till och kunde inte köras samtidigt som Terraform utan att de
motarbetade varandra — selfHeal återställde det Terraform ändrade och
prune tog bort det Terraform skapade. Kvar utanför Terraform är bara
postgres-init.sql, som läses av både definitionen och integrationstestet
så att schemat inte kan glida isär från det som testas.

Säkerhetskopieringen var en förhoppning: en StatefulSet med en volym och
ingen kopia. Går volymen förlorad är det inte "data" som försvinner utan
varje ärendes bevisvärde — vad som kontrollerades, av vem, när, med
vilken evidens — och det går inte att återskapa i efterhand.

databas_lage är därför ett obligatoriskt val utan standardvärde:

  extern    managerad Postgres, leverantörens backup och PITR
            (rekommenderat i produktion)
  cnpg      CloudNativePG i klustret: basbackup 02:30, kontinuerlig
            WAL-arkivering till objektlagring, PITR och failover
  inbyggd   en volym, ingen backup — spärras av en precondition när
            miljön är produktion

Preconditions fångar felkonfiguration vid plan i stället för vid drift:
extern utan anslutning, cnpg utan backupmål eller nycklar, inbyggd i
produktion.

Driftsättningen är nu två åtskilda flöden. Publicera bygger och taggar
bilderna vid varje main-push; Driftsätt startas för hand med en tagg mot
en GitHub-miljö som kan kräva godkännande, kör fmt/init/validate/plan/
apply, skriver ut kartan och rökkontrollerar hälsa och API-spec. En bild
i registret är inte samma sak som en bild som kör. Rollback är att köra
Driftsätt igen med en tidigare tagg. CI kör dessutom terraform validate
på varje PR — den kontroll jag inte kunde köra själv.

Två fel hittade vid egengranskning av definitionen: schemafilen delades
på semikolon, vilket hade klippt itu plpgsql-funktionen med
append-only-triggern (nu hela filen via postInitApplicationSQLRefs), och
null-satta fält i kubernetes_manifest utelämnas nu i stället.

Verifierat: 87 vitest-tester, typkontroll, eslint, OpenAPI-validering,
terraform fmt, statisk referenskontroll av modulen och integrationstest
mot riktig Postgres. terraform validate kunde inte köras här —
registry.terraform.io är blockerad av sessionens egress-policy, därav
CI-jobbet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-03 22:16:52 +00:00

4.3 KiB

Infrastrukturen

Hela systemet i Terraform. Filerna är numrerade i den ordning de är begripliga att läsa:

Fil Vad
versions.tf Leverantörer och tillståndsbackend
variables.tf Allt som skiljer en installation från en annan
karta.tf Systemet som data — tjänster, portar, routing, hemligheter, dataflöden, gränser
10-namnrymd.tf Namnrymd, hemligheten, databasschemat
20-databas.tf Händelseloggen — tre lägen, se nedan
30-plattform.tf Backend: auth, händelse-API, delning, integrationer
40-orkester.tf AI-orkestern
50-web.tf Klienten
60-ingress.tf Trafiken utifrån
70-natverk.tf Nätverkspolicyer — vem får prata med vem
outputs.tf Kartan utskriven

Börja i karta.tf. Den beskriver systemet en gång, som data; resten av filerna läser därifrån i stället för att upprepa portar och namn.

Kom igång

cp terraform.tfvars.exempel terraform.tfvars   # fyll i domän, register, nycklar
terraform init
terraform plan
terraform apply
terraform output karta                         # hela systemet i klartext

terraform output karta svarar på frågorna "vad kör var", "vem ser vilken hemlighet", "vad pratar med vad" och "vad ingår inte" — utan att någon behöver läsa .tf-filerna.

Kontroll utan kluster

terraform fmt -check -diff        # formatering
terraform init -backend=false     # hämtar leverantörer
terraform validate                # typer och referenser

terraform validate kräver att leverantörerna hämtats från registry.terraform.io.

Databasen: tre lägen

var.databas_lage saknar standardvärde med flit. Valet avgör om det finns säkerhetskopiering, och det ska inte kunna bli fel av slentrian.

Läge Backup Failover Använd när
extern Leverantörens, med PITR Leverantörens Produktion. Cloud SQL, RDS, Neon, Azure Flexible Server
cnpg Basbackup 02:30 + WAL-arkiv → objektlagring, PITR Ja, databas_instanser styr Produktion när databasen måste ligga i klustret
inbyggd Ingen Nej Prov och demo. Blockeras av en precondition när miljo = "produktion"

Går händelseloggen förlorad är det inte "data" som försvinner utan varje ärendes bevisvärde: vad som kontrollerades, av vem, när, med vilken evidens. Det går inte att återskapa i efterhand.

cnpg kräver att CloudNativePG-operatorn redan är installerad — Terraform slår upp dess CRD vid plan:

kubectl apply --server-side -f \
  https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.25/releases/cnpg-1.25.0.yaml

I extern läge ansvarar ni själva för att köra infra/postgres-init.sql mot databasen. Det är samma fil som integrationstestet kör, så schemat kan inte glida isär från det som testas.

Driftsättning

Bilderna byggs av publicera.yml vid varje push till main och taggas med git-SHA:t. Driftsättningen är ett eget flöde, driftsatt.yml, som startas för hand med en tagg och kör mot GitHub-miljön produktion — den kan kräva godkännande. Rollback är att köra flödet igen med en tidigare tagg.

Kustomize- och Argo CD-vägen är borttagen. Den beskrev samma system en gång till och kunde inte köras samtidigt som Terraform utan att de motarbetade varandra (selfHeal återställde det Terraform ändrade, prune tog bort det Terraform skapade).

Det som medvetet inte ingår

Står också i terraform output karta under avgränsningar:

  • Objektlagring. Foton och video ligger som data-URL:er i händelseloggen. Det gör loggen till systemets enda sanningskälla, men också stor och tung att säkerhetskopiera.
  • Observability. Ingen metrikexport, ingen tracing.
  • Takt-begränsning på inloggning. Bara den publika beslutsvägen är begränsad, och bara per pod.
  • Återkallelse av JWT. En utfärdad token gäller sina 12 timmar ut även om användaren tagits bort.

Krav på klustret

  • En CNI som tillämpar NetworkPolicy (Cilium, Calico, Antrea). Utan det är 70-natverk.tf dokumentation, inte skydd.
  • ingress-nginx, med kontrollern i namnrymden var.ingress_namnrymd.
  • cert-manager med en ClusterIssuer.
  • En metrics-server för autoskalningen.
  • En StorageClass som klarar ReadWriteOnce.