Назад | Перейти на главную страницу

Несоответствие между запросом внешнего IP-адреса и правилом переадресации k8s service target

У нас есть два отдельных поддомена, каждый на отдельном внешнем IP-адресе, и каждый соответствует своей собственной службе kubernetes nginx. Конфигурация выглядит так:

#--------------------
# config for administrative nginx ssl termination deployment and associated service


apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: admin-nginx
labels:
  name: admin-nginx
spec:
replicas: 1
template:
  metadata:
    name: admin-nginx
    labels:
      name: admin-nginx
  spec:
    nodeSelector:
      cloud.google.com/gke-nodepool: currentNodePool
    containers:
    - name: admin-nginx
      image: path/to/nginx-ssl-image:1
      ports:
        - name: admin-http
          containerPort: 80
        - name: admin-https
          containerPort: 443

apiVersion: v1
kind: Service
metadata: 
name: admin-nginx
spec: 
ports: 
  - name: https
    port: 443
    targetPort: admin-https
    protocol: TCP
  - name: http
    port: 80
    targetPort: admin-http
    protocol: TCP
selector: 
  name: admin-nginx
type: LoadBalancer


#--------------------
# config for our api's nginx ssl termination deployment and associated service


apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: public-nginx
labels:
  name: public-nginx
spec:
replicas: 2
strategy:
  rollingUpdate:
    maxUnavailable: 0
template:
  metadata:
    labels:
      name: public-nginx
  spec:
    nodeSelector:
      cloud.google.com/gke-nodepool: currentNodePool
    containers:
    - name: public-nginx
      image: path/to/nginx-ssl-image:1
      ports:
        - name: public-http
          containerPort: 80
        - name: public-https
          containerPort: 443


apiVersion: v1
kind: Service
metadata: 
name: public-nginx
spec: 
ports: 
  - name: https
    port: 443
    targetPort: public-https
    protocol: TCP
  - name: http
    port: 80
    targetPort: public-http
    protocol: TCP
selector: 
  name: public-nginx
type: LoadBalancer


#--------------------

Внутри нашего кластера kubernetes у нас есть, связанный с каждым развертыванием nginx, настраиваемый маршрутизатор / шлюз API, который мы используем внутри. Каждый из этих маршрутизаторов имеет конечную точку / health для, ах, проверок работоспособности. Это будет важно через секунду.

Некоторые из вышеперечисленных деталей опущены; есть также небольшая конфигурация, которая сообщает nginx об адресе и порту целевой службы.

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

{"kubernetes.io/service-name":"default/admin-nginx"}

Также создается соответствующая запись брандмауэра с аналогичной аннотацией в поле описания:

{"kubernetes.io/service-name":"default/admin-nginx", "kubernetes.io/service-ip":"external.ip.goes.here"}

Затем внешние IP-адреса подключаются к одному из наших поддоменов через службу DNS CloudFlare.

В идеале, как это все должно работать и как это работало в прошлом, выглядит следующим образом.

Входящий запрос к admin.ourdomain.com/health возвращает страницу состояния работоспособности для всего, что обрабатывается развертыванием маршрутизатора API (ну, служба, указывающая на модули, которые все равно реализуют это развертывание), которая имеет дело с административными материалами. Он делает это с помощью модуля nginx, на который указывает служба nginx, на которую указывает аннотация описания правила пересылки, на которую указывает диспетчер внешних IP-адресов GCE и брандмауэр, хотя я не совсем понимаю заказ этой последней части.

Как это:

server          status  lookupMicros
https://adminservice0:PORT/health    Ok  910
https://adminservice1:PORT/health    Ok  100
https://adminservice2:PORT/health    Ok  200
https://adminservice3:PORT/health    Ok  876

И так далее.

Между тем, запрос к public.ourdomain.com/health должен возвращать почти то же самое, за исключением общедоступных сервисов.

Как это:

server          status  lookupMicros
https://service0:PORT/health    Ok  910
https://service1:PORT/health    Ok  100
https://service2:PORT/health    Ok  200
https://service3:PORT/health    Ok  876

И т.п.

Довольно разумно, правда?

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

Только ... Я сейчас не это вижу. Вместо этого я вижу следующее: каждая пара обновлений на admin.ourdomain.com/health, который определенно находится на другом IP-адресе, чем общедоступный поддомен, возвращает страницу работоспособности для общедоступного поддомена. Это плохо.

С другой стороны, я по какой-то причине не вижу, чтобы запросы, предназначенные для общедоступного поддомена / health, в конечном итоге возвращали результаты со стороны администратора, но это все равно довольно тревожно.

Что бы ни происходило, также может быть интересно отметить, что запросы, отправленные с неправильной стороны, например admin.ourdomain.com/publicendpoint, отправляются правильно. Я предполагаю, что это только потому, что / health является единственной конечной точкой, которая по своей сути принадлежит маршрутизатору API, и, кроме того, это подтверждает тот факт, что все, что происходит, похоже, происходит из-за проблемы на пути от правила пересылки GCE к правильный сервис Kubernetes.

Итак, я думаю, мы наконец подошли к той части, где я задаю вопрос. Поехали:

Почему запросы через внешний IP-адрес, связанные с правилом переадресации, нацеленным на конкретную службу Kubernetes, периодически отправляются не в ту службу Kubernetes?

Мы будем благодарны за любую помощь или информацию по этому вопросу.