Как направить весь трафик c из контейнера через другой контейнер в той же капсуле Kubernetes? - PullRequest
1 голос
/ 23 марта 2020

Я создаю веб-приложение, которое включает React внешний интерфейс и node.js (express) сервер, Интерфейс выполняет внутренний вызов API для сервера express, а сервер express затем выполняет внешний вызов API для сбора некоторых данных. Интерфейс и сервер находятся в разных контейнерах в одном и том же модуле Kubernetes.

Сервис внешнего интерфейса представляет собой nginx:1.14.0-alpine образ. Файлы stati c создаются (npm build) в конвейере CI, а каталог build копируется в образ во время docker build. package.json содержит прокси-ключ "proxy": "http://localhost:8080", который направляет трафик c из приложения в localhost:8080 - это порт, который сервер express прослушивает для внутреннего вызова API. Я думаю, что клавиша proxy не будет иметь никакого отношения после того, как файлы будут упакованы в stati c файлы и переданы в nginx образ?

При локальном запуске, то есть при запуске npm start вместо npm build, это все работает. Сервер express принимает запросы API, отправленные внешним интерфейсом через порт 8080.

Сервер express - это простая служба, которая добавляет аутентификацию к вызову API, который интерфейс делает, вот и все. Но аутентификация опирается на секреты как переменные среды, что делает их несовместимыми с React. Сервер запускается с помощью команды node server.js; локально серверная служба успешно прослушивает (app.listen(8080)) вызовы API от внешнего интерфейса React, добавляет некоторую аутентификацию к запросу, затем делает запрос к внешнему API и передает ответ обратно во внешний интерфейс после его получения.

На производстве, в стручке Кубернетеса, все не так просто. Трафи c из React-интерфейса , проксирующего через сервер узла , теперь должен обрабатываться kubernetes, и я не смог понять это.

Может быть важно отметить, что нет никаких обстоятельств, при которых интерфейс будет напрямую выполнять любые внешние вызовы API, все они будут go через сервер .

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 Ответ

3 голосов
/ 23 марта 2020

В Kubernetes этот модуль использует один и тот же сетевой интерфейс со всеми контейнерами внутри него, поэтому для контейнера внешнего интерфейса localhost: 8080 является внутренним, а для внутреннего контейнера localhost: 80 это внешний интерфейс. Как и для любого контейнерного приложения, вы должны убедиться, что они прослушивают интерфейсы, отличные от 127.0.0.1, если вы хотите traffi c извне.

Перенос приложения с одного сервера - где каждое приложение говорит с 127.0.0.1 - чтобы модуль был простым, как на выделенном компьютере.

Ваш 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

приложение. 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, так что если IP-адрес модуля было 172.17.0.7 Мне нужно сделать:

* 10 60 *

Если у вас был вход спереди, он все еще должен работать. Я включил входной контроллер 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/
...