当流量请求到后端ECS,我们可以通过nginx这类的http服务器来实现会话保持,但是在k8s集群中真正提供服务的是Pod,那么如何实现ECS到Pod这条链路的会话保持呢。

service sessionAffinity

通过在service配置文件中加入 sessionAffinity: ClientIP 实现会话保持。

测试例子

该deployment会有2个nginx pod副本,在容器中有postStart钩子函数会将pod名称写入到nginx的index.html中,用来使我们看到会话保持的效果。

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 2
progressDeadlineSeconds: 600
revisionHistoryLimit: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity: {}
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
lifecycle:
postStart:
exec:
command:
- "/bin/sh"
- "-c"
- "echo $POD_NAME > /usr/share/nginx/html/index.html"
resources:
requests:
cpu: 250m
memory: 512Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}

创建service

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

通过不同客户端使用curl访问service地址可以看到会话保持的效果

ingress-nginx

ingress-nginx提供了大量的注释配置来配置会话保持的策略。列举常用的配置如下:

属性名称 描述
nginx.ingress.kubernetes.io/affinity 会话保持类型,设置为cookie为启用会话保持 nginx仅支持cookie
nginx.ingress.kubernetes.io/affinity-mode 定义会话的粘性。balanced在扩展pod时重新分配一些会话;persistent则是保证用户永远访问同一个pod balanced(默认) or persistent
nginx.ingress.kubernetes.io/session-cookie-name cookie的名称 INGRESSCOOKIE(默认)
nginx.ingress.kubernetes.io/session-cookie-max-age cookie过期时间 秒数
nginx.ingress.kubernetes.io/session-cookie-expires 与旧浏览器兼容的旧注释版本。Expires通过将秒数添加到当前日期生成cookie指令 秒数

测试例子

pod与上面使用的一样,修改之前的service

apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: ClusterIP
selector:
app: nginx
ports:
- port: 80
targetPort: 80

创建ingress

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/affinity-mode: "balanced"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
spec:
rules:
- host: nginx.twf.com
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80

最后通过浏览器页面发现同一主机访问显示的都是同一个pod,显示同一个pod的名称。