Hopp til innhold

Modellert feilsøking av en app

Skip to content

Følg feilen fra symptom til sluttkontroll

Du skal kunne begrunne neste test ut fra et resultat og forklare hvordan du kontrollerer at en feil er rettet. Her følger du et gjennomarbeidet eksempel. Stopp ved spørsmålene og svar før du åpner svarforslagene.

Terminalanimasjonene gjengir ekte kommandoresultater fra en kontrollert øvelse på debian-vm. De viser en liten HTTP-testtjeneste i containeren min-app, bundet til 127.0.0.1:5000. DNS og proxy inngår i tankemodellen og kontrollpunktene, men er ikke med i terminalopptakene. Du kan gjøre analysen uten en egen server.

Før du begynner

Du trenger å kjenne forskjellen på en container, en app og en omvendt proxy (reverse proxy). Proxyen mottar forespørselen fra klienten og sender den videre til appen. DNS brukes til å finne adressen til proxyen; DNS transporterer ikke nettsiden.

Bruk Feilsøkingsmetode som støtte til observasjon, hypotese og test. Publisere applikasjon viser oppsettet med app, navn og proxy.

Vil du følge praktisk, trenger du dette oppsettet i et testmiljø du har lov til å endre. Alle Docker-kommandoene kjøres i appens Linux-VM, ikke på Proxmox-verten eller egen PC. Stopp bare din egen testcontainer. Tilbakeføringen er å starte den samme containeren igjen.

I animasjonene brukes en administratorterminal, merket root og #. I ditt eget miljø bruker du den Docker-tilgangen som er satt opp; enkelte oppsett krever sudo. Animasjonene spilles i løkke. Kommandoene, resultatene og forklaringene står også i teksten.

Startsjekk: Hvor kjører appen, og hvilken adresse brukte du sist for å teste den direkte? Hvis du er usikker, finn svaret i Docker-øvelsen før du kjører kommandoer.

1. Dokumenter normaltilstanden

Appcontaineren heter min-app. Ruten /status skal gi HTTP 200 og JSON med "status": "ok". Vi bekrefter to tester før vi lager en feil:

  • Test A fra klienten: Åpne /status gjennom det avtalte navnet, proxyen og protokollen. Noter hele adressen og svaret.
  • Test B fra app-VM-en: Test /status direkte mot appens publiserte port. Noter hele adressen og svaret.

Test A går gjennom navn og proxy til appen. Test B går direkte fra app-VM-en. Begge skal gi det dokumenterte statussvaret.

«Jeg trenger en kjent normaltilstand. Ellers kan en feil testadresse se ut som en feil i appen. Jeg beholder samme adresse, port, protokoll og rute når jeg tester igjen.»

Den direkte adressen avhenger av portbindingen. Med binding til 127.0.0.1:5000 bruker vi http://127.0.0.1:5000/status. Med binding bare til VM-ens nettverksadresse bruker vi http://APP-VM-IP:5000/status, der APP-VM-IP erstattes med den faktiske adressen. Etter en slik ombinding skal vi ikke forvente at loopback-adressen virker.

På app-VM-en lagrer vi den direkte adressen i variabelen APP_URL. Eksemplet under gjelder loopback-binding; erstatt adressen hvis din binding er annerledes. Ikke endre portbindingen for å få den til å passe eksemplet.

APP_URL='http://127.0.0.1:5000/status'
curl --include --silent --show-error --fail --max-time 5 "$APP_URL"

Debian: direkte HTTP-test gir 200 OK og status ok før feilen.

--include viser HTTP-statusen. --silent --show-error skjuler fremdriftsmåleren og beholder feilmeldinger. --max-time 5 begrenser ventetiden. Variabelen gjelder denne terminaløkten; sett den på nytt hvis du åpner en ny terminal.

