如何将所有流量从一个容器路由到同一Kubernetes连网中的另一个容器?

时间:2020-03-22 23:43:19

标签: node.js docker nginx kubernetes amazon-eks

我正在创建一个Web应用程序,其中包含一个 React 前端和一个 node.js (表示)服务器。前端对快递服务器进行内部api调用,然后快递服务器进行外部api调用以收集一些数据。前端和服务器位于同一Kubernetes容器内的不同容器中。

前端服务是一张nginx:1.14.0-alpine图像。静态文件在CI管道中构建(npm build),并且build目录在docker build期间复制到映像。 package.json包含一个代理密钥"proxy": "http://localhost:8080",该代理密钥将流量从应用程序路由到localhost:8080-这是Express服务器正在侦听内部api调用的端口。我认为proxy键一旦将文件打包成静态文件并放到nginx图像上就不会起作用了?

在本地运行(即运行npm start而不是npm build时,所有这些都有效。快递服务器接收前端在端口8080上发出的api请求。

express服务器是一项简单的服务,它将身份验证添加到前端进行的api调用中,仅此而已。但是身份验证依赖于机密作为环境变量,从而使它们与React不兼容。通过运行node server.js启动服务器;在本地,服务器服务成功侦听(app.listen(8080))来自React前端的api调用,向请求添加了一些身份验证,然后将请求发送到外部api,并在收到响应后将响应传递回前端

在生产中,在Kubernetes窗格中,事情并不是那么简单。通过节点服务器来自 React前端代理的流量现在需要由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/;
        }

.....

1 个答案:

答案 0 :(得分:3)

在Kubernetes中,thes pod与其中的所有容器共享相同的网络接口,因此对于前端容器 localhost:8080 是后端,对于后端容器 localhost:80 < / strong>是前端。 对于任何容器应用程序,如果需要外部流量,则应确保它们在127.0.0.1以外的其他接口中侦听。

将复制从一台服务器(每个应用程序从 127.0.0.1 进行对话)迁移到Pod,就像在专用计算机中一样简单。

您的 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/;
    }

}

创建此 ConfigMap

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

然后,创建 pod 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入口控制器,因此我们需要创建服务和入口:

服务

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/