Einleitung: Warum TypeScript und Kubernetes das ideale Paar sind
Moderne Webentwicklung ist ohne zwei Dinge undenkbar: statische Typisierung und skalierbare Infrastruktur. TypeScript bietet Code-Zuverlässigkeit zur Kompilierzeit, und Kubernetes (K8s) bietet automatische Containerverwaltung, Lastverteilung und Self-Healing. In diesem Leitfaden gehen wir den gesamten Weg von einer einfachen TypeScript-Anwendung bis zu ihrem Start in einem Kubernetes-Cluster. Sie erfahren, wie Sie Code in ein Docker-Image packen, Manifeste schreiben und einen production-ready Dienst bereitstellen.
Schritt 1: Vorbereitung der TypeScript-Anwendung für die Containerisierung
Bevor Sie an Kubernetes denken, müssen Sie sicherstellen, dass Ihre Anwendung bereit ist, in einem Container ausgeführt zu werden. Wir erstellen eine einfache Express-Anwendung in TypeScript. Stellen Sie sicher, dass sich im Stammverzeichnis des Projekts package.json, tsconfig.json und der Einstiegspunkt src/index.ts befinden.
// src/index.tsimport express, { Request, Response } from 'express';
const app = express();const PORT = process.env.PORT || 3000;
app.get('/health', (_req: Request, res: Response) => { res.json({ status: 'ok', timestamp: new Date().toISOString() });});
app.get('/', (_req: Request, res: Response) => { res.send('Hello from TypeScript on Kubernetes!');});
app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});Ein wichtiger Punkt: In der Produktion verwenden wir ts-node nicht. Fügen Sie daher in package.json ein Build-Skript hinzu:
"scripts": { "build": "tsc", "start": "node dist/index.js"}Nach der Ausführung von npm run build erscheint im Ordner dist der kompilierte JavaScript-Code. Genau diesen Ordner werden wir in das Docker-Image kopieren.
Schritt 2: Erstellen eines Docker-Images mit minimaler Größe
Für die Produktionsbereitstellung ist die Image-Größe entscheidend. Wir verwenden einen Multi-Stage-Build: Zuerst kompilieren wir TypeScript in einem Container mit vollständigem SDK, dann kopieren wir das Ergebnis in ein leichtes Image auf Basis von node:18-alpine.
# Dockerfile# Stage 1: BuildFROM node:18-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ci --only=productionCOPY tsconfig.json ./COPY src/ ./src/RUN npm run build
# Stage 2: ProductionFROM node:18-alpineWORKDIR /appCOPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesEXPOSE 3000CMD ["node", "dist/index.js"]Erstellen Sie das Image und testen Sie es lokal:
docker build -t my-ts-app:latest .docker run -p 3000:3000 my-ts-app:latestÖffnen Sie http://localhost:3000 – Sie sollten die Begrüßung sehen.
Schritt 3: Kubernetes-Manifeste – Deployment und Service
Jetzt übertragen wir unser Image in den Cluster. Dazu werden zwei grundlegende Manifeste benötigt: Deployment (verwaltet Replikate und Updates) und Service (stellt den Netzwerkzugriff sicher).
deployment.yaml
apiVersion: apps/v1kind: Deploymentmetadata: name: ts-app-deploymentspec: replicas: 2 selector: matchLabels: app: ts-app template: metadata: labels: app: ts-app spec: containers: - name: ts-app image: my-ts-app:latest imagePullPolicy: IfNotPresent ports: - containerPort: 3000 env: - name: PORT value: "3000" livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 5 periodSeconds: 10 readinessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 3 periodSeconds: 5service.yaml
apiVersion: v1kind: Servicemetadata: name: ts-app-servicespec: selector: app