You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Windows Docker Desktop的K8s中,如何通过Service访问指定Pod?

解决方案:让客户端连接到处理请求的同一个Stream-Server Pod

你的核心问题是会话粘性:客户端需要和处理初始请求的同一个Pod建立WebSocket连接,同时还要支持Pod的水平扩缩容(HPA)。下面是几种适配你场景的方案,按实现复杂度和实用性排序:

方案1:Service会话亲和性(最简单的快速方案)

Kubernetes的Service原生支持会话亲和性,能让来自同一个客户端IP的请求始终路由到同一个Pod。这个方案不需要修改业务代码,配置简单,完全适配HPA需求。

修改你的Service配置:

apiVersion: v1
kind: Service
metadata:
  name: my-service1
  labels:
    app: stream
spec:
  ports:
  - port: 8090
    targetPort: 8090
    name: port8090
  selector:
    app: stream
  type: LoadBalancer
  # 添加会话亲和性配置
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 3600  # 会话保持时长,可根据业务调整,比如设置为WebSocket连接的超时时间

优点:

  • 零业务代码修改,直接用K8s原生能力解决问题
  • 完美兼容HPA:扩缩容时K8s会自动调整会话路由,新Pod会接收新的客户端请求,不影响现有会话
  • 配置简单,几分钟就能生效

注意事项:

  • 如果多个客户端共享同一个公网IP(比如通过NAT网关访问),会导致所有这些客户端都被路由到同一个Pod,可能造成负载不均
  • WebSocket是长连接,只要连接保持,会话亲和性就会一直生效;如果连接断开重连,只要客户端IP不变,还是会回到同一个Pod

方案2:StatefulSet+Ingress精准路由(适配复杂场景)

如果会话亲和性不满足你的需求(比如客户端IP经常变化),可以改用StatefulSet部署Stream-Server,利用其稳定的网络标识,再通过Ingress实现路径到特定Pod的路由。

步骤1:将Deployment改为StatefulSet

StatefulSet会给每个Pod分配稳定的DNS标识(比如stream-deployment-0.stream-service.default.svc.cluster.local),即使Pod重启或扩缩容,这个标识也不会改变。

apiVersion: v1
kind: Service
metadata:
  name: stream-service
  labels:
    app: stream
spec:
  ports:
  - port: 8090
    targetPort: 8090
    name: port8090
  selector:
    app: stream
  clusterIP: None  # 配置为Headless Service,用于StatefulSet的DNS解析
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: stream-deployment
  labels:
    app: stream
spec:
  replicas: 3
  serviceName: stream-service  # 关联上面的Headless Service
  selector:
    matchLabels:
      app: stream
  template:
    metadata:
      labels:
        app: stream
    spec:
      containers:
      - image: stream-server-mock:latest
        name: stream-server-mock
        imagePullPolicy: Never
        env:
        - name: STREAMER_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: STREAMER_ADDRESS
          value: "$(HOSTNAME).stream-service.default.svc.cluster.local:8090"  # 使用稳定DNS标识
        ports:
        - containerPort: 8090

步骤2:配置Ingress路径路由

以Nginx Ingress为例,配置路径转发规则,让客户端可以通过http://<loadbalancer-ip>/pod0访问stream-deployment-0,/pod1访问stream-deployment-1:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: stream-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - http:
      paths:
      - path: /pod0/(.*)
        pathType: Prefix
        backend:
          service:
            name: stream-service
            port:
              number: 8090
      - path: /pod1/(.*)
        pathType: Prefix
        backend:
          service:
            name: stream-service
            port:
              number: 8090
      # 后续扩缩容时,只需添加对应Pod的路径规则即可

步骤3:调整业务逻辑

让Stream-Server返回对应的Ingress路径(比如http://<loadbalancer-ip>/pod0),客户端通过该路径建立WebSocket连接,Ingress会直接转发到对应的Pod。

优点:

  • 完全不受客户端IP变化的影响,精准路由到指定Pod
  • StatefulSet的稳定标识适配HPA:新Pod会自动获得新的DNS标识,只需同步更新Ingress配置(可以用自动化脚本或Argo CD等工具实现批量更新)

缺点:

  • 需要将Deployment改为StatefulSet,同时调整业务代码返回的地址格式
  • Ingress路径需要和Pod数量同步,扩缩容时需要额外的配置维护

方案3:自定义会话跟踪(灵活性最高)

如果上面的方案都不满足你的特殊需求,你可以在REST-Server中实现自定义会话跟踪逻辑:

  1. 当Stream-Server处理请求时,把自身的Pod名称/ID返回给REST-Server
  2. REST-Server将该Pod标识与客户端会话绑定(比如存储在Redis中)
  3. 客户端建立WebSocket连接时携带会话ID,REST-Server根据会话ID找到对应的Pod,再通过代理服务(比如Spring Cloud Gateway)将请求转发到该Pod

这种方式复杂度较高,但灵活性最强,适合有特殊业务规则的场景。

推荐方案

如果你的客户端IP相对稳定(比如企业内网客户端),**方案1(Service会话亲和性)**是最优选择,配置简单且完全兼容HPA。如果客户端IP经常变化或需要精准路由,**方案2(StatefulSet+Ingress)**是更好的选择,虽然需要一些配置调整,但能满足复杂场景的需求。

内容的提问来源于stack exchange,提问作者Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:06:13