我正在创建一个包含 React 的 Web 应用程序前端和一个 node.js (express) 服务器 .前端对 express 服务器进行内部 api 调用,然后 express 服务器进行外部 api 调用以收集一些数据。前端和服务器位于同一个 Kubernetes pod 内的不同容器中。
前端服务是 nginx:1.14.0-alpine
图片。静态文件在 CI 管道中构建 (npm build
) 和 build
在 docker build
期间将目录复制到镜像中. package.json
包含代理 key "proxy": "http://localhost:8080"
,将流量从应用程序路由到 localhost:8080
- 这是 express 服务器正在监听内部 api 调用的端口。我认为 proxy
一旦文件被打包成静态文件并提供给 nginx
, key 将没有任何影响。图片?
在本地运行时,即运行 npm start
而不是 npm build
,这一切都有效。 express 服务器在端口 8080
上接收前端发出的 api 请求.
express 服务器是一个简单的服务,它将身份验证添加到前端进行的 api 调用,仅此而已。但是身份验证依赖于 secret 作为环境变量,这使得它们与 React 不兼容。服务器通过运行 node server.js
启动。 ;服务器服务在本地成功监听(app.listen(8080)
)来自 React 前端的 api 调用,为请求添加一些身份验证,然后向外部 api 发出请求,并在收到响应后将响应传回前端。
在生产环境中,在 Kubernetes pod 中,事情并不那么简单。来自的流量 react 前端 通过代理 Node 服务器 现在需要kubernetes来处理,一直没搞清楚。
可能需要注意的是, 在任何情况下都不会出现。前端将直接进行任何外部 api 调用,它们都将通过 服务器 .React frontend Dockerfile
FROM nginx:1.14.0-alpine
# Copy static files
COPY client/build/ /usr/share/nginx/html/
# The rest has been redacted for brevity but is just copying of favicons etc.
Express Node Server
FROM node:10.16.2-alpine
# Create app directory
WORKDIR /app
# Install app dependencies
COPY server/package*.json .
RUN npm install
EXPOSE 8080
CMD [ "node", "server.js" ]
Kubernetes Manifest
- 为简洁而编辑apiVersion: apps/v1beta1
kind: Deployment
containers:
- name: frontend
image: frontend-image:1.0.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/conf.d/default.conf
name: config-dir
subPath: my-config.conf
- name: server
image: server-image:1.0.0
imagePullPolicy: IfNotPresent
volumes:
- name: config-tmpl
configMap:
name: app-config
defaultMode: 0744
- name: my-config-directory
emptyDir: {}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: my-namespace
data:
my-conf.conf: |-
server {
listen 80;
server_name _;
location api/ {
proxy_pass http://127.0.0.1:8080/;
}
.....
最佳答案
在 Kubernetes 中,这些 pod 与其中的所有容器共享相同的网络接口(interface),因此对于前端容器 本地主机:8080 是后端,对于后端容器本地主机:80 是前端。
对于任何容器应用程序,如果您想要来自外部的流量,您应该确保它们正在监听 127.0.0.1 以外的其他接口(interface)。
从一台服务器迁移应用程序 - 每个应用程序都从 进行通信127.0.0.1 - 一个 pods 的目的是像在专用机器中一样简单。
您的 nginx.conf 看起来有点奇怪,应该是location /api/ {
.
这是功能示例:
nginx.conf
server {
server_name localhost;
listen 0.0.0.0:80;
error_page 500 502 503 504 /50x.html;
location / {
root html;
}
location /api/ {
proxy_pass http://127.0.0.1:8080/;
}
}
创建这个配置图 :
kubectl create -f nginx.conf
app.js
const express = require('express')
const app = express()
const port = 8080
app.get('/', (req, res) => res.send('Hello from Express!'))
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
Dockerfile
FROM alpine
RUN apk add nodejs npm && mkdir -p /app
COPY . /app
WORKDIR /app
RUN npm install express --save
EXPOSE 8080
CMD node app.js
您可以构建此图像或使用我制作的 hectorvido/ express .
然后,创建 pods YAML 定义:
pod.yml
apiVersion: v1
kind: Pod
metadata:
name: front-back
labels:
app: front-back
spec:
containers:
- name: front
image: nginx:alpine
volumeMounts:
- name: nginx-conf
mountPath: /etc/nginx/conf.d/
ports:
- containerPort: 80
- name: back
image: hectorvido/express
ports:
- containerPort: 8080
volumes:
- name: nginx-conf
configMap:
name: nginx
装上集群:
kubectl create -f pod.yml
获取IP:
kubectl get pods -o wide
我用 Minikube 进行了测试,所以如果 pod IP 是 172.17.0.7 我必须这样做:
minikube ssh
curl -L 172.17.0.7/api
如果前面有入口,它应该仍然可以工作。我在 minikube 上启用了一个 nginx 入口 Controller ,所以我们需要创建一个服务和一个入口:
服务
kubectl expose pod front-back --port 80
ingress.yml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: front-back
spec:
rules:
- host: fb.192-168-39-163.nip.io # minikube ip
http:
paths:
- path: /
backend:
serviceName: front-back
servicePort: 80
测试仍然有效:
curl -vL http://fb.192-168-39-163.nip.io/api/
关于node.js - 如何将来自容器的所有流量路由到同一个 Kubernetes pod 中的另一个容器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60806249/