Skip to content

Oppgradering

Denne guiden dekker oppgraderingsprosessen for Lumi installert med Helm.

Støttegrense

Alle publiserte 1.x-images og -charts var teknisk forhåndsvisning. Det finnes ingen kundestøttede eksterne 1.x-installasjoner og ingen støttet oppgradering på stedet fra 1.x. Første kundestøttede baseline blir en ren 2.0.0-installasjon som inneholder både dashboardets eksplisitte teamvalg og API-ets strenge håndheving. Versjonsbump og publisering skjer i en separat release-PR. Forhåndsvisningsmiljøer må opprettes på nytt; bevaring eller migrering av data derfra er utenfor støttekontrakten.

Denne guiden definerer ingen støttet 1.x→2.0.0-oppgradering. Støttede oppgraderingsløp begynner mellom senere releaser etter en ren 2.0.0-installasjon. Fra denne baselinen gjelder igjen kontraktene om additive API-endringer, forward-only migrasjoner og kontrollert mixed-version rollout.

Forutsetninger

  • helm og kubectl installert
  • Tilgang til Kubernetes-clusteret der Lumi kjører
  • Kjenn gjeldende versjon: helm list -n lumi

Versjonspinning

Lumi publiserer Docker-images og Helm chart med semantisk versjonering. Når en release inneholder ny app-kode, følger chart-versjon og appVersion hverandre 1:1. Chart-only patcher kan bumpe chart-versjonen uten å endre appVersion; da peker chartet fortsatt på samme API- og dashboard-image.

Release-artefakter publiseres fra Git-taggen v<chart-version>. Main-CI oppdaterer bare latest og commit-SHA-tagger; release-workflowen promoterer de main-testede SHA-manifestene til eksplisitte versjonstagger for API/dashboard og publiserer Helm chart. Versjonstagger skal ikke repushes manuelt.

ArtefaktAnbefalt pinning
Helm chart--version 1.2.3
API-imageapi.image.tag=1.2.3
Dashboard-imagedashboard.image.tag=1.2.3
PostgreSQL subchart runtime imagepostgresql.image.digest=sha256:...
Valkey subchart runtime imagevalkey.image.digest=sha256:...
PostgreSQL/Valkey metrics imagespostgresql.metrics.image.digest=sha256:..., valkey.metrics.image.digest=sha256:...
PostgreSQL/Valkey volume-permissions imagepostgresql.volumePermissions.image.digest=sha256:..., valkey.volumePermissions.image.digest=sha256:...

Hvis api.image.tag eller dashboard.image.tag er tom (default i values.yaml), faller chart-en tilbake til Chart.AppVersion. PostgreSQL og Valkey defaulter til digest-pinnede runtime images, inkludert opt-in metrics exporter og volume-permissions images. Eksplisitt pinning i egne values-filer er fortsatt anbefalt for produksjon — da er du ikke avhengig av chart-revisjonen som ble installert.

Ikke bruk latest-tag i produksjon

latest oppdateres ved hver commit til main og er ikke egnet for produksjon. Bruk alltid eksplisitte versjonstagger.

Før oppgradering

1. Ta backup av databasen

sh
kubectl exec -n lumi lumi-postgresql-0 -- \
  pg_dump -U lumi -d lumi > lumi-backup-$(date +%F).sql

Ekstern database

Hvis du bruker ekstern PostgreSQL (postgresql.enabled=false), bruk din vanlige backup-prosedyre (f.eks. pg_dump direkte eller managed snapshots).

2. Les endringslogg

Sjekk CHANGELOG.md i din lokale klone for breaking changes mellom din gjeldende versjon og målversjonen.

3. Kontroller Secret-kombinasjoner

Chartet validerer values.yaml før installasjon og oppgradering, og feiler lukket når et medfølgende datalager bruker en eksisterende Secret mens en app fortsatt ville lest samme påloggingsverdi fra inline chart-verdier. Kontroller disse kombinasjonene før oppgradering:

  • postgresql.auth.existingSecret eller den høyere prioriterte global.postgresql.auth.existingSecret krever både api.existingSecret og dashboard.existingSecret.
  • valkey.auth.existingSecret krever api.existingSecret.
  • Medfølgende Valkey tillater ikke valkey.auth.enabled=false. Sett valkey.enabled=false dersom cachelaget skal slås helt av.

