基础设施¶
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]
- ClusterIssuer:
letsencrypt-prod(集群范围的证书颁发机构) - 验证类型:通过Traefik的HTTP-01
- 续期:到期前自动续期
- 存储:证书存储为Kubernetes Secrets
Ingress资源通过单个注解请求证书:
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 |