Beispiele zum Nachbauen
Jedes Beispiel zeigt die Blöcke, die Schritte und das exakte YAML, das BYOBYaml daraus erzeugt. Das YAML stammt direkt aus dem Generator der App.
| Beispiel | Art |
|---|---|
| Statischer Webserver | Compose |
| App wartet auf gesunde Datenbank | Compose |
| Image-Tag und Port als Variablen | Compose |
| ConfigMap und Secret in einen Container | Kubernetes |
| Persistenter Speicher | Kubernetes |
| Ingress mit TLS und zwei Pfaden | Kubernetes |
| Route mit eigenem Hostnamen | OpenShift |
| Nächtlicher CronJob | Kubernetes |
| Extras: Felder ohne eigenen Block | Kubernetes |
| Eigene Ressource: PodDisruptionBudget | Kubernetes |
| Autoscaling nach CPU und RAM | Kubernetes |
Statischer Webserver
Compose Ein nginx, der einen lokalen Ordner read-only ausliefert und nach einem Absturz neu startet.
So baust du es:
- Compose-Datei anlegen; der Startblock Docker Compose · Projekt ist schon da.
- Compose → Service unter den Startblock ziehen, Name
web, Imagenginx:1.27-alpine. - Service → Port in den Service legen: Host
8080, Container80. - Service → Volume in den Service legen:
./html→/usr/share/nginx/html, Häkchen nur lesen. - Service → Neustart
unless-stopped.
Blöcke:
Ergebnis:
name: website
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
restart: unless-stopped
Ports schreibt BYOBYaml immer in Anführungszeichen ("8080:80"). Sonst kann YAML 1.1 Werte wie 22:22 als Zahl im 60er-System lesen.
App wartet auf gesunde Datenbank
Compose Die App startet erst, wenn PostgreSQL seinen Healthcheck besteht. Die Daten liegen in einem benannten Volume.
So baust du es:
- Service
dbmit Imagepostgres:16-alpine, drei Variable-Blöcke für User, Passwort und Datenbank. - Volume
pgdata→/var/lib/postgresql/dataund Healthcheckpg_isready -U app. - Service
appmit leerem Image, dafür Build Ordner.. - Im Service
app: wartet aufdbbis gesund. - Ganz unten unter dem Startblock: Compose → Volume
pgdata. Benannte Volumes müssen auf oberster Ebene deklariert werden.
Blöcke:
Ergebnis:
name: shop
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: change-me
POSTGRES_DB: app
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test:
- CMD-SHELL
- pg_isready -U app
interval: 10s
timeout: 5s
retries: 5
app:
build: .
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://app:change-me@db:5432/app
depends_on:
db:
condition: service_healthy
volumes:
pgdata:
Image-Tag und Port als Variablen
Compose Derselbe Service mit unterschiedlichen Werten je Umgebung. Die Tabelle zeigt die Variablen, das YAML entsteht mit der Umgebung prod.
So baust du es:
- Im Tab Variablen die Variablen
TAGundPORTanlegen. - In den Blöcken
${TAG}und${PORT}in die Felder schreiben. - Oben rechts die Umgebung
prodwählen.
Blöcke:
Ergebnis (Umgebung prod):
services:
api:
image: registry.example.com/api:1.4.2
ports:
- "80:8080"
environment:
RELEASE: api-1.4.2
| Variable | dev | prod |
|---|---|---|
TAG | latest | 1.4.2 |
PORT | 8080 | 80 |
ConfigMap und Secret in einen Container
Kubernetes Drei Dokumente in einer Datei: ConfigMap, Secret und ein Deployment, das alles als Umgebungsvariablen bekommt.
So baust du es:
- Ressourcen → ConfigMap auf die Fläche ziehen, darunter zwei Config & Daten → Eintrag-Blöcke.
- Ressourcen → Secret daneben ziehen, darunter ein Eintrag
DB_PASSWORD. - Deployment mit Container. Im Container: alle Variablen aus ConfigMap und Variable … aus Secret … Schlüssel … für einen einzelnen Wert.
Blöcke:
Ergebnis:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: info
FEATURE_X: "true"
---
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
stringData:
DB_PASSWORD: change-me
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 1
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: registry.example.com/app:1.0
envFrom:
- configMapRef:
name: app-config
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: DB_PASSWORD
stringData nimmt Klartext an; Kubernetes speichert ihn base64-kodiert. Das ist keine Verschlüsselung.
Persistenter Speicher
Kubernetes Ein PVC wird als Volume im Pod definiert und im Container eingehängt. Der Name data verbindet beides.
So baust du es:
- Ressourcen → Speicher (PVC)
app-data,5Gi,ReadWriteOnce. - Im Deployment: Pod → Volume aus PVC mit Name
dataund Claimapp-data. - Im Container: Container → Volume einhängen mit Name
dataund Pfad/var/lib/app.
Blöcke:
Ergebnis:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 1
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: registry.example.com/app:1.0
volumeMounts:
- name: data
mountPath: /var/lib/app
volumes:
- name: data
persistentVolumeClaim:
claimName: app-data
Bei ReadWriteOnce kann nur ein Node das Volume einhängen. Für mehrere Replicas auf verschiedenen Nodes brauchst du ReadWriteMany oder ein StatefulSet mit pro Pod Speicher.
Ingress mit TLS und zwei Pfaden
Kubernetes Ein Hostname, zwei Backends: / geht ans Frontend, /api an die API. Das Zertifikat stellt cert-manager aus.
So baust du es:
- Ressourcen → Ingress mit Klasse
nginx. - Netzwerk → cert-manager Issuer
letsencryptund TLS für Host plus Secret-Name. - Zwei Regel-Blöcke mit demselben Host. BYOBYaml fasst sie unter einem
hostzusammen.
Blöcke:
Ergebnis:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
annotations:
cert-manager.io/cluster-issuer: letsencrypt
spec:
ingressClassName: nginx
tls:
- hosts:
- shop.example.com
secretName: shop-tls
rules:
- host: shop.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
name: http
Steht im Port-Feld eine Zahl, wird daraus port.number. Steht dort ein Name wie http, wird daraus port.name.
Route mit eigenem Hostnamen
OpenShift Eine HTTPS-Route mit Edge-Termination: HTTP wird auf HTTPS umgeleitet.
So baust du es:
- Ressourcen → Route mit Service
webund Porthttp(Name des Service-Ports). - Netzwerk → Hostname und HTTPS
edgemit umleiten.
Blöcke:
Ergebnis:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: web
spec:
host: web.apps.example.com
to:
kind: Service
name: web
port:
targetPort: http
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
Nächtlicher CronJob
Kubernetes Ein Backup um 02:00 Uhr. Läuft noch ein alter Job, startet kein neuer; dafür sorgt ein Extras-Feld.
So baust du es:
- Ressourcen → CronJob mit Zeitplan
0 2 * * *. - Extras → Feld
spec.concurrencyPolicy=Forbid. Diese Option hat keinen eigenen Block. - Container mit Command. Anführungszeichen halten Argumente zusammen.
Blöcke:
Ergebnis:
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup
spec:
schedule: 0 2 * * *
jobTemplate:
spec:
template:
metadata:
labels:
app: backup
spec:
containers:
- name: backup
image: alpine:3.20
command:
- /bin/sh
- -c
- tar czf /backup/data.tgz /data
restartPolicy: OnFailure
concurrencyPolicy: Forbid
Extras: Felder ohne eigenen Block
Kubernetes Tolerations, ein Lifecycle-Hook und ein abweichendes Feld. Alles mit den drei Extras-Blöcken.
So baust du es:
- zu Liste … hinzufügen direkt unter dem Deployment: Der Pfad beginnt bei der Ressource (
spec.template.spec.tolerations). - Feld im Container: Der Pfad beginnt beim Container (
lifecycle.preStop). - YAML einmischen für Schlüssel mit Punkten (Annotation).
Blöcke:
Ergebnis:
apiVersion: apps/v1
kind: Deployment
metadata:
name: worker
annotations:
app.openshift.io/connects-to: db
spec:
replicas: 2
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
spec:
containers:
- name: worker
image: registry.example.com/worker:2.0
lifecycle:
preStop:
exec:
command:
- sh
- -c
- sleep 5
tolerations:
- key: dedicated
operator: Equal
value: batch
effect: NoSchedule
Eigene Ressource: PodDisruptionBudget
Kubernetes Für Ressourcen ohne eigenen Startblock. Hier sorgt ein PDB dafür, dass bei Node-Wartungen immer ein Pod läuft.
So baust du es:
- Ressourcen → Eigene Ressource: kind
PodDisruptionBudget, apiVersionpolicy/v1. - Inhalt mit Feld-Blöcken.
Blöcke:
Ergebnis:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: web
Autoscaling nach CPU und RAM
Kubernetes Zwischen 2 und 10 Pods; das Herunterskalieren beginnt erst nach 5 Minuten ohne Last.
So baust du es:
- Ressourcen → Autoscaler für Deployment
web, min2, max10. - Zwei Skalierung → Ziel-Blöcke und ein herunterskalieren erst nach.
Blöcke:
Ergebnis:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
Auslastung bezieht sich auf die requests der Container. Ohne resources.requests kann der HPA nicht rechnen.