Terug naar overzicht
Cloud Architecture

Cloudkosten en Performance Audit: Inefficiënties Opsporen in Azure en Kubernetes

Cloudkosten en Performance Audit: Inefficiënties Opsporen in Azure en Kubernetes

Cloudrekeningen groeien regelmatig sneller dan het daadwerkelijke applicatieverkeer. In Azure Kubernetes Service (AKS)-omgevingen stellen engineeringteams vaak te ruime CPU- en geheugenreserveringen in om pod-evictions te voorkomen, configureren ze database-connectiepools verkeerd over tientallen microservices en laten ze ongebruikte opslag gekoppeld aan actieve clusters. Een gestructureerde audit van cloudkosten en performance brengt deze structurele inefficiënties aan het licht en verlaagt de maandelijkse Azure-uitgaven zonder de stabiliteit van workloads in gevaar te brengen.

Fase 1: Pod-Resourceverspilling Diagnostiseren met Prometheus en VPA

Kubernetes plant workloads in op basis van pod-resource requests, niet op basis van daadwerkelijk verbruik. Wanneer een engineeringteam ruime veiligheidsmarges instelt (zoals het aanvragen van 2 CPU-cores en 4 GB RAM voor een API-service die gemiddeld 0,15 cores en 600 MB RAM gebruikt), reserveert de Kubernetes scheduler die capaciteit op de node. De node rapporteert een hoge bezetting terwijl de onderliggende hardware niets doet, waardoor de Azure cluster autoscaler gedwongen wordt dure extra virtuele machines op te starten.

Resource Veld Kubernetes Scheduler Gedrag Runtime Handhaving & Kostenimpact
requests.cpu Reserveert nodecapaciteit tijdens schedulingbeslissingen Bepaalt het totale aantal nodes en de directe Azure VM-kosten
limits.cpu Genegeerd door de scheduler Handhaaft CFS throttling-quota; overmatige throttling verslechtert de P99-responstijd
requests.memory Reserveert fysiek RAM-geheugen op de worker node Voorkomt node-overcommit; bepaalt de omvang van node pools
limits.memory Genegeerd tijdens scheduling Activeert de Linux cgroup Out-Of-Memory (OOM) killer die de container beëindigt

Stap 1: Kwantificeer CPU- en Geheugenreserves met PromQL

Audit container-allocaties door aangevraagde capaciteit te vergelijken met het daadwerkelijke 95e percentiel-verbruik over een periode van 14 dagen:

# PromQL: Bereken onbenutte CPU-requests per Deployment
sum(kube_pod_container_resource_requests{resource="cpu"}) by (namespace, container)
- sum(quantile_over_time(0.95, container_cpu_usage_seconds_total[14d])) by (namespace, container)

# PromQL: Bereken de overprovisioning-ratio voor geheugen
(sum(kube_pod_container_resource_requests{resource="memory"}) by (namespace, container)
- sum(quantile_over_time(0.95, container_memory_working_set_bytes[14d])) by (namespace, container))
/ sum(kube_pod_container_resource_requests{resource="memory"}) by (namespace, container)

Workloads met meer dan 50% aanhoudende overcapaciteit in CPU of geheugen moeten worden bijgesteld in hun pod-manifesten.

Stap 2: Verzamel Aanbevelingen met de Vertical Pod Autoscaler (VPA)

Implementeer de Kubernetes Vertical Pod Autoscaler in Off-modus. In deze modus berekent VPA historische verbruikspercentielen en schrijft aanbevelingen direct naar de resource status zonder draaiende pods te herstarten.

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: order-processing-service-vpa
  namespace: production
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: order-processing-service
  updatePolicy:
    updateMode: "Off"
  resourcePolicy:
    containerPolicies:
      - containerName: '*'
        minAllowed:
          cpu: 100m
          memory: 256Mi
        maxAllowed:
          cpu: 2000m
          memory: 4Gi
        controlledResources: ["cpu", "memory"]

Lees de aanbevelingen uit via kubectl get vpa -n production -o yaml. Vergelijk de waarden van target en lowerBound met de huidige specificaties om potentiële node-besparingen te bepalen.

Fase 2: Valkuilen in Database Connection Pooling en Trage Queries

In gedistribueerde .NET-microservices op AKS leidt database-connectiebeheer geregeld tot onnodige kostenstijgingen. Teams schalen pod-replica's op tijdens piekmomenten, waardoor het aantal actieve databaseverbindingen ongemerkt explodeert totdat de database vastloopt of overbelast raakt.

De Vermenigvuldigingsval

