Blog

Framtiden för Kubernetes – och varför utvecklare bör se bortom Kubernetes 2022

FEB 22, 2022

Kubernetes är allestädes närvarande inom containerorkestrering, och dess popularitet visar inga tecken på att minska. Det betyder dock inte att utvecklingen inom containerorkestrering har stannat av. I den här bloggen lyfter vi några argument för varför Kubernetes-användare, och särskilt utvecklare, bör se bortom det traditionella Kubernetes som vi har lärt känna de senaste åren och utforska paradigm som kan vara bättre lämpade för Cloud Native-applikationer.

Michael Vittrup Larsen

Michael is a Consultant at our office in Aarhus. He has an MScEE from Aalborg University where he specialized in digital signal processing. Before joining us Michael was working on building and optimizing cloud infrastructure for the telecoms sector. In his spare time, he likes to explore the wilderness on his mountain bike.

Kubernetes framväxt

En del av anledningen till att Kubernetes har blivit så populärt är att det byggdes ovanpå Docker. Containers har en lång historia inom Linux och BSD-varianter, men Docker gjorde containers mycket populära genom att fokusera på användarupplevelsen och göra det väldigt enkelt att bygga och köra containers. Kubernetes byggde vidare på containers popularitet och gjorde det enkelt att köra (även kallat orkestrera) containers i ett kluster av beräkningsnoder.

En annan anledning till Kubernetes popularitet och breda användning är att det inte förändrade modellen för att köra mjukvara särskilt mycket. Det var ganska enkelt att se en väg från hur vi körde mjukvara före Kubernetes till hur vi kunde köra mjukvara på Kubernetes.

Du kan inte lära gamla paradigm nya trick

Att bygga container images för att låsa beroenden och skapa en upplevelse där applikationer kan köras överallt, kombinerat med specifikationer för Kubernetes-resursen Deployment för att hantera orkestreringen av containerrepliker, är mycket kraftfullt. Men det skiljer sig inte radikalt från hur vi drev VMs före Docker och Kubernetes. Det lilla mentala steget gjorde Kubernetes enkelt att ta till sig, men det är också därför vi bör se bortom det ”traditionella” Kubernetes vi känner i dag.

I den här bloggen tittar vi på Kubernetes framtid ur utvecklarens perspektiv. I allmänhet kommer det Kubernetes vi känner i dag att försvinna, och utvecklare kommer inte att bry sig. Det betyder inte att Kubernetes försvinner ur vår stack, utan att vi kommer att förbättra hur vi bygger och driver applikationer med hjälp av nya abstraktioner som i sin tur bygger på Kubernetes. Applikationer kommer att byggas med hjälp av plattformar som bygger på Kubernetes-plattformen:

Kelsey hightower's tweet

Intressant nog var Linux plattformen som vi byggde allt på för ett decennium eller mer sedan. Linux finns fortfarande överallt och är en del av vår stack, men få utvecklare bryr sig särskilt mycket om det eftersom vi sedan dess har lagt till några abstraktioner ovanpå. Samma sak kommer att hända med det traditionella Kubernetes vi känner i dag.

Nya paradigm städar upp mer

Säkerhet: OIDC är bättre än secrets

Kubernetes tillhandahåller resursen Secret för att ange statiska secrets, till exempel API-nycklar och lösenord. Utvecklare bör inte använda Kubernetes Secret-resurser.

Explicit angivna secrets som kodas i Secret-resurser kan läcka och är besvärliga att rotera och återkalla. I GitOps-arbetsflöden kräver secrets också särskild hantering för att undvika att lagras i klartext. Applikationer bör i stället använda en rollbaserad metod för autentisering och auktorisering. Det innebär att applikationers autentisering och auktorisering, i stället för att baseras på ”sådant du vet” (lösenord, API-nycklar), bör baseras på ”vem vi är”.

Starka identiteter är grunden för all säkerhet. Det är meningslöst att kryptera nätverkstrafik om du inte är säker på identiteten hos servern du kommunicerar med. Det är vad certifikat och Certificate Authorities gör för HTTPS-trafik, vilket i stort sett säkrar internet.

