Невозможно подключиться к серверной службе из внешней службы в Kubernetes

Я изо всех сил пытаюсь совершать Http-вызовы из внешнего приложения в серверное приложение в Kubernetes.

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

Это сообщение об ошибке, которое я получаю

ПОЛУЧИТЬ http://spring-boot-vuejs:8080/api/courses net :: ERR_NAME_NOT_RESOLVED

Я пытаюсь создать простое веб-приложение, используя Vuejs в качестве внешнего интерфейса и загрузку Spring как серверную часть. Бэкэнд предоставляет REST api в конечной точке / api / course / *, а интерфейс потребляет его.

Я развернул два отдельных модуля: один для внешнего интерфейса, а другой - для внутреннего в голом железном кластере Kubernetes. Я также установил контроллер входящего трафика Nginx.

если я запустил оба образа докеров на своем локальном компьютере, все будет работать нормально, потому что я использую "http://localhost:8080" в качестве конечной точки серверной части, но в тот момент, когда я развертываю приложения в Kubernetes, он больше не будет работать, поскольку может разрешать имя службы "http://spring-boot-vuejs:8080 "

Я уже упоминал о проблемах, упомянутых здесь, здесь, здесь, но ни один из них мне не помог.

Ниже приведены соответствующие файлы yaml. Пожалуйста, поправьте меня, если я ошибаюсь в каких-либо файлах yaml или правилах входа.

Бэкэнд:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-boot-vuejs
  labels:
    app: spring-boot-vuejs
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-boot-vuejs
  template:
    metadata:
      labels:
        app: spring-boot-vuejs
    spec:
      containers:
        - name: spring-boot-vuejs
          imagePullPolicy: ifNotPresent
          image: <my docker hub username>/spring-boot-vuejs:0.0.1
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: spring-boot-vuejs
  labels:
    app: spring-boot-vuejs
spec:
  clusterIP: None
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
      name: spring-boot-vuejs
  selector:
    app: spring-boot-vuejs

Правила входа

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: spring-boot-vuejs
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  backend:
    serviceName: default-http-backend
    servicePort: 80

  rules:
    - host: spring-boot-vuejs
    - http:
        paths:
          - path: /api/.*
            backend:
              serviceName: spring-boot-vuejs
              servicePort: 8080

Yaml-файлы для внешнего интерфейса

Развертывание и обслуживание

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vuejs-frontend
  labels:
    app: vuejs-frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: vuejs-frontend
  template:
    metadata:
      labels:
        app: vuejs-frontend
    spec:
      containers:
        - name: vuejs-frontend
          imagePullPolicy: ifNotPresent
          image: <my dockerhub username>/vuejs-frontend:0.0.1
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: vuejs-frontend
  labels:
    app: vuejs-frontend
spec:
  clusterIP: None
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
      name: vuejs-frontend
  selector:
    app: vuejs-frontend

Правила входа

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: vuejs-frontend
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /

spec:
  backend:
    serviceName: default-http-backend
    servicePort: 80
  rules:
    - host: spring-boot-vuejs
    - http:
        paths:
          - path: /
            backend:
              serviceName: vuejs-frontend
              servicePort: 8080

person rakesh    schedule 20.04.2020    source источник
comment
spring-boot-vuejs не может быть именем хоста. Какое имя хоста Nginx?   -  person Simon Martinelli    schedule 20.04.2020
comment
Обязательно ли указывать имя хоста? Я удалил его, но все равно не повезло. Это имя модуля сведений о nginx ngress-nginx nginx-ingress-controller-6879cf6459-8cg44 1/1 Running 0 64d Служба Nginx ingress-nginx ingress-nginx NodePort 10.105.123.73 <none> 80:32372/TCP,443:30907/TCP 64d   -  person rakesh    schedule 20.04.2020
comment
Я не думаю, что это ваша проблема ... но вам не нужен входной ресурс для бэкэнда, если ваш интерфейс и бэкэнд находятся в одном кластере k8s. Я бы удалил внутреннюю службу входящего трафика, если вы не хотите, чтобы внешние приложения могли напрямую обращаться к серверной части?   -  person TuxInvader    schedule 20.04.2020
comment
также проверьте свой файл resolv.conf во внешнем интерфейсе ... попробуйте kubectl exec pod/<frontend-pod-name> cat /etc/resolv.conf Что это вернет? Вы должны увидеть список поисковых доменов кластера k8s?   -  person TuxInvader    schedule 20.04.2020
comment
Это то, что у меня /etc/resolv.conf на интерфейсном модуле. # cat /etc/resolv.conf nameserver 10.96.0.10 search vuejs.svc.cluster.local svc.cluster.local cluster.local lswv130.leasewebcloud.com options ndots:5 Я удалил вход для серверной части   -  person rakesh    schedule 21.04.2020
comment
@rakesh, не могли бы вы добавить вывод для kubectl get pods -o wide, а также для служб и конечных точек? Я не заметил селекторов, когда отвечал   -  person Nick    schedule 21.04.2020
comment
@rakesh Удалось ли вам решить эту проблему?   -  person Mark    schedule 28.04.2020
comment
@Hanx нет. Вместо того, чтобы использовать отдельные службы для внешнего интерфейса и внутреннего интерфейса, я объединил интерфейс и серверную часть в один модуль, используя тимелеаф. Итак, у меня больше нет двух сервисов и только одна базовая серверная служба, к которой можно получить прямой доступ.   -  person rakesh    schedule 28.04.2020
comment
Если вы все еще можете предоставить более подробную информацию о предыдущих развертываниях, пожалуйста, поделитесь более подробной информацией: 1. kubectl get pods,svc,ep,ingress, 2. kubectl describe ingress, 3. kubectl logs <your_frontend> (при свертывании изнутри и вне кластера)   -  person Mark    schedule 28.04.2020
comment
@Hanx, извините, я удалил все пространство имен, и у меня больше нет этих данных :(   -  person rakesh    schedule 29.04.2020


Ответы (1)


Если я вас правильно понял, проблема в том, что vuejs-frontend не может достичь spring-boot-vuejs на порту 8080.

Я вижу, что вы создали headless Service (Сервис с clusterIP: None). Более того, у этой службы нет селекторов, указанных в yaml, поэтому не было создано EndPoinds)

