引言:为什么 TypeScript 和 Kubernetes 是理想组合
现代 Web 开发离不开两件事:静态类型和可扩展的基础设施。TypeScript 在编译阶段提供了代码的可靠性,而 Kubernetes (K8s) 则提供了自动化的容器管理、负载均衡和自我修复。在本指南中,我们将走完从简单的 TypeScript 应用程序到在 Kubernetes 集群中运行的完整路径。您将学习如何将代码打包成 Docker 镜像、编写清单以及部署生产就绪的服务。
步骤 1:准备用于容器化的 TypeScript 应用程序
在考虑 Kubernetes 之前,需要确保您的应用程序已准备好运行在容器中。让我们创建一个简单的基于 TypeScript 的 Express 应用程序。确保项目根目录下有 package.json、tsconfig.json 和入口文件 src/index.ts。
// 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}`);});一个重要细节:在生产环境中,我们不使用 ts-node。因此,请在 package.json 中添加构建脚本:
"scripts": { "build": "tsc", "start": "node dist/index.js"}执行 npm run build 后,dist 文件夹中会出现编译后的 JavaScript。我们将把这个文件夹复制到 Docker 镜像中。
步骤 2:创建最小尺寸的 Docker 镜像
对于生产环境部署,镜像大小至关重要。我们使用多阶段构建:首先在包含完整 SDK 的容器中编译 TypeScript,然后将结果复制到基于 node:18-alpine 的轻量级镜像中。
# Dockerfile# 阶段 1:构建FROM node:18-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ci --only=productionCOPY tsconfig.json ./COPY src/ ./src/RUN npm run build
# 阶段 2:生产环境FROM node:18-alpineWORKDIR /appCOPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesEXPOSE 3000CMD ["node", "dist/index.js"]构建镜像并在本地测试:
docker build -t my-ts-app:latest .docker run -p 3000:3000 my-ts-app:latest打开 http://localhost:3000 — 您应该会看到欢迎信息。
步骤 3:Kubernetes 清单 — Deployment 和 Service
现在将我们的镜像迁移到集群中。这需要两个基本的清单:Deployment(管理副本和更新)和 Service(提供网络访问)。
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