Trafiken in i klustret
Hoppa till
Var vi är
Introduktionen lämnade en mening obesvarad. Den sa att databasen kan ligga bakom en Service som bara är nåbar inifrån klustret, medan frontend exponeras utåt. Men inte ett ord om hur den sista delen går till.
Det är hålet vi fyller här. Den här delen handlar om vägen utifrån och in: vilka Service-typer som finns, vad en Ingress gör, och varför saker ser rätt ut men ändå inte svarar.
Varför klustret är stängt utåt
En Service är av typen ClusterIP om du inte säger något annat, och en ClusterIP finns bara på klustrets interna nätverk.
Det är ett medvetet säkerhetsval: allt är stängt utåt tills någon uttryckligen öppnar det. För databasen är det precis vad du vill. För frontend måste du göra något aktivt.
Lisa märker det när hon testat sitt API inifrån klustret och det svarar — men ingenting händer när hon försöker nå samma adress från sin egen dator. Det är inte ett fel. Det är standardläget.
Vad en Service-typ är
Typen avgör hur långt utanför klustret en Service är nåbar.
Tre värden är viktigast för trafik till dina poddar: ClusterIP, NodePort och LoadBalancer.
Utelämnar du fältet blir det ClusterIP.
Det finns också ExternalName, som är ett DNS-alias till något utanför klustret. Den exponerar inte
poddar och ligger utanför den här artikelns resa in i klustret.
Typen ändrar inte vad Servicen gör — den hittar fortfarande poddar och fördelar trafik. Den ändrar bara vem som kan nå den.
ClusterIP
ClusterIP ger Servicen en intern adress som bara finns inne i klustret.
Det är den http://api:5000 pekar på. Andra poddar når den; ingenting utanför klustret gör det.
Det här är rätt val för allt som bara ska pratas med internt: databaser, köer, interna API:er. I ett verkligt system är de allra flesta Services ClusterIP.
NodePort
NodePort öppnar samma port på varje nod i klustret. Standardintervallet är 30000–32767, men klustrets administratör kan konfigurera ett annat intervall.
Kan du nå en nods IP-adress kan du nå tjänsten. Det gör NodePort användbart i test och i lokala kluster.
I drift är det klumpigt: portnumret är högt och obekvämt, du måste veta nodernas adresser, och de ändras när kluster växer eller krymper.
LoadBalancer
LoadBalancer ber molnleverantören skapa en riktig lastbalanserare med en publik IP-adress.
Det är den typ som faktiskt gör en tjänst nåbar från internet på ett rimligt sätt. Den kostar också pengar — en lastbalanserare per Service.
I ett lokalt kluster utan molnleverantör blir en LoadBalancer-Service ofta stående med EXTERNAL-IP
i läget <pending> för alltid, eftersom ingen finns där som kan skapa den.
De tre typerna bygger på varandra
Det är lätt att tro att typerna är tre alternativ att välja mellan. De är snarare tre lager, där varje typ innehåller det som ligger under.
http://api:5000 pekar på.En LoadBalancer har alltså fortfarande en intern adress som andra poddar kan använda. Den skapar normalt även NodePort, men NodePort-allokeringen kan stängas av i vissa kluster.
Du behöver inte välja bort det interna för att lägga till det externa.
Hur Servicen hittar poddarna
Servicen letar upp poddar med hjälp av labels — etiketter du sätter i manifestet.
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector:
app: api # matchar poddarnas label
ports:
- port: 5000 # adressen andra anropar
targetPort: 5000 # porten i containern
Fältet selector säger vilka poddar Servicen ska skicka trafik till. Alla poddar som bär label
app: api kommer med, och nya plockas in automatiskt när de startar.
Selector vs Deployment-namn
En förväxling som kostar mycket felsökningstid.
Servicen känner inte till någon Deployment. Den vet ingenting om vad som skapade poddarna eller vad den heter.
Servicen matchar bara labels. Den letar upp poddar som bär rätt etikett, oavsett var de kommer ifrån.
Det får två följder. Byter du namn på Deploymenten händer ingenting med trafiken. Men stavar du fel
i en label — app: api mot app: API — hittar Servicen inga poddar alls, och det syns inte som ett
fel någonstans. Trafiken tar bara slut.
port vs targetPort
Två portnummer i samma block, och de betyder olika saker.
port är porten på Servicen. Det är den andra anropar: http://api:5000.
targetPort är porten i containern, alltså den applikationen faktiskt lyssnar på.
De sätts ofta till samma nummer, vilket gör skillnaden lätt att missa. Lyssnar din app på 8080 men
du vill att andra ska anropa 5000 sätter du port: 5000 och targetPort: 8080.
Vad en Ingress är
En Ingress är en uppsättning regler för hur inkommande trafik ska fördelas mellan flera tjänster, utifrån värdnamn och sökväg.
I stället för en publik ingång per tjänst får du en enda ingång och en fil som säger vad som ska gå vart.
Ingress vs LoadBalancer per tjänst
Lisa skulle kunna sätta type: LoadBalancer på frontend och vara klar. Problemet dyker upp när
systemet växer.
Frontend, API och admin får varsin lastbalanserare — och varsin publik IP-adress.
Tre poster i DNS, tre certifikat att förnya, tre fakturarader varje månad.
Sökvägsregler går inte att göra alls: en lastbalanserare pekar på en tjänst, punkt.
En lastbalanserare tar emot all trafik och skickar den vidare enligt regler du skriver.
Ett certifikat, en DNS-post, en kostnad.
shop.example.se/api går till API:et, allt annat till frontend — bestämt i en fil.
Ingress-objektet vs Ingress-controllern
Den här skillnaden är den enskilt vanligaste anledningen till att en Ingress “inte fungerar”.
Ingress-objektet är beskrivningen. En text i klustret som säger vad som borde hända.
Ingress-controllern är programmet som läser beskrivningen och faktiskt dirigerar trafiken. Exempel: ingress-nginx eller Traefik.
Kubernetes-API:t innehåller ingen Ingress-controller. Många lokala och hanterade kluster installerar däremot en controller som tillägg.
Skapar du bara objektet utan en controller accepteras det utan invändning, kubectl get ingress
listar din regel, och ingenting händer — ADDRESS-kolumnen förblir tom. Kontrollera därför vad just
ditt kluster har.
Fältet ingressClassName är kopplingen dem emellan. Stavar du fel där ignoreras hela objektet, tyst.
Reglerna
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
spec:
ingressClassName: nginx
rules:
- host: shop.example.se
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 5000
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 3000
Reglerna matchas efter hur specifika de är, inte efter ordningen i filen: /api matchar före /.
pathType: Prefix matchar hela sökvägselement. /api matchar /api, /api/ och
/api/produkter, men inte /apibutik.
Exemplet pekar på Services, inte på poddar. Ingress-specifikationen kan också peka på en annan resurstyp genom en resource-backend, men den fördjupningen behövs inte här. Kedjan i den här artikeln är Ingress → Service → pod.
Hela vägen in
shop.example.se i webbläsaren.slår upp namnetDNSPekar på lastbalanserarens publika IP-adress.TCP 443Molnets lastbalanserareSkapas åt dig när en Service av typen LoadBalancer finns i klustret.vidare in i klustretIngress-controllernLäser dina Ingress-regler och avgör vilken tjänst anropet ska till, utifrån värdnamn och sökväg./api → tjänsten apiService → PodServicen fördelar anropet på en av de friska poddarna.Felsök utifrån och in
kubectl get ingress— finns en adress iADDRESS-kolumnen? Nej → controllern saknas elleringressClassNameär fel.kubectl get svc— har tjänsten rätt typ, och har LoadBalancern fått enEXTERNAL-IP?kubectl get endpoints api— står det några IP-adresser? Tomt → Servicensselectormatchar inga poddar.kubectl get pods -l app=api— körs poddarna, och bär de rätt label?
Nio gånger av tio faller felet ut på det tredje kommandot: en label som inte stämmer.
Vad det här betyder i ditt arbete
Som utvecklare skriver du Service- och Ingress-manifest, och du felsöker med de fyra kommandona ovan. Det är den delen som återkommer varje vecka.
Att sätta upp själva Ingress-controllern, hantera certifikat och koppla DNS är oftast någon annans jobb — men det är också det som gör att din regel plötsligt slutar fungera. Att veta att kedjan är DNS → lastbalanserare → controller → Service → pod räcker för att kunna säga var det brister, även när du inte äger varje steg.
TLS-certifikat, cert-manager och Gateway API — efterföljaren till Ingress — kan du skjuta upp. De
blir aktuella när du själv äger klustrets ingång.
Vanliga nybörjarförväxlingar
En Service är inte publik som standard. Utan type blir den ClusterIP och syns bara inifrån.
Servicen hittar inte poddar via Deploymenten. Den matchar labels, och en felstavad label ger ett tyst fel: Servicen hittar inga poddar utan eget felmeddelande.
port och targetPort är inte samma sak. Den ena är utåt, den andra in i containern.
Ett Ingress-objekt gör ingenting av sig självt. Utan controller är det en text som ingen läser.
En Ingress pekar inte på poddar. Den pekar på Services, som i sin tur pekar på poddar.
En tom ADDRESS-kolumn är inte ett fel som skrivs ut. Du måste titta efter den.
Prova själv
Du behöver ett kluster. Slå på Kubernetes i Docker Desktop under Settings → Kubernetes om du inte redan gjort det, och rulla ut något att titta på.
Titta först på vad typerna heter i verkligheten:
kubectl get svc
Kolumnen TYPE visar ClusterIP för allt du inte gett en annan typ. Kolumnen EXTERNAL-IP är tom
för dem — precis som avsnittet påstod.
Kontrollera sedan att Servicen faktiskt hittat några poddar:
kubectl get endpoints api
Står det IP-adresser matchar labeln. Är listan tom matchar den inte, och då är det där felet ligger.
Nå slutligen en intern tjänst från din egen dator utan att ändra någonting i klustret:
kubectl port-forward svc/api 8080:5000
Låt det fönstret stå öppet och anropa http://localhost:8080 i ett annat. Du har nu en tunnel förbi
hela den externa kedjan — vilket är exakt varför port-forward är rätt verktyg för felsökning och
fel verktyg för drift.
Tre saker som kan förvirra: port-forward blockerar terminalen tills du avbryter med Ctrl+C. En LoadBalancer-Service i ett lokalt kluster kan bli stående på <pending> för alltid eftersom ingen
molnleverantör finns. I nyare Kubernetes-versioner har endpoints ersatts av endpointslices —
kubectl get endpointslices visar samma sak med mer detaljer.
- En Service är ClusterIP som standard — intern, osynlig utifrån. Det är avsiktligt.
- LoadBalancer skapar normalt NodePort, som bygger på ClusterIP. NodePort kan stängas av i vissa kluster.
- Servicen hittar poddar via labels, inte via Deployment-namnet.
portär adressen utåt,targetPortär porten i containern.- Ingress ger en ingång för många tjänster, med regler på värdnamn och sökväg.
- Ett Ingress-objekt utan Ingress-controller gör ingenting alls, utan eget felmeddelande.
Du skapar en Service utan att ange type. Vad får du, och vem kan nå den?
http://api:5000. Ingenting utanför klustret når den.Vad är skillnaden mellan port och targetPort i en Service?
port är porten andra anropar Servicen på. targetPort är porten containern faktiskt lyssnar på. De sätts ofta till samma nummer, men behöver inte vara det.kubectl get endpoints api returnerar en tom lista. Vad är felet?
selector matchar inga poddar. Antingen körs inga poddar med den labeln, eller så skiljer sig labeln i Deployment från selectorn i Service — ofta en stavning eller ett bindestreck.Varför räcker det inte att skapa ett Ingress-objekt?
Vad är den praktiska nackdelen med type: LoadBalancer på varje tjänst?
Du byter namn på Deploymenten men inte på labels. Vad händer med trafiken?
Snabb sammanfattning
- Allt i ett kluster är stängt utåt tills du öppnar det. Standardtypen ClusterIP är intern.
- Service-typen avgör hur långt utanför klustret tjänsten är nåbar, inte vad den gör.
- NodePort öppnar en hög port på varje nod. Standardintervallet kan ändras av klustrets administratör.
- LoadBalancer ber molnet om en publik IP. En per Service, och den kostar pengar.
- Typerna är ofta lager: LoadBalancer skapar normalt NodePort, som bygger på ClusterIP.
- Servicen hittar poddar via labels. En felstavad label ger ett tyst fel, inte ett eget felmeddelande.
portär adressen utåt,targetPortporten i containern.- En Ingress fördelar trafik till flera tjänster utifrån värdnamn och sökväg — en ingång i stället för tio.
- Ett Ingress-objekt är en beskrivning. Utan Ingress-controller läser ingen den.
- Felsök utifrån och in: ingress → svc → endpoints → pods. Felet ligger oftast i labeln.
Nästa del
I nästa del tar vi hand om det som ligger inuti poddarna: hur samma image kan köras i test och produktion med olika inställningar. Och hur Kubernetes egentligen avgör om en pod mår bra.