Forventet i begge tester: HTTP 200 og det dokumenterte JSON-svaret. I eksemplet består begge normaltestene. Praktisk øving begynner først når begge også virker hos deg. Hvis /status gir HTTP 404, har en HTTP-server svart, men ruten er ikke bekreftet. Kontroller ruten og oppsettet i Docker-øvelsen før du lager feilen.

Stopp 1: Hva har vi bekreftet?

Den direkte testen består. Er det alene nok til å si at appen virker gjennom navnet og proxyen?

Svarforslag

Nei. Den direkte testen bruker ikke navnet eller proxyen. Den bekrefter akkurat forespørselen fra app-VM-en. Derfor trenger vi også test A fra klienten.

2. Se symptomet

Vi lager én kjent feil i testmiljøet ved å stoppe appcontaineren. Appkode, adressebinding og proxyinnstillinger beholdes:

docker stop min-app

Vi gjentar test A fra klienten. Nå kommer ikke det forventede statussvaret. Proxyen kan for eksempel gi HTTP 502, men den konkrete feilmeldingen avhenger av miljøet. Noter det faktiske resultatet.

Dette er symptomet: Det vi observerer at ikke virker.

«Brukeren får ikke svaret som kom i normaltesten. Flere ledd kan forklare det. Jeg vil undersøke appen direkte før jeg endrer noe.»

3. Bruk en test til å avgrense

Vi gjentar test B på app-VM-en med samme direkte adresse som før:

curl --include --silent --show-error --fail --max-time 5 "$APP_URL"

Debian: appcontaineren stoppes, og samme direkte HTTP-test får tilkoblingsfeil.

Forventet: HTTP 200 og "status": "ok".

Faktisk i opptaket: curl: (7) Failed to connect og ingen HTTP-respons fra den direkte adressen. Ordlyden kan variere i ditt miljø.

Både brukerhandlingen og den direkte testen feiler. Neste undersøkelse rettes mot appen, portbindingen og containeren. Resultatet bekrefter ingen DNS-feil.

«Den direkte testen går utenom navnet og proxyen. Jeg undersøker derfor appen, portbindingen og containeren først. Jeg har ennå ikke bevist hvorfor forespørselen feiler.»

Stopp 2: Velg neste kontroll

Vil du endre DNS, endre proxyinnstillingen eller undersøke containerstatus? Begrunn valget med testresultatet.

Svarforslag

Undersøk containerstatus. Den direkte testen feiler uten å bruke navnet og proxyen. Resultatet gir ingen grunn til å begynne med endringer i DNS eller proxy. Det beviser heller ikke at disse leddene er feilfrie.

Vi undersøker både kjørende og stoppede containere:

docker ps -a --filter name=min-app --format 'table {{.Names}}\t{{.State}}'

Debian: containeroversikten viser min-app med tilstand exited.

Les raden med det nøyaktige navnet min-app; filteret kan også finne navn som inneholder teksten. I opptaket viser kolonnen STATE verdien exited, som betyr at containeren har stoppet. Den vanlige oversikten uten --format viser en mer detaljert status som begynner med Exited. Uten -a viser docker ps normalt bare kjørende containere.

«Nå har jeg to observasjoner: Den direkte testen feiler, og appcontaineren er stoppet. Hypotesen min er at den stoppede containeren hindrer appen i å svare.»

--format begrenser visningen til navn og tilstand. Slik blir resultatet enklere å lese.

Observasjon er det vi har sett. En hypotese er en mulig forklaring som vi prøver å teste. Exited forteller ikke alene hvorfor containeren stoppet. Her kjenner vi hendelsen fordi vi brukte docker stop.

4. Gjør én begrunnet retting

Containeren finnes allerede. Vi starter den samme containeren:

docker start min-app

«Jeg starter containeren uten å bygge appen på nytt eller endre portbindingen. Da kan jeg undersøke virkningen av én endring.»

Startkommandoen oppretter ingen ny container og bygger ikke et nytt image.

Stopp 3: Er vi ferdige?

Startkommandoen fullføres uten feil. Hva må vi undersøke før vi avslutter saken?

