一、什么时候需要多端口 Service

如果一个应用同时暴露多个功能端口,就不能只写一个 ports 条目。原文用 RabbitMQ 做了非常典型的示例:

  • 15672:管理界面
  • 5672:AMQP 业务端口

对应的 Service 可以这样定义:

apiVersion: v1
kind: Service
metadata:
  name: rabbitmq
spec:
  type: NodePort
  selector:
    app: rabbitmq
  ports:
  - name: http
    protocol: TCP
    port: 15672
    targetPort: 15672
  - name: amqp
    protocol: TCP
    port: 5672
    targetPort: 5672

这里最重要的规则是:只要定义多个端口,就应该给每个端口都起名字,避免歧义。

二、多端口 Service 创建后怎么看

原文创建后通过 kubectl get svc 看到:

15672:32082/TCP,5672:30563/TCP

这表示:

  • 管理端口通过某个 NodePort 对外开放
  • AMQP 端口也通过另一个 NodePort 对外开放

对像 RabbitMQ 这种既有人机管理入口、又有程序访问入口的中间件来说,这种方式非常常见。

三、会话保持解决的是什么问题

默认情况下,Service 会把请求分发到多个后端 Pod,客户端的连续请求不一定落到同一个实例上。对大多数无状态服务这没有问题,但如果你希望短期内来自同一客户端的请求尽量命中同一后端,就可以启用会话保持。

Kubernetes Service 上配置会话保持的正确方式是:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800

这里真正生效的关键字段是 sessionAffinity: ClientIP

四、怎么验证请求是否被“粘”到了同一个 Pod

原文先创建了 3 副本 nginx:

kubectl create deploy nginx --image=registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 -r 3
kubectl get pods -o wide | grep nginx

然后多次访问同一个 Service:

curl 10.97.146.170:80/admin

再分别看 3 个 Pod 的日志。结果是请求主要落在其中一个 Pod,而不是轮询地散到 3 个实例上,这就说明粘性会话已经生效。

五、会话保持适合哪里,不适合哪里

原文特别提醒了一点:集群内部可以通过 Service 实现会话保持,但集群外部访问通常不建议继续靠 Service 来做,而是更适合通过 Ingress 或更上层网关实现。

原因很简单:

  • Service 的会话保持能力偏基础
  • 集群外入口通常还要结合域名、TLS、路径路由和网关策略
  • 更复杂的粘性策略往往应放在 Ingress/LB 层

六、怎么理解这两个特性的关系

多端口 Service 和会话保持看起来是两件事,背后其实都在回答同一个问题:Service 不只是“把端口映射出去”,它还负责表达流量应该以什么方式进入后端。

一个负责“开放哪些入口”,一个负责“入口进来后怎么分发”,两者配合起来,才更接近真实业务网络需求。