docs(plane): 自托管 Plane 落地事实入仓库 + plane-health runbook + hardening 草稿
记录源 Linear→Plane (2026-09-03 起, Plane MCP) + plane.chans.xyz 服务行/upstream 段; inventory + hosts/synapse.chans.xyz.md 补 Plane 部署事实 (Helm plane-ce-1.8.0 / app v1.4.1, ns plane, IngressRoute/自有证书 issuer/PVC 5+5Gi local-path/无备份层); 新增 runbooks/plane-health.md (只读健康检查) 与 docs/plane-hardening/ 草稿 (values.hardened.yaml、secrets.yaml.example 占位、backup/ CronJob), 均为未应用设计稿; .gitignore 增加 .tmp-* agent 临时文件。
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
# Plane CE 备份方案(DB-only)— DRAFT (2026-09-03), 未应用
|
||||
|
||||
> 关联:`plane-backup.yaml`(CronJob);追踪:Plane vps 项目条目(记录源,2026-09-03 起不用 Linear)。
|
||||
> 现状(实测):pg 全库 **88 MB**(310 issues / 1 user);MinIO uploads **264 KB**(几乎空)。
|
||||
|
||||
## 范围决策(2026-09-03,实际角度)
|
||||
|
||||
- **做:PostgreSQL 逻辑备份** —— 覆盖现实故障(误删、升级失败、磁盘坏、重装),成本≈0。
|
||||
- **不做:MinIO/附件备份** —— 桶仅 264 KB,个人实例附件可接受丢失;不为它付日常维护。
|
||||
日后附件明显变多再按原完整版思路加 `mc mirror`(历史版本见本目录 git 历史/Plane 条目评论)。
|
||||
- 异机同步暂不启用(见下"局限/阻塞")。
|
||||
|
||||
## 方案
|
||||
|
||||
集群内 CronJob(ns `plane`,每天 **01:30 UTC = 03:30 本地**,控制器按 UTC 跑):
|
||||
|
||||
1. 单容器 `postgres:15.7-alpine`:`pg_dump -Fc`(自定义压缩格式)打 `plane` 库
|
||||
→ `/var/backups/plane/pg/plane-<UTC时间戳>.dump`(hostPath `DirectoryOrCreate`)
|
||||
2. 保留 7 天(`find -mtime +7 -delete`),成功/失败历史各留 3/2
|
||||
3. 凭据:现 chart Secret `plane-app-pgdb-secrets`(Phase A 外部化后改 `plane-pgdb-credentials`)
|
||||
|
||||
## 容量
|
||||
|
||||
- 库 88 MB → `-Fc` 快照约 10–40 MB/天 × 7 天 ≈ **<300 MB**,对 83 G 可用盘可忽略。
|
||||
|
||||
## 还原(未演练;应用前先做一次隔离测试)
|
||||
|
||||
```bash
|
||||
# 目标 PG15 实例(临时起一个 postgres:15.7-alpine 容器或另一台机):
|
||||
# 先建空库: createdb plane (user=plane)
|
||||
pg_restore -h <target> -U plane -d plane --clean --if-exists /var/backups/plane/pg/plane-<TS>.dump
|
||||
# 还原后确认 310 issues 量级一致;附件为空属预期(未备份 MinIO)
|
||||
```
|
||||
|
||||
## 验收(应用前逐项过)
|
||||
|
||||
- [ ] CronJob 建立后手动触发一次:`kubectl -n plane create job --from=cronjob/plane-backup plane-backup-manual-1`,Job `Completed`
|
||||
- [ ] `/var/backups/plane/pg/plane-*.dump` 可被 `pg_restore -l` 列出
|
||||
- [ ] 备份 Job 只依赖 pgdb 服务,不依赖 Plane 应用 Pod(应用故障期间也能出备份)
|
||||
- [ ] 保留清理 dry-run(`find ... -print`)正确;`df -h /` 前后对比记录
|
||||
|
||||
## 局限 / 阻塞
|
||||
|
||||
- **本地方案不是离机备份**:单节点磁盘/整机故障即丢。如日后要离机,纳入
|
||||
[Restic 异机 repository 决策与存取隔离](https://plane.chans.xyz/space/projects/56874283-7e1d-43a8-afa4-631cf1c4ad5b/issues/7825d564-ae15-446b-bced-be26b648346b/)
|
||||
(与 Matrix 备份同一决策);恢复演练纪律见
|
||||
[服务级 restore runbook 与隔离复元演练](https://plane.chans.xyz/space/projects/56874283-7e1d-43a8-afa4-631cf1c4ad5b/issues/a9bea3ba-c958-4a74-b2f1-6bbb653f21d3/)。
|
||||
- 提醒:同一节点 **Matrix 数据价值远高于 Plane 且同样无备份** —— 若投入备份精力,顺序上 Matrix 优先。
|
||||
@@ -0,0 +1,63 @@
|
||||
# Plane CE PostgreSQL backup CronJob — DRAFT (2026-09-03), NOT applied.
|
||||
# ns: plane (synapse K3s single node). Output: hostPath /var/backups/plane (root disk, auto-created).
|
||||
#
|
||||
# Scope decision (2026-09-03, practical): DB-only. MinIO dropped — uploads bucket
|
||||
# measured at 264 KB / 444 KB total; attachments are acceptable loss for this
|
||||
# personal 1-user instance (310 issues / 88 MB DB). Revisit only if usage grows.
|
||||
#
|
||||
# Credentials: read from the CURRENT chart-generated Secret (works today). After the
|
||||
# optional external-secrets migration (docs/plane-hardening/README.md Phase A) switch
|
||||
# the secretKeyRef name to plane-pgdb-credentials.
|
||||
#
|
||||
# Apply:
|
||||
# ssh windy@synapse.chans.xyz 'sudo k3s kubectl apply -n plane -f -' < plane-backup.yaml
|
||||
# Manual run + verify:
|
||||
# sudo k3s kubectl -n plane create job --from=cronjob/plane-backup plane-backup-manual-1
|
||||
# sudo k3s kubectl -n plane get cronjob,job,pods | grep plane-backup
|
||||
# sudo ls -lh /var/backups/plane/pg
|
||||
# Restore steps + tuning: see backup/README.md
|
||||
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: plane-backup
|
||||
namespace: plane
|
||||
spec:
|
||||
# 01:30 UTC daily = 03:30 local (CEST). CronJob controller runs in UTC.
|
||||
schedule: "30 1 * * *"
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 2
|
||||
jobTemplate:
|
||||
spec:
|
||||
backoffLimit: 2
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
volumes:
|
||||
- name: backup
|
||||
hostPath:
|
||||
path: /var/backups/plane
|
||||
type: DirectoryOrCreate
|
||||
containers:
|
||||
- name: pg-dump
|
||||
image: postgres:15.7-alpine
|
||||
env:
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: plane-app-pgdb-secrets # -> plane-pgdb-credentials after Phase A
|
||||
key: POSTGRES_PASSWORD
|
||||
command: ["/bin/sh", "-c"]
|
||||
args:
|
||||
- |
|
||||
set -euo pipefail
|
||||
TS=$(date -u +%Y%m%dT%H%M%SZ)
|
||||
mkdir -p /backup/pg
|
||||
pg_dump -h plane-app-pgdb.plane.svc.cluster.local -U plane -d plane \
|
||||
-Fc -f "/backup/pg/plane-${TS}.dump"
|
||||
find /backup/pg -type f -name 'plane-*.dump' -mtime +7 -delete
|
||||
echo "pg_dump done: /backup/pg/plane-${TS}.dump ($(du -h /backup/pg/plane-${TS}.dump | cut -f1))"
|
||||
volumeMounts:
|
||||
- name: backup
|
||||
mountPath: /backup
|
||||
Reference in New Issue
Block a user