Svarforslag

Vi må gjenta både den direkte testen og den opprinnelige brukerhandlingen gjennom navnet. En startet container beviser ikke at appen svarer riktig eller fortsetter å kjøre.

5. Kontroller rettingen

På app-VM-en gjentar vi statuskontrollen og test B:

docker ps -a --filter name=min-app --format 'table {{.Names}}\t{{.State}}'
curl --include --silent --show-error --fail --max-time 5 "$APP_URL"

Debian: samme container startes, HTTP-testen gir 200 OK og containeren er running.

Deretter gjentar vi test A fra klienten, med samme navn, protokoll og rute som i normaltesten.

Opptaket viser at min-app har tilstand running, og at den direkte testen gir HTTP 200 og forventet JSON igjen. Det bekrefter test B. Test A må prøves separat i oppsettet med navn og proxy; først når den også består, er hele den opprinnelige brukerhandlingen kontrollert.

Etter at containeren er startet, gjentas både den direkte testen og den opprinnelige testen gjennom proxyen. Først da kan dette avviket avsluttes.

«Den samme brukerhandlingen som feilet, virker nå igjen. Det støtter at den stoppede containeren forklarte dette avviket. Vi har kontrollert /status, ikke alle funksjonene i appen.»

Hvis containeren stopper igjen eller testen fortsatt feiler, er saken åpen. Les containerstatus og relevante logger før du velger neste endring:

docker logs --tail 50 min-app

Får du No such container, kontroller containernavn og at du arbeider på riktig VM. Ved manglende tilgang til Docker følger du tilgangsveiledningen i Docker – Kom i gang. Ikke behandle en mislykket statuskommando som bevis for at appcontaineren er stoppet.

6. Dokumenter resonnementet

Dette er en eksempellogg, ikke dokumentasjon av en faktisk hendelse:

Punkt Eksempelnotat
Normaltilstand Test A og B ga HTTP 200 og forventet JSON.
Symptom Samme brukerhandling gjennom navnet ga ikke forventet statussvar.
Observasjon Direkte test feilet også. min-app hadde status Exited.
Hypotese Den stoppede containeren hindret appen i å svare.
Retting Startet eksisterende container med docker start min-app.
Sluttkontroll Både test A og B ga samme forventede svar som før feilen.
Avgrensning Bare /status er kontrollert. Vi kjenner stopphendelsen i øvelsen; ved en ukjent hendelse må stoppårsaken undersøkes.

I egen logg bruker du dine faktiske adresser, resultater og feilmeldinger. Skill mellom det du observerte og det du fortsatt tror kan være årsaken.

Prøv med mindre støtte

I et nytt tilfelle gir den direkte testen HTTP 200 og forventet JSON, men /status gjennom navnet feiler. Containeren kjører.

Forklar muntlig eller skriftlig:

  1. Hva viser den direkte testen, og hva står fortsatt åpent?
  2. Hvilken konkret test vil du velge videre, og hvilket resultat forventer du?
  3. Hvorfor er det foreløpig svakt begrunnet å starte appcontaineren på nytt?
Svarforslag

Den direkte testen bekrefter /status fra app-VM-en. Navneoppslag, proxyens innstilling og forbindelsen fra proxyen til appen er fortsatt åpne spørsmål. Én mulig neste kontroll er om navnet slår opp til riktig proxyadresse. Bruk resultatet og den konkrete feilmeldingen til å velge videre test. At appen svarer direkte, gir foreløpig ingen støtte for at en omstart løser problemet.

Du er ferdig når du kan begrunne neste test og forklare hvorfor sluttkontrollen må gjenta handlingen som feilet. Er dette uklart, gå tilbake til stopp 2 og 3 og prøv igjen med egne ord. Praktisk feilsøkingskompetanse viser du videre ved å undersøke og rette en ny feil i eget testmiljø.

Kilder: Docker-dokumentasjonen om containerstatus, stopp og start.