# 精油配方计算器 - 部署文档 ## 架构 - **前端**: 静态 HTML(由 FastAPI 直接 serve) - **后端**: FastAPI + SQLite,端口 8000 - **部署**: Kubernetes (k3s) on `oci.euphon.net` - **域名**: https://oil.oci.euphon.net - **TLS**: Traefik + Let's Encrypt (自动) ## 目录结构 ``` ├── backend/ │ ├── main.py # FastAPI 应用 │ ├── database.py # SQLite 数据库操作 │ ├── defaults.json # 默认精油和配方数据(首次启动时 seed) │ └── requirements.txt ├── frontend/ │ └── index.html # 前端页面 ├── deploy/ │ ├── namespace.yaml │ ├── deployment.yaml │ ├── service.yaml │ ├── pvc.yaml # 1Gi 持久卷,存放 SQLite 数据库 │ ├── ingress.yaml │ ├── setup-kubeconfig.sh # 生成受限 kubeconfig 的脚本 │ └── kubeconfig # 受限 kubeconfig(仅 oil-calculator namespace) ├── Dockerfile └── doc/deploy.md ``` ## 首次部署 已完成,以下为记录。 ```bash # 1. SSH 到服务器 ssh fam@oci.euphon.net # 2. 上传项目 scp oil-calc.tar.gz fam@oci.euphon.net:/tmp/ ssh fam@oci.euphon.net "mkdir -p ~/oil-calculator && cd ~/oil-calculator && tar xzf /tmp/oil-calc.tar.gz" # 3. 构建并推送镜像 cd ~/oil-calculator docker build -t registry.oci.euphon.net/oil-calculator:latest . docker push registry.oci.euphon.net/oil-calculator:latest # 4. 部署 k8s 资源 cd deploy kubectl apply -f namespace.yaml kubectl apply -f pvc.yaml kubectl apply -f deployment.yaml kubectl apply -f service.yaml kubectl apply -f ingress.yaml # 5. 需要 regcred 才能拉取私有镜像(从已有 ns 复制) kubectl get secret regcred -n guitar -o yaml | sed 's/namespace: guitar/namespace: oil-calculator/' | kubectl apply -f - ``` ## 更新部署 ```bash # 在本地打包上传 cd "/Users/hera/Hera DOCS/Projects/Essential Oil Formula Cost Calculator" tar czf /tmp/oil-calc.tar.gz Dockerfile backend/ frontend/ deploy/ scp /tmp/oil-calc.tar.gz fam@oci.euphon.net:/tmp/ # SSH 到服务器构建并重启 ssh fam@oci.euphon.net cd ~/oil-calculator && tar xzf /tmp/oil-calc.tar.gz docker build -t registry.oci.euphon.net/oil-calculator:latest . docker push registry.oci.euphon.net/oil-calculator:latest kubectl rollout restart deploy/oil-calculator -n oil-calculator ``` 或者使用受限 kubeconfig(仅重启,不含构建): ```bash KUBECONFIG=deploy/kubeconfig kubectl rollout restart deploy/oil-calculator ``` ## 受限 Kubeconfig 文件位于 `deploy/kubeconfig`,权限范围: - **Namespace**: `oil-calculator` only - **ServiceAccount**: `oil-calculator-deployer` - **权限**: pods, services, deployments, replicasets, ingresses, PVC, configmaps, secrets, pods/log 的完整 CRUD - **无法**访问其他 namespace 或集群级资源 重新生成:`bash deploy/setup-kubeconfig.sh` ## K8s 配置要点 - **Ingress class**: `traefik` - **TLS annotation**: `traefik.ingress.kubernetes.io/router.tls.certresolver: le` - **镜像仓库**: `registry.oci.euphon.net`(需要 `regcred` secret) - **数据持久化**: PVC 挂载到 `/data`,SQLite 数据库在 `/data/oil_calculator.db` ## API 端点 | Method | Path | 说明 | |--------|------|------| | GET | /api/oils | 所有精油列表 | | POST | /api/oils | 添加/更新精油 | | DELETE | /api/oils/{name} | 删除精油 | | GET | /api/recipes | 所有配方列表 | | POST | /api/recipes | 新增配方 | | PUT | /api/recipes/{id} | 更新配方 | | DELETE | /api/recipes/{id} | 删除配方 | | GET | /api/tags | 所有标签 | | POST | /api/tags | 新增标签 | | DELETE | /api/tags/{name} | 删除标签 |