Standaard ADO.NET- en Npgsql-connectiepools staan tot 100 verbindingen per proces toe. Wanneer een service onder belasting opschaalt van 3 naar 30 pods, springt het potentiële aantal verbindingen van 300 naar 3.000. Een Azure SQL Database of PostgreSQL Flexible Server bereikt zijn connectielimiet, waardoor teams geneigd zijn om dure hogere tiers te kiezen puur voor connectiegeheugen.

SNAT-Poortuitputting

Kortstondige databaseverbindingen of niet-gepoolde uitgaande HTTP-clients putten de SNAT-poorten van de Azure Load Balancer uit. Onder zware belasting leidt dit tot willekeurige time-outs, wat ten onrechte wordt toegeschreven aan databaseproblemen.

Connectiepools Optimaliseren in .NET Workloads

Beperk de omvang van de client-side pool en plaats een dedicated server-side connection pooler (zoals PgBouncer voor PostgreSQL of Azure SQL Database Elastic Pools) tussen de containers en de database:

// appsettings.Production.json
{
  "ConnectionStrings": {
    "PrimaryDatabase": "Server=tcp:sql-neneos-prod.database.windows.net,1433;Database=orders;Authentication=Active Directory Default;Max Pool Size=20;Min Pool Size=2;Connection Timeout=15;Pooling=true;"
  }
}

Door Max Pool Size=20 per pod in te stellen, blijft het totale aantal verbindingen onder de 400 bij 20 pod-replica's. Hierdoor kan de database op een lagere vCore-tier draaien met een voorspelbaar geheugenprofiel.

Niet-Geïndexeerde Queries Oplossen

Ontbrekende indexen dwingen de database tot volledige table scans, wat leidt tot pieken in IOPS en CPU-gebruik. Bij Azure SQL en Azure Database for PostgreSQL maskeert een hoog compute-verbruik vaak ontbrekende indexen. Organisaties upgraden regelmatig van een 4-vCore instantie (€280/maand) naar een 16-vCore instantie (€1.120/maand) om querypieken op te vangen die met een eenvoudige index opgelost hadden kunnen worden.

Voer tijdens de audit gerichte query-analyses uit om de zwaarste CPU-verbruikers te identificeren:

-- Azure SQL / SQL Server: Top 5 Queries op Basis van Totale CPU-werktijd
SELECT TOP 5
    qs.total_worker_time / qs.execution_count AS AvgCpuTimeMicroseconds,
    qs.execution_count,
    SUBSTRING(st.text, (qs.statement_start_offset/2)+1,
        (((CASE qs.statement_end_offset
            WHEN -1 THEN DATALENGTH(st.text)
            ELSE qs.statement_end_offset
        END) - qs.statement_start_offset)/2) + 1) AS StatementText,
    qp.query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) AS qp
ORDER BY qs.total_worker_time DESC;

Fase 3: Noisy Neighbors en Inefficiënte Opslag Aanpakken

Zonder expliciete resourcebeperkingen en opslagbeleid veroorzaken achtergrondtaken en verweesde data verborgen kosten binnen het cluster.

Noisy Neighbors Beheersen via Quality of Service (QoS)

Batchverwerking en synchronisatietaken die op dezelfde nodes draaien als klantgerichte API's veroorzaken CPU-starvation en netwerkvertraging wanneer QoS-klassen ontbreken. Kubernetes kent QoS toe op basis van hoe requests en limits zijn gedefinieerd:

  • Guaranteed: CPU- en geheugen-requests zijn exact gelijk aan limits. De node-kernel reserveert de resources en voorkomt het wegsturen van deze pods. Gebruik dit voor bedrijfskritische API's.
  • Burstable: requests zijn lager dan limits. Pods kunnen onbenutte headroom benutten wanneer beschikbaar. Geschikt voor standaard applicaties met wisselend verkeer.
  • BestEffort: Geen requests of limits ingesteld. Deze pods worden als eerste beëindigd bij geheugentekort. Sta geen BestEffort-pods toe in productieomgevingen.

Stel LimitRanges in om standaard requests en limits per namespace af te dwingen:

apiVersion: v1
kind: LimitRange
metadata:
  name: core-limits
  namespace: production
spec:
  limits:
  - default:
      cpu: 500m
      memory: 512Mi
    defaultRequest:
      cpu: 100m
      memory: 256Mi
    type: Container

Verweesde Schijven en Overbemeten Opslag Opschonen

