如何仅在一个后端服务上使用 nginx-ingress 应用会话粘性?

How do I apply session stickiness with nginx-ingress on just one backend service?

我有一个具有多个后端的 Ingress 对象,如下所示:

kind: Ingress
apiVersion: extensions/v1beta1
metadata:
  name: my-app
  annotations:
    certmanager.k8s.io/issuer: letsencrypt-prod
    fabric8.io/generated-by: exposecontroller
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: 'true'
    nginx.ingress.kubernetes.io/affinity: cookie
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/proxy-body-size: 500m
    nginx.ingress.kubernetes.io/session-cookie-expires: '172800'
    nginx.ingress.kubernetes.io/session-cookie-max-age: '172800'
spec:
  tls:
    - hosts:
        - my-app.<tld>
      secretName: tls-my-app
  rules:
    - host: my-app.<tld>
      http:
        paths:
          - path: /_ui/
            backend:
              serviceName: ui
              servicePort: 443
          - backend:
              serviceName: api
              servicePort: 443

我的 api 服务只需要会话粘性。但是 nginx.ingress.kubernetes.io/affinity: cookie 注解适用于所有后端服务。有人知道我怎样才能完成我需要的吗?

注释是在您的 Ingress 对象上定义的 applied to every path(位置)。如果您需要为每个路径使用不同的注释,您可以为每个 path:

创建一个不同的 Ingress
  • Annotations are applied to all the paths in the Ingress.
  • Multiple Ingresses can define different annotations. These definitions are not shared between Ingresses.
  • If multiple Ingresses define different paths for the same host, the ingress controller will merge the definitions.

Nginx Ingress Controller 将观察并收集那些 Ingress 规则,并相应地应用它们。

例如:

kind: Ingress
apiVersion: extensions/v1beta1
metadata:
  name: my-app-ui
  annotations:
    certmanager.k8s.io/issuer: letsencrypt-prod
    fabric8.io/generated-by: exposecontroller
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: 'true'
    # No session affinity here
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/proxy-body-size: 500m
    nginx.ingress.kubernetes.io/session-cookie-expires: '172800'
    nginx.ingress.kubernetes.io/session-cookie-max-age: '172800'
spec:
  tls:
    - hosts:
        - my-app.<tld>
      secretName: tls-my-app
  rules:
    - host: my-app.<tld>
      http:
        paths:
          - path: /_ui/
            backend:
              serviceName: ui
              servicePort: 443
---
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
  name: my-app-api
  annotations:
    certmanager.k8s.io/issuer: letsencrypt-prod
    fabric8.io/generated-by: exposecontroller
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: 'true'
    nginx.ingress.kubernetes.io/affinity: cookie  # <-- Session affiniy is here
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/proxy-body-size: 500m
    nginx.ingress.kubernetes.io/session-cookie-expires: '172800'
    nginx.ingress.kubernetes.io/session-cookie-max-age: '172800'
spec:
  tls:
    - hosts:
        - my-app.<tld>
      secretName: tls-my-app
  rules:
    - host: my-app.<tld>
      http:
        paths:
          - path: /_api/
            backend:
              serviceName: api
              servicePort: 443
---

注意:API extensions/v1beta1 在 Kubernetes 1.16 上是 deprecated。考虑迁移到 networking.k8s.io/v1beta1.