Files
Claude ac24938108 AWS-basen: allt eget, inget GitHub
Guidad Felsökning får en egen AWS-grund i felsokning/infra/aws — nät,
kluster, databas, objektlagring, register, hemligheter, domän och
observation. Inget GHCR, ingen extern byggtjänst.

Två lager i ordning, och uppdelningen är inte smak: en enda apply som
både skapar ett EKS-kluster och schemalägger in i det är en känd fälla,
eftersom kubernetes-leverantören måste konfigureras med uppgifter som
inte finns förrän klustret existerar.

Nätet ligger i tre lager. Publikt bara för lastbalanserare och NAT,
privat för noderna, och ett eget datalager för Aurora utan routing ut
alls — att databasen inte kan nå internet hänger då inte på att en
säkerhetsgrupp är rätt konfigurerad. VPC-endpoints för S3, ECR, loggar,
Secrets Manager, STS och ELB gör att bilddragningar och loggar aldrig
lämnar nätet, vilket både är säkrare och sänker NAT-notan rejält.

IRSA i stället för nodroller: plattformens tjänstekonto har en roll
bunden till exakt en namnrymd och ett tjänstekonto, så grannpodden på
samma nod får ingenting på köpet. IMDSv2 med hoppgräns 1 hindrar
dessutom en pod från att låna nodens roll via metadatatjänsten.

Bygge och drift har delade rättigheter. Byggrollen får publicera till
ECR men inte röra klustret; driftrollen tvärtom. Ett komprometterat
bygge kan därför inte driftsätta.

Aurora PostgreSQL Serverless v2 med 30 dagars säkerhetskopiering och
PITR ned till sekunden — det som gör den duglig för händelseloggen är
inte prestandan utan att förlorad logg annars hade tagit varje ärendes
bevisvärde med sig. S3-hinken för bilagor har versionshantering,
SSE-KMS, TLS-krav och blockerad publik åtkomst; plattformens roll får
läsa och skriva men aldrig radera, eftersom bilagorna hör till en
append-only logg.

Larmen är fyra och ett av dem larmar på saknad data: uteblir mätvärdet
för säkerhetskopiering finns ingen backup, och en backup man tror finns
är värre än ingen.

Verifierat: terraform fmt och en statisk referenskontroll (88 resurser,
5 datakällor, inga dinglande referenser). terraform validate kunde inte
köras här — registry.terraform.io är blockerad av sessionens
egress-policy — så CI-jobbet kör den i stället.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-04 12:39:42 +00:00

143 lines
3.8 KiB
Terraform

variable "region" {
description = "AWS-region. eu-north-1 (Stockholm) håller fordonsdata inom EU."
type = string
default = "eu-north-1"
}
variable "miljo" {
description = "Miljöns namn — ingår i alla resursnamn och taggar."
type = string
default = "produktion"
}
variable "doman" {
description = "Domänen tjänsten nås på, t.ex. felsokning.exempel.se."
type = string
}
variable "zon_id" {
description = <<-TEXT
Befintlig Route 53-zon att skapa posten i. Lämnas den tom skapas en
ny publik zon för domänens rot — då måste namnservrarna pekas om hos
registraren innan certifikatet kan utfärdas.
TEXT
type = string
default = ""
}
# ---- Nät ---------------------------------------------------------------
variable "vpc_cidr" {
description = "Adressrymd för VPC:n."
type = string
default = "10.42.0.0/16"
validation {
condition = can(cidrsubnet(var.vpc_cidr, 4, 0))
error_message = "vpc_cidr måste vara ett giltigt CIDR med plats för /20-subnät."
}
}
variable "antal_zoner" {
description = "Antal tillgänglighetszoner. Tre ger failover som överlever att en zon försvinner."
type = number
default = 3
validation {
condition = var.antal_zoner >= 2 && var.antal_zoner <= 4
error_message = "antal_zoner måste vara mellan 2 och 4."
}
}
variable "nat_per_zon" {
description = <<-TEXT
En NAT-gateway per zon i stället för en delad. Rätt i produktion —
med en delad blir den zonen en enskild felkälla för all utgående
trafik. Kostar mer, så av i test.
TEXT
type = bool
default = true
}
# ---- Kluster -----------------------------------------------------------
variable "kubernetes_version" {
description = "EKS-version."
type = string
default = "1.31"
}
variable "nod_typer" {
description = "Instanstyper för nodgruppen. Flera ökar chansen att kapacitet finns."
type = list(string)
default = ["m7g.large", "m6g.large"]
}
variable "noder" {
description = "Nodgruppens storlek."
type = object({
minsta = number
onskad = number
hogsta = number
})
default = {
minsta = 3
onskad = 3
hogsta = 10
}
}
variable "tillatna_api_cidr" {
description = <<-TEXT
Varifrån EKS API-server får nås. Standard är öppet eftersom det
annars inte går att komma åt klustret alls från en ny miljö —
begränsa till kontorets och byggrunnernas adresser i produktion.
TEXT
type = list(string)
default = ["0.0.0.0/0"]
}
# ---- Databas -----------------------------------------------------------
variable "databas" {
description = <<-TEXT
Aurora PostgreSQL. Serverless v2 skalar efter last; min_kapacitet
0.5 ACU räcker för en liten verkstad, max sätter taket.
backup_dagar styr både automatisk säkerhetskopiering och hur långt
tillbaka PITR går.
TEXT
type = object({
version = optional(string, "16.6")
min_kapacitet = optional(number, 0.5)
max_kapacitet = optional(number, 8)
instanser = optional(number, 2)
backup_dagar = optional(number, 30)
raderingsskydd = optional(bool, true)
})
default = {}
}
# ---- Larm --------------------------------------------------------------
variable "larm_epost" {
description = "Adress som larm skickas till. Tom = inget SNS-abonnemang skapas."
type = string
default = ""
}
# ---- Självhostad git ---------------------------------------------------
variable "gitea" {
description = <<-TEXT
Självhostad git med egna byggrunners, så varken källkod, bygge eller
register ligger hos någon annan. Slås av om ni tills vidare kör git
någon annanstans.
TEXT
type = object({
aktiv = optional(bool, true)
doman = optional(string, "")
runners = optional(number, 2)
})
default = {}
}