使用 cookie affinity 配置 Ingress 时出现问题

Problems configuring Ingress with cookie affinity

我一直在寻找如何在 GKE 中使用 cookie affinity,为此使用 Ingress。

我发现以下 link 可以做到这一点:https://cloud.google.com/kubernetes-engine/docs/how-to/configure-backend-service

我创建了一个包含以下内容的 yaml:

---
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
---

一切似乎都很顺利。当我检查创建的 Ingress 时,我看到了 2 个后端服务。其中一个设置了cookie,另一个没有。

如果我创建部署,并从 GCP 的控制台创建服务和入口,则只会出现一个后端服务。

有人知道为什么使用 yaml 我得到 2 个,但从控制台执行它我只得到一个?

提前致谢

奥斯卡

您可以像

那样在入口处启用 cookie
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: /

您可以像这样创建服务:

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

如果您使用的是 traefik ingress 而不是 nginx 和 deault GKe ingress,您可以像这样编写服务

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

你的定义很好

你有两个后端的原因是你的入口没有定义默认后端。 GCE LB 需要一个默认后端,因此在 LB 创建期间,第二个后端被添加到 LB 作为默认后端(这个后端除了提供 404 响应外什么都不做)。默认后端不使用backendConfig。

这应该不是问题,但如果您想确保仅使用您的后端,请通过添加 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

但是,就像我说的,您不需要定义它,额外的后端不会真正发挥作用,也不需要会话关联(反正只有一个 pod)。如果你很好奇,有问题的默认后端 pod 在 kube-system 命名空间

中称为 l7-default-backend-[replicaSet_hash]-[pod_hash]