App-Secretene må inneholde nøklene som er dokumentert i values.yaml, med påloggingsverdier som matcher datalagerets Secrets. Alternativt må datalagerets existingSecret fjernes og chart-styrte påloggingsverdier konfigureres etter virksomhetens Secret-policy. Kjør helm lint med den faktiske values-filen og de samme --set-verdiene som deploy-jobben før helm upgrade; schema- eller template-validering stopper oppgraderingen før Kubernetes-ressurser endres.

4. Kontroller ingress TLS

Lumi feiler Helm render/upgrade når ingress.enabled=true og ingress.tls.enabled=false. Dette hindrer at dashboard, API og widget submissions eksponeres over plaintext HTTP som default. Sett TLS eksplisitt i values-filen eller CLI-flaggene:

yaml
ingress:
  enabled: true
  tls:
    enabled: true
    secretName: lumi-dashboard-tls

Hvis installasjonen bevisst kjører uten TLS i et lukket lokalt testmiljø, må den opt-in verdien settes eksplisitt:

yaml
ingress:
  tls:
    allowInsecure: true

Ikke bruk ingress.tls.allowInsecure=true i kunde- eller produksjonsmiljøer.

5. Forbered publishable API keys

Fra og med versjonen som innfører påkrevde allowedOrigins, avviser API-et nye pk_-nøkler uten minst én origin med HTTP 400. Eksisterende aktive pk_-nøkler uten allowedOrigins er en upgrade-blocker: preflight og API-startup feiler før ny versjon begynner å serve.

Remediering er å opprette nye pk_-nøkler med eksplisitte allowedOrigins, oppdatere widget-konfigurasjonen, og deretter revokere de gamle nøklene. Ikke bruk eksisterende rotate-endepunkt som remediation for legacy unrestricted keys: rotasjon kopierer nøkkelens eksisterende allowedOrigins.

Oppdater automatisering eller runbooks som oppretter publishable keys før oppgradering. CLI-bruk må sende én eller flere --allowed-origin <origin> når den lager pk_-nøkler. Bruk bare api.env.allowUnrestrictedPkOrigins=true / LUMI_ALLOW_UNRESTRICTED_PK_ORIGINS=true som et midlertidig, eksplisitt unntak for lokal utvikling eller lukkede/trusted deployments. Ikke la unntaket stå på i produksjon.

Helm chartet kjører en pre-upgrade Job (check-pk-origins) før API Deployment oppdateres. Jobben bruker nåværende live DB-env fra eksisterende API ConfigMap/Secret, target API-image, og target-verdi for unrestricted-origin-unntaket. Hvis oppgraderingen samtidig bytter DB host, DB_JDBC_URL, database-credentials eller Secret-navn, kjør DB-endringen i et separat steg eller kjør check-pk-origins manuelt mot target-databasen før Deployment apply.

For GitOps og helm template-flyter: kjør den rendrerte preflight-Jobben alene og vent på Complete før resten av manifestene applyes. Hvis hook-ressursene ikke brukes av verktøyet ditt, kjør tilsvarende one-off Job med samme API-image og DB-env. En startup-guard i API-et stopper fortsatt ny pod før serving hvis preflighten er hoppet over.

6. Forbered team-roller

Versjonen som innfører teamroller legger til role på OIDC group mappings med database-default admin. Eksisterende mappings beholder dermed dagens tilgang etter oppgradering. Nye mappings kan settes til viewer, editor eller admin.