Kubernetes har ett system för stark identitet för workloads. Alla workloads är kopplade till service accounts och har kortlivade OpenID-Connect (OIDC)-identity-tokens issued by Kubernetes. Kubernetes API-server signerar dessa OIDC-tokens, och andra workloads kan validera tokens via Kubernetes API-server. Detta ger starka identiteter för workloads som körs på Kubernetes och kan användas som grund för rollbaserad autentisering och auktorisering.

I stället för att använda Kubernetes Secrets bör utvecklare basera autentisering och auktorisering på OIDC-tokens. Det innebär att vi, i stället för att till exempel lagra ett databaslösenord i en Secret-resurs, bör säkerställa att vår databas endast accepterar förfrågningar som har en giltig token som inte har gått ut.

Exempel på hur OIDC-tokens används för att integrera med externa system är AWS IAM roles for service accounts och Hashicorp Vault Kubernetes auth.

Nätverk: Ingress räcker inte till

Kubernetes tillhandahåller en Ingress-resurs för att ange hur HTTP-trafik ska routas till workloads. Som Tim Hockin, medgrundare av Kubernetes, konstaterar finns det mycket som inte fungerar med Ingress-resursen. Huvudproblemet är att den bara låter oss hantera det mest grundläggande inom routning av HTTP-trafik. Att låta utvecklare använda Ingress-resurser blir ett huvudbry för infrastruktur- och Site Reliability Engineering (SRE)-team som behöver koppla samman en omfattande infrastruktur och få den att fungera tillförlitligt. Ingress-resursen är för enkel, och utvecklare bör inte använda den för att konfigurera nätverk.

Behovet av mer kontroll och programmerbarhet i Kubernetes-nätverket syns i framväxten av service meshes (se vår utbildning om Istio service mesh, Kiali and Jaeger). De delar upp Ingress-resursen i flera resurser för en bättre ansvarsfördelning och erbjuder ytterligare funktionalitet för routning, observerbarhet, säkerhet och feltolerans.

Allt fler abstraktioner som byggs ovanpå Kubernetes förutsätter ett programmerbart nätverk som går bortom vad som är möjligt med Ingress (Knative, Kubeflow, Continuous Delivery-verktyg som Argo Rollouts osv.). Detta understryker att en mer robust nätverksmodell i Kubernetes redan är en de facto-standard.

Kubernetes-communityt har utvecklat en ”Ingress v2” – gateway-API. Även om den löser vissa av problemen med Ingress täcker den bara en liten del av den funktionalitet som de flesta service meshes erbjuder.

Kubernetes har stöd för ACL:er som begränsar vilka workloads som kan kommunicera via resursen NetworkPolicy. Resursen implementeras i Kubernetes nätverkspluginer och översätts ofta till Linux iptables-filterregler, alltså en IP-adressbaserad lösning som liknar brandväggar – återigen ett gammalt paradigm. Vissa service mesh-lösningar utökar Kubernetes starka OIDC-baserade workload-identiteter för att implementera ömsesidig TLS mellan workloads. Det ger konfidentialitet och autenticitet i Kubernetes nätverkskommunikation, baserat på starkare principer än IP-adresser.

När Kubernetes-applikationer paketeras finns det olika sätt att inkludera nätverkskonfiguration. Många Helm charts innehåller mallar för Ingress-resurser. Men när vi går över till mer avancerade nätverksmodeller kan dessa definitioner inte användas. Framöver bör applikationsdistributioner som Helm charts betrakta nätverkskonfiguration som en separat fråga som lämnas utanför applikationens distributionsartefakt. Det finns kanske ingen universallösning för applikationers nätverkskonfiguration, och organisationer vill sannolikt utveckla egna distributionsartefakter för ”routing för applikationer”.

Kubernetes gjorde nätverk enkelt genom att skapa ett enhetligt nätverk över alla noder i klustret. Om din applikation körs i flera kluster eller i flera moln kan den på samma sätt dra nytta av ett enhetligt nätverk över kluster eller moln. Kubernetes nätverksmodell erbjuder inte detta, och du behöver något mer kraftfullt, till exempel en service mesh.

