[英]How to route all traffic from a container through another container in the same Kubernetes pod?
我正在創建一個包含React前端和node.js (express) server的 Web 應用程序。 前端對 express 服務器進行內部 api 調用,然后 express 服務器進行外部 api 調用以收集一些數據。 前端和服務器位於同一個 Kubernetes pod 內的不同容器中。
前端服務是一個nginx:1.14.0-alpine
鏡像。 靜態文件在 CI 管道中構建 ( npm build
),並且build
目錄在docker build
期間復制到映像。 package.json
包含一個代理密鑰, "proxy": "http://localhost:8080"
,它將流量從應用程序路由到localhost:8080
- 這是 express 服務器正在偵聽內部 api 調用的端口. 我認為一旦文件被打包成靜態文件並提供給nginx
圖像, proxy
密鑰將沒有任何意義?
在本地運行時,即運行npm start
而不是npm build
,這一切都有效。 express 服務器接收前端在端口8080
上發出的 api 請求。
express 服務器是一個簡單的服務,它為前端進行的 api 調用添加了身份驗證,僅此而已。 但是身份驗證依賴於作為環境變量的秘密,這使得它們與 React 不兼容。 服務器通過運行node server.js
啟動; 服務器服務在本地成功偵聽( app.listen(8080)
)來自 React 前端的 api 調用,向請求添加一些身份驗證,然后將請求發送到外部 api 並將響應傳遞回前端已收到。
在生產環境中,在 Kubernetes pod 中,事情並沒有那么簡單。 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/;
}
.....
在 Kubernetes 中,pod 與其中的所有容器共享相同的網絡接口,因此對於前端容器localhost:8080是后端,對於后端容器localhost:80是前端。 對於任何容器應用程序,如果您想要來自外部的流量,您應該確保它們正在偵聽 127.0.0.1 以外的其他接口。
將應用程序從一台服務器(其中每個應用程序都從127.0.0.1進行通信)遷移到 pod 的目的是像在專用機器上一樣簡單。
你的nginx.conf看起來有點奇怪,應該是location /api/ {
。
這是功能示例:
配置文件
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}!`))
文件
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
入口.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/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.