Etter oppgraderingen krever muterende teamoperasjoner og eksport eksplisitt ?team=. Dashboardet sender dette automatisk; egne integrasjoner mot /api/v1/intern/* må sende team-slug på export, feedback-tagging/delete, survey-delete, marker CRUD, theme CRUD og dashboard API-key lifecycle.

7. Forbered strengt teamvalg

Fra den støttede 2.0.0-baselinen velger vanlige lesekall team implisitt bare når brukeren har nøyaktig ett autorisert team. Ved flere team må klienten sende en eksplisitt, ikke-tom ?team=<slug>; å få tilgang til team nummer to kan derfor endre et manglende teamvalg fra 200 til 400. GET /api/v1/intern/filters/bootstrap er det avgrensede unntaket og velger stabilt laveste slug med ordinal, case-sensitiv sammenligning. GET /api/v1/intern/teams er aggregert bare når team-parameteren er helt fraværende.

Survey-pathen /api/v1/dashboard/surveys/{teamSlug} velger aldri team. Egne klienter må sende samme autoriserte slug i ?team=; ulik query og path avvises. Ved gjentatt query-parameter brukes første verdi (?team=A&team=B velger A), og en tom eller uautorisert første verdi reddes ikke av en senere verdi.

Dashboard- og API-endringene må finnes sammen i den første støttede baselinen. Midlertidige kombinasjoner av preview-images kan gi både 200 og 400 for gamle klienter og er uttrykkelig utenfor støttekontrakten.

8. Verifiser at nåværende deployment er sunn

sh
# Sjekk pod-status
kubectl get pods -n lumi

# Sjekk API health
kubectl exec -n lumi deploy/lumi-api -- curl -s localhost:8080/internal/isAlive
# Forventet: OK

kubectl exec -n lumi deploy/lumi-api -- curl -s localhost:8080/internal/isReady
# Forventet: OK

Oppgradering

sh
helm upgrade lumi oci://ghcr.io/asorheim/lumi-analytics/charts/lumi \
  --namespace lumi \
  --version <ny-versjon> \
  --reuse-values

Hva skjer under oppgradering

  1. Helm bytter API-pods med Recreate-strategi, slik at gamle og nye API-versjoner ikke håndterer innsendinger samtidig
  2. Nye API-pods kjører Flyway-migrasjoner automatisk ved oppstart
  3. Dashboard-pods oppdateres med vanlig Kubernetes rolling update

Chart-genererte ConfigMaps og Secrets inngår i pod-template checksum. Endringer i chart-verdier for DB, Valkey, OIDC client secret eller session secret trigger derfor ny API/dashboard-pod ved helm upgrade.

Eksterne Secrets

Når api.existingSecret eller dashboard.existingSecret peker på en forhåndsopprettet Kubernetes Secret, kan ikke Helm se endringer i Secret-dataene. Etter rotasjon av en slik Secret må du enten endre Secret-navnet i values eller kjøre manuell rollout, for eksempel kubectl rollout restart deploy/lumi-api deploy/lumi-dashboard -n lumi.

Ingen blandede API-versjoner

Kjør ikke blue/green, canary, flere Helm-releaser eller manuelle ekstra API-Deployments mot samme database under oppgraderinger som endrer survey-definition-semantikk. Kun én API-versjon skal kunne motta /api/v1/submission-trafikk om gangen.

Dette gjelder også origin-guard-oppgraderingen: gamle pods kan fortsatt opprette eller godta unrestricted pk_-nøkler. Ikke kjør gamle og nye API-versjoner parallelt mot samme database når du fjerner legacy unrestricted keys.

Rollback etter midlertidig unntak

Hvis du aktiverer unrestricted-origin-unntaket for å komme gjennom en oppgradering, må unntaket spores til alle legacy pk_-nøkler er erstattet og revokert. Rollback til en eldre chart/image uten remediation gjør at unrestricted keys igjen aksepteres uten startup-guard.

Mellom støttede releaser etter 2.0.0 skal du alltid oppgradere én minor-versjon om gangen. Ikke hopp over versjoner.

Databasemigrasjoner

Lumi bruker Flyway for databasemigrasjoner. Migrasjoner kjøres automatisk når API-et starter — ingen manuell intervensjon er nødvendig.

Migrasjonsbaseline

Den første kundestøttede 2.0.0-installasjonen starter fra den squashede V1__baseline.sql, men publiserte 1.x-miljøer er tekniske forhåndsvisninger og kan ikke oppgraderes på stedet. Opprett et rent miljø for 2.0.0.

Viktige egenskaper:

  • Forward-only — migrasjoner kan ikke reverseres
  • Automatisk — kjøres ved oppstart, før API-et mottar trafikk
  • Bakoverkompatible — nye migrasjoner er designet for å fungere med forrige app-versjon

Migreringsregler

Alle migrasjoner følger disse reglene for å sikre trygg rollback:

  • Ingen DROP COLUMN eller DROP TABLE på eksisterende objekter
  • Ingen ALTER COLUMN TYPE på eksisterende kolonner
  • Ingen kolonneendringer (rename)
  • Nye NOT NULL-kolonner må ha DEFAULT-verdi
  • Kun additive endringer: nye tabeller, nye kolonner, nye indekser

Teknisk preview og baseline-squash

Den tidligere migrasjonshistorikken (V1-V7) ble slått sammen før den første støttede baselinen. Preview-databaser, også databaser startet med publiserte 1.x-bilder, skal ikke oppgraderes videre. De må opprettes på nytt; bevaring eller migrering av preview-data er ikke en støttet leveranse.

Cache (Valkey)

Valkey er et rent cache-lag uten persistent tilstand. Det er trygt å tømme Valkey under oppgradering.

Cacheatferd fra 2.0.0-baselinen

  • Uten VALKEY_URI_LUMI_CACHE, eller når en konfigurert Valkey er utilgjengelig ved oppstart, er analytics-caching for statistikk og filter-bootstrap deaktivert. Ved Valkey-feil under kjøring åpner den berørte API-prosessen en circuit breaker, går utenom cachen og gjenopptar caching først etter at alle cache-navnerom har fått nye epoker. API-et leser fortsatt korrekte data fra PostgreSQL, men databasebelastning og responstid kan øke mens cachen er utilgjengelig. Bruk delt Valkey i produksjon, særlig når API-et kjører med flere replikaer.
  • GET /api/v1/intern/filters/bootstrap svarer med Cache-Control: no-store. Nettlesere og mellomliggende cacher skal derfor ikke gjenbruke responsen; hver klientoppfriskning når API-et og teller mot analytics-rategrensen. API-et kan fortsatt betjene responsen fra den tenant-avgrensede Valkey-cachen i opptil fem minutter. Dimensjoner rategrense og API-kapasitet etter faktisk dashboardbruk.
  • Det medfølgende Valkey-subchartet bruker maxmemory-policy=noeviction som defense-in-depth for generasjonsnøklene. API-et erstatter samtidig manglende eller ugyldige generasjoner atomisk med en ny epoke, slik at eviction i en ekstern Valkey gir cache-miss i stedet for å gjenopplive gamle data. Andre eviction-policyer er derfor correctness-sikre, men hyppig eviction gir lavere treffrate og flere cache-writes. Hvis du overstyrer valkey.primary.extraFlags, verifiser den effektive policyen i rendret Helm-output.

Brukersesjoner

Aktive brukersesjoner er lagret i PostgreSQL-tabellen sessions og krypteres med LUMI_SESSION_SECRET. Det er trygt å tømme Valkey uten å logge ut brukere, men sletting av sessions-tabellen eller rotasjon uten gammel session secret vil kreve ny innlogging.

LUMI_WIDGET_PREVIEW (demo only — DO NOT SET ON CUSTOMER DEPLOYMENTS)

dashboard.env.lumiWidgetPreview mounts a survey widget overlay on the dashboard for demo purposes. It hardcodes a demo API key into the client bundle. CI includes a leak guard that fails if this value renders under prod defaults.

Rollback

App-kode

sh
helm rollback lumi -n lumi

Rollback er kun trygt til forrige versjon (N-1) når den nye versjonen ikke har akseptert data som den gamle app-koden tolker annerledes. Helm ruller tilbake API- og dashboard-containere, men påvirker ikke PostgreSQL-subchartet. PVC-er (databasedata) beholdes.

Survey-definition hash

Ikke rull tilbake over versjonen som innfører order-sensitive definition_hash etter at API-et har akseptert submissions. Eldre API-kode sorterte field/order-semantikk i hashberegningen og kan derfor godta eller skrive om reorderede fields/options under samme surveyId. Ved nødvendig rollback: stopp all /api/v1/submission-trafikk først, vurder restore fra backup, og ikke start gammel API-kode mot databaser som har mottatt nye order-sensitive definitions.

Database

Databasemigrasjoner kan ikke rulles tilbake. Fordi migrasjoner er bakoverkompatible med forrige versjon, vil den gamle app-koden fungere mot det nye skjemaet.

Worst case (inkompatibel migrasjon): Restore fra backup.

sh
# Restore fra backup
kubectl exec -i -n lumi lumi-postgresql-0 -- \
  psql -U lumi -d lumi < lumi-backup-YYYY-MM-DD.sql

Validering etter oppgradering

sh
# 1. Sjekk pod-status
kubectl get pods -n lumi

# 2. Sjekk API health
kubectl exec -n lumi deploy/lumi-api -- curl -s localhost:8080/internal/isAlive
# Forventet: OK

# 3. Sjekk Flyway-migrasjoner i API-logg
kubectl logs -n lumi deploy/lumi-api | grep "Flyway"
# Forventet: "Database migrations completed!" og "Migrations executed: N"

# 4. Sjekk at dashboardet laster
kubectl exec -n lumi deploy/lumi-dashboard -- curl -s localhost:3000
# Forventet: HTML-respons

Docker Compose (utvikling)

For lokale utviklingsmiljøer med Docker Compose: docker compose pull && docker compose up -d.

Lumi Analytics — bygget på navikt/lumi (MIT-lisens)