本地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访问:
- 执行命令获取客户端Service的ClusterIP:
kubectl get svc {{ .Values.client.name }} - 直接使用
http://<service-cluster-ip>:<node-port>访问即可,单机集群环境下主机默认能访问ClusterIP。
- 执行命令获取客户端Service的ClusterIP:
问题2:推测CORS错误因客户端访问Uri http://server:4000,客户端不知“server”含义,为何请求不在集群内发起而在浏览器中?正确方案是什么?
- 原因:客户端代码在浏览器中运行,所有API请求都是从浏览器(主机环境)发起,而非K8s集群内的客户端Pod。
server是K8s ClusterIP Service的内部域名,只有集群内的Pod能解析,浏览器无法识别该域名,因此出现DNS解析失败和跨域错误。 - 正确方案:
- Ingress方案(推荐):
- 在集群中安装Ingress控制器(比如nginx-ingress)
- 编写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 - 客户端配置API请求地址为
/graphql,通过Ingress自动转发到服务器Service,避免跨域。
- 服务器开启CORS:
- 在服务器代码中配置允许客户端Origin(比如
http://localhost:<client-node-port>)的跨域请求 - 将服务器Service改为NodePort类型,客户端配置API地址为
http://localhost:<server-node-port>
- 在服务器代码中配置允许客户端Origin(比如
- 客户端Pod代理:
- 修改客户端Pod,添加Nginx反向代理,将API请求转发到
server:4000 - 客户端配置API地址为相对路径,由代理转发到集群内的服务器
- 修改客户端Pod,添加Nginx反向代理,将API请求转发到
- Ingress方案(推荐):
问题3:要实现「输入localhost:3XXXX连客户端→客户端通过server-service连服务器→数据库返回数据」流程,部署缺少哪些配置?
需要补充以下配置:
- 跨域处理配置:参考问题2的方案,选择Ingress、服务器CORS或客户端代理中的一种实现跨域访问
- 服务器访问配置(若不用Ingress):将服务器Service从ClusterIP改为NodePort,让浏览器能直接访问服务器
- Ingress控制器(若用Ingress方案):必须先在集群中部署Ingress控制器,否则Ingress资源无法生效
- 客户端API地址修正:确保客户端配置的API地址是浏览器可解析的地址(相对路径或主机+端口)
- 数据库相关配置(后续需要时):数据库的Deployment、Service,以及服务器的环境变量(数据库地址、账号密码等),当前可暂不配置
内容的提问来源于stack exchange,提问作者coding_potato
相关产品推荐
相关产品推荐

