Problems configuring Ingress with cookie affinity

9/10/2019

I was looking for how to use cookie affinity in GKE, using Ingress for that.

I've found the following link to do it: https://cloud.google.com/kubernetes-engine/docs/how-to/configure-backend-service

I've created a yaml with the following:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-bsc-deployment
spec:
  selector:
    matchLabels:
      purpose: bsc-config-demo
  replicas: 3
  template:
    metadata:
      labels:
        purpose: bsc-config-demo
    spec:
      containers:
      - name: hello-app-container
        image: gcr.io/google-samples/hello-app:1.0
---
apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: my-bsc-backendconfig
spec:
  timeoutSec: 40
  connectionDraining:
    drainingTimeoutSec: 60
  sessionAffinity:
    affinityType: "GENERATED_COOKIE"
    affinityCookieTtlSec: 50
---
apiVersion: v1
kind: Service
metadata:
  name: my-bsc-service
  labels:
    purpose: bsc-config-demo
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-bsc-backendconfig"}}'
spec:
  type: NodePort
  selector:
    purpose: bsc-config-demo
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-bsc-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-bsc-service
          servicePort: 80
---

Everything seems to go well. When I inspect the created Ingress I see 2 backend services. One of them has the cookie configured, but the other doesn't.

If I create the deployment, and from GCP's console, create the Service and Ingress, only one backend service appears.

Somebody knows why using a yaml I get 2, but doing it from console I only get one?

Thanks in advance

Oscar

-- blue
affinity
cookies
google-kubernetes-engine
kubernetes
kubernetes-ingress

2 Answers

9/10/2019

You can enable the cookies on the ingress like

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-sticky
  annotations:
    nginx.ingress.kubernetes.io/affinity: "cookie"
    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: ingress.example.com
    http:
      paths:
      - backend:
          serviceName: http-svc
          servicePort: 80
        path: /

You can create the service like :

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

If you are using the traefik ingress instead of the nginx and deault GKe ingress you can write the service like this

apiVersion: v1
kind: Service
metadata:
  name: session-affinity
  labels:
    app: session-affinity
  annotations:
    traefik.ingress.kubernetes.io/affinity: "true"
    traefik.ingress.kubernetes.io/session-cookie-name: "sticky"
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: session-affinity-demo
-- Harsh Manvar
Source: StackOverflow

9/12/2019

Your definition is good.

The reason you have two backend's is because your ingress does not define a default backend. GCE LB require a default backend so during LB creation, a second backend is added to the LB to act as the default (this backend does nothing but serve 404 responses). The default backend does not use the backendConfig.

This shouldn't be a problem, but if you want to ensure only your backend is used, define a default backend value in your ingress definition by adding the spec.backend:

apiVersion: extensions/v1beta1 kind: Ingress metadata: name: my-bsc-ingress spec: backend: serviceName: my-bsc-service servicePort: 80 rules:

  • http: paths:
    • path: /* backend: serviceName: my-bsc-service servicePort: 80

But, like I said, you don't NEED to define this, the additional backend won't really come into play and no sessions affinity is required (there is only a single pod anyway). If you are curious, the default backend pod in question is called l7-default-backend-[replicaSet_hash]-[pod_hash] in the kube-system namespace

-- Patrick W
Source: StackOverflow