Как сделать запрос от Flask API в пространстве имен Kubernetes к другому Flask API внутри другого пространства имен внутри (с использованием DNS), используя minikube - PullRequest
0 голосов
/ 18 января 2020

Я прочитал, что мне нужно запустить другую службу в пространстве имен B, которая отображается на службу пространства имен A loadbalancer. (Вы можете увидеть эту услугу на моем yaml b).

Я не хочу использовать внешние IP-адреса, предоставляемые балансировщиком нагрузки (Если мой сценарий был реплицирован в облаке с использованием облака GCP / Azure / AWS / IBM /OpenShift).

Я развернул следующий сценарий, используя minikube v1.6.2 и Kubernetes v1.17 :

Пространство имен a:

deployment/python-hello-world  READY: 1/1

service/python-hello-world  
TYPE: Loadbalancer CLUSTER-IP: 10.96.167.227 EXT-IP: <pending> PORTS: 80:31603/TCP

Пространство имен b:

deployment/python-hello-world  READY: 1/1

service/python-hello-world  
TYPE: Loadbalancer CLUSTER-IP: 10.96.67.10 EXT-IP: <pending> PORTS: 80:31595/TCP

service/connection 
TYPE: ExternalName CLUSTER-IP: <none> EXTERNAL-IP: python-hello-world-external.a.svc.cluster.local PORT: 31603/TCP

Kubernetes yaml a :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-hello-world
  namespace: a
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python-hello-world
  template:
    metadata:
      labels:
        app: python-hello-world
    spec:
      containers:
      - name: server
        image: python-hello-world
        ports:
        - containerPort: 9090
        env:
        - name: PORT
          value: "9090"

---

apiVersion: v1
kind: Service
metadata:
  name: python-hello-world-external
  namespace: a
spec:
  type: LoadBalancer
  selector:
    app: python-hello-world
  ports:
  - name: http
    port: 80
    targetPort: 9090

Kubernetes yaml b :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-hello-world
  namespace: b
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python-hello-world
  template:
    metadata:
      labels:
        app: python-hello-world
    spec:
      containers:
      - name: server
        image: python-hello-world
        ports:
        - containerPort: 9091
        env:
        - name: PORT
          value: "9091"

---

apiVersion: v1
kind: Service
metadata:
  name: python-hello-world-external
  namespace: b
spec:
  type: LoadBalancer
  selector:
    app: python-hello-world
  ports:
  - name: http
    port: 80
    targetPort: 9091

---

apiVersion: v1
kind: Service
metadata:
  name: connection
  namespace: b
spec:
  type: ExternalName
  externalName: python-hello-world-external.a.svc.cluster.local
  ports:
  - port: 31603

Для доступа к API A в моем браузере Я запустил в терминале:

$ minikube service python-hello-world-external -n a
|-----------|-----------------------------|-------------|-----------------------------|
| NAMESPACE |            NAME             | TARGET PORT |             URL             |
|-----------|-----------------------------|-------------|-----------------------------|
| a         | python-hello-world-external | http        | http://192.168.39.196:31603 |
|-----------|-----------------------------|-------------|-----------------------------|

Для доступа к API B :

$ minikube service python-hello-world-external -n b
|-----------|-----------------------------|-------------|-----------------------------|
| NAMESPACE |            NAME             | TARGET PORT |             URL             |
|-----------|-----------------------------|-------------|-----------------------------|
| b         | python-hello-world-external | http        | http://192.168.39.196:31595 |
|-----------|-----------------------------|-------------|-----------------------------|

Flask API A :

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "Hello World A"

if __name__ == '__main__':
    app.run(debug=False, port=9090, host='0.0.0.0')

Flask API B :

import requests
from flask import Flask

app = Flask(__name__)

@app.route('/a')
def call_a():
    response = requests.get("I DONT KNOW WHAT TO PUT HERE")
    return response

if __name__ == '__main__':
    app.run(debug=False, port=9091, host='0.0.0.0') 
  1. Можно ли отправить запрос внутренне с помощью minikube?
  2. Если да, то что-то не хватает в моей конфигурации?
  3. Если это так, какой URL-адрес я пишу в запросах .get ("")?

Ответы [ 2 ]

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

Вот 1 пример доступа к 1 службе API из 2-й службы API, но в том же пространстве имен. Может быть, это поможет.

