一、什么时候需要多端口 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 不只是“把端口映射出去”,它还负责表达流量应该以什么方式进入后端。
一个负责“开放哪些入口”,一个负责“入口进来后怎么分发”,两者配合起来,才更接近真实业务网络需求。