eventRT/deploy/deploy.md

484 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 项目部署指南
本项目依赖 `MongoDB`(事件持久化存储)与 `RabbitMQ`mTLS 消息队列),并通过 `OpenTelemetry + Jaeger` 完成链路追踪。
## 前提条件
1. 已安装 `Docker``kubectl`
2. `Minikube` 集群已启动并可访问
3. 确保以下端口在宿主机上未被占用:`27017`MongoDB、`5671`RabbitMQ AMQP
---
### 1\. 部署 MongoDB 数据库Docker
使用官方 `mongo:7.0` 镜像,在 Ubuntu 宿主机(`192.168.1.101`)上以 Docker 容器运行。
#### 1.1 部署命令
```bash
docker run --name mongodb \
-e MONGO_INITDB_ROOT_USERNAME=coslight \
-e MONGO_INITDB_ROOT_PASSWORD=coslight@tj \
-p 27017:27017 \
-d mongo:7.0
```
#### 1.2 连接信息
| 参数 | 值 | 说明 |
| :--- | :--- | :--- |
| **容器名称** | `mongodb` | 容器名 |
| **镜像版本** | `mongo:7.0` | MongoDB 7.0 |
| **主机端口** | `27017` | 外部应用连接端口 |
| **用户名** | `coslight` | Root 管理员 |
| **密码** | `coslight@tj` | 启动时通过 `MONGO_INITDB_ROOT_USERNAME` 设置 |
| **鉴权数据库** | `admin` | `auth_db` |
| **业务数据库** | `eventdb` | EventRT 事件存储库 |
#### 1.3 状态检查
```bash
# 检查容器启动状态
docker ps -a | grep mongodb
# 检查启动日志
docker logs mongodb
```
#### 1.4 初始化 eventdb 数据库
MongoDB 启动后进入容器,为 `eventdb` 库授权:
```bash
docker exec -it mongodb mongosh \
-u coslight -p coslight@tj --authenticationDatabase admin
```
`mongosh` 中执行:
```javascript
// 切换到 eventdb若不存在则自动创建
use eventdb
// 授予 coslight 用户对 eventdb 的读写权限(根用户已有全库权限,此步可选)
db.createUser({
user: "coslight",
pwd: "coslight@tj",
roles: [{ role: "readWrite", db: "eventdb" }]
})
```
---
### 2\. 部署 RabbitMQKubernetes
RabbitMQ 配置为仅允许 TLS 连接(`listeners.tcp = none`),所有客户端须持有由同一 CA 签发的证书。YAML 文件位于 `deploy/mq/`
#### 2.1 TLS 证书生成
##### 2.1.1 生成根 CA
```bash
git clone https://github.com/rabbitmq/tls-gen.git
cd tls-gen/basic
# 生成根 CA结果输出至 result/
make CN=rabbitmq-server
# ca_certificate.pem 与 ca_key.pem即 cakey.pem生成于 result/
```
##### 2.1.2 生成服务端证书
服务端证书需包含 SAN使其同时匹配集群内 DNS 和 Minikube IP。使用 `deploy/mq/server.conf`(已预置正确配置):
```bash
# 将 ca_certificate.pem 和 cakey.pem 放在当前目录
openssl genrsa -out server_key.pem 2048
openssl req -new -key server_key.pem \
-out server_cert.csr -config deploy/mq/server.conf
openssl x509 -req -in server_cert.csr \
-CA ca_certificate.pem -CAkey cakey.pem -CAcreateserial \
-out server_certificate.pem -days 730 -sha256 \
-extfile deploy/mq/server.conf -extensions v3_server
rm server_cert.csr
```
##### 2.1.3 生成 EventRT 客户端证书
CN 必须与 RabbitMQ 中注册的用户名一致(`eventrt-client`)。使用 `deploy/mq/eventrt.conf`
```bash
openssl genrsa -out eventrt_client_key.pem 2048
openssl req -new -key eventrt_client_key.pem \
-out eventrt_client.csr -config deploy/mq/eventrt.conf
openssl x509 -req -in eventrt_client.csr \
-CA ca_certificate.pem -CAkey cakey.pem -CAcreateserial \
-out eventrt_client_cert.pem -days 365 \
-extensions v3_client -extfile deploy/mq/eventrt.conf
rm eventrt_client.csr
```
##### 2.1.4 生成 ModelRT 客户端证书
使用 `deploy/mq/modelrt.conf`CN 为 `modelrt-client`
```bash
openssl genrsa -out modelrt_client_key.pem 2048
openssl req -new -key modelrt_client_key.pem \
-out modelrt_client.csr -config deploy/mq/modelrt.conf
openssl x509 -req -in modelrt_client.csr \
-CA ca_certificate.pem -CAkey cakey.pem -CAcreateserial \
-out modelrt_client_cert.pem -days 365 \
-extensions v3_client -extfile deploy/mq/modelrt.conf
rm modelrt_client.csr
```
##### 2.1.5 验证证书
```bash
# 验证服务端证书
openssl verify -CAfile ca_certificate.pem server_certificate.pem
# 验证客户端证书
openssl verify -CAfile ca_certificate.pem eventrt_client_cert.pem
openssl verify -CAfile ca_certificate.pem modelrt_client_cert.pem
# 确认 CN 和扩展clientAuth / serverAuth
openssl x509 -in server_certificate.pem -noout -subject -ext subjectAltName
openssl x509 -in eventrt_client_cert.pem -noout -subject -text | grep -A1 "Extended Key Usage"
openssl x509 -in modelrt_client_cert.pem -noout -subject
```
#### 2.2 部署 RabbitMQ
##### 2.2.1 创建证书 Secret
在证书文件所在目录执行:
```bash
sh deploy/mq/secert.sh
```
该脚本等价于:
```bash
kubectl create secret generic rabbitmq-certs \
--from-file=ca_certificate.pem=./certs/ca_certificate.pem \
--from-file=server_certificate.pem=./certs/server_certificate.pem \
--from-file=server_key.pem=./certs/server_key.pem
```
##### 2.2.2 部署
```bash
kubectl apply -f deploy/mq/rabbitmq-secret.yaml
kubectl apply -f deploy/mq/rabbitmq-users-config.yaml
kubectl apply -f deploy/mq/rabbitmq-config.yaml
kubectl apply -f deploy/mq/rabbitmq-deployment.yaml
kubectl apply -f deploy/mq/rabbitmq-service.yaml
```
##### 2.2.3 端口汇总
| 端口 | NodePort | 说明 |
| :--- | :--- | :--- |
| `5671` | `30671` | AMQP over TLS客户端连接 |
| `5672` | `30672` | AMQP 明文(内部备用,生产禁用) |
| `15671` | `31671` | Management UI over TLS |
| `15672` | `31672` | Management UI 明文(内部备用) |
##### 2.2.4 用户与权限说明
用户定义在 `rabbitmq-users-config.yaml``definitions.json` 中,启动时通过 `load_definitions` 自动加载:
| 用户 | 认证方式 | 权限 | 说明 |
| :--- | :--- | :--- | :--- |
| `coslight` | 密码 | administrator | 管理员,密码在 `rabbitmq-secret.yaml` |
| `eventrt-client` | X.509 证书CN | configure/read/write | EventRT 服务专用 |
| `modelrt-client` | X.509 证书CN | configure/read/write | ModelRT 服务专用 |
| `web-client` | X.509 证书CN | read/write | Web 客户端 |
> **注意:** 证书认证用户的 `password_hash` 留空RabbitMQ 通过 `ssl_cert_login_from = common_name` 将证书 CN 映射为用户名。
---
### 3\. 部署 EventRTKubernetes
所有资源部署在 `default` 命名空间YAML 文件位于 `deploy/k8s/`
#### 3.1 构建并推送镜像
镜像采用三阶段构建,最终基于 `scratch`
| 阶段 | 基础镜像 | 作用 |
| :--- | :--- | :--- |
| **builder** | `golang:1.26-alpine` | 编译 Go 二进制(`CGO_ENABLED=0``-trimpath -ldflags="-s -w"` |
| **certs** | `alpine:3.21` | 提取 CA 证书、时区数据及非 root 用户定义UID 默认 `1000` |
| **runtime** | `scratch` | 仅含可执行文件与运行时依赖,无 shell、无包管理器 |
**方式一:从源码构建并加载**
```bash
# 在项目根目录执行(默认运行用户 UID=1000
docker build -f deploy/dockerfile/eventrt.Dockerfile -t coslight/eventrt:latest .
# 自定义运行用户 UID
docker build -f deploy/dockerfile/eventrt.Dockerfile \
--build-arg USER_ID=2000 \
-t coslight/eventrt:latest .
# 加载到 Minikube无需私有仓库
minikube image load coslight/eventrt:latest
```
**方式二:直接加载已有本地镜像**
Ubuntu 宿主机上已存在构建好的镜像(如 `eventrt:v1`)时,无需重新构建,直接导入 Minikube
```bash
# 确认本地镜像存在
docker images eventrt:v1
# 加载到 Minikube
minikube image load eventrt:v1
# 验证镜像已进入 Minikube 缓存
minikube image ls | grep eventrt
```
> **注意:** `deploy/k8s/eventrt-deployment.yaml` 中的 `image` 字段需与加载的镜像名称一致,并将 `imagePullPolicy` 设为 `Never`,防止 Minikube 尝试从远端拉取。
#### 3.1.1 镜像冒烟测试
```bash
# 查看镜像大小scratch 镜像预期 ≤ 25 MB
docker images coslight/eventrt:latest
# 检查镜像元信息(确认 User、Cmd、架构
docker inspect coslight/eventrt:latest
# 验证二进制可执行(无 config 时程序报错退出属预期行为,说明镜像构建正常)
docker run --rm coslight/eventrt:latest
# 挂载示例配置做完整启动验证Ctrl+C 退出)
docker run --rm \
-v "$(pwd)/configs/config.example.yaml:/app/configs/config.yaml" \
-p 8081:8081 \
coslight/eventrt:latest
```
> **注意:** `scratch` 镜像不含 shell无法使用 `docker exec` 进入容器调试;如需排查问题,可临时将最终阶段改为 `alpine` 进行本地调试,确认后再切回 `scratch`。
#### 3.2 创建客户端证书 Secret
在 RabbitMQ TLS 证书生成完成后(见 2.1),进入证书文件所在目录执行:
```bash
kubectl create secret generic eventrt-certs \
--from-file=ca_certificate.pem=./ca_certificate.pem \
--from-file=eventrt_client_cert.pem=./eventrt_client_cert.pem \
--from-file=eventrt_client_key.pem=./eventrt_client_key.pem
```
#### 3.3 部署
```bash
kubectl apply -f deploy/k8s/eventrt-secret.yaml
kubectl apply -f deploy/k8s/eventrt-configmap.yaml
kubectl apply -f deploy/k8s/eventrt-deployment.yaml
kubectl apply -f deploy/k8s/eventrt-service.yaml
```
#### 3.4 配置说明
| 配置项 | 方式 | 说明 |
| :--- | :--- | :--- |
| `mongodb.password` | Secret `eventrt-secret` | 不写入 ConfigMap通过环境变量 `MONGODB_PASSWORD` 注入 |
| `service.secret_key` | Secret `eventrt-secret` | 不写入 ConfigMap通过环境变量 `SERVICE_SECRET_KEY` 注入 |
| RabbitMQ 客户端证书 | Secret `eventrt-certs` | 挂载至 `/app/configs/certs/` |
| `config.yaml` 其余配置 | ConfigMap `eventrt-config` | `rabbitmq.host` 已设为 K8s Service 名 `rabbitmq-service` |
| `K8S_NAMESPACE` / `K8S_NODE_NAME` | Downward API | 注入至日志全局字段 |
#### 3.5 状态检查
```bash
# 查看 Pod 状态
kubectl get pods -l app=eventrt
# 查看启动日志
kubectl logs -l app=eventrt --tail=50
# 查看 Service
kubectl get svc eventrt-service
```
#### 3.6 端口汇总
| NodePort | 说明 |
| :--- | :--- |
| `30081` | EventRT HTTP API |
#### 3.7 清理
```bash
kubectl delete -f deploy/k8s/eventrt-service.yaml \
-f deploy/k8s/eventrt-deployment.yaml \
-f deploy/k8s/eventrt-configmap.yaml \
-f deploy/k8s/eventrt-secret.yaml
kubectl delete secret eventrt-certs
```
---
### 4\. Mac 本地访问SSH 隧道)
`EventRT` 在 Mac 本地运行时RabbitMQ 部署在 Ubuntu 宿主机(`192.168.1.101`)的 Minikube 中MongoDB 直接运行在宿主机上。需通过 SSH 本地端口转发建立访问隧道。
#### 4.1 网络拓扑
```text
Mac 本地端口 ──SSH隧道──▶ Ubuntu 宿主机 (192.168.1.101) ──▶ Minikube NodePort (192.168.49.2)
└──▶ MongoDB Docker (宿主机 27017)
```
#### 4.2 建立隧道
```bash
ssh -L 27017:127.0.0.1:27017 \
-L 5671:192.168.49.2:30671 \
-L 15671:192.168.49.2:31671 \
-L 4318:192.168.49.2:31318 \
-L 16686:192.168.49.2:31686 \
douxu@192.168.1.101
```
如需后台静默运行(不占用终端):
```bash
ssh -fN \
-L 27017:127.0.0.1:27017 \
-L 5671:192.168.49.2:30671 \
-L 15671:192.168.49.2:31671 \
-L 4318:192.168.49.2:31318 \
-L 16686:192.168.49.2:31686 \
douxu@192.168.1.101
```
#### 4.3 端口映射说明
| Mac 本地端口 | 目标 | 服务 | 说明 |
| :--- | :--- | :--- | :--- |
| `27017` | 宿主机 `127.0.0.1:27017` | MongoDB | EventRT 事件数据库 |
| `5671` | Minikube `192.168.49.2:30671` | RabbitMQ AMQP | 消息队列 mTLS 连接 |
| `15671` | Minikube `192.168.49.2:31671` | RabbitMQ Management | 管理界面 `http://localhost:15671` |
| `4318` | Minikube `192.168.49.2:31318` | OTLP HTTP | OTel Trace 上报Jaeger Collector |
| `16686` | Minikube `192.168.49.2:31686` | Jaeger UI | 链路追踪查询 `http://localhost:16686` |
> **注意:** 隧道建立后,本地 `config.yaml` 中所有服务地址填 `localhost:<本地端口>` 即可直接运行服务。
#### 4.4 关闭隧道
前台运行时直接 `Ctrl+C`;后台运行时查找并终止进程:
```bash
# 找到 ssh 隧道进程
ps aux | grep "ssh -fN"
# 终止(替换为实际 PID
kill <PID>
```
---
### 5\. 本地开发配置config.yaml
`configs/config.example.yaml` 复制为 `configs/config.yaml` 并按以下说明调整:
#### 5.1 配置参数说明
| 类别 | 参数名 | 作用描述 | 示例值 |
| :--- | :--- | :--- | :--- |
| **MongoDB** | `host` | MongoDB 服务器地址 | `"localhost"` |
| | `port` | MongoDB 端口 | `27017` |
| | `user` | 连接用户名 | `"coslight"` |
| | `password` | 连接密码 | `"coslight@tj"` |
| | `database` | 业务数据库名 | `"eventdb"` |
| | `auth_db` | 鉴权数据库 | `"admin"` |
| | `timeout` | 连接超时(秒) | `10` |
| **RabbitMQ** | `host` | RabbitMQ 服务器地址 | `"localhost"` |
| | `port` | AMQP over TLS 端口 | `5671` |
| | `server_name` | TLS SNI / 证书 CN | `"rabbitmq-server"` |
| | `ca_cert_path` | CA 证书路径 | `"./configs/certs/ca_certificate.pem"` |
| | `client_cert_path` | 客户端证书路径 | `"./configs/certs/eventrt_client_cert.pem"` |
| | `client_key_path` | 客户端私钥路径 | `"./configs/certs/eventrt_client_key.pem"` |
| | `insecure_skip_verify` | 是否跳过证书校验(开发临时用) | `false` |
| **Logger (Zap)** | `mode` | 日志模式 `development` / `production` | `"development"` |
| | `level` | 最低日志级别 | `"debug"` |
| | `filepath` | 日志文件路径(空字符串输出到 stdout | `""` |
| | `maxsize` | 单文件最大大小MB | `1` |
| | `maxbackups` | 保留旧文件最大个数 | `5` |
| | `maxage` | 保留旧文件最大天数 | `30` |
| | `compress` | 是否压缩备份文件 | `false` |
| **Service** | `service_addr` | HTTP 监听地址 | `":8081"` |
| | `service_name` | 服务名(日志/监控标识) | `"eventRT"` |
| | `secret_key` | 内部签名密钥 | `"eventrt_key"` |
| | `deploy_env` | 部署环境 `development` / `production` | `"development"` |
| **OTel** | `endpoint` | OTLP HTTP 上报地址(不含协议前缀) | `"localhost:4318"` |
| | `insecure` | 是否不启用 TLS | `true` |
---
### 6\. 排查手册
#### 6.1 证书权限检查
确认客户端证书包含 `TLS Web Client Authentication`
```bash
openssl x509 -in configs/certs/eventrt_client_cert.pem -noout -text \
| grep -A1 "Extended Key Usage"
```
预期输出包含 `TLS Web Client Authentication`
#### 6.2 握手连通性验证
```bash
openssl s_client -connect localhost:5671 \
-cert configs/certs/eventrt_client_cert.pem \
-key configs/certs/eventrt_client_key.pem \
-CAfile configs/certs/ca_certificate.pem
```
预期结果:看到 `Verify return code: 0 (ok)`
#### 6.3 RabbitMQ 日志检查
连接成功后RabbitMQ 日志应出现:
```
connection <xxx>: user 'eventrt-client' authenticated and granted access to vhost '/'
```
查看 Pod 日志:
```bash
kubectl logs -l app=rabbitmq --tail=50 | grep eventrt-client
```
#### 6.4 MongoDB 连通性验证
```bash
mongosh "mongodb://coslight:coslight@tj@localhost:27017/eventdb?authSource=admin"
```
预期进入 `mongosh` 提示符,执行 `show collections` 无报错。