昨天一位打榜人员在某榜单上提交打榜策略的时候,遇到了测试流程卡住的情况。

当前,一个榜单有多个数据集。在测试的时候,会针对每个数据集启动一个测试服务和被测服务,其中被测服务也就是打榜人员提交的打榜策略。正常来说,测试的时候测试服务 A 只会和被测服务 a 通信,测试服务 B 只会和被测服务 b 通信,不同数据集的测试服务和被测服务之间在测试中是不会有通信的需要。但是通过日志发现,测试服务 A 和测试服务 B 发送的某个请求都被被测服务 a 接受到了,导致测试服务 b 没有接收到测试请求,从而测试流程卡住。(判断接收到的方式是,Flask 日志会显示请求来源的 IP 地址。)

由于当前榜单平台已经全面禁网测试,所以打榜人员无法调用外部服务,只能在容器内部启动大模型。为了满足打榜策略启动多容器的需要,该榜单提供了提交 helm chart 来部署多容器进行测试的功能,该打榜人员就使用的这种方式进行提交。

在排查过程中,首先根据日志判断测试服务在发送请求时的请求域名是正确的。当前测试服务发送请求的方式是被测服务的 service name 加上端口号。对于被测服务,要求了容器的 service name 按照一定的格式去填写,保证每次启动时 service name 都是不同的。然后通过 K8S 命令行去查看每个 service 对应的 IP,确定了被测服务 a 和被测服务 b 对应的 IP 是不同的。此时就很奇怪,IP 不同,那应该是发送到正确的 service 了,为什么会出现同一个 POD 接收到两个请求呢?

后来又进入到测试服务 A 的 POD 内,通过 curl 命令发送多条请求给被测服务 a。然后去查看了被测服务 a 和被测服务 b 的日志,发现这些请求确实被分发到两个被测服务 POD 中了。这个时候开始怀疑问题是否出现在 service 的配置中,导致一个 service 对应了多个 POD。

通过查看 service 的配置信息和 POD 的配置信息,发现确实存在这样的情况。测试平台会给每个 POD 注入不同值的 label 信息,来对 POD 进行区分。但是该打榜人员在 helm chart 中配置 service 的时候并没有对 selector 进行修改,导致 service 匹配到了多个 POD,从而发生最开始流程卡住的情况。

以下为打榜人员最开始的 helm chart template 信息(仅含有关键信息):

# template/deployment.yaml
spec:
  selector:
    matchLabels:
      app: xxx-backend
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        app: xxx-backend
        {{- with .Values.global.podLabels }}
        {{- toYaml . | nindent 8 }}
# template/service.yaml
spec:
  selector:
    app: xxx-backend
  type: NodePort

更改后的 template 信息:

# template/service.yaml
spec:
  selector:
    app: xxx-backend
    {{- with .Values.global.podLabels }}
    {{- toYaml . | nindent 4 }}
    {{- end }}
  type: NodePort