跳转至

Kubernetes清单

所有Kubernetes资源定义在k8s/目录中,按编号顺序应用。

清单概览

文件 资源 用途
00-namespace.yaml Namespace 创建jlpt-kanji命名空间
01-secrets.yaml Secret 数据库URL、JWT密钥、OpenAI密钥
02-postgres-pvc.yaml PersistentVolumeClaim PostgreSQL的10Gi存储
03-postgres-deployment.yaml Deployment + Service PostgreSQL 15数据库
04-libretranslate-deployment.yaml Deployment + Service 自托管翻译(可选)
05-deployment.yaml Deployment 主应用(前端 + 后端容器)
06-service.yaml Service (x2) 前端(:80)和后端(:8080)服务
07-ingress.yaml Ingress jlpt.iqquest.app的Traefik路由
08-security-middlewares.yaml Middleware (CRD) 速率限制和安全头
ingress-kanjiiq.yaml Ingress kanjiiq.com域名路由
ingress-docs.yaml Ingress docs.kanjiiq.app路由
docs-deployment.yaml Deployment 文档站点
docs-service.yaml Service 文档服务

初始部署

按顺序应用清单:

# Create namespace and secrets
kubectl apply -f k8s/00-namespace.yaml
kubectl apply -f k8s/01-secrets.yaml

# Database
kubectl apply -f k8s/02-postgres-pvc.yaml
kubectl apply -f k8s/03-postgres-deployment.yaml

# Application
kubectl apply -f k8s/05-deployment.yaml
kubectl apply -f k8s/06-service.yaml

# Networking
kubectl apply -f k8s/07-ingress.yaml
kubectl apply -f k8s/08-security-middlewares.yaml
kubectl apply -f k8s/ingress-kanjiiq.yaml

命名空间:jlpt-kanji

所有资源都在同一个命名空间中:

apiVersion: v1
kind: Namespace
metadata:
  name: jlpt-kanji

这提供了:

  • 与其他工作负载的资源隔离
  • 范围化的RBAC(如需要)
  • 便捷的清理(kubectl delete namespace jlpt-kanji
  • 资源配额强制执行(如需要)

密钥管理

敏感值存储在Kubernetes Secrets中(不提交到Git):

apiVersion: v1
kind: Secret
metadata:
  name: jlpt-kanji-secrets
  namespace: jlpt-kanji
type: Opaque
stringData:
  database-url: "postgresql://user:pass@jlpt-postgres:5432/jlpt_flashcard"
  jwt-secret: "random-secret-string"
  openai-api-key: "sk-..."

仓库中的01-secrets.yaml是一个模板——实际值在服务器上手动应用。

Pod设计

主应用Pod并行运行两个容器:

spec:
  replicas: 2
  template:
    spec:
      imagePullSecrets:
        - name: forgejo-registry
      containers:
        - name: backend
          image: <registry>/jlpt-kanji-backend:latest
          ports:
            - containerPort: 8080
          resources:
            requests: { memory: "256Mi", cpu: "250m" }
            limits: { memory: "512Mi", cpu: "500m" }

        - name: frontend
          image: <registry>/jlpt-kanji-frontend:latest
          ports:
            - containerPort: 80
          resources:
            requests: { memory: "128Mi", cpu: "100m" }
            limits: { memory: "256Mi", cpu: "200m" }

健康检查

两个容器都有存活和就绪探针:

  • 存活探针:如果容器无响应则重启(每10秒检查,3次失败后触发)
  • 就绪探针:在容器就绪前将Pod从Service端点移除(每5秒检查,2次失败后触发)

安全上下文

所有容器以非root用户运行(UID 1000):

securityContext:
  runAsUser: 1000
  runAsGroup: 1000
  runAsNonRoot: true

服务

两个ClusterIP服务将Pod的容器暴露给集群:

# Frontend service (port 80 → 80)
name: jlpt-kanji-frontend
ports:
  - port: 80
    targetPort: 80

# Backend service (port 80 → 8080)
name: jlpt-kanji-backend
ports:
  - port: 80
    targetPort: 8080

后端服务将外部端口80映射到内部端口8080,因此Traefik在同一端口上路由到所有服务。

Ingress

通过Traefik实现基于主机的路由:

spec:
  ingressClassName: traefik
  tls:
    - hosts:
        - kanjiiq.com
        - api.kanjiiq.com
        - admin.kanjiiq.com
      secretName: kanjiiq-tls
  rules:
    - host: kanjiiq.com       → jlpt-kanji-frontend:80
    - host: api.kanjiiq.com   → jlpt-kanji-backend:80
    - host: admin.kanjiiq.com → jlpt-kanji-backend:80

创建Ingress时,cert-manager会自动配置TLS证书。