跳转至

基础设施

KanjiIQ运行在Hetzner上的自托管Kubernetes集群上,使用Traefik作为Ingress,cert-manager实现自动TLS。

托管:Hetzner专用服务器

整个生产环境运行在一台Hetzner专用服务器上:

  • Kubernetes发行版:k3s(轻量级、单二进制文件Kubernetes)
  • 操作系统:Linux
  • 网络:公网IPv4,使用Cloudflare DNS

为什么选择Hetzner?

  • 可预测的月度定价(无按请求或按小时收费)
  • 欧洲数据中心位置(GDPR友好)
  • 优秀的性价比
  • 完全root访问,便于k3s安装

Kubernetes: k3s

k3s是一个轻量级、CNCF认证的Kubernetes发行版,内置:

  • 容器运行时:containerd
  • Ingress控制器:Traefik(预装)
  • 服务负载均衡器:Klipper
  • 存储:本地路径供应器
  • DNS:CoreDNS

k3s以单个二进制文件(约100MB)运行Kubernetes,而非多组件的kubeadm方式。它完全兼容标准Kubernetes API——所有kubectl命令和清单的使用方式完全相同。

Ingress: Traefik

Traefik作为集群的Ingress控制器,负责处理:

  • TLS终止:所有域名自动HTTPS
  • 路由:基于主机的服务路由(kanjiiq.com → 前端,api.kanjiiq.com → 后端)
  • 速率限制:通过CRD中间件实现按IP的请求限流
  • 安全头:通过中间件链设置HSTS、X-Frame-Options、CSP

中间件配置

# Public traffic: rate limit + security headers
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: public-security-chain
spec:
  chain:
    middlewares:
      - name: rate-limit        # 100 req/min, burst 50
      - name: security-headers  # HSTS, X-Frame-Options, etc.
# Admin traffic: stricter rate limit + auth
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: admin-security-chain
spec:
  chain:
    middlewares:
      - name: api-rate-limit    # 50 req/min, burst 25
      - name: security-headers
      - name: admin-auth

TLS: cert-manager + Let's Encrypt

自动TLS证书管理:

graph LR
    I[Ingress with<br/>cert-manager annotation] --> CM[cert-manager]
    CM --> LE[Let's Encrypt<br/>ACME challenge]
    LE --> C[TLS Certificate]
    C --> S[Kubernetes Secret]
    S --> T[Traefik uses cert<br/>for HTTPS]
  • ClusterIssuerletsencrypt-prod(集群范围的证书颁发机构)
  • 验证类型:通过Traefik的HTTP-01
  • 续期:到期前自动续期
  • 存储:证书存储为Kubernetes Secrets

Ingress资源通过单个注解请求证书:

annotations:
  cert-manager.io/cluster-issuer: letsencrypt-prod

DNS: Cloudflare

域名DNS通过Cloudflare管理:

  • A记录:指向Hetzner服务器IP
  • 代理:可选的Cloudflare CDN/WAF层
  • CF-IPCountry头:后端用于地理定位,无需IP数据库

容器仓库:Forgejo

Docker镜像存储在<registry>的Forgejo Container Registry中:

  • 与源码同一平台(单一平台)
  • Kubernetes中配置了镜像拉取密钥(forgejo-registry
  • 标签:每次构建使用:latest + :COMMIT_SHA
  • 无外部仓库依赖(Docker Hub、GHCR等)

资源分配

组件 CPU请求 CPU限制 内存请求 内存限制
后端 250m 500m 256Mi 512Mi
前端 100m 200m 128Mi 256Mi
PostgreSQL 250m 500m 256Mi 512Mi
文档 10m 100m 32Mi 64Mi