Ur både ett organisatoriskt och arkitektoniskt perspektiv finns det alltså flera skäl till att utvecklare inte bör programmera nätverket med Ingress-resurser. Det är viktigt att utvärdera alternativen ur ett övergripande organisatoriskt perspektiv för att säkerställa en hanterbar och långsiktigt hållbar strategi för nätverkskonfiguration och -hantering.

Workload-definition: Rakt på sak

Kärnan i nästan alla Kubernetes-applikationer är en Deployment-resurs. En Deployment är en resurs som definierar hur vår workload, i form av containers i Pods, ska köras. Skalningen av en Deployment kan styras med en HorizontalPodAutoscaler-resurs (HPA) för att hantera varierande kapacitetsbehov. HPA:er använder ofta containrarnas CPU-belastning som mått för att lägga till eller ta bort Pods, och HPA-algoritmen har ofta en målutnyttjandegrad på omkring 70 %. Det innebär att vi utformar för ett svinn på 30 %. Ett annat skäl till att använda konservativa målutnyttjandegrader är att HPA:n ofta har en svarstid på en minut eller mer. För att hantera varierande kapacitetsbehov behöver vi viss reservkapacitet medan HPA:n lägger till fler Pods.

Att hantera workloads med Deployments och HPA:er fungerar bra om applikationen har långsamt varierande kapacitetsbehov. Men med övergången till mikrotjänster, händelsedrivna arkitekturer och funktioner (som hanterar en eller möjligen några händelser/förfrågningar och sedan avslutas) är denna form av workload-hantering långt ifrån idealisk.

Kubernetes Event-Driven Autoscaler (KEDA) kan förbättra skalningsbeteendet för mikrotjänster och workloads som förändras snabbt, till exempel funktioner. KEDA definierar en egen uppsättning Kubernetes-resurser för att definiera skalningsbeteende och kan ses som en ”HPA v3” (eftersom HPA-resursen redan är i ”v2”).

Ett ramverk som kombinerar Kubernetes Deployment-modell, skalning samt händelse- och nätverksrouting är Knative. Knative är en plattform som bygger ovanpå Kubernetes och har ett tydligt synsätt på workload-hantering genom resursen Knative-Service. Kärnan i Knative är CloudEvents, och Knative-tjänster är i grunden funktioner som utlöses och skalas av händelser, antingen CloudEvents eller vanliga HTTP-förfrågningar. Knative använder en Pod-sidecar för att övervaka händelsefrekvenser och skalar därför mycket snabbt när händelsefrekvenserna ändras. Knative stöder även skalning till noll och möjliggör därmed mer finkornig workload-skalning som passar bättre för mikrotjänster och funktioner.

Knative-tjänster implementeras med traditionella Kubernetes Deployments/Services, och uppdateringar av Knative-tjänster (till exempel en ny container image) skapar parallella Kubernetes Deployment/Service-resurser. Knative använder detta för att implementera distributionsmönster som blue/green och canary, där routningen av HTTP-trafik ingår i definitionen av Knative-tjänstens resurs.

Därmed blir Knative-tjänstens resurs och tillhörande resurser för att definiera routing av händelser de primära resurser som utvecklare använder när de definierar sin applikationsdistribution på Kubernetes. Precis som vi i dag ofta interagerar med Kubernetes genom Deployment-resurser och låter Kubernetes hantera Pods, innebär Knative att utvecklare främst fokuserar på Knative-tjänsten, medan Deployments hanteras av Knative-plattformen.

Även om jag förväntar mig att Knative-modellen passar en stor majoritet av användningsfallen kan det se annorlunda ut för dig. Om du i stället arbetar med maskininlärning kan Kubeflow vara en bättre abstraktion. Om du är mer fokuserad på DevOps och leveranspipelines kan kpack, Tekton eller Cartographer vara rätt abstraktion för dig. Oavsett vad du gör på Kubernetes finns det en abstraktion för det!

