Elk platform team vraagt zich uiteindelijk af: moeten we een Internal Developer Platform bouwen?
Het antwoord is waarschijnlijk ja. De vraag is hoe.
Ik heb platforms gezien die miljoenen kostten en nooit geadopteerd werden. Ik heb ook scrappy interne tools gezien die developer productiviteit van de ene op de andere dag transformeerden. Het verschil is geen budget of technologie — het is aanpak.
Wat Is een Internal Developer Platform?
Een Internal Developer Platform (IDP) is een self-service laag die infrastructuur complexiteit abstraheert van developers. In plaats van Kubernetes YAML te schrijven, beschrijven developers wat ze nodig hebben. Het platform regelt hoe.
flowchart TD
subgraph before["Zonder Platform"]
D1["Developer"] --> K8s["Kubernetes YAML"]
D1 --> CI["CI Pipeline"]
D1 --> Sec["Security Config"]
D1 --> Mon["Monitoring Setup"]
end
subgraph after["Met Platform"]
D2["Developer"] --> IDP["Platform API"]
IDP --> K8s2["Kubernetes"]
IDP --> CI2["CI/CD"]
IDP --> Sec2["Security"]
IDP --> Mon2["Monitoring"]
end
Het platform is de interface tussen developer intentie en infrastructuur realiteit.
Waarom Platforms Falen
Gebouwd in Isolatie
Platform team bouwt wat ze denken dat developers nodig hebben. Developers gebruiken het niet. Platform team geeft developers de schuld dat ze de visie niet begrijpen.
Te Veel Te Snel
Beginnen met een compleet platform — service catalogus, self-service alles, custom UI. Zes maanden later, nog steeds niet productie-ready.
Verkeerd Abstractieniveau
Platform is of te low-level (gewoon Kubernetes met extra stappen) of te high-level (geen escape hatches wanneer je ze nodig hebt).
Geen Migratiepad
Bestaande services kunnen niet migreren. Platform is alleen voor greenfield. Team onderhoudt nu twee systemen voor altijd.
Begin Met Problemen, Niet Oplossingen
Voordat je iets bouwt, begrijp:
Waar verliezen developers tijd?
- Wachten op infrastructuur requests?
- Boilerplate configuratie schrijven?
- Deployment failures debuggen?
- Productie toegang krijgen?
Waar vragen ze steeds om?
- Check je ticketing systeem
- Kijk naar Slack vragen
- Praat met mensen (revolutionair, ik weet het)
Waar ontstaan incidenten?
- Verkeerd geconfigureerde services?
- Ontbrekende security policies?
- Incorrecte resource limits?
De antwoorden onthullen wat je platform eerst moet automatiseren.
Het Minimaal Viable Platform
Begin met drie componenten:
1. Golden Paths
Opinionated templates die best practices coderen:
# service-template/
├── deployment.yaml # Standaard deployment patroon
├── service.yaml # Service met verstandige defaults
├── networkpolicy.yaml # Security by default
├── servicemonitor.yaml # Automatische monitoring
└── values.yaml # Customization punten
Developers krijgen een werkende setup by default. Ze customizen alleen wat anders is aan hun service.
2. Self-Service Deployment
Push code, krijg deployment. Geen tickets, geen wachten.
Met GitOps:
# Application definitie in Git
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-service
namespace: argocd
spec:
source:
repoURL: https://gitlab.internal/my-service
path: deploy
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: my-service
syncPolicy:
automated:
prune: true
selfHeal: true
Developer merged naar main, ArgoCD deployt. Geen platform UI nodig initieel.
3. Guardrails
Kyverno policies die fouten voorkomen:
# Vereis resource limits
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-limits
spec:
validationFailureAction: Enforce
rules:
- name: require-limits
match:
resources:
kinds:
- Pod
validate:
message: "CPU en memory limits zijn vereist"
pattern:
spec:
containers:
- resources:
limits:
cpu: "?*"
memory: "?*"
Developers kunnen niet deployen zonder limits. Het platform dwingt standaarden automatisch af.
Bouwstenen
Service Templates met Helm
Maak een base chart die teams uitbreiden:
# base-service/Chart.yaml
apiVersion: v2
name: base-service
version: 1.0.0
description: Standaard service template
# base-service/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.name }}
spec:
replicas: {{ .Values.replicas | default 2 }}
selector:
matchLabels:
app: {{ .Values.name }}
template:
metadata:
labels:
app: {{ .Values.name }}
annotations:
prometheus.io/scrape: "true"
spec:
containers:
- name: {{ .Values.name }}
image: {{ .Values.image }}
ports:
- containerPort: {{ .Values.port | default 8080 }}
resources:
requests:
cpu: {{ .Values.resources.requests.cpu | default "100m" }}
memory: {{ .Values.resources.requests.memory | default "128Mi" }}
limits:
cpu: {{ .Values.resources.limits.cpu | default "500m" }}
memory: {{ .Values.resources.limits.memory | default "512Mi" }}
readinessProbe:
httpGet:
path: {{ .Values.healthPath | default "/health" }}
port: {{ .Values.port | default 8080 }}
Teams gebruiken het:
# my-service/values.yaml
name: my-service
image: registry.internal/my-service:v1.2.3
replicas: 3
port: 8080
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1
memory: 1Gi
Namespace als Grens
Elk team krijgt een namespace met alles vooraf geconfigureerd:
apiVersion: v1
kind: Namespace
metadata:
name: team-payments
labels:
team: payments
environment: production
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: team-payments
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
pods: "50"
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: team-payments
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Teams ownen hun namespace. Platform biedt de grenzen.
Self-Service via GitOps
Developers wijzigen hun namespace config via pull requests:
infrastructure/
├── teams/
│ ├── payments/
│ │ ├── namespace.yaml
│ │ ├── applications/
│ │ │ ├── api.yaml
│ │ │ └── worker.yaml
│ │ └── secrets/
│ │ └── external-secret.yaml
│ ├── orders/
│ └── ...
Pull request triggert review. Merge triggert ArgoCD sync. Geen tickets.
Progressieve Uitbreiding
Fase 1: Templates en Guardrails
- Helm charts voor veelvoorkomende patronen
- Kyverno policies voor veiligheid
- GitOps voor deployment
- Basis documentatie
Resultaat: Developers kunnen veilig deployen zonder Kubernetes diep te begrijpen.
Fase 2: Observability Integratie
- Automatische Prometheus scraping
- Loki log aggregatie
- Tempo trace collectie
- Pre-built Grafana dashboards
Resultaat: Developers krijgen visibility zonder configuratie.
Fase 3: Developer Portal
Voeg een UI laag toe (Backstage, custom, of vergelijkbaar):
flowchart TD
Portal["Developer Portal"] --> Catalog["Service Catalogus"]
Portal --> Templates["Maak van Template"]
Portal --> Docs["Documentatie"]
Portal --> Status["Service Status"]
Templates --> Git["Git Repository"]
Git --> ArgoCD["ArgoCD"]
ArgoCD --> K8s["Kubernetes"]
Resultaat: Developers hebben een single entry point.
Fase 4: Geavanceerde Mogelijkheden
- Secret management integratie (Vault)
- Database provisioning
- Environment cloning
- Kosten visibility
Resultaat: Echte self-service voor de meeste behoeften.
Wat Niet Te Bouwen
Custom YAML DSL
Verzin geen configuratietaal. Gebruik bestaande tools (Helm, Kustomize, cdk8s).
Ticket-Gebaseerde Workflows
Als developers nog steeds tickets maken, heb je niet genoeg geautomatiseerd.
One-Size-Fits-All
Bied golden paths, maar sta afwijking toe. Expert teams moeten lager niveau kunnen gaan.
Feature Factory
Platform moet stabiel zijn. Continue feature churn betekent dat je verkeerde problemen oplost.
Succes Meten
Tijd naar Productie
Hoe lang van “nieuwe service idee” naar “draait in productie”?
- Weken → Platform werkt niet
- Dagen → Op weg
- Uren → Succes
Ticket Volume
Platform requests moeten afnemen over tijd:
Voor: 50 infrastructuur tickets/week
Na: 10 infrastructuur tickets/week (alleen edge cases)
Developer NPS
Vraag developers: “Zou je dit platform aanbevelen aan een collega?”
Incident Correlatie
Hebben platform-deployed services minder incidenten dan handmatig geconfigureerde?
Team Structuur
Platform Team Grootte
Vuistregel: 1 platform engineer per 10-15 applicatie developers.
Te klein → Platform evolueert niet Te groot → Platform team bouwt features die niemand nodig heeft
Verantwoordelijkheden
Platform team:
- Onderhoudt templates en tools
- Schrijft policies
- Handelt platform incidenten af
- Biedt migratie ondersteuning
Applicatie teams:
- Ownen hun services
- Deployen hun code
- Definiëren hun resource behoeften
- First responders voor service incidenten
Embedded vs Centralized
Begin gecentraliseerd. Als platform matuur wordt, embed platform engineers part-time in product teams om echte behoeften te begrijpen.
Real-World Voorbeeld
Mijn homelab platform gebruikt:
Golden path:
# Standaard service template
dependencies:
- base-service # Helm dependency
values:
name: my-app
image: registry/my-app:latest
Self-service:
- Push naar main → ArgoCD deployt
- PR voor namespace wijzigingen → Auto-merged na review
Guardrails:
- Kyverno dwingt limits, labels, security context af
- NetworkPolicy default deny
Observability:
- ServiceMonitor auto-gemaakt
- Grafana dashboard gegenereerd
Totaal custom code: ~500 regels Helm templates en Kyverno policies. Al het andere is configuratie van bestaande tools.
Veelgemaakte Fouten
Beginnen met de Portal
Bouw geen UI tot workflows bewezen zijn. Test eerst met GitOps en CLI.
Bestaande Services Negeren
Platform moet migratie ondersteunen, niet alleen greenfield. Anders onderhoud je twee systemen.
Over-Engineering Security
Blokkeer niet elke edge case. Begin permissive, verscherp gebaseerd op incidenten.
Alle Complexiteit Verbergen
Sommige developers willen begrijpen. Bied escape hatches en documentatie.
Waarom Dit Ertoe Doet
Developer tijd is duur. Elk uur besteed aan vechten met infrastructuur is een uur niet besteed aan product bouwen.
Een goed platform vermenigvuldigt productiviteit:
- Junior developers deployen veilig op dag één
- Senior developers focussen op moeilijke problemen
- Operations last verschuift van repetitief naar interessant
Begin klein. Los echte problemen op. Groei gebaseerd op feedback.
Het beste platform is onzichtbaar — developers denken alleen “deployen is makkelijk hier.”
Een platform is geen product. Het is de afwezigheid van frictie.
