# 工作台与 Manager 内部配置运维说明 更新时间:2026-09-17 ## 1. 背景 `im_workbench` 需要从 `im_manager` 读取系统配置,例如: - `im.uid_encryption_key` 读取链路如下: ```text im_workbench -> GET https://admin.118im.com/internal/im-config/third-party/im?keys=uid_encryption_key,UID_ENCRYPTION_KEY,uid_key -> im_manager 校验 HMAC 签名 -> 返回系统配置 ``` 这个接口是服务间内部接口,不是普通前端接口。调用方必须带 HMAC 请求头: ```http X-Service-Name: im-workbench X-Timestamp: X-Nonce: X-Signature: ``` 签名使用的密钥来自 `im_manager` 测试环境 Secret 中的: ```text manager-system / im-manager-secrets / IM_CONFIG_API_SECRET ``` 注意:不要把真实密钥写进 Git 文档或代码。 ## 2. 为什么 .env 不生效 测试环境运行在 Kubernetes Pod 中,服务启动时不会自动读取仓库里的 `.env` 文件。 当前代码和启动方式是: - `im_workbench` 只读取进程环境变量和 `IM_WORKBENCH_CONFIG` 指向的 JSON 配置文件。 - `im_manager` 的 entrypoint 使用 Pod 环境变量做 `envsubst` 生成 `config.yaml`。 - 两个服务都没有 `godotenv.Load()`、`source .env` 或 docker compose `env_file` 逻辑。 所以测试环境真正生效的是: ```text Kubernetes Secret / Deployment 环境变量 ``` 不是仓库中的 `.env`。 ## 3. 当前 Kubernetes 配置关系 ### im_workbench 命名空间: ```text workbench-system ``` Deployment: ```text im-workbench ``` 当前 Pod 里只显式注入: ```text IM_WORKBENCH_CONFIG=/etc/im-workbench/workbench.json ``` `/etc/im-workbench/workbench.json` 来自: ```text workbench-system / im-workbench-secrets / workbench.json ``` 因此 workbench 的运行时配置要改这个 Secret 里的 `workbench.json`,或在 Deployment 里显式加环境变量。 ### im_manager 命名空间: ```text manager-system ``` Deployment: ```text im-manager ``` Secret: ```text manager-system / im-manager-secrets ``` 其中和内部配置接口相关的 key: ```text IM_CONFIG_API_SERVICE_NAME IM_CONFIG_API_SECRET ``` ## 4. 必须配置什么 ### 4.1 im_manager 需要允许 im_workbench 调配置接口 `im_manager` 的 `IM_CONFIG_API_SERVICE_NAME` 需要支持两个调用方: ```text im-server,im-workbench ``` 原因: - `im_server` 也需要读取 manager 配置。 - `im_workbench` 也需要读取 manager 配置。 - 如果只配置 `im-workbench`,会影响 `im_server`。 - 如果只配置 `im-server`,`im_workbench` 用正确 service name 调用会 401。 目标配置: ```text IM_CONFIG_API_SERVICE_NAME=im-server,im-workbench ``` `IM_CONFIG_API_SECRET` 保持现有值,不要改成空,也不要泄露到日志或文档。 ### 4.2 im_workbench 需要配置 manager 连接信息 `workbench.json` 中需要有: ```json { "manager": { "base_url": "https://admin.118im.com", "service_name": "im-workbench", "secret": "<填 manager-system/im-manager-secrets 中的 IM_CONFIG_API_SECRET>", "uid_key_group": "im", "uid_key_keys": [ "uid_encryption_key", "UID_ENCRYPTION_KEY", "uid_key" ], "timeout_ms": 3000 } } ``` 也可以不用改 JSON,改成 Deployment 环境变量: ```text IM_WORKBENCH_MANAGER_BASE_URL=https://admin.118im.com IM_WORKBENCH_MANAGER_SERVICE_NAME=im-workbench IM_WORKBENCH_MANAGER_SECRET=<填 manager-system/im-manager-secrets 中的 IM_CONFIG_API_SECRET> ``` 建议优先统一放到 `workbench.json`,因为当前 workbench 已经通过 Secret 挂载 JSON 配置。 ## 5. 推荐操作流程 ### 步骤 1:更新 manager Secret 将: ```text manager-system / im-manager-secrets / IM_CONFIG_API_SERVICE_NAME ``` 改为: ```text im-server,im-workbench ``` `IM_CONFIG_API_SECRET` 保持现有值。 ### 步骤 2:更新 workbench Secret 从: ```text manager-system / im-manager-secrets / IM_CONFIG_API_SECRET ``` 取值,写入: ```text workbench-system / im-workbench-secrets / workbench.json ``` 目标字段: ```json { "manager": { "base_url": "https://admin.118im.com", "service_name": "im-workbench", "secret": "" } } ``` ### 步骤 3:重启服务 更新 Secret 后需要重启 Pod,确保进程重新读取配置。 建议顺序: ```text 1. 重启 im-manager 2. 重启 im-workbench ``` 原因: - 先让 manager 支持 `im-workbench` service name。 - 再让 workbench 使用 `im-workbench` service name 去调用 manager。 ## 6. 验证方法 ### 6.1 验证 manager 是否接受 im-workbench 用 `IM_CONFIG_API_SECRET` 对请求签名,请求: ```text GET https://admin.118im.com/internal/im-config/third-party/im?keys=uid_encryption_key,UID_ENCRYPTION_KEY,uid_key X-Service-Name: im-workbench ``` 期望结果: ```json { "code": 0, "data": { "values": { "uid_encryption_key": "..." } } } ``` 如果返回 401,重点检查: - `IM_CONFIG_API_SERVICE_NAME` 是否包含 `im-workbench` - 请求里的 `X-Service-Name` 是否是 `im-workbench` - `IM_CONFIG_API_SECRET` 是否和 manager 当前 Secret 一致 - 签名文本是否为: ```text METHOD RequestURI BodySHA256 Timestamp Nonce ``` ### 6.2 验证 workbench 是否加载到 manager 配置 进入 workbench Pod 看环境和配置摘要,注意不要打印真实 secret: ```bash kubectl -n workbench-system exec -- sh -c 'env | grep IM_WORKBENCH_MANAGER' ``` 或查看挂载配置: ```bash kubectl -n workbench-system exec -- sh -c 'cat /etc/im-workbench/workbench.json' ``` 检查: ```text manager.base_url = https://admin.118im.com manager.service_name = im-workbench manager.secret 非空 ``` ### 6.3 验证业务接口 从 IM 登录获取 token 后,请求 workbench 接口: ```http GET https://api.118im.com/v1/workbench Authorization: Bearer X-MeetingIM-APIKey: X-IM-Schema: 1 X-Tenant-Code: ``` 期望: ```json { "code": 0 } ``` 再创建会议,确认 user id 编解码和展示名正常: ```http POST https://api.118im.com/v1/workbench/meetings Idempotency-Key: Authorization: Bearer X-MeetingIM-APIKey: X-IM-Schema: 1 X-Tenant-Code: Content-Type: application/json ``` 请求体示例: ```json { "title": "运维验证会议", "start_at": "2026-09-18T08:00:00Z", "end_at": "2026-09-18T09:00:00Z", "location": "", "recorder_user_id": "usr...", "attendee_user_ids": ["usr..."], "reminder_minutes": [] } ``` 期望: ```json { "code": 0, "data": { "state": "scheduled", "organizer": { "user_id": "usr...", "display_name": "..." }, "participant_names": ["..."] } } ``` ## 7. 常见问题 ### 7.1 为什么不能从 manager 读取 manager secret 因为 `IM_CONFIG_API_SECRET` 是调用 manager 配置接口的 HMAC 引导凭证。 如果要读取 manager 配置接口,必须先有这个 secret 才能签名。 所以它不能从同一个 manager 配置接口中获取,只能来自部署环境,例如 Kubernetes Secret。 ### 7.2 为什么 service name 不是 im-server `X-Service-Name` 表示调用方服务名。 - `im_server` 调 manager 时,应使用 `im-server` - `im_workbench` 调 manager 时,应使用 `im-workbench` manager 侧应该允许多个合法调用方: ```text im-server,im-workbench ``` ### 7.3 为什么配置了 .env 还是没用 因为 Kubernetes 不会自动读取仓库 `.env`。 `.env` 只有在以下情况才会生效: - 程序代码主动 `godotenv.Load()` - 启动脚本 `source .env` - docker compose 配了 `env_file` - CI/CD 将 `.env` 内容写进 Deployment 或 Secret 当前测试环境都不是这些方式。 ### 7.4 只改 workbench 会怎样 如果只把 workbench 改成: ```text X-Service-Name: im-workbench ``` 但 manager 仍然只允许: ```text IM_CONFIG_API_SERVICE_NAME=im-server ``` 那么 workbench 调 manager 会返回 401。 所以需要 manager 和 workbench 一起配置。 ## 8. 最终配置清单 manager: ```text Namespace: manager-system Secret: im-manager-secrets IM_CONFIG_API_SERVICE_NAME=im-server,im-workbench IM_CONFIG_API_SECRET=<保持现有值> ``` workbench: ```text Namespace: workbench-system Secret: im-workbench-secrets Key: workbench.json ``` `workbench.json`: ```json { "manager": { "base_url": "https://admin.118im.com", "service_name": "im-workbench", "secret": "", "uid_key_group": "im", "uid_key_keys": [ "uid_encryption_key", "UID_ENCRYPTION_KEY", "uid_key" ], "timeout_ms": 3000 } } ```