Appearance
私有化部署 — 交付基线与购机清单
面向采购客户机器的同事。规格由我们定 —— 这样兼容测试面才收敛,200 个客户跑的是同一种环境。
装好机器之后的部署由 nuwa 下发,chart 与排障看 Helm Chart 指南。
〇、先看时间线:备案是长杆项
采购本身半天就能点完,但有两件事排在前面,必须在合同签订当周就启动:
| 前置项 | 周期 | 谁做 |
|---|---|---|
| ICP 备案 | 1~3 周 | 客户(主体是客户,我们只能协助) |
| 域名注册/转入 | 1~3 天 | 客户 |
| 云账号实名认证 | 1 天 | 客户 |
| 买机器 + 装 | 半天 | 我们 |
域名解析到中国大陆境内的服务器,没有 ICP 备案就访问不了 80/443 —— 不是"可能被查",是云厂商在接入层直接拦。买了机器装完了,客户打不开页面,这是交付里最常见的"莫名其妙延期两周"。
用境外区域(AWS 新加坡/东京等)不需要备案,但要先确认客户接受数据出境与延迟。这是商务决定,不是技术决定。
一、先定部署形态,再买机器
买什么机器完全取决于走哪一种。签合同前就要问清楚客户有没有 DBA、愿不愿意为 RDS 付月费。
| 形态 A:全自建 | 形态 B:云托管中间件 | |
|---|---|---|
| MySQL | 集群内 Pod + 云盘 | RDS |
| Redis / RabbitMQ | 集群内 | 云 Redis / 自建(见下) |
| 机器 | 1 台 8C16G | 1 台 4C16G + RDS |
| 月成本 | 低 | 高约 40%~80% |
| 数据可靠性 | 靠我们做备份 | 云厂商托管,多可用区 |
| 出事谁扛 | 我们 | 云厂商 |
| chart 配置 | 默认 | mysql.deploy: false + external.host |
默认推荐形态 B 的 MySQL 部分。 数据库是整个系统里唯一"丢了就完了"的组件,把它交给云厂商换来的是:不用自己做主从、不用自己盯磁盘、客户半夜删库能用云厂商的时间点恢复。多出来的月费远低于一次数据事故的代价。
RabbitMQ 反过来 —— 云托管版本各家差异大、价格贵,我们用得也浅(就是个可靠队列),留在集群内即可。Redis 两可,客户已有云 Redis 就用,没有就集群内。
形态之间可以后期切换,服务侧零改动(见 Chart 指南 §三),只需要一次数据迁移。所以拿不准时先上形态 A 也不算错。
二、容量怎么算出来的
规格不是拍脑袋。按 chart 里各服务实际声明的 requests 累加:
L1 底座(必装)
| 组件 | 副本 | CPU requests | 内存 requests |
|---|---|---|---|
| gateway | 2 | 400m | 1.0 Gi |
| public | 2 | 1000m | 2.0 Gi |
| admin-ui | 1 | 50m | 64 Mi |
| Nacos | 1 | 250m | 1.0 Gi |
| 小计 | 1.7 C | 4.1 Gi |
L2 业务应用:默认每个 200m / 512Mi requests、1Gi limit。整条 vem 链(user + finance + vem + socket)约 +0.8C / +2Gi requests,limits 到 4Gi。
再加上:k3s 系统组件(coredns / metrics-server / local-path)约 0.5C / 1Gi;形态 A 还要加集群内 MySQL + Redis + RabbitMQ,保守留 1.5C / 4Gi。
于是:
| 形态 | requests 合计 | 买 | 说明 |
|---|---|---|---|
| B(RDS) + 底座 | ~2.2C / 5.1Gi | 4C16G | 4C8G 装上两三个应用就开始 Pending |
| B + 全部应用 | ~3.5C / 9Gi | 8C16G | |
| A(集群内 MySQL) + 底座 | ~3.7C / 9.1Gi | 8C16G | |
| A + 全部应用 | ~5C / 13Gi | 8C32G |
内存永远比 CPU 先不够。 全是 JVM,CPU 大部分时间闲着,内存是硬占用。所以选**通用型(1:4)**而不是计算型(1:2)。
⚠️ chart 目前没有给三个 bitnami 子 chart 显式设置
resources,用的是 bitnami 自己的 preset。集群内 MySQL 在默认 preset 下对生产偏小。走形态 A 的客户,建议在客户 values 里显式压上mysql.primary.resources,别让它按默认值跑。
三、通用采购清单
不分云厂商,每个客户都要走一遍:
- [ ] ECS 一台,通用型(vCPU:内存 = 1:4),规格按上表
- [ ] OS:Ubuntu 22.04 LTS —— 三家云都有、k3s 一等公民。不要 CentOS / Alinux / Amazon Linux,k3s 在这些发行版上的问题排查成本不值得
- [ ] 系统盘 100G SSD(ESSD / SSD云硬盘 / gp3)
- [ ] 数据盘独立一块,挂
/data。不要合进系统盘 —— 重装系统时数据不丢,扩容也独立- 形态 A:200G 起(MySQL 数据 + 镜像 + 日志)
- 形态 B:100G 够(镜像 + 日志 + Nacos)
- [ ] 弹性公网 IP 一个,绑到 ECS
- [ ] VPC:ECS 与 RDS 必须同 VPC,RDS 走内网地址
- [ ] 安全组:仅开 22 / 80 / 443(详见 §六)
- [ ] 对象存储 Bucket 一个(OSS / COS / S3),存 mysqldump 备份,私有读写
- [ ] 形态 B 追加:RDS MySQL 8.0 高可用版,配置见 §五
- [ ] 不买 SLB / CLB / ALB —— k3s 自带 servicelb,
Service type=LoadBalancer直接绑节点 80/443 + 弹性 IP。每客户每月省数百元,单节点部署下负载均衡器没有意义
关于自动化开机器
原先按"3 个独立客户"判断不上 Terraform。2026-07-28 规模重估为每年 100~200 个独立部署(约每周 4 个),手工点购按理已经过线。
目前的决定是由专职同事按本清单采购,不做 IaC。这份 checklist 因此是硬约束而不是参考 —— 规格一旦漂移,200 个客户就是 200 种环境。
四、三家云对照
规格换算规则一样,只是叫法不同。认准"通用型 / 标准型,1:4",型号迭代了按这个规则找新的就行。
| 阿里云 | 腾讯云 | AWS | |
|---|---|---|---|
| 4C16G | ecs.g7.xlarge(通用型 g7) | S6.LARGE16(标准型 S6) | m6i.xlarge |
| 8C16G | ecs.c7.2xlarge(计算型) | C6.2XLARGE16 | c6i.2xlarge |
| 8C32G | ecs.g7.2xlarge | S6.2XLARGE32 | m6i.2xlarge |
| 云盘 | ESSD PL1 | 增强型SSD / SSD云硬盘 | gp3 |
| 数据库 | RDS MySQL 8.0 高可用版 | 云数据库 MySQL 8.0 高可用 | RDS MySQL 8.0 Multi-AZ |
| 对象存储 | OSS | COS | S3 |
| 镜像仓库 | ACR | TCR | ECR |
| 备份快照 | 自动快照策略 | 定期快照 | EBS Snapshot Lifecycle |
镜像怎么拉过去
我们的镜像在深圳的阿里云 ACR(registry.cn-shenzhen.aliyuncs.com/hiapi-cloud)。客户机器在哪,决定了走哪条路:
| 客户环境 | 拉法 |
|---|---|
| 阿里云,同地域(深圳) | 用 VPC 内网地址 registry-vpc.cn-shenzhen.aliyuncs.com,免公网流量费,快 |
| 阿里云,其它地域 | 公网地址,或开 ACR 跨地域同步 |
| 腾讯云 / AWS | 只能走公网地址;流量大时考虑同步一份到客户自己的 TCR / ECR |
| 完全无外网 | 必须提前把镜像同步进客户内网仓库,并改 global.imageRegistry。这种客户在报价阶段就要识别出来,交付工作量完全不同 |
⚠️
hiapi-cloud-public含 JNI 授权保护模块,任何情况下都不能推到公开仓库。admin-ui 可以公开,它不含保护逻辑。
五、MySQL 的硬要求
这一节最容易出事,建 RDS 时就要按这个填,建完再改代价很大。
| 项 | 要求 | 建完还能不能改 |
|---|---|---|
| 版本 | 8.0+ | — |
| 字符集 | utf8mb4 | 能,但已有表要逐个转 |
lower_case_table_names | 1 | ❌ 实例初始化后不可修改,填错只能重建实例 |
max_connections | ≥ 300 | 能 |
| 时区 | +08:00 | 能 |
| 账号权限 | 必须含 DDL | 能 |
为什么是 8.0+:各服务打包的是 mysql-connector-j 9.1.0,官方支持矩阵已不含 5.7。实测该驱动能连上 5.7.31,但不受官方支持,不写进交付基线。客户已有 5.7 实例想复用时,明确告知不支持。
为什么账号必须有 DDL 权限:各服务是 ddl-auto: update(Hibernate 启动时建表/加列),分表逻辑还会在运行时执行 CREATE TABLE ... LIKE。给一个只有增删改查权限的账号,服务起不来。 这一点常常和客户 DBA 的安全规范冲突,要在采购阶段就摊开谈,别等装的时候才发现。
这也是 P5 Flyway 改造存在的理由 —— 迁完之后就可以收权限了,但现在还不行。
max_connections 怎么算:每个服务实例一个 Druid 连接池,maxActive 用的是 Druid 默认值 8。全部应用装满约 10 个服务、十几个副本,再加 Nacos 自己的连接,300 足够,给 500 更稳。
建库
不用手工建。 chart 的 hiapi-db-init Job 会按这个客户实际开启的服务把业务库建出来(ddl-auto: update 只建表不建库,所以这一步必须有人做)。
只有一种情况要手工:客户 DBA 坚持自己建库、只给一个没有 CREATE 权限的账号。这时设 dbInit.enabled=false,并请对方按 values.yaml 里 enabled 服务的 db 字段执行:
sql
CREATE DATABASE IF NOT EXISTS hiapi_cloud_public DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS hiapi_cloud_user DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS hiapi_cloud_finance DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 其余按 values.yaml 里 enabled 的服务的 db 字段漏建的表现是该服务 CrashLoop、日志报 Unknown database 'xxx'。
⚠️ 即使库是 DBA 建的,账号仍然必须有 DDL 权限 —— 建表和运行时分表都要用到,这一条没有商量余地。
六、网络与安全组
公网 ──▶ 弹性 IP ──▶ ECS(k3s servicelb 占 80/443)──▶ Ingress ──▶ gateway / admin-ui
│
同 VPC 内网 ──▶ RDS / 云 Redis安全组只开三个端口:
| 端口 | 来源 | 用途 |
|---|---|---|
| 22 | 仅我们的运维出口 IP | SSH |
| 80 | 0.0.0.0/0 | HTTP(跳转 HTTPS) |
| 443 | 0.0.0.0/0 | HTTPS |
🔴 6443 绝不对公网开放。 那是 k3s 的 API Server,暴露出去等于把整个集群的控制权挂在公网上。运维走 SSH 隧道或客户的 VPN。
同理不开:3306 / 6379 / 5672 / 8848 / 15672。要连数据库就 SSH 隧道,要看 Nacos 控制台就 kubectl port-forward。
RDS 的白名单只加 ECS 的内网 IP,不加 0.0.0.0/0,也不开 RDS 公网地址。
七、备份是硬性交付物
不是"建议做",是交付验收项。 尤其形态 A —— 数据库在客户自己的机器上,除了我们没人管它。
两层,缺一不可:
| 层 | 做法 | 频率 | 保留 | 能恢复什么 |
|---|---|---|---|---|
| 云盘快照 | 云厂商自动快照策略 | 每天 | 7 天 | 整机回滚 |
mysqldump | CronJob → 对象存储 | 每天 | 30 天 | 单库、单表 |
只有快照没有 dump = 客户误删一张表时只能整机回滚,把这段时间里所有其它业务数据一起回滚掉。这个场景一定会发生。
形态 B 的客户,RDS 自带备份和时间点恢复,但仍然要做 dump 到我们能访问的对象存储 —— 客户注销云账号、欠费停机时,RDS 里的备份跟着一起没了。
八、开工前要从客户拿到的信息
买机器之前先把这张表填完,少一项就会在交付当天卡住:
| 项 | 例 | 缺了会怎样 |
|---|---|---|
| 云厂商 + 地域 | 阿里云 深圳 | — |
| 云账号(或子账号)+ 权限 | 能建 ECS/RDS/OSS | 买不了机器 |
| 访问域名 | admin.customer-a.com | Ingress host 填不了 |
| 域名是否已备案 | 是 / 否 + 备案号 | 见 §〇,可能延期两周 |
| SSL 证书 | 客户提供 / 我们签 Let's Encrypt | 只能先跑 HTTP |
| 购买了哪些应用 | user + finance + vem | 决定机器规格和依赖链 |
| 是否有外网 | 有 / 无 | 无外网时交付工作量翻倍 |
| 运维联系人 | 姓名/电话/微信 | 出事找不到人 |
| 客户是否有 DBA | 有 → 倾向形态 B | 决定形态 |
九、交付后要交接给客户的
- [ ] 管理后台地址 + 初始管理员账号密码(要求客户首次登录即改)
- [ ] 这套环境的资源清单(ECS / RDS / OSS 的实例 ID 与规格)
- [ ] 备份策略说明 + 一次真实的恢复演练记录
- [ ] 我们的运维出口 IP(客户改安全组时不要误删)
- [ ] 升级流程与窗口约定
- [ ] 支持渠道与响应时效
⚠️ 中间件密码不交给客户。 密码在 nuwa 里加密保管;客户要自行运维数据库时,单独给一个只读账号。
九点五、机器到手之后:装机
不要手敲 k3s 安装命令。 nuwa 下发的交付包里带 install-k3s.sh, 它顺带把本文档里这些要求做成了硬检查(不合格直接拦,而不是装完才发现):
bash
sudo ./install-k3s.sh # 一台机器只跑一次,幂等
sudo DATA_DIR=/data ./install-k3s.sh # 挂了数据盘就带上,别让 PVC 落在系统盘
sudo K3S_VERSION=v1.31.5+k3s1 ./install-k3s.sh # 按交付批次钉版本体检项对应本文:CPU/内存(§二,内存永远比 CPU 先不够)、磁盘、80/443/6443 占用、 发行版是否为基线的 Ubuntu 22.04、NTP 是否同步(授权票据带有效期,时钟偏了会 表现成"授权无效",而没人会往这个方向想)。
装完它会等到 traefik rollout 完成、默认 StorageClass 就位才算成功 —— 少等 traefik 就会出现"脚本说装完了,但域名还不通"。
用法与后续的 ./deploy.sh 见 nuwa 教程 §6.5。
十、常见踩坑
| 现象 | 原因 |
|---|---|
| 装完了域名打不开,IP 直连正常 | 域名没备案,被云厂商接入层拦了 |
Pod 一直 Pending,describe 说 Insufficient memory | 机器买小了。见 §二,内存永远比 CPU 先不够 |
服务起不来,Unknown database 'hiapi_cloud_xxx' | hiapi-db-init Job 没跑成功,或关了 dbInit.enabled 又没手工建库,见 §五 |
| 服务起不来,建表报权限错误 | 数据库账号没有 DDL 权限,见 §五 |
| RDS 表名大小写行为异常 | lower_case_table_names 建实例时没设成 1,只能重建实例 |
| 拉镜像特别慢 / 走了公网计费 | 阿里云同地域没用 registry-vpc. 内网地址 |
| 磁盘满了,系统盘 100% | 数据盘没挂 /data,或 local-path 还指在系统盘 |
| 客户说"我们有 5.7 实例能不能用" | 不支持,见 §五 |