React 没有在 kubernetes 集群上访问 django api

IT技术 reactjs django docker kubernetes
2021-05-01 02:12:50

我是 Kubernetes 的新手,这是我第一次将 react-django Web 应用程序部署到 Kubernetes 集群。

我创造了:

  1. frontend.yaml # 运行 npm 服务器
  2. backend.yaml # 运行 django 服务器
  3. backend-service.yaml # 使 Django 服务器可访问以进行react。

在我的 frontend.yaml 文件中,我传递REACT_APP_HOSTREACT_APP_PORT作为环境变量并将我的react应用程序中的 URL 更改为:

axios.get('http://'+`${process.env.REACT_APP_HOST}`+':'+`${process.env.REACT_APP_PORT}`+'/todolist/api/bucket/').then(res => {
      setBuckets(res.data);
      setReload(false);
    }).catch(err => {
      console.log(err);
    })

我的网址变成 http://backend-service:8000/todolist/api/bucket/

backend-service是我使用 env 变量传递的后端服务的名称REACT_APP_HOST

我没有收到任何错误,但是当我使用kubectl port-forward <frontend-pod-name> 3000:3000和访问时,localhost:3000我看到了我的 react 应用程序页面,但它没有遇到任何 django api。

在 chrome 上,我收到错误:

net::ERR_NAME_NOT_RESOLVED

在 Mozilla 中:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://backend-service:8000/todolist/api/bucket/. (Reason: CORS request did not succeed).

请帮助解决这个问题,我花了 3 天时间但没有得到任何想法。

前端.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: frontend
  name: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: frontend
    spec:
      containers:
      - image: 1234567890/todolist:frontend-v13
        name: react-todolist
        env:
          - name: REACT_APP_HOST
            value: "backend-service"
          - name: REACT_APP_PORT
            value: "8000"
        ports:
          - containerPort: 3000
        volumeMounts:
          - mountPath: /var/log/
            name: frontend
        command: ["/bin/sh", "-c"]
        args:
          - npm start;
      volumes:
        - name: frontend
          hostPath:
            path: /var/log/

后端.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: backend
  name: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: backend
    spec:
      serviceAccountName: backend-sva
      containers:
      - image: 1234567890/todolist:backend-v11
        name: todolist
        env:
          - name: DB_NAME
            value: "todolist"
          - name: MYSQL_HOST
            value: "mysql-service"
          - name: MYSQL_USER
            value: "root"
          - name: MYSQL_PORT
            value: "3306"
          - name: MYSQL_PASSWORD
            value: "mysql123"
        ports:
          - containerPort: 8000
        volumeMounts:
          - mountPath: /var/log/
            name: backend
        command: ["/bin/sh", "-c"]
        args:
          - apt-get update;
            apt-get -y install vim;
            python manage.py makemigrations bucket;
            python manage.py migrate;
            python manage.py runserver 0.0.0.0:8000
      volumes:
        - name: backend
          hostPath:
            path: /var/log/

后端服务.yaml

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: backend
  name: backend-service
spec:
  ports:
  - port: 8000
    targetPort: 8000
  selector:
    app: backend
status:
  loadBalancer: {}

前端docker文件

FROM node:14.16.1-alpine

COPY package.json /app/react-todolist/react-todolist/
WORKDIR /app/react-todolist/react-todolist/

RUN npm install

COPY . /app/react-todolist/react-todolist/

EXPOSE 3000

后台docker文件

FROM python:3.6

COPY requirements.txt ./app/todolist/
WORKDIR /app/todolist/

RUN pip install -r requirements.txt

COPY . /app/todolist/

Django 设置

CORS_ORIGIN_ALLOW_ALL=True

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Rest Frame Work
    'rest_framework',
    # CORS
    'corsheaders',

    # Apps
    'bucket',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

入口.yaml

apiVersion: extensions/v1beta1

kind: Ingress

metadata:
  name: todolist-ingress

spec:
  rules:
    - host: kubernetes.docker.internal
      http:
       paths:
        - path: /
          backend:
            serviceName: frontend-service
            servicePort: 3000
        
        - path: /
          backend:
            serviceName: backend-service
            servicePort: 8000
  