Lagring: Bort från persistenta volymer

Kubernetes erbjuder resurserna PersistentVolume och PersistentVolumeClaim för att hantera lagring för workloads. Det är sannolikt den resurs jag minst av allt vill låta utvecklare använda, förutom för tillfällig cachedata.

Ur ett övergripande perspektiv är ett problem med PersistentVolumes (PV:er) att de kombinerar applikationens primära ansvarsområde med ett lagringsansvar, vilket inte är ett optimalt Cloud Native-designmönster. Metodiken twelve-factor app vägleder oss att betrakta alla stödtjänster som nätverksanslutna. Det beror på hur vi skalar workloads horisontellt i Kubernetes och hanterar data (tänk CAP-teoremet).

PV:er representerar filsystem med filer och kataloger, och vi hanterar data via ett POSIX-filsystemsgränssnitt. Åtkomsträttigheter bygger också på en POSIX-modell, där användare och grupper kan få läs- eller skrivåtkomst. Modellen passar inte bara dåligt för utformningen av Cloud Native-applikationer, utan är också svår att använda i praktiken. Därför monteras PV:er oftast i ett läge där ”containern kan komma åt all data”.

Utvecklare bör bygga tillståndslösa applikationer, även när de hanterar tillstånd. Det innebär att data ska hanteras utanför applikationen med andra abstraktioner än filsystem, till exempel i databaser eller objektlagring. Databas- och objektlagringsapplikationer kan använda PV:er för sina lagringsbehov, men systemen bör administreras av infrastruktur-/SRE-team och användas som en tjänst av utvecklare.

En dramatisk förbättring av datasäkerheten är möjlig när vi ser lagring som nätverksansluten, till exempel objektlagring via REST API:er. Med REST API:er kan vi implementera autentisering och auktorisering genom kortlivade åtkomsttoken baserade på Kubernetes arbetsbelastningsidentiteter, enligt beskrivningen ovan.

När vi inför ett serverless arbetsbelastningsmönster bör vi förvänta oss mer dynamiska och kortlivade arbetsbelastningar, till exempel serverless-funktioner som hanterar en händelse per Pod. I sådana situationer blir skillnaden mellan arbetsbelastningar och ”gammaldags diskar” ännu tydligare.

I Kubernetes har Container Storage Interface (CSI) varit gränssnittet för att lägga till filsystems- och blocklagring till arbetsbelastningar via PV:er. Kubernetes special interest group för objektlagring arbetar med Container Object Storage Interface (COSI), som kan göra objektlagring till en förstklassig del av Kubernetes.

O, du sköna nya värld

I den här bloggen har jag argumenterat för att det finns goda skäl att se bortom de ”traditionella” Kubernetes-resurserna när vi definierar Kubernetes-applikationer. Det betyder inte att vi aldrig kommer att använda de traditionella resurstyperna. Det kommer fortfarande att finnas äldre applikationer som vi inte enkelt kan konvertera, och SRE-team kan fortfarande behöva drifta tillståndsfulla tjänster som kan användas av applikationer som utvecklare bygger. Detta gäller särskilt för privata molninfrastrukturer.

Kubernetes framtid ligger i Custom Resource Definitions (CRD:er) och de abstraktioner som vi bygger ovanpå Kubernetes och gör tillgängliga för användare genom CRD:er. Kubernetes blir ett control plane för abstraktioner, och det är dessa abstraktioners CRD:er som utvecklare bör fokusera på. Kubernetes control planes kan hantera resurser i Kubernetes eller till och med utanför Kubernetes, precis som Crossplane hanterar molninfrastruktur.

graph future of kubernetes-1

Som sammanfattats ovan kan de flesta traditionella Kubernetes-resurser ha bättre alternativ för utvecklare. Genom att använda alternativ förbättrar vi hur vi utvecklar och driftar Cloud Native-applikationer under de kommande åren. Kubernetes är trots allt en plattform för att bygga plattformar. Det är inte slutmålet!

  • DevOps
  • Cloud

Subscribe to our newsletter