生产环境

部署

从一个开发用的 standalone 实例到一个生产集群,需要做四个决定:密钥放在哪、跑几个控制平面节点、日志去哪、怎么升级。本页一一过。

生产加固

有两个配置字段带不能跨重启幸存的开发友好回退。上线前显式设定它们。

KEK —— 静态加密密钥

crypto:
  kek_file: "/etc/tiyi/kek.bin"     # 32 字节静态密钥

所有信封加密的 blob(TLS 私钥、ACME 账户密钥、ACME DNS provider 凭据、bundle 签名密钥)用这个 KEK 解密。生成一次并备份到 state 数据库旁边:

$ install -m 0600 /dev/null /etc/tiyi/kek.bin
$ head -c 32 /dev/urandom > /etc/tiyi/kek.bin

丢失 KEK 等于丢失所有加密 blob。把它备份到 state.db 同处。轮换 KEK 需要重包所有加密 blob —— v3.0.0-rc.1 暂不支持。

另:如果不显式配置 crypto.kek_file,Tiyi 在首次启动时会在 <state-db-dir>/kek.bin 自动生成。这对单机开发足够,但在 state 目录可能短暂的生产环境很脆弱。

JWT 签名密钥

auth:
  jwt_secret: "<32+ 字节随机>"     # 或通过 TIYI_AUTH_JWT_SECRET 环境变量

Access token 的 HS256 签名密钥。字段为空时,Tiyi 在每次重启时生成 32 字节临时密钥,并打印 WARNING。会话在重启时失效,副本之间不能共享 refresh token —— 在生产中通常都是问题。

Bundle 签名密钥

服务端的 ed25519 配置签名密钥落在 bundle_signing_key 单例行,使用 KEK 信封加密。节点首次接入时固定公钥(TOFU),之后拒绝重新固定。轮换需要重新入网 —— 用 tiyi agents issue-token 签新 token,把节点重新拉起。

HA 故障转移

Tiyi 集群可以只有一个主节点 + N 个节点(零热备也允许)。规模较大的部署建议跑一个热备,主节点宕机时不至于长时间不能写。

拓扑

# 全部四个节点都代理流量。L4/L7 LB 在每个节点上轮询 /healthz。
$ TOKEN_B="$(tiyi agents issue-token --tag secondary | jq -r .token)"
$ TOKEN_C="$(tiyi agents issue-token --tag edge-c | jq -r .token)"

Node A: tiyi server     --addr 0.0.0.0:8080
Node B: tiyi secondary  --primary-api http://A:8080 --enrollment-token $TOKEN_B
Node C: tiyi agent      --api http://A:8080 --enrollment-token $TOKEN_C

提主

Node A 宕机,在 Node B 上跑 tiyi promote。两阶段切换避免脑裂:

  1. 通过 SystemService.Demote 联系老主节点 —— 主节点切换为只读,返回当前 epoch 与最后一次写序号。
  2. 验证备节点已经追到了主节点最后的序号。如果落后则放弃。
  3. 在备节点上自增 epoch(primary_epoch + 1),切换角色为主,接受写入。
  4. 老主节点的嵌入式节点重新连接到新主节点,变成普通节点。

主节点确认不可达时,tiyi promote --force 跳过 demote。你接受最后一次 bundle 同步到主节点失败之间的写丢失。如果老主节点回来,看到节点报告了更高 epoch 会自动降级为节点。

Epoch 隔离避免脑裂。每一次写入检查本地 epoch;任何节点收到 state 报告中的更高 epoch 会自动降级。Epoch 单调递增,持久化在 cluster_state

客户端 IP 信任配置

Tiyi 在 CDN 或 L4 LB 后时,到达 WAF 的客户端 IP 不是真实 IP —— 那是前面的代理。信任配置告诉 Tiyi 哪些代理可信、哪个 header 携带真实 IP。

从 UI(设置 → 信任配置标签)或 CLI 设置一次:

$ tiyi trust set \
    --trusted-proxies 10.0.0.0/8,172.16.0.0/12 \
    --client-ip-headers X-Forwarded-For

# 自动拉取 CDN 段:
$ tiyi trust cdn list
$ tiyi trust cdn refresh cloudflare
$ tiyi trust cdn refresh fastly

# 把任意 (peer, headers) 元组回溯到解析后的客户端 IP:
$ tiyi trust test --peer 10.0.0.5 --header "X-Forwarded-For: 1.2.3.4, 10.0.0.5"

默认开启的 Origin Bypass Attempt 告警在请求通过 XFF 声称客户端 IP 但 peer 不是受信任代理时触发。

SIEM 转发

Tiyi 把安全、访问、错误、(可选)审计事件以 RFC 5424、CEF 或 LEEF 通过尽力的 TCP / UDP / unixgram 转发出去。从 设置 → SIEM 标签 或 CLI 配置一次:

$ tiyi system settings update --key siem.enabled --value true
$ tiyi system settings update --key siem.address --value "tcp://siem.internal:514"
$ tiyi system settings update --key siem.format --value rfc5424
$ tiyi system settings update --key siem.filter.include_audit --value true

SIEM 转发是有意尽力的。接收端健康、可靠投递、回放属于 SIEM 管道,而不是 Tiyi。转发器为每个 dispatcher 缓存一条 net.Conn,出错时重连。

可观测性

滚动升级

导入二进制 release 后,tiyi release applyAPPLY_BINARY 命令散到所有 OS/arch 匹配的节点。每个节点下载替换、校验 SHA-256,然后退出让 supervisor 重启进入新二进制。

$ tiyi release import --tarball ./tiyi-3.0.1.tar.gz
$ tiyi release list
$ tiyi release apply <release-id>             # 所有匹配节点
$ tiyi release apply <release-id> --agent-id A  # 灰度部署
$ tiyi release runs                          # 进行中的滚动
$ tiyi release rollback                      # 回滚到上一个二进制

备份

有三样东西要备份:

支持(并推荐)Litestream 风格的 WAL 流式异地备份。logs/ 分区文件不属于备份集 —— 它们是有自己保留循环的运营数据。

上线检查表

  • crypto.kek_file 设为已备份的文件
  • auth.jwt_secret 设为 32+ 字节随机值
  • 用真实账号替换引导管理员密码
  • 如果 Tiyi 在 CDN/LB 后,配置信任配置
  • 选定一个 SIEM 目的地并验证测试事件能落地
  • /healthz 接到 L4/L7 LB
  • 从 Prometheus 抓取 /metrics
  • state.db + kek.bin 加入备份管道
  • 至少签发一个备节点,这样单主丢失不致命
  • 校验审计链:tiyi audit verify-chain 退出 0