ac24938108
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
143 lines
3.8 KiB
Terraform
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 = {}
|
|
}
|