Session Persistence
4 minute read
Session Persistence allows client requests to be consistently routed to the same backend service instance. This is useful in many scenarios, such as when an application needs to maintain state across multiple requests. In Envoy Gateway, session persistence can be enabled by configuring HTTPRoute.
Envoy Gateway supports following session persistence types:
- Cookie-based Session Persistence: Session persistence is achieved based on specific cookie information in the request.
- Header-based Session Persistence: Session persistence is achieved based on specific header information in the request.
Prerequisites
Install Envoy Gateway
Follow the steps below to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP.
Expand for instructions
Install the Gateway API CRDs and Envoy Gateway using Helm:
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.3.2 -n envoy-gateway-system --create-namespace
Install the GatewayClass, Gateway, HTTPRoute and example app:
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.3.2/quickstart.yaml -n default
Verify Connectivity:
You can also test the same functionality by sending traffic to the External IP. To get the external IP of the Envoy service, run:
export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')
Note: In certain environments, the load balancer may be exposed using a hostname, instead of an IP address. If so, replace
ip
in the above command withhostname
.Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/get
Get the name of the Envoy service created by the example Gateway:
export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')
Port forward to the Envoy service:
kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 &
Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://localhost:8888/get
For better testing the session persistence, you can add more hosts in upstream cluster by increasing the replicas of one deployment:
kubectl patch deployment backend -n default -p '{"spec": {"replicas": 4}}'
Cookie-based Session Persistence
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: cookie
spec:
parentRefs:
- name: eg
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: backend
port: 3000
sessionPersistence:
sessionName: Session-A
type: Cookie
absoluteTimeout: 10s
cookieConfig:
lifetimeType: Permanent
EOF
Save and apply the following resource to your cluster:
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: cookie
spec:
parentRefs:
- name: eg
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: backend
port: 3000
sessionPersistence:
sessionName: Session-A
type: Cookie
absoluteTimeout: 10s
cookieConfig:
lifetimeType: Permanent
After updating the
ConfigMap
, you will need to wait the configuration kicks in.
You can force the configuration to be reloaded by restarting theenvoy-gateway
deployment.kubectl rollout restart deployment envoy-gateway -n envoy-gateway-system
Testing
Send a request to get a cookie and test:
COOKIE=$(curl --verbose http://localhost:8888/get 2>&1 | grep "set-cookie" | awk '{print $3}')
for i in `seq 5`; do
curl -H "Cookie: $COOKIE" http://localhost:8888/get 2>/dev/null | grep pod
done
You can see all responses are from the same pod:
"pod": "backend-765694d47f-lxwdf"
"pod": "backend-765694d47f-lxwdf"
"pod": "backend-765694d47f-lxwdf"
"pod": "backend-765694d47f-lxwdf"
"pod": "backend-765694d47f-lxwdf"
Wait for cookie expiration, test again:
sleep 10 && for i in `seq 5`; do
curl -H "Cookie: $COOKIE" -H "Host: www.example.com" http://localhost:8888/get 2>/dev/null | grep pod
done
"pod": "backend-765694d47f-kvwqb"
"pod": "backend-765694d47f-lxwdf"
"pod": "backend-765694d47f-kvwqb"
"pod": "backend-765694d47f-2ff9s"
"pod": "backend-765694d47f-lxwdf"
Due to cookie expiration, no session any more.
Header-based Session Persistence
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: header
spec:
parentRefs:
- name: eg
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: backend
port: 3000
sessionPersistence:
sessionName: Session-A
type: Header
absoluteTimeout: 10s
EOF
Save and apply the following resource to your cluster:
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: header
spec:
parentRefs:
- name: eg
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: backend
port: 3000
sessionPersistence:
sessionName: Session-A
type: Header
absoluteTimeout: 10s
Testing
Send a request to get a cookie and test:
HEADER=$(curl --verbose http://localhost:8888/get 2>&1 | grep "session-a" | awk '{print $3}')
for i in `seq 5`; do
curl -H "Session-A: $HEADER" http://localhost:8888/get 2>/dev/null | grep pod
done
You can see all responses are from the same pod:
"pod": "backend-765694d47f-gn7q2"
"pod": "backend-765694d47f-gn7q2"
"pod": "backend-765694d47f-gn7q2"
"pod": "backend-765694d47f-gn7q2"
"pod": "backend-765694d47f-gn7q2"
We remove the header and test again:
for i in `seq 5`; do
curl http://localhost:8888/get 2>/dev/null | grep pod
done
"pod": "backend-765694d47f-2ff9s"
"pod": "backend-765694d47f-kvwqb"
"pod": "backend-765694d47f-2ff9s"
"pod": "backend-765694d47f-lxwdf"
"pod": "backend-765694d47f-kvwqb"
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.