Wanneer PersistentVolumeClaims (PVC's) of AKS-worker nodes worden verwijderd, blijven onderliggende Azure Managed Disks soms ontkoppeld achter terwijl de maandelijkse opslagkosten gewoon doorlopen.

Spoor ontkoppelde managed disks op via de Azure CLI:

# Toon alle ontkoppelde beheerde schijven binnen het abonnement
az disk list \
  --query "[?managedBy==null].[id, resourceGroup, name, diskSizeGb, sku.name]" \
  --output table

Fase 4: Concrete Maatregelen voor Structurele Run-Rate Verlaging

Nadat individuele workloads zijn geoptimaliseerd, kunnen infrastructurele kostenbesparingen over het hele cluster worden doorgevoerd:

Gespecialiseerde Node Pools & Spot VM's

Scheid continue applicaties van asynchrone achtergrondtaken. Draai achtergrondverwerking en batchtaken op Azure Spot VM node pools voor kortingen tot 70–80% ten opzichte van reguliere prijzen.

Event-Driven Schalen met KEDA

Vervang vaste replica-aantallen door KEDA-scalers op basis van Azure Service Bus- of RabbitMQ-wachtrijlengtes. Schaal verbruikers buiten piektijden terug naar nul en schaal alleen op wanneer er berichten binnenkomen.

Log Analytics Ingestion Filtering

Azure Monitor en Container Insights kunnen aanzienlijke data-ingestiekosten veroorzaken. Filter hoog-frequente HTTP 200 health-checks en uitgebreide debug-logs al op collectorniveau.

Azure Savings Plans & Reserveringen

Na het elimineren van verspilling en het stabiliseren van de basiscapaciteit kunnen 1- of 3-jarige Azure Savings Plans voor Compute worden ingezet om 40–60% korting te borgen op de stabiele basisvoetafdruk.

Audit Checklist: Cloudkosten en Prestaties

Gebruik deze referentiechecklist tijdens periodieke architectuurbeoordelingen en infrastructuuraudits:

01

Kubernetes & Compute

Beoordeel pod CPU- en geheugen-requests: Stem requests af op het daadwerkelijke 95e percentielverbruik uit Prometheus of VPA.
Verwijder arbitraire CPU-limits: Voorkom onnodige CFS-throttling op latency-gevoelige API's, tenzij strikte multi-tenant isolatie vereist is.
Handhaaf Namespace LimitRanges: Zorg dat er geen container kan worden uitgerold zonder expliciete requests en limits.
Scheid workloads in dedicated node pools: Draai batchverwerking op Spot-instanties en stabiele diensten op reguliere instances.
Activeer KEDA voor wachtrijverwerkers: Schaal pod-aantallen terug naar nul wanneer wachtrijen leeg zijn.
02

Databases & Netwerk

Limiteer client-side connectiepools: Bereken de maximale connectielast (Max Pool Size × Max Pods) om database-uitputting te voorkomen.
Gebruik server-side connection pooling: Zet PgBouncer of Azure SQL Elastic Pools in bij microservices met hoge gelijktijdigheid.
Audit top queries op CPU-werktijd: Voeg ontbrekende indexen toe en herschrijf trage queries voordat compute-tiers worden geüpgraded.
Bewaak SNAT-poortbezetting: Controleer dat herbruikbare HTTP-clients en geoptimaliseerde pooling uitgaande poortuitputting voorkomen.
03

Opslag, Logging & Reserveringen

Verwijder verweesde Azure Managed Disks: Voer maandelijks een query uit op ontkoppelde schijven over alle resource groups.
Filter Log Analytics data-ingestie: Verwijder overbodige health-check pings en trace-logs vóór verzending naar Log Analytics.
Stel lifecycle-beleid in op Blob storage: Verplaats oudere diagnostische data en back-ups automatisch van Hot naar Cool/Archive tiers.
Sluit Savings Plans af op de stabiele basis: Activeer reserveringen pas nadat pods en node pools zijn geoptimaliseerd.

Onafhankelijk Cloud Architectuuradvies

Het auditen van een complex multi-cluster cloudlandschap vereist diepgaande inspectie van applicatiecode, containerorkestratie en cloudconfiguraties.

Onze Software Architecture Assessment, Kubernetes & Cloud Native en Azure Cloud Engineering diensten bieden diepgaande technische inspecties van je infrastructuur en codebase. We brengen verborgen kostenposten in kaart, lossen prestatieknelpunten op en leveren een concreet verbeterplan voor jouw engineeringteam.

#Kubernetes #AKS #Azure #Cost Optimization #Performance #Architecture Assessment #Prometheus #KEDA