You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

本地Kubernetes集群客户端无法访问服务器问题咨询

K8s + Helm部署TodoList项目问题解答

背景信息

一个简单的TodoList项目,包含客户端、服务器及数据库连接(数据库目前暂不相关)。使用GraphQL,访问客户端时,它会向服务器发送请求查询初始状态,出现CORS ERROR及NS_ERROR_DOM_BAD_URI错误。

客户端配置(templates/client-deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.client.name }}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: {{ .Values.client.name }} # this will make it recieve traffic
  template:
    metadata:
      labels:
        app: {{ .Values.client.name }}
    spec:
      containers:
      - name: {{ .Values.client.name }}
        image:  "Client\image:{{ .Values.client.tag }}"
        ports:
        - containerPort: 3000
        envFrom:
        - configMapRef:
            name: client-configmap
---
apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.client.name }}
spec:
  type: NodePort
  selector:
    app: {{ .Values.client.name }}  # send traffic to the matching label
  ports:
    - protocol: TCP
      port: 3000 # port of the service
      targetPort: 3000 # forward traffic to a pod to the following port
      nodePort: {{ .Values.client.nodePort }} # recieve traffic from this port
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: client-configmap
data:
{{- $jsonData := tpl (.Files.Get "clientconfig.json") . | fromJson }}
{{- range $key, $value := $jsonData }}
  {{ $key }}: {{ quote $value | trimSuffix "\n" }}
{{- end }}

服务器配置(templates/server-deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: {{ .Values.server.name }}
  template:
    metadata:
      labels:
        app: {{ .Values.server.name }}
    spec:
      containers:
      - name: server
        image:  "server\image:{{ .Values.server.tag }}"
        ports:
        - containerPort: 4000
        envFrom:
        - configMapRef:
            name: server-configmap

---
apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.server.name }}
spec:
  type: ClusterIP
  selector:
    app: {{ .Values.server.name }}  # send traffic to the matching label
  ports:
    - protocol: TCP
      port: 4000
      targetPort: 4000

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: server-configmap
data:
{{- $jsonData := tpl (.Files.Get "serverconfig.json") . | fromJson }}
{{- range $key, $value := $jsonData }}
  {{ $key }}: {{ quote $value | trimSuffix "\n" }}
{{- end }}

问题1:可通过localhost:3xxxx访问客户端而非客户端Service生成的IP,是否因K8s集群与主机同机?如何通过<SERVICE_IP>:<NODE_PORT>访问客户端?

  • 是的,因为你使用的是单机K8s集群(比如minikube、kind),集群节点和主机是同一台机器,localhost直接映射到集群节点IP,因此能通过localhost:<NodePort>访问客户端。
  • 要通过Service IP:NodePort访问:
    1. 执行命令获取客户端Service的ClusterIP:kubectl get svc {{ .Values.client.name }}
    2. 直接使用http://<service-cluster-ip>:<node-port>访问即可,单机集群环境下主机默认能访问ClusterIP。

问题2:推测CORS错误因客户端访问Uri http://server:4000,客户端不知“server”含义,为何请求不在集群内发起而在浏览器中?正确方案是什么?

  • 原因:客户端代码在浏览器中运行,所有API请求都是从浏览器(主机环境)发起,而非K8s集群内的客户端Pod。server是K8s ClusterIP Service的内部域名,只有集群内的Pod能解析,浏览器无法识别该域名,因此出现DNS解析失败和跨域错误。
  • 正确方案:
    • Ingress方案(推荐):
      1. 在集群中安装Ingress控制器(比如nginx-ingress)
      2. 编写Ingress资源,将同一个域名的不同路径转发到客户端和服务器Service,例如:
        apiVersion: networking.k8s.io/v1
        kind: Ingress
        metadata:
          name: todolist-ingress
        spec:
          rules:
          - host: localhost
            http:
              paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: {{ .Values.client.name }}
                    port:
                      number: 3000
              - path: /graphql
                pathType: Prefix
                backend:
                  service:
                    name: {{ .Values.server.name }}
                    port:
                      number: 4000
        
      3. 客户端配置API请求地址为/graphql,通过Ingress自动转发到服务器Service,避免跨域。
    • 服务器开启CORS:
      1. 在服务器代码中配置允许客户端Origin(比如http://localhost:<client-node-port>)的跨域请求
      2. 将服务器Service改为NodePort类型,客户端配置API地址为http://localhost:<server-node-port>
    • 客户端Pod代理:
      1. 修改客户端Pod,添加Nginx反向代理,将API请求转发到server:4000
      2. 客户端配置API地址为相对路径,由代理转发到集群内的服务器

问题3:要实现「输入localhost:3XXXX连客户端→客户端通过server-service连服务器→数据库返回数据」流程,部署缺少哪些配置?

需要补充以下配置:

  • 跨域处理配置:参考问题2的方案,选择Ingress、服务器CORS或客户端代理中的一种实现跨域访问
  • 服务器访问配置(若不用Ingress):将服务器Service从ClusterIP改为NodePort,让浏览器能直接访问服务器
  • Ingress控制器(若用Ingress方案):必须先在集群中部署Ingress控制器,否则Ingress资源无法生效
  • 客户端API地址修正:确保客户端配置的API地址是浏览器可解析的地址(相对路径或主机+端口)
  • 数据库相关配置(后续需要时):数据库的Deployment、Service,以及服务器的环境变量(数据库地址、账号密码等),当前可暂不配置

内容的提问来源于stack exchange,提问作者coding_potato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:44:59