Azure 当目标应用程序部署在不同的命名空间中时,使用Nginx入口控制器的AKS中的粘性会话不起作用

Azure 当目标应用程序部署在不同的命名空间中时,使用Nginx入口控制器的AKS中的粘性会话不起作用,azure,nginx,kubernetes,Azure,Nginx,Kubernetes,我在Azure Kubernetes服务(K8S版本1.18.14)群集上部署了以下设置: Nginx通过安装并缩小到单个实例。它部署在名称空间“入口”中 一个简单的有状态应用程序(App A)部署在一个单独的命名空间中,有5个副本。应用程序的“状态”由启动时生成的单个随机整数表示。应用程序公开一个只返回随机int的http端点。它部署在名称空间“test”中 ClusterIP类型的服务A公开了应用程序A的http端口,也部署在命名空间“test”中: 类型为“ExternalName”

我在Azure Kubernetes服务(K8S版本1.18.14)群集上部署了以下设置:

  • Nginx通过安装并缩小到单个实例。它部署在名称空间“入口”中
  • 一个简单的有状态应用程序(App A)部署在一个单独的命名空间中,有5个副本。应用程序的“状态”由启动时生成的单个随机整数表示。应用程序公开一个只返回随机int的http端点。它部署在名称空间“test”中
  • ClusterIP类型的服务A公开了应用程序A的http端口,也部署在命名空间“test”中:
  • 类型为“ExternalName”(代理服务)的服务B指向部署在命名空间“ingress”中的群集名称服务A:
  • 启用粘性会话的应用程序的入口描述符:
问题在于,粘性会话无法正确使用此设置。发出“路由”cookie,但不保证“粘性”。尽管发送了相同的粘性会话cookie,但请求被发送到后端服务的不同POD。确切地说,pod每100个请求更改一次,这似乎是默认的循环设置-在没有启用粘性会话的情况下也是一样的

当所有内容都部署在同一名称空间中并且没有使用“代理”服务时,我能够使粘性会话工作。然后就可以了——携带相同“路由”cookie的请求总是落在同一个pod上

但是,我的安装程序使用多个名称空间,建议在其他名称空间中部署的应用程序上使用入口,并使用代理服务


有什么办法解决这个问题吗?

这是一个社区维基答案。请随意扩展它

有两种方法可以解决此问题:

  • 常见方法:将入口规则部署在它们配置的应用所在的同一命名空间中

  • 潜在的棘手方法:尝试使用
    ExternalName
    服务类型。您可以使用命名空间a中的
    ExternalName
    类型定义入口和服务,而
    ExternalName
    指向命名空间B中服务的DNS。有两个写得很好的答案更详细地解释了这种方法:

    请注意并记住:

    警告:对于一些常见协议,包括HTTP和HTTPS,使用ExternalName时可能会遇到问题。如果使用ExternalName,则 集群内客户端使用的主机名与 ExternalName引用的名称

    对于使用主机名的协议,此差异可能会导致错误或错误 意外的反应。HTTP请求将有一个
    主机:
    头 源服务器无法识别;TLS服务器将无法 提供与客户端连接的主机名匹配的证书 对


    你好@vap78。我正在调查你的问题。如前所述,您是否尝试使用值为
    persistent
    nginx.ingres.kubernetes.io/affinity mode
    注释?@WytrzymałyWiktor是-我也尝试了此选项-效果相同。只要服务的类型为ExternalName,会话关联cookie就无效。顺便说一句,我找到了一个解决这个特定场景的方法(尽管它可能不适用于所有场景)-可以在“测试”命名空间中部署ingres,然后它可以直接使用服务a。我仍然想知道为什么它不能与ExternalName服务一起工作。Hi@vap78。很抱歉反应太晚。有进展吗?你还需要帮助吗?抱歉-没有注意到这个问题。到目前为止,我找到的唯一可行的解决方案是,对于需要粘性会话的入口,不使用ExternalName类型的服务。
    apiVersion: v1
    kind: Service
    metadata:
      name: stateful-service
      namespace: "test"
    spec:
      selector:
        app: stateful
      ports:
        - name: http
          port: 80
          targetPort: 8080
      type: ClusterIP
    
    apiVersion: "v1"
    kind: "Service"
    metadata:
      name: "stateful-proxy-service"
      namespace: "ingress"
    spec:
      type: "ExternalName"
      externalName: "stateful-service.test.svc.cluster.local"
    
    apiVersion: extensions/v1beta1
    kind: "Ingress"
    metadata:
      annotations:
        kubernetes.io/ingress.class: internal
        nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
        nginx.ingress.kubernetes.io/affinity: "cookie"
        nginx.ingress.kubernetes.io/session-cookie-name: "route"
      name: "ingress-stateful"
      namespace: "ingress"
    spec:
      rules:
        - host: stateful.foo.bar
          http:
            paths:
              - path: /
                backend:
                  serviceName: "stateful-proxy-service"
                  servicePort: 80