У нас есть два отдельных поддомена, каждый на отдельном внешнем 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?
Мы будем благодарны за любую помощь или информацию по этому вопросу.