Официальная документация по теме гласит:

Иногда вам не нужна балансировка нагрузки и только один IP-адрес службы. В этом случае вы можете создать так называемые «безголовые» службы, явно указав "None" для IP-адреса кластера (.spec.clusterIP).

Для headless Services IP-адрес кластера не выделяется, kube-proxy не обрабатывает эти службы, и платформа не выполняет для них балансировку нагрузки или проксирование. Автоматическая настройка DNS зависит от того, определены ли в службе селекторы.

Для автономных служб, которые не определяют селекторы, контроллер конечных точек не создает Endpoints записей. Однако система DNS ищет и настраивает либо:

  • Записи CNAME для служб типа ExternalName.
  • A записи для любых Endpoints, имеющих общее имя с Сервисом, для всех других типов

Здесь есть несколько решений.

  • создать EP вручную.
apiVersion: v1  
kind: Endpoints  
metadata:  
  name: spring-boot-vuejs  
  namespace: default  
subsets:  
- addresses:  
  - ip: IP_spring-boot-vuejs_pod 
  ports:  
  - name: http  
    port: 8080  
    protocol: TCP

в результате DNS будет настроен правильно.

  • создать Сервис другого типа или хотя бы добавить селекторы к вашему текущему сервису.

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

$ kubectl create -f  deployment.yaml
deployment.apps/server-go-deploy created

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
server-go-deploy      1/1     1            1           9s

$ kubectl create deployment nginx --image=nginx
deployment.apps/nginx created

$ kubectl get pods -o wide 
NAME                         READY   STATUS  AGE     IP           
nginx-65f88748fd-vzgxx       1/1     Running 9m16s   10.52.3.13
server-go-6c84bbd44d-r5bsb   1/1     Running 14m     10.52.3.12

$ kubectl create -f service.yaml 
service/hello-go created

$ kubectl get services   -o wide 
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE    SELECTOR
hello-go     ClusterIP   None          <none>        8180/TCP   13s    <none>
kubernetes   ClusterIP   10.0.0.1      <none>        443/TCP    123d   <none>

$ kubectl exec -it nginx-65f88748fd-vzgxx -- curl hello-go:8180
curl: (6) Could not resolve host: hello-go
command terminated with exit code 6

## As you can see K8s knows nothing that request to 'hello-go' should be routed to 'hello-go' Pod. 

$ kubectl create -f ep.yaml 
endpoints/hello-go created

$ kubectl get ep  -o wide 
NAME         ENDPOINTS            AGE
hello-go     10.52.3.12:8180      3s
kubernetes   35.234.103.244:443   123d

kiwi@kiwi-dv7:~/PycharmProjects/innovative-solutions/61326587-svc$ kubectl exec -it nginx-65f88748fd-vzgxx -- curl hello-go:8180/whoo-hoo
Hello from ServerGo. You requested: /whoo-hoo 

#And now it works.

Надеюсь, это поможет.

person Nick    schedule 21.04.2020
comment
Спасибо за подробное объяснение. Похоже, конечная точка уже создана, и мне не нужно было ее создавать. $ k get ep -o wide NAME ENDPOINTS AGE spring-boot-vuejs 10.1.140.79:8080 24h vuejs-frontend 10.1.196.146:8080 23h Я отправил ssh в модуль vuejs и сделал запись в /etc/hosts файле, например, 10.1.140.79 spring-boot-vuejs. Теперь curl spring-boot-vuejs: 8080 / api / курсы работает как шарм, но если я обращаюсь к модулю внешнего интерфейса vuejs из своего браузера с использованием общедоступного IP-адреса кластера kubernetes, модуль внешнего интерфейса все еще может получить доступ к модулю внутреннего интерфейса. Получение такой же ошибки - person rakesh; 21.04.2020
comment
не уверен, понял ли я тебя. Я прав, что вы установили ssh на Frontend и изменили /etc/hosts там? Так что теперь фронтенд может дойти до бэкэнда. - person Nick; 21.04.2020
comment
Да, я подключился к модулю внешнего интерфейса, добавил имя серверной службы вместе с IP-адресом службы в файле /etc/hosts, и теперь я могу успешно отправить запрос на получение в серверную службу. - person rakesh; 22.04.2020
comment
@rakesh, это всего лишь исправление, основная причина в том, что вы сможете подключиться к нему через службу. Если хотите, мы можем решить эту проблему дальше, но мне понадобится информация из моего последнего комментария. Кроме того, было бы хорошо, если бы вы могли объяснить, какой CNI вы используете, потому что, как я вижу, в DNS уже должна быть запись (служба с селектором) - person Nick; 22.04.2020
comment
Я использовал бязь. Да, это было просто исправление, и я перестал разбираться в проблеме. Спасибо за вашу помощь - person rakesh; 28.04.2020