单个服务公开的多个 Pod 的会话关联设置

Posted

技术标签:

【中文标题】单个服务公开的多个 Pod 的会话关联设置【英文标题】:Session Affinity Settings for multiple Pods exposed by a single service 【发布时间】:2019-10-12 20:59:02 【问题描述】:

我将 Metallb 设置为 LB,并在 K8S 集群上安装了 nginx Ingress。 我已经阅读了有关会话亲和性及其重要性的信息,但到目前为止我还没有清楚的了解。

如何创建一个服务来公开同一应用程序的多个 pod? 创建单服务入口点后,如何将具体的客户端 IP 映射到服务抽象的 Pod 上?

是否有任何博客根据客户端 IP 和 POD 之间的映射是如何在 kubernetes 中完成这个概念来解释这个概念的?

但我在 YAML 中没有看到客户的 IP。那么,该服务如何将流量映射到各个客户端到其端点?这是我的问题。

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10000

【问题讨论】:

因为你使用 nginx 作为入口控制器,我们谈论的是 http 会话,这意味着你需要在入口规则中设置 cookie 粘性,如果你进入 nginx 入口的 github repo控制器,你有很多例子 @c4f4t0r 我想在基于 cookie 之前使用正常的会话亲和性。另外,我想验证一下 Client 请求是否根据其 IP 映射到 Pod。 如果你有web应用根据ip做粘性不太好,如果你有移动用户,ip可以多次变化 我正在尝试首先验证此功能。如果使用粘性会话的 Web 应用程序很有用,那么您是对的。这是我想说的会话控制中更高级的部分。我想我需要先学习基本的映射。 【参考方案1】:

会话关联的主要概念是将流量从一个客户端始终重定向到特定节点。请记住,会话亲和性是一种尽力而为的方法,在某些情况下它会由于 pod 重启或网络错误而失败。 Session Affinity 主要有两种类型:

1) 基于客户端 IP

此选项适用于每个 IP 只有一个客户端的情况。在这种方法中,您不需要 K8s 服务和客户端之间的 Ingress/Proxy。 客户端 IP 应该是静态的,因为每次客户端更改 IP 时,他都会被重定向到另一个 pod。

要在 Kubernetes 中启用会话亲和性,我们可以在服务定义中添加以下内容。

service.spec.sessionAffinity: ClientIP

因为社区提供了适当的清单来使用这种方法,所以我不会重复。

2) 基于 Cookies

当有来自同一个 IP 的多个客户端时,它可以工作,因为它存储在网络浏览器级别。此方法需要 Ingress 对象。可以在 Session affinity based on Cookie 部分下找到应用此方法的步骤以及更详细的信息。

创建 NGINX 控制器部署 创建 NGINX 服务 创建入口 将您的公共 DNS 名称重定向到 NGINX 服务公共/外部 IP。

关于映射ClientIP和POD,根据Documentation kube-proxy 负责 SessionAffinity。 Kube-Proxy 工作之一 正在写信给 IPtables,更多细节here 就是这样 映射。

可能有助于理解 Session Affinity 的文章: https://sookocheff.com/post/kubernetes/building-stateful-services/ https://medium.com/@diegomrtnzg/redirect-your-users-to-the-same-pod-by-using-session-affinity-on-kubernetes-baebf6a1733b

【讨论】:

【参考方案2】:

按照会话亲和性的服务参考

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10000

【讨论】:

是的,到目前为止,我已经看到这个 YAML 到处都被用作示例。但我在 YAML 中没有看到客户的 IP。该服务如何将流量映射到各自的客户端到其端点?这是我的问题。 sessionAffinity: ClientIP 上述属性会根据clientIP将流量路由到同一个后端pod 我们是否需要对 Ingress 文件进行任何更改?或单独的服务文件足以满足上述粘性会话配置。 是的,您可能需要启用 nginx.ingress.kubernetes.io/affinity

以上是关于单个服务公开的多个 Pod 的会话关联设置的主要内容,如果未能解决你的问题,请参考以下文章

Swift:如何设置与其他人优雅混合的音频会话(又名 Pod)

将 Stripe 结帐会话与订阅 webhook 关联

Rails - 多个***域和单个会话/cookie

在 K8s 上使用单个 LoadBalancer 公开多个 TCP/UDP 服务

Hibernate将对象保存到多个会话

如何在多个 apache 服务器上管理单个 PHP5 会话?