safety-eval-service/docs/本地JAR打包发布到100服务器完整流程.md

577 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# safety-eval-service 本地 JAR 打包发布到 100 服务器 K8s 完整流程
> 本文档记录了将本地 Windows 开发机上的 `safety-eval-service` JAR 包发布到 GBS K8s 集群(主节点 `192.168.20.100`)的全链路操作步骤,包括所用工具、命令、账号密码和注意事项。
---
## 1. 环境总览
### 1.1 网络与服务器
| 角色 | IP | 说明 |
|---|---|---|
| K8s Master | `192.168.20.100` | 控制面Docker/Maven/Nexus/NFS |
| K8s Worker01 | `192.168.20.110` | Pod 运行节点 |
| K8s Worker02 | `192.168.20.120` | Pod 运行节点 |
| Nexus 私服 | `192.168.20.100:8578` | Maven snapshots/releases 仓库 |
| MySQL | `192.168.20.100:33080` | GBS 共享数据库 |
| Nacos | `prod-nacos:8848`(集群内)/ `192.168.20.100:30290`NodePort | 配置中心 + 注册中心 |
| Gateway | `192.168.20.100:30140`NodePort | SCG 统一入口 |
K8s 版本 `v1.27.6`,命名空间 `jjb-dragon`
### 1.2 本地开发机
- OSWindowsGit Bash / cmd / PowerShell 均可)
- 项目路径:`E:\works\projects\safety-eval-service`
- 模块Maven 多模块DDD 六层),启动模块为 `safety-eval-start`
- 本地 JDK1.8.x
- 构建产物:`safety-eval-start/target/safety-eval-start-1.0-SNAPSHOT.jar`
### 1.3 容器镜像仓库
| 仓库 | 地址 | 用途 | 用户名 | 密码 |
|---|---|---|---|---|
| 杭州 ACR默认发布仓 | `jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com` | 主镜像仓K8s `image-pull-secret` 指向此处 | `10952138@qq.com` | `idurCT!rIq9EzISD` |
| 张家口 ACR备用/本地构建仓) | `registry.cn-zhangjiakou.aliyuncs.com` / VPC: `registry-vpc.cn-zhangjiakou.aliyuncs.com` | 另一台阿里云服务器本地构建用 | `kilaa` | `Kilaa@6666` |
| 张家口 ACR AK | — | — | `LTAI5tF8GbtKizLAowJbAYmT` | `G0ZYeaZtnpxhp0bO1rPp4HPrq57LaT` |
镜像命名规范:
- 杭州 ACR`{ACR}/ali_img_ns/prod-aly-{env}-dragon-{app}:{env}-YYYYMMDD-{N}`
- 示例:`jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com/ali_img_ns/prod-aly-ota-dragon-jjb-saas-safety-eval:ota-20260703-1`
- 张家口 ACR`registry.cn-zhangjiakou.aliyuncs.com/kilaa/zcloud-gbs-operation:jjb-saas-safety-eval-ota-YYYYMMDD-{N}`
### 1.4 SSH / 系统账号
| 目标 | 用户 | 密码 |
|---|---|---|
| `192.168.20.100`masterSSH | `root` | `Zcloud@zcloud100` |
### 1.5 K8s 拉取凭据
- Secret 名:`image-pull-secret`(底座镜像)/ `image-pull-secret1`(应用镜像)
- 类型:`kubernetes.io/dockerconfigjson`
- **当前只配置了杭州 ACR 的 auth**,因此 K8s 部署必须使用杭州 ACR 地址
### 1.6 数据库
| 项 | 值 |
|---|---|
| Host | `192.168.20.100:33080` |
| 用户 | `root` |
| 密码 | `Mysql@zcloud33080` |
---
## 2. 本服务基础信息
| 配置项 | 值 |
|---|---|
| app.name | `jjb-saas-cq-anquan` |
| gateway 路由名 | `cqanquan` |
| server.port本地 / K8s 容器内) | `8095` |
| context-path | `/safety-eval` |
| Dubbo 端口 | `20895` |
| Nacos 服务名 | `safety-eval-service` |
| Spring Boot 版本 | `2.7.18` |
| 架构 | DDD 六层adapter / app / client / domain / infrastructure / start |
> **端口说明**:本服务在 K8s 容器内仍监听 `8095`与本地一致Service 通过 `port: 80 / targetPort: 8095` 对外暴露 80 端口。GBS 其他部分服务会在 Nacos prod 配置中将 `server.port` 覆盖为 80本服务暂未做此覆盖部署时务必确认实际监听端口再填写 `containerPort` 与 `targetPort`。
K8s 资源:
- Deployment`jjb-saas-safety-eval-deploy`
- Pod Label`app=jjb-saas-safety-eval-pod`
- Service`jjb-saas-safety-eval`ClusterIP80→809520895→20895
---
## 3. 完整发布流程
发布流程分为 5 个阶段:**本地编译 → 上传 JAR → 构建镜像 → 推送 ACR → K8s 部署**。
### 阶段 1本地 Maven 编译
在 Windows 本地打包:
```bash
cd E:\works\projects\safety-eval-service
mvn clean package -DskipTests
```
产物路径:`safety-eval-start/target/safety-eval-start-1.0-SNAPSHOT.jar`(约 226 MB
> 也可将源码上传到 master 节点用 `/opt/maven`Maven 3.8.8,阿里云镜像)远程编译,避免本地环境差异。
### 阶段 2上传 JAR 到 master 节点
使用 SFTP 或 SCP 将 JAR 上传到 `192.168.20.100`
```bash
# 方式 Ascp需要 sshpass 或在 Git Bash 中交互式输密码)
scp safety-eval-start/target/safety-eval-start-1.0-SNAPSHOT.jar root@192.168.20.100:/tmp/safety-eval.jar
# 方式 BPython paramiko 脚本(推荐,见 docs/build-tools/build_push.py
python docs/build-tools/build_push.py ^
E:\works\projects\safety-eval-service\safety-eval-start\target\safety-eval-start-1.0-SNAPSHOT.jar ^
jjb-saas-safety-eval ota 1
```
### 阶段 3构建 Docker 镜像
#### 方式 A使用 `build.sh`(推荐,在 master 上执行)
`docs/build-tools/build.sh` 会在 master 上自动:
1. 将 JAR + JDK + Dockerfile 组装为 build context
2. `docker build` 生成镜像
3. `docker push` 推到杭州 ACR
```bash
ssh root@192.168.20.100
cd /path/to/build-tools
./build.sh jjb-saas-safety-eval ota /tmp/safety-eval.jar 1
```
生成镜像:`jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com/ali_img_ns/prod-aly-ota-dragon-jjb-saas-safety-eval:ota-YYYYMMDD-1`
#### 方式 B使用根目录 Dockerfile
项目根 `Dockerfile` 基于 `jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com/pub/jdk:1.8.0_202`(镜像已含 JDK构建更轻量
```bash
# 在 master 上
mkdir -p /tmp/build-safety-eval/start/target
cp /tmp/safety-eval.jar /tmp/build-safety-eval/start/target/start.jar
cp Dockerfile /tmp/build-safety-eval/
cd /tmp/build-safety-eval
docker build -t jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com/ali_img_ns/prod-aly-ota-dragon-jjb-saas-safety-eval:ota-YYYYMMDD-1 .
```
#### 方式 C复用 master 上已有的张家口 ACR 镜像(最快)
如果张家口 ACR 已有当天构建的镜像(如 `jjb-saas-safety-eval-ota-YYYYMMDD-N`),直接 retag + push 到杭州 ACR免去重新构建
```bash
# 在 master 上
SRC=registry.cn-zhangjiakou.aliyuncs.com/kilaa/zcloud-gbs-operation:jjb-saas-safety-eval-ota-YYYYMMDD-N
DST=jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com/ali_img_ns/prod-aly-ota-dragon-jjb-saas-safety-eval:ota-YYYYMMDD-1
docker pull $SRC
docker tag $SRC $DST
echo 'idurCT!rIq9EzISD' | docker login --username=10952138@qq.com --password-stdin jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com
docker push $DST
```
### 阶段 4部署到 K8s
#### 首次部署create
```bash
# 在 master 上
/usr/bin/kubectl apply -f deployment.yaml -n jjb-dragon
/usr/bin/kubectl apply -f service.yaml -n jjb-dragon
```
`deployment.yaml` 参考(见 docs/deploy/safety-eval-deploy.yaml
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
deployLabel: jjb-saas-safety-eval-deploy
name: jjb-saas-safety-eval-deploy
namespace: jjb-dragon
spec:
replicas: 1
selector:
matchLabels:
app: jjb-saas-safety-eval-pod
template:
metadata:
labels:
app: jjb-saas-safety-eval-pod
namespace: jjb-dragon
spec:
containers:
- name: jjb-saas-safety-eval-app
image: jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com/ali_img_ns/prod-aly-ota-dragon-jjb-saas-safety-eval:ota-YYYYMMDD-N
imagePullPolicy: Always
command: ["/opt/jdk1.8.0_202/bin/java"]
args:
- -Dnacos.namespace=jjb-dragon
- -Dnacos.url=prod-nacos:8848
- -Dspring.profiles.active=prod
- -Dmysql.password=Mysql@zcloud33080
- -Dmysql.host=192.168.20.100
- -Dmysql.port=33080
- -Dmysql.username=root
- -jar
- /opt/app.jar
env:
- name: TZ
value: Asia/Shanghai
ports:
- containerPort: 8095
name: http
- containerPort: 20895
name: dubbo
resources:
limits:
cpu: "1"
memory: 2048M
requests:
cpu: 500m
memory: 512M
imagePullSecrets:
- name: image-pull-secret
```
`service.yaml` 参考(见 docs/deploy/safety-eval-svc.yaml
```yaml
apiVersion: v1
kind: Service
metadata:
name: jjb-saas-safety-eval
namespace: jjb-dragon
spec:
type: ClusterIP
selector:
app: jjb-saas-safety-eval-pod
ports:
- name: http
port: 80
targetPort: 80
- name: dubbo
port: 20895
targetPort: 20895
```
#### 更新部署(已存在 deploy
只替换镜像 tag
```bash
/usr/bin/kubectl set image deployment/jjb-saas-safety-eval-deploy \
jjb-saas-safety-eval-app=jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com/ali_img_ns/prod-aly-ota-dragon-jjb-saas-safety-eval:ota-YYYYMMDD-N \
-n jjb-dragon
# 强制滚动(不修改镜像时触发重启)
/usr/bin/kubectl rollout restart deployment/jjb-saas-safety-eval-deploy -n jjb-dragon
```
### 阶段 5验证
```bash
# Pod 状态
/usr/bin/kubectl get pods -n jjb-dragon | grep safety-eval
# 启动日志
/usr/bin/kubectl logs -f deployment/jjb-saas-safety-eval-deploy -n jjb-dragon --tail=100
# Nacos 注册检查(通过 NodePort
curl -s "http://192.168.20.100:30290/nacos/v1/ns/instance/list?serviceName=safety-eval-service&namespaceId=jjb-dragon"
# Endpoints
/usr/bin/kubectl get endpoints jjb-saas-safety-eval -n jjb-dragon
```
正常日志标志:
```
Tomcat started on port(s): 8095 (http) with context path ''
Nacos registry, DEFAULT_GROUP safety-eval-service 10.x.x.x:8095 register finished
```
---
## 4. 工具清单
| 工具 | 版本 | 位置 | 用途 |
|---|---|---|---|
| Maven | 3.8.8 | 本地 / master `/opt/maven` | JAR 编译打包 |
| JDK | 1.8.0_202 | 本地 / master `/opt/jdk1.8.0_202` | Java 运行环境 |
| Docker | 26.1.4 | master `/usr/bin/docker` | 镜像构建推送 |
| kubectl | v1.27.6 | master `/usr/bin/kubectl` | K8s 资源管理 |
| scp / sftp | — | 本地 → master | JAR 文件上传 |
| paramiko | 5.0.0 | 本地 Python 3.11 | SSH 自动化(推荐) |
| ssh | OpenSSH | 本地 Git Bash / cmd | 远程登录 master |
| curl | — | master / 本地 | Nacos/HTTP 验证 |
| build.sh | 自研 | `docs/build-tools/build.sh` | 一键构建推送Shell 版) |
| build_push.py | 自研 | `docs/build-tools/build_push.py` | 本地 Windows 一键构建推送Python 版) |
---
## 5. 常用命令速查
```bash
# 登录 master
ssh root@192.168.20.100 # 密码Zcloud@zcloud100
# 登录杭州 ACR
echo 'idurCT!rIq9EzISD' | docker login --username=10952138@qq.com --password-stdin jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com
# 登录张家口 ACR
echo 'Kilaa@6666' | docker login --username=kilaa --password-stdin registry.cn-zhangjiakou.aliyuncs.com
# 查看 deploy
/usr/bin/kubectl get deploy,pods,svc -n jjb-dragon | grep safety-eval
# 查看日志
/usr/bin/kubectl logs -f deployment/jjb-saas-safety-eval-deploy -n jjb-dragon
# 重启(不改镜像)
/usr/bin/kubectl rollout restart deployment/jjb-saas-safety-eval-deploy -n jjb-dragon
# 进入 Pod
/usr/bin/kubectl exec -it deployment/jjb-saas-safety-eval-deploy -n jjb-dragon -- /bin/bash
# Nacos 控制台
http://192.168.20.100:30290/nacos # nacos/nacos
# Nexus 私服
http://192.168.20.100:8578 # admin/admin123
```
---
## 6. 注意事项与踩坑
1. **端口差异排查**:本服务本地与容器内均为 `8095`Service 用 `port: 80 / targetPort: 8095`。但 GBS 部分老服务会被 Nacos `xxx-prod.yml` 覆盖为 `80`,因此新服务上线前必须用 `kubectl get endpoints -n jjb-dragon` 或 Pod 启动日志确认实际监听端口,再填写 `containerPort``targetPort`。Dubbo 端口 `20895` 不受影响。
2. **镜像仓库选择**K8s `image-pull-secret` 只配了杭州 ACR。如果从张家口 ACR 拉镜像Pod 会报 `ImagePullBackOff`。解决方案:
- 方案 A在 master 上 retag + push 到杭州 ACR推荐
- 方案 B`image-pull-secret` 追加张家口 ACR 的 auth
3. **lb:// URI scheme**SCG 网关路由中若有 `lb://` 协议,不会在 K8s 中被解析,需改为 `http://{svc-name}` 直连 K8s DNS并设 `filterGatewaName=NULL`
4. **Dubbo 注册 namespace**Dubbo provider 注册到 Nacos 的命名空间是 `jjb-dragon-facade`(带 `-facade` 后缀consumer 必须配置 `dubbo.registry.parameters.namespace=jjb-dragon-facade`
5. **Nacos 不可达导致启动失败**Dubbo 3.2.x 无显式 `config-center` 时会自动从 registry 推导,需同时检查 config-center 配置。
6. **镜像 tag 冲突**每天多次发布时version-suffix`ota-YYYYMMDD-N` 的 `N`)需递增,否则 `ImagePullPolicy: Always` 拉到的可能是缓存的旧镜像。
7. **主节点构建依赖**master 上的 `/opt/jdk1.8.0_202` 是从 Docker 镜像提取的,`/opt/maven` 配置了阿里云镜像。`/opt/docker-templates/` 下有 Dockerfile 模板。
---
## 7. 附:账号密码汇总
| 用途 | 地址 | 账号 | 密码/Token |
|---|---|---|---|
| Master SSH | `192.168.20.100:22` | `root` | `Zcloud@zcloud100` |
| 杭州 ACR | `jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com` | `10952138@qq.com` | `idurCT!rIq9EzISD` |
| 张家口 ACR | `registry.cn-zhangjiakou.aliyuncs.com` | `kilaa` | `Kilaa@6666` |
| 张家口 ACR AK | — | `LTAI5tF8GbtKizLAowJbAYmT` | `G0ZYeaZtnpxhp0bO1rPp4HPrq57LaT` |
| MySQL | `192.168.20.100:33080` | `root` | `Mysql@zcloud33080` |
| Nacos | `http://192.168.20.100:30290/nacos` | `nacos` | `nacos` |
| Nexus | `http://192.168.20.100:8578` | `admin` | `admin123` |
---
## 8. 文件索引
```
docs/
├── build-tools/
│ ├── build.sh # Shell 一键构建推送(在 master 上执行)
│ ├── build_push.py # Python 一键构建推送Windows 本地执行)
│ ├── Dockerfile # CentOS7+JDK 版 Dockerfile 模板
│ ├── README.md # build-tools 使用说明
│ └── install_env.sh # master 环境初始化脚本
├── deploy/
│ ├── safety-eval-deploy.yaml # K8s Deployment
│ └── safety-eval-svc.yaml # K8s Service
└── 本地JAR打包发布到100服务器完整流程.md # 本文档
Dockerfile # 项目根 Dockerfile基于 pub/jdk:1.8.0_202
```
---
## 9. 服务启动验证(多种确认方式)
部署完成后需要多维度确认服务已真正可用。下面按"由浅入深"列出 8 种验证方式,建议至少跑完 14 步。
> 所有命令默认在 master 节点(`192.168.20.100`)上执行,已登录 root。
### 9.1 K8s 资源状态检查
```bash
# Pod / Deployment 是否 READY 1/1、Running
/usr/bin/kubectl get deploy,pods,svc -n jjb-dragon | grep safety-eval
# 滚动升级是否完成(无旧 ReplicaSet 残留)
/usr/bin/kubectl rollout status deployment/jjb-saas-safety-eval-deploy -n jjb-dragon --timeout=180s
# Endpoints 是否绑到 Pod IP空说明 Service 没选到 Pod
/usr/bin/kubectl get endpoints jjb-saas-safety-eval -n jjb-dragon
# 最近事件ImagePullBackOff、CrashLoopBackOff、OOMKilled 等都能在这里看到)
/usr/bin/kubectl get events -n jjb-dragon --sort-by=.metadata.creationTimestamp \
| grep -i safety-eval | tail -20
# Pod 详情(重点看 Conditions、ContainerStatus、LastState
/usr/bin/kubectl describe pod -n jjb-dragon -l app=jjb-saas-safety-eval-pod
```
**判断标准**
| 项 | 健康值 |
|---|---|
| Deployment READY | `1/1` |
| Pod STATUS | `Running` |
| RESTARTS | `0`(或长期稳定的小数字) |
| Endpoints | 非空,且包含 Pod IP + `8095,20895` |
### 9.2 启动日志
```bash
# 实时跟踪日志
/usr/bin/kubectl logs -f deployment/jjb-saas-safety-eval-deploy -n jjb-dragon --tail=200
# 只看最后 50 行
/usr/bin/kubectl logs deployment/jjb-saas-safety-eval-deploy -n jjb-dragon --tail=50
```
**关键日志标志**
```
Tomcat started on port(s): 8095 (http) with context path ''
Nacos registry, DEFAULT_GROUP safety-eval-service 10.244.x.x:8095 register finished
```
**失败标志**(出现任一则服务不可用):
- `APPLICATION FAILED TO START`
- `BeanCreationException` / `UnsatisfiedDependencyException`
- `Connection refused` 到 MySQL / Nacos / Redis
- `Unable to acquire JDBC Connection`
- `Address already in use`
- `Killed`OOM需调大 `resources.limits.memory`
### 9.3 Nacos 服务注册(控制台 + API
**控制台**:浏览器打开 `http://192.168.20.100:30290/nacos`,账号 `nacos/nacos`
1. 左上角切换命名空间到 `jjb-dragon`
2. 菜单 → 服务管理 → 服务列表 → 搜索 `safety-eval-service`
3. 点进去查看实例列表,健康状态应为绿色 `健康`
**API 方式**(适合脚本化):
```bash
# 列出 jjb-dragon 命名空间下所有服务
curl -s "http://192.168.20.100:30290/nacos/v1/ns/service/list?pageNo=1&pageSize=200&namespaceId=jjb-dragon" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print([s for s in d['doms'] if 'safety' in s])"
# 查看 safety-eval-service 的实例健康状态
curl -s "http://192.168.20.100:30290/nacos/v1/ns/instance/list?serviceName=safety-eval-service&namespaceId=jjb-dragon" \
| python3 -m json.tool
```
**判断标准**`hosts[].healthy=true`、`enabled=true`、`port=8095`,且至少有一条实例 IP 是当前 Pod IP。
### 9.4 Dubbo Provider 注册
Dubbo 服务注册在独立的命名空间 `jjb-dragon-facade`
```bash
# 列出 Dubbo 服务
curl -s "http://192.168.20.100:30290/nacos/v1/ns/service/list?pageNo=1&pageSize=500&namespaceId=jjb-dragon-facade" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print([s for s in d['doms'] if 'safety' in s.lower() or 'Cqanquan' in s or 'cqanquan' in s])"
# 查看某个 Dubbo 接口的实例
curl -s "http://192.168.20.100:30290/nacos/v1/ns/instance/list?serviceName=providers:com.xxx.XxxService::&namespaceId=jjb-dragon-facade"
```
**判断标准**`providers:com.xxx.XxxService::jjb-dragon` 形式的条目存在且健康。
### 9.5 Spring Boot Actuator
如果 `application.yml` 开启了 actuator可直接访问健康/信息端点。
```bash
# 从 Pod 内部访问
/usr/bin/kubectl exec -it deployment/jjb-saas-safety-eval-deploy -n jjb-dragon -- \
curl -s http://localhost:8095/actuator/health
# 从 master 经 Pod IP 访问
POD_IP=$(/usr/bin/kubectl get pod -n jjb-dragon -l app=jjb-saas-safety-eval-pod \
-o jsonpath='{.items[0].status.podIP}')
curl -s "http://${POD_IP}:8095/actuator/health"
curl -s "http://${POD_IP}:8095/actuator/info"
```
**判断标准**`{"status":"UP"}` 且各 componentdb、nacos、dubbo 等)无 DOWN。
### 9.6 集群内直连Pod → Pod
进入一个同集群的 Pod直接 curl 目标服务的 HTTP 接口:
```bash
# 进入 safety-eval 自己的 Pod 测试
/usr/bin/kubectl exec -it deployment/jjb-saas-safety-eval-deploy -n jjb-dragon -- /bin/bash
# 在 Pod 内
curl -s http://localhost:8095/safety-eval/ # context-path
curl -s http://localhost:8095/actuator/health
# 从另一个 Pod如 jjb-saas-base测试跨服务调用
/usr/bin/kubectl exec -it deployment/jjb-saas-base-deploy -n jjb-dragon -- \
curl -s http://jjb-saas-safety-eval/safety-eval/
```
**判断标准**HTTP 200 或返回业务 JSON而非 `Connection refused` / `502`
### 9.7 通过网关访问NodePort
网关 NodePort `30140`,路由通过 MySQL `jjb-saas-gateway.route` 表配置。本服务的 `gateway=cqanquan`,需携带 `filterGatewaName` 请求头:
```bash
# 从 master / 任意能访问 100 的机器
curl -i "http://192.168.20.100:30140/safety-eval/" \
-H "filterGatewaName: cqanquan"
# 带 Token 的业务请求示例
curl "http://192.168.20.100:30140/safety-eval/api/xxx" \
-H "filterGatewaName: cqanquan" \
-H "Authorization: Bearer <token>"
```
**判断标准**
- `200/401/404` 等业务状态码 → 服务已通
- `502 Bad Gateway` / `503 Service Unavailable` → 服务未注册或端口不对
- `404` 但网关日志有路由 → 路由正常,接口路径不对
### 9.8 本地开发机 port-forward调试用
把 K8s Service 映射到本地,浏览器或 Postman 直接访问:
```bash
# 本地 Windows PowerShell / Git Bash
ssh -L 8095:jjb-saas-safety-eval:80 root@192.168.20.100
# 或
kubectl port-forward svc/jjb-saas-safety-eval 8095:80 -n jjb-dragon
```
然后本地访问 `http://localhost:8095/safety-eval/` 即可。
---
### 验证清单(推荐顺序)
| # | 检查项 | 命令 / 工具 | 预期 |
|---|---|---|---|
| 1 | Pod Running + Endpoints 有值 | `kubectl get pods,endpoints` | `1/1 Running`、IP:8095,20895 |
| 2 | 启动日志无报错 | `kubectl logs --tail=200` | 出现 `Tomcat started on port(s): 8095` |
| 3 | Nacos 注册成功 | Nacos 控制台 / API | `safety-eval-service` healthy=true |
| 4 | Dubbo Provider 注册 | Nacos APIjjb-dragon-facade | `providers:xxx::jjb-dragon` 存在 |
| 5 | Actuator 健康 | `curl /actuator/health` | `{"status":"UP"}` |
| 6 | Pod 内 HTTP 可达 | `curl localhost:8095/safety-eval/` | 200 或业务 JSON |
| 7 | 网关路由可达 | `curl :30140/safety-eval/ -H filterGatewaName:cqanquan` | 非 502/503 |
| 8 | 业务接口冒烟 | Postman 或 curl 调用真实接口 | 业务返回正常 |