对于本地开发,我有一个工作的迷你管。我们部署了不同的服务。现在我想将前端连接到后端。
前端是一个有棱有角的应用程序,并以自己的服务为生。 后端是一个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
答案 0 :(得分:5)
首先,我将尝试解决您的具体问题
当我第一次启动后端时,接近了唯一的工作状态 使用NodePort类型的服务并将url和端口复制到 前端目标URL。我觉得这对我来说非常不洁净。在那儿 另一种获取后端请求的URL的方法 前端?
这里有几个选项1)如你所说,使用type =" LoadBalancer"。或2)通过前端服务器代理所有后端呼叫
我知道何时在生产系统上部署服务 类型="负载平衡器"该服务由外部IP公开 我可以从那里访问该服务。而外部IP 将永久保存在pod更新等等。我也看到的问题是 需要将后端IP注入到docker容器中 一个额外的提交。
如果您通过前端的服务器端路由(或愿意路由)所有微服务/后端呼叫,并且如果将前端和后端部署在同一命名空间中的同一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