Kubernetes前端和后端之间的通信

时间:2017-07-18 11:23:58

标签: kubernetes

对于本地开发,我有一个工作的迷你管。我们部署了不同的服务。现在我想将前端连接到后端。

前端是一个有棱有角的应用程序,并以自己的服务为生。 后端是一个node.js应用程序,它也使用单独的服务,并使用DNS连接到其他内部服务,如mongodb。

现在我想从前端与后端进行沟通。 DNS无法正常工作,因为前端不知道如何解析命名路由。问题是告诉前端它应该使用哪个后端URL和端口来发送请求?

当我第一次使用NodePort类型启动Backend服务并将url和port复制到Frontends目标URL时,接近了唯一的工作状态。我觉得这对我来说非常不洁净。是否有另一种方法可以将后端请求的URL添加到前端?

我知道当我们在具有type =“LoadBalancer”的生产系统上部署服务时,该服务是由外部IP公开的,我可以从那里访问该服务。并且外部IP将在pod更新等方面永久保留。我还看到的问题是后端IP需要通过额外的提交注入到docker容器中。

编辑(1):后端服务

apiVersion: v1
kind: Service
metadata:
  name: backend
  labels:
    app: some-app
    tier: backend
spec:
  type: NodePort
  ports:
  - port: 3000
  selector:
    app: some-app
    tier: backend

编辑(2):当我从客户端请求fqn:

时,我也收到此响应
OPTIONS http://backend.default.svc.cluster.local:3000/signup/ net::ERR_NAME_NOT_RESOLVED

4 个答案:

答案 0 :(得分:5)

首先,我将尝试解决您的具体问题

  

当我第一次启动后端时,接近了唯一的工作状态   使用NodePort类型的服务并将url和端口复制到   前端目标URL。我觉得这对我来说非常不洁净。在那儿   另一种获取后端请求的URL的方法   前端?

这里有几个选项1)如你所说,使用type =" LoadBalancer"。或2)通过前端服务器代理所有后端呼叫

  

我知道何时在生产系统上部署服务   类型="负载平衡器"该服务由外部IP公开   我可以从那里访问该服务。而外部IP   将永久保存在pod更新等等。我也看到的问题是   需要将后端IP注入到docker容器中   一个额外的提交。

  1. 通过将配置从您的代码移动到平台(让他们说到k8s配置图或外部KV注册表,如此,使其成为12因素应用程序(或距离12因素应用程序更近一步:))领事/尤里卡)
  2. 即使它在代码中留下,正如您所说,外部IP将是可参考的,除非您这样做,否则它不会改变。我不明白为什么你需要另一次部署
  3. 通过前端服务器代理所有后端呼叫

    如果您通过前端的服务器端路由(或愿意路由)所有微服务/后端呼叫,并且如果将前端和后端部署在同一命名空间中的同一k8s群集中,那么您可以使用KubeDNS附加组件(如果它尚未在您的k8s群集中可用,您可以与k8s管理员联系)将后端服务名称解析为它的IP。从您的前端服务器,您的后端服务将始终以其名称解析。

    由于您的k8s群集中有kubeDNS,并且前端和后端服务都驻留在相同的k8s群集和相同的命名空间中,我们可以使用k8s'内置服务发现机制。后端服务和前端服务将以其名称相互发现。这意味着,您只需使用DNS名称" backend"从前端 pods 获取后端服务。因此,只需通过前端nginx将所有后端请求代理到您的上游后端服务。在前端nginx pods 中,后端服务的IP将可解析为域名"后端"。这也将为您节省CORS的麻烦。这种设置是可移植的,这意味着,无论您是在dev或stage或prod中部署,名称" backend"将始终解析为相应的后端。

    这种方法的一个潜在缺陷是,你的后端可能无法独立于前端扩展;在我的拙见中,这不是什么大不了的事;在k8s环境中,如果需要,只需要旋转更多的pod。

    好奇 - 什么是为您的前端服务(哪种服务器技术将index.html提供给用户的浏览器)?是静态服务器,如nginx或apache httpd,还是你在这里使用nodejs?

答案 1 :(得分:2)

我们使用的方法不同于so-random-dude(这是一个很好的解决方案)的答案:我们让后端服务器提供前端文件。我们为两者分离了泊坞窗图像,但仅使用1个吊舱。前端作为init容器运行,并将文件复制到emptydir卷。后端还安装该卷并在/上提供服务(所有后端资源都在其他路径上提供)。这样,前端和后端在同一主机上提供。

您可以使用window.location.protocol + '//' + window.location.host在Angular代码中获取当前主机(现在也是后端主机)。

在本地开发机器上进行开发时,我们在自己独立的服务器上运行前端和后端。所以我们有一个小帮助函数来获取所有情况下正确的后端URL:

public getBackendUrl(): string {
  return this.getBackendUrlInternal(window.location.protocol, window.location.host);
}

private getBackendUrlInternal(protocol: string, host: string): string {
  if (host === 'localhost:3000') {
    // running in local dev server, connect to local dev backend
    return 'http://localhost:8585';
  } else {
    // running in docker compose or on k8s, backend is on same host and port as we are
    return protocol + '//' + host;
  }
}

(有两种方法,因为我们对第二种方法进行了一些测试)

答案 2 :(得分:1)

我会使用Kubernetes使用Ingress / IngressController进行灵活的tarffic摄取方式。在集群中部署了Havin入口控制器,您可以轻松创建Ingress定义,告诉控制器在特定URL下公开服务。您需要做的就是将DNS中的名称指向Ingress控制器负载均衡器(在大多数云设置中,将使用CNAME到LB fqdn)。

https://kubernetes.io/docs/concepts/services-networking/ingress/ https://github.com/kubernetes/ingress

答案 3 :(得分:0)

这就是我配置 Ingress 使用服务名称将前端应用连接到后端的方式。

银行帐户(Spring Boot应用)请注意服务的名称属性

  • 服务配置
apiVersion: v1
kind: Service
metadata:
  name: student-app-api
spec:
  selector:
    app: student-app-api
  ports:
    - port: 8080
      protocol: TCP
      targetPort: 8080

前端前端不需要了解后端服务器。

让我们假设前端需要调用后端的getAllStudents API。前端可以这样调用API 样本React代码

const get = id => {
  return http.get(`api/students/`);
};

//这会将请求发送到自己的服务器,我们将使用如下所示的Ingress配置将该请求重定向到后端

入口

apiVersion: networking.k8s.io/v1beta1 # for versions before 1.14 use extensions/v1beta1
kind: Ingress
metadata:
  name: student-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - http:
      paths:
        - path: /?(.*)
          backend:
            serviceName: student-app-client-service
            servicePort: 80
        - path: /api/?(.*)   //Redirect all request to backend (backend service name)
          backend:
            serviceName: student-app-api
            servicePort: 8080