kubernetes session会话保持
前提
基于kubernetes部署Java项目,发现在多pod模式下,会出现登录成功但是页面无法跳转的问题,在单一pod时却可以成功登录并页面正常跳转,于是推测是cookie的问题。
网上的大部分文章提供的解决方案都是在service的配置文件中加入sessionAffinity: ClientIP
,功能是选择与请求来源ip更接近的pod,这样就会固定同一个session,但是好像并不适用于我这个项目。
最终的解决当然还是要靠自己读官方的文档,ingress-nginx
有大量的注释配置,官方针对这种情况已经做了说明,需要细细阅读,详见Cookie affinity。
解决方案
注释nginx.ingress.kubernetes.io/affinity
在Ingress的所有上游中启用和设置相似性类型。这样,请求将始终定向到同一上游服务器。Nginx唯一可用的相似性类型是cookie
。
如果为一个主机定义了多个
Ingress nginx.ingress.kubernetes.io/affinity: cookie
,并且至少一个Ingress使用,则只有Ingress使用的路径nginx.ingress.kubernetes.io/affinity
将使用会话Cookie相似性。通过随机选择后端服务器,可以在主机的其他入口定义的所有路径进行负载均衡。
如果您使用Cookie affinity
,则还可以使用注释nginx.ingress.kubernetes.io/session-cookie-name
来指定将用于路由请求的cookie名称。 默认是创建一个名为INGRESSCOOKIE
的cookie。
注释nginx.ingress.kubernetes.io/affinity-mode
定义了会话的粘性。如果将部署规模扩大,balance
则将此选项设置为(默认)将重新分配一些会话,从而重新平衡服务器上的负载。将此设置为persistent
不会重新平衡与新服务器的会话,因此提供了最大的粘性。
以上是官方文档的直译。
简而言之,在ingress-nginx
配置中应做以下操作:
-
设置
nginx.ingress.kubernetes.io/affinity
属性,启用会话保持。 -
设置
nginx.ingress.kubernetes.io/affinity-mode
属性,设置为balance
在集群扩大pod时,会自动分配一些会话到新创建的pod上,用于平衡服务器的负载;设置为persistent
则永远保证用户访问pod的一致性,不会访问到其他pod。 -
设置
nginx.ingress.kubernetes.io/session-cookie-name
属性,自定义cookie名称。
可见cookie示例。
对我用到了其中的三个属性进行描述:
属性名称 | 描述 | 值 |
---|---|---|
nginx.ingress.kubernetes.io/affinity | 亲和力类型,设置该属性为 cookie 来启用会话保持 |
仅支持设置为cookie |
nginx.ingress.kubernetes.io/affinity-mode | 定义会话的粘性。 进行集群的扩容时,可设置为balanced 属性来重新分配某些会话,或者使用persistent 来保证用户永远访问至同一个pod。 |
balanced (默认设置) or persistent
|
nginx.ingress.kubernetes.io/session-cookie-name | 将要被创建的cookie名称 | 默认设置为 INGRESSCOOKIE ,可自定义 |
配置文件
使用session会话保持可以用于解决多tomcat的pod下,登录由于session问题导致页面无法跳转的问题。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-tomcat
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/affinity-mode: "persistent"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
spec:
tls:
- hosts:
- your.host.cn
secretName: https-secret
rules:
- host: your.host.cn
http:
paths:
- path:
backend:
serviceName: your service name
servicePort: 8280
以下为其他网友提供的解决方案:
在service的配置文件中加入sessionAffinity: ClientIP
,功能是选择与请求来源ip更接近的pod,这样就会固定同一个session。
apiVersion: v1
kind: Service
metadata:
name: tomcat
namespace: default
spec:
selector:
app: tomcat
release: canary
ports:
- name: http
targetPort: 8280
port: 8280
sessionAffinity: ClientIP
欢迎访问我的个人博客:Lemon - 万事顺遂