Условный обратный прокси в kubernetes на основе ответа сервера - PullRequest
1 голос
/ 03 апреля 2020

TLDR: я ищу решение, которое позволило бы мне прокси-трафик c между двумя различными сервисами Kubernetes на основе их ответа.

Справочная информация: у меня есть выходящее приложение, размещенное в Kubernetes. Недавно я начал переписывать один из своих микросервисов, чтобы ускорить его и добавить несколько новых функций. Я хочу позволить моим пользователям решать, хотят ли они начать использовать эту новую услугу или придерживаться старой (поскольку некоторые функции имеют критические изменения для своего варианта использования). Поскольку пользователи обычно обращаются к этому микросервису, используя адрес, такой как username.given-microservice.example.com, я изначально планировал установить прокси-сервер между этими службами, который мог бы запрашивать одну из моих конечных точек с помощью запроса, например: http://my-new-service.example.com/enabled-for-client?=username

  • если он вернул код 200, тогда клиент будет перенаправлен на новую услугу
  • , если код ответа был чем-то еще, то клиент будет перенаправлен на старый service.

Конечно, ответ от URI выше будет зависеть от пользовательских настроек.

Этот сценарий очень похож на A / B-тестирование, но я не знаю и не имею проблема с поиском любого способа настроить прокси на основе ответа URL.

Я был бы очень признателен за любые предложения, сообщения в блогах или ссылки на документацию, которые могли бы помочь мне решить мой сценарий - в тот момент, когда у меня кончились идеи, я чувствую себя застрявшим.

Ответы [ 2 ]

0 голосов
/ 06 апреля 2020

Этого можно добиться, используя NGINX Вход с аннотациями custom-http-errors и default-backend.

Я создал лабораторию, чтобы доказать эту концепцию. Давайте погрузимся в это вместе.

Прежде всего вам необходимо установить NGINX Ingress в вашем кластере. Если у вас его нет, следуйте руководству по установке .

. На этом ПО C мы развернем 2 разных приложения. Один из них называется old-http-backend и обслуживает целевую страницу по умолчанию nginx. Второй называется new-http-backend и обслуживает целевую страницу echo-server.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: old-http-backend
spec:
  selector:
    matchLabels:
      app: old-http-backend
  template:
    metadata:
      labels:
        app: old-http-backend
    spec:
      containers:
      - name: old-http-backend
        image: nginx
        ports:
        - name: http
          containerPort: 80
        imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
  name: old-http-backend
spec:
  selector:
    app: old-http-backend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: new-http-backend
spec:
  selector:
    matchLabels:
      app: new-http-backend
  template:
    metadata:
      labels:
        app: new-http-backend
    spec:
      containers:
      - name: new-http-backend
        image: inanimate/echo-server
        ports:
        - name: http
          containerPort: 8080
        imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
  name: new-http-backend
spec:
  selector:
    app: new-http-backend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

После применения этого манифеста у нас есть следующие развертывания и службы:

$ kubectl get deployments 
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
new-http-backend   1/1     1            1           2s
old-http-backend   1/1     1            1           43m
$ kubectl get service
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes         ClusterIP   10.31.240.1     <none>        443/TCP   152m
new-http-backend   ClusterIP   10.31.240.168   <none>        80/TCP    44m
old-http-backend   ClusterIP   10.31.242.175   <none>        80/TCP    44m

И теперь мы можем применить наш Ingress, который будет отвечать за то, что сделали за нас все маги c:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-app-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: "/"
    nginx.ingress.kubernetes.io/custom-http-errors: '403,404,500,502,503,504'
    nginx.ingress.kubernetes.io/default-backend: old-http-backend
spec:
  rules:
  - host: app.company.com
    http:
      paths:
      - path: "/"
        backend:
          serviceName: new-http-backend
          servicePort: 80

Что делает этот вход?

В документации по пользовательским ошибкам HTTP мы не можем прочитать, что если на входе указана стандартная аннотация по умолчанию , ошибки будут перенаправляться в базовую службу этой аннотации по умолчанию (вместо глобальной бэкэнд по умолчанию).

Поэтому, вставляя эти аннотации в наше правило входа, мы говорим, что все запросы должны go new-http-backend, если только он не получит код возврата, указанный в custom-http-errors. Если это произойдет, пользователь будет перенаправлен на old-http-backend, как указано в аннотации default-backend.

nginx.ingress.kubernetes.io/custom-http-errors: '403,404,500,502,503,504'
nginx.ingress.kubernetes.io/default-backend: old-http-backend
0 голосов
/ 03 апреля 2020

Посланник может управлять таким сценарием, начните с просмотра HTTP маршрутизация . Если вы не можете найти то, что ищете, вы всегда можете написать правила фильтрации / маршрутизации в Lua.

...