react axios api

useEffect(() => {
    axios.get('http://'+`${process.env.REACT_APP_HOST}`+':'+`${process.env.REACT_APP_PORT}`+'/todolist/api/bucket/', {
      headers: {"Access-Control-Allow-Origin": "*"}
    }).then(res => {
      setBuckets(res.data);
      setReload(false);
    }).catch(err => {
      console.log(err);
    })
  }, [reload])

网络应用程序 github 链接 https://github.com/vgautam99/ToDoList

1个回答

欢迎来到社区!

我复制了您的示例并使其正常工作。我分叉了您的存储库,对 js 文件和 package.json 进行了一些更改并添加了 Dockerfiles(您可以在此处查看此提交

由于我没有更改数据库设置,因此settings.py我将其附加为configMap后端部署(参见此处是如何完成的)。配置映射是由这个命令创建的:

kubectl create cm django1 --from-file=settings.py

这里最棘手的部分是使用您的域名kubernetes.docker.internal并添加您的端口以及/backend您传递给前端应用程序的环境变量的路径(请参阅此处

完成此操作后,就该设置入口控制器了(该控制器使用 apiVersion -extestions/v1beta1正如在您的示例中所做的那样,但它很快就会被弃用,因此建议使用networking.k8s.io/v1-此处提供了较新的 apiVersion 示例):

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: todolist-backend-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  rules:
    - host: kubernetes.docker.internal
      http:
       paths:
        - path: /backend(/|$)(.*)
          backend:
            serviceName: backend-service
            servicePort: 8000
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: todolist-frontend-ingress
  annotations:
spec:
  rules:
    - host: kubernetes.docker.internal
      http:
       paths:
        - path: /
          backend:
            serviceName: frontend-service
            servicePort: 3000

我将它设置在两个不同的入口中,因为根路径rewrite-targetregex使用存在一些问题/正如您所看到的,我们rewrite-target在这里使用是因为请求应该命中/todolist/api/bucket路径而不是/backend/todolist/api/bucket路径。请看nginx重写注解

下一步是从运行 kubernetes 的节点和 Web 中找到一个 IP 地址来测试您的应用程序。要查找 IP 地址和端口,请运行kubectl get svcfind ingress-nginx-controller

NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                      AGE
backend-service                      ClusterIP      10.100.242.79    <none>          8000/TCP                     21h
frontend-service                     ClusterIP      10.110.102.96    <none>          3000/TCP                     21h
ingress-nginx-controller             LoadBalancer   10.107.31.20     192.168.1.240   80:31323/TCP,443:32541/TCP   8d

有两种选择:CLUSTER-IPEXTERNAL-IP,如果您有负载均衡器设置。在您的 kubernetes 控制平面上,您可以curl使用CLUSTER-IPaddress使用命令运行简单的检查测试就我而言,它看起来像:

curl http://kubernetes.docker.internal/ --resolve kubernetes.docker.internal:80:10.107.31.20

下一个测试是:

curl -I http://kubernetes.docker.internal/backend/todolist/api/bucket --resolve kubernetes.docker.internal:80:10.107.31.20

输出将类似于:

HTTP/1.1 301 Moved Permanently
Date: Fri, 14 May 2021 12:21:59 GMT
Content-Type: text/html; charset=utf-8Content-Length: 0
Connection: keep-alive
Location: /todolist/api/bucket/
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Vary: Origin

下一步是通过 Web 浏览器访问您的应用程序。您需要/etc/hosts在本地计算机(Linux/Mac OS,对于 Windows 有点不同,但很容易找到)上进行更正,以将kubernetes.docker.internal域与正确的 IP 地址匹配

如果您使用的是load balancerthenEXTERNAL-IP是正确的地址。如果您没有,load balancer则可以直接联系该节点。您可以在云控制台中找到 IP 地址并将其添加到/etc/hosts. 在这种情况下,您将需要使用不同的端口。就我而言,它是31323(您可以在上面的kubectl get svc输出中找到它)。

设置好后,我在我的网络浏览器中点击了应用程序 http://kubernetes.docker.internal:31323

(存储库在这里可以随意使用您需要的一切)