后端服务部署¶
适用于所有环境。完成 Nginx 与网络配置 后执行。
部署架构¶
三个项目通过 CNB 流水线独立部署,共享同一台服务器和 Docker 网络 tfrs-net。
环境变量体系¶
环境变量分为两类,存放在 CNB 密钥仓库 turingfocus/build_env 中:
1. 部署凭证(按环境独立,每个环境一个文件)¶
| 文件 | 用途 |
|---|---|
tfrsmanager_deploy_ssh.yml |
Beta 服务器 SSH + Docker 凭证 |
tfrsmanager_deploy_ssh_staging.yml |
Staging 服务器 SSH + Docker 凭证 |
模板:
# 服务器 SSH 登录
PROD_SSH_HOST: "{服务器公网IP}"
PROD_SSH_PORT: "22"
PROD_SSH_USER: "deploy"
PROD_SSH_KEY: |
-----BEGIN RSA PRIVATE KEY-----
{deploy 用户的 SSH 私钥}
-----END RSA PRIVATE KEY-----
# Docker 镜像仓库凭证(CNB Registry)
PROD_DOCKER_USER: "{CNB 用户名}"
PROD_DOCKER_PASSWORD: "{CNB Token}"
注意: SSH 私钥需要在目标服务器上生成并添加到
deploy用户的authorized_keys。
2. 业务环境变量(按环境独立,区分沙箱/生产配置)¶
| 文件 | 用途 |
|---|---|
tfrsmanager_env.prod.yml |
Beta 后端业务变量 |
tfrsmanager_env.staging.yml |
Staging 后端业务变量 |
tfrs_user_portal.yaml |
Beta UserPortal 变量 |
tfrs_user_portal_staging.yaml |
Staging UserPortal 变量 |
tfrs_admin_portal.yaml |
Beta AdminPortal 变量 |
tfrs_admin_portal_staging.yaml |
Staging AdminPortal 变量 |
Staging 环境变量配置指南¶
TFRSManager 后端 (tfrsmanager_env.staging.yml)¶
以下变量需要用户手动配置。标记 ⚠️ 沙箱 的项目必须使用沙箱/测试环境配置,不得使用生产值。
# ===== 基础服务 =====
GIN_MODE: "release"
DB_HOST: "postgres" # Docker 容器名
DB_PORT: "5432"
DB_USER: "tfrs"
DB_PASSWORD: "{自行设置}"
DB_NAME: "tfrs_staging"
DB_DRIVER: "postgres"
DB_SSL_MODE: "disable"
REDIS_ADDR: "redis:6379" # Docker 容器名
REDIS_PASSWORD: "{自行设置}"
REDIS_DB: "0"
REDIS_ENABLED: "true"
# ===== 认证 =====
JWT_SECRET: "{自行生成,openssl rand -hex 32}"
# ===== 日志 =====
LOG_LEVEL: "info"
LOG_ENVIRONMENT: "staging"
LOG_DIR: "/app/logs"
LOG_MAX_SIZE: "100"
LOG_MAX_BACKUPS: "5"
LOG_MAX_AGE: "30"
LOG_COMPRESS: "true"
# ===== ⚠️ 沙箱:微信支付 =====
WECHAT_APPID: "{沙箱 AppID}"
WECHAT_MCHID: "{沙箱商户号}"
WECHAT_MCH_PRIVATE_KEY: "{沙箱私钥}"
WECHAT_MCH_SERIAL_NO: "{沙箱证书序列号}"
WECHAT_APIV3_KEY: "{沙箱 APIv3 密钥}"
WECHAT_NOTIFY_URL: "https://user-staging.turingfocus.cn/api/v1/payment/wechat/notify"
WECHAT_IS_SANDBOX: "true"
# ===== ⚠️ 沙箱:支付宝 =====
ALIPAY_APPID: "{沙箱 AppID}"
ALIPAY_APP_PRIVATE_KEY: "{沙箱应用私钥}"
ALIPAY_ALIPAY_PUBLIC_KEY: "{沙箱支付宝公钥}"
ALIPAY_SIGN_TYPE: "RSA2"
ALIPAY_NOTIFY_URL: "https://user-staging.turingfocus.cn/api/v1/payment/alipay/notify"
ALIPAY_IS_SANDBOX: "true"
# ===== 短信(可共用生产配置或使用测试模板) =====
SMS_PROVIDER: "tencent"
SMS_TENCENT_SECRET_ID: "{腾讯云 SecretId}"
SMS_TENCENT_SECRET_KEY: "{腾讯云 SecretKey}"
SMS_TENCENT_SDK_APP_ID: "{SDK AppID}"
SMS_TENCENT_SIGN_NAME: "{签名}"
SMS_CODE_TTL_MINUTES: "5"
# ===== 对象存储(可共用或独立 Bucket) =====
COS_BUCKET_NAME: "{Staging Bucket}"
COS_REGION: "ap-beijing"
COS_SECRET_ID: "{SecretId}"
COS_SECRET_KEY: "{SecretKey}"
COS_BASE_URL: "https://{bucket}.cos.{region}.myqcloud.com"
COS_MAX_AVATAR_SIZE: "2097152"
# ===== K8s 集群 =====
K8S_CONFIG_DIR: "/app/data/kubeconfigs"
# ===== Infisical 密钥管理 =====
INFISICAL_CLIENT_ID: "{Staging Machine Identity ID}"
INFISICAL_CLIENT_SECRET: "{Staging Machine Identity Secret}"
INFISICAL_PROJECT_ID: "{Project ID}"
INFISICAL_ENVIRONMENT: "staging"
INFISICAL_SITE_URL: "https://secret-staging.turingfocus.cn"
# ===== 加密 =====
SECRET_ENCRYPTION_KEY: "{自行生成,openssl rand -hex 32}"
SECRET_CACHE_TTL: "3600"
# ===== 可观测性 =====
OTEL_SERVICE_NAME: "tfrsmanager-staging"
OTEL_SERVICE_VERSION: "1.0.0"
OTEL_ENVIRONMENT: "staging"
JAEGER_ENDPOINT: "http://jaeger:4318/v1/traces"
OTEL_SAMPLING_RATIO: "1.0"
# ===== 飞书应用 =====
FEISHU_CALLBACK_BASE_URL: "https://user-staging.turingfocus.cn"
FEISHU_OAUTH_REDIRECT_URL: "https://user-staging.turingfocus.cn/auth/feishu/callback"
FEISHU_ISV_ENABLED: "false"
FEISHU_ISV_APP_ID: ""
FEISHU_ISV_APP_SECRET: ""
# ===== 监控指标 =====
METRICS_QUERY_URL: "http://victoriametrics:8428"
CONSUMPTION_SCHEDULE_INTERVAL: "5m"
CONSUMPTION_PULL_WINDOW_MINUTES: "6"
# ===== 集群初始化 =====
CLUSTER_INIT_OPERATOR_IMAGE: "{Operator 镜像地址}"
CLUSTER_INIT_OPERATOR_NAMESPACE: "tfrs-system"
CLUSTER_INIT_VM_REMOTE_WRITE_URL: "https://metrics-staging.turingfocus.cn/api/v1/write"
CLUSTER_INIT_DEFAULT_CLUSTER_TYPE: "standard"
CLUSTER_INIT_INFISICAL_REGISTRY_PATH: "/docker-registry"
# ===== Helm/Operator =====
OPERATOR_HELM_REPO_URL: "{Helm Repo URL}"
OPERATOR_CHART_VERSION: "{Chart 版本}"
OPERATOR_IMAGE_TAG: "{Operator 镜像 Tag}"
HELM_STORAGE_DRIVER: "secret"
前端项目 (tfrs_user_portal_staging.yaml / tfrs_admin_portal_staging.yaml)¶
# UserPortal Staging
NEXT_PUBLIC_API_URL: "https://user-staging.turingfocus.cn"
NEXT_PUBLIC_ENV: "staging"
# 其他前端特定变量...
# AdminPortal Staging
NEXT_PUBLIC_API_URL: "https://admin-staging.turingfocus.cn"
NEXT_PUBLIC_ENV: "staging"
# 其他前端特定变量...
CNB 流水线配置¶
每个项目的 .cnb.yml 中添加 staging 部署事件:
# 手动触发 Staging 部署
$:
web_trigger_deploy_staging:
- <<: *deploy-staging-pipeline
api_trigger_deploy_staging:
- <<: *deploy-staging-pipeline
Staging 流水线与 Prod 流水线的唯一区别是 imports 引用的密钥文件不同:
| 配置项 | Beta (Prod) | Staging |
|---|---|---|
| SSH 凭证 | tfrsmanager_deploy_ssh.yml |
tfrsmanager_deploy_ssh_staging.yml |
| 后端业务变量 | tfrsmanager_env.prod.yml |
tfrsmanager_env.staging.yml |
| UserPortal 变量 | tfrs_user_portal.yaml |
tfrs_user_portal_staging.yaml |
| AdminPortal 变量 | tfrs_admin_portal.yaml |
tfrs_admin_portal_staging.yaml |
部署步骤¶
前置准备(首次部署)¶
-
生成 deploy 用户 SSH 密钥(在 staging 服务器上):
-
在 CNB 密钥仓库创建配置文件(参照上述模板填充)
-
各项目
.cnb.yml添加 staging 流水线
触发部署¶
# 通过 CNB MCP 触发(API 方式)
cnb_startBuild(repo: "turingfocus/k8s/tfrsmanager", branch: "main", event: "api_trigger_deploy_staging")
cnb_startBuild(repo: "turingfocus/ui/TFRobotFrontPortal", branch: "main", event: "api_trigger_deploy_staging")
cnb_startBuild(repo: "turingfocus/ui/TFRobotAdminPortal", branch: "main", event: "api_trigger_deploy_staging")
或通过 CNB Web 界面手动触发 web_trigger_deploy_staging。