Создайте 2 API-сервера в Python следующим образом, опробовано и протестировано на моем Minikube. Проведите 1-й в Куберне в качестве услуги ClusterIp. Хост 2-го хоста с использованием NodePort для доступа вне кластера Minikube.

Доступ к 1-му сервису осуществляется через его ClusterIp внутри 2-го сервиса, как показано в коде Python ниже, я пытался получить доступ с использованием имени сервиса, но не смог работа.


Вот 1-й flask сервер API (файл .py), который будет вызываться из 2-го flask сервера API:

import flask
from flask import Flask
import json
from flask import request


application = Flask(__name__)


@application.route('/api/v1/square', methods=['GET'])
def square():
    # sample api call: http://0.0.0.0:8003/api/v1/square?nb1=11
    nb1 = request.args.get('nb1')
    sq_nb1 = int(nb1)*int(nb1)
    return flask.jsonify(sq_nb1)


if __name__ == '__main__':
    application.run(debug=True, host="0.0.0.0", port=8003)

2-й API сервер (файл .py), который вызывает первый сервер API, размещенный как ClusterIP в Kubernetes

import flask
from flask import Flask
import json
from flask import request
import requests


application = Flask(__name__)


@application.route('/api/v1/sumsq', methods=['GET'])
def sumSq():
    # sample api call: http://0.0.0.0:8002/api/v1/sumsq?nb1=111&nb2=222
    nb1 = request.args.get('nb1')
    nb2 = request.args.get('nb2')
    sum_val = int(nb1) + int(nb2)

    #  call square micro-service (Svc: 3-Internal-API-Server)
    api_url = "http://10.96.55.98/api/v1/square?nb1={v}".format(v=sum_val)
    # get IP using 'kubectl get svc -n <ns_name>' command

    res = requests.get(url=api_url)
    sum_sq_val = res.json()
    return flask.jsonify(sum_sq_val)


if __name__ == '__main__':
    application.run(debug=True, host="0.0.0.0", port=8002)
0 голосов
/ 20 января 2020

Как уже предлагали парни в комментариях LoadBalancer не лучший выбор здесь. На самом деле у него совершенно иное назначение, а именно, оно служит для внешней демонстрации вашего приложения, которое, кстати, не будет работать в Minikube предполагаемым образом (вместо этого создается простой NodePort сервис). Чтобы использовать полнофункциональный LoadBalancer, вам необходимо воспользоваться услугами какого-либо облачного провайдера. Все основные игроки, такие как GCP, AWS или Azure поддерживают эту функцию. Возможно, вы решили использовать LoadBalancer для реализации функции балансировки нагрузки, но не беспокойтесь, простой ClusterIP также может это сделать. Если у вас есть, скажем, 3 фронта Pods (обычно управляемый Deployment), и им нужно связаться с 3 другими Pods, которые предоставляют back-end-сервис, простой ClusterIP Сервис (вы можете опустить тип, так как это тип по умолчанию) выполнит работу, включая правильную балансировку нагрузки запросов ко всем базовым серверам Pods. Как сказал @David Maze, ознакомьтесь с этой статьей в официальном Kubernetes docs , и вы должны легко asp изложить всю концепцию.

Здесь Вы можете найти один из моих старых ответов на очень похожую тему c. Я полагаю, что это может оказаться полезным, поскольку в нем подробно объясняется, как следует осуществлять связь между различными наборами Pods, представляющими разные microservices в архитектуре вашего приложения, в Kubernetes Cluster .

* 1028. * Что касается связи между ресурсами, живущими в разных пространствах имен, это также легко сделать в Kubernetes , используя краткую форму, предложенную @jordanm: <service_name>.<namespace> или полностью определенное доменное имя <service-name>.<namespace-name>.svc.cluster.local (даже более рекомендуемое). Подробнее вы можете найти здесь .

Когда вы создаете Сервис , он создает соответствующую DNS-запись . Эта запись имеет вид <service-name>.<namespace-name>.svc.cluster.local, что означает, что если контейнер просто использует <service-name>, он будет преобразован в службу, которая является локальной для пространства имен. Это полезно для использования одной и той же конфигурации в нескольких пространствах имен, таких как разработка, подготовка и производство. Если вы хотите охватить пространства имен, вам нужно использовать полное доменное имя (FQDN).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...