kubernetesdocker-composecorsclient-serverkubernetes-helm

Client cant access server in Kubernetes local cluster


I'm learning about helm and deployment on k8s using my PC and have several questions.

Some background:
A simple TodoList - client and server with a connection to a database (database currently not relevant).
I'm using graphql so when you connect to the client it loads a request to the server to run a query for my initial client state.
That's when i get a CORS ERROR & NS_ERROR_DOM_BAD_URI.

Here's my client\server yamls:

Client

# 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 }}

Server

# 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 }}

Question 1:
using my client deployment, i managed to access my client using localhost:3xxxx instead of the IP created by the client-service, is this because the k8s cluster and the host are on the same machine? if not how can i access the client without using local-host but <SERVICE_IP>:<NODE_PORT>?

Question 2:
I assume the CORS error happens because the client is accessing the Uri http://server:4000 i assume the client has no idea what is server however, shouldn't the request be made within the cluster and not run in the browser? if not, whats the correct approach here?

** Question 3:**
Whats the correct config\ whats missing in my deployment for the following flow:

  1. Enter localhost:3XXXX to connect to client.
  2. client connects to server Via server-service.
  3. data is received from the database and returned to client

If I'm missing anything please mention it and i will edit the question
Thanks!


Solution

  • using my client deployment, i managed to access my client using localhost:3xxxx instead of the IP created by the client-service, is this because the k8s cluster and the host are on the same machine?

    Most likely, yes. Your client Service is of type NodePort, so it is binding to a port on your "node" (localhost). What is the value of .Values.client.nodePort?

    if not how can i access the client without using local-host but <SERVICE_IP>:<NODE_PORT>?

    Depends on the networking setup for your cluster. If your localhost is the kubernetes node itself (no virtualization or bridge network). If you're intending to reach the client service from outside the cluster, you would use node_ip:node_port. Depending on how your cluster is networked with your localhost, cluster_ip:node_port may also be possible. cluster_ip:node_port is definitely possible within the cluster.

    I assume the CORS error happens because the client is accessing the Uri http://server:4000 i assume the client has no idea what is server however, shouldn't the request be made within the cluster and not run in the browser? if not, whats the correct approach here?

    This probably warrants a new StackOverflow question if this brief answer does not suffice: From your description, it sounds like "client" is serving HTTP pages and a javascript bundle that comprise your client-side application. Server is presumably an API backend for persisting and querying data (via GraphQL).

    In this case, your browser loads the HTML page at localhost:3XXXX, but then attempts to make HTTP requests to server:4000? If that's all true, your "client" pods are not making the requests to server:4000, it's your browser. Since server:4000 is a different domain, CORS policies apply. The browser is the only thing enforcing CORS.

    Whats the correct config\ whats missing in my deployment for the following flow

    It seems possible to me that you are conflating the "client" pods with the browser itself. If it's your browser that's requesting a page from the client pod, and the browser is also going to make a request to the server-service, you will want to expose your server-service the same way you exposed your client service AND add CORS headers allowing the browser on origin localhost to make these requests.

    From your current configuration, your server is only exposed inside the cluster via a ClusterIP. If NodePort works for you, expose the server on a NodePort as well so the browser can reach it (from outside of the cluster) the same way its reaching the client service.