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:
If I'm missing anything please mention it and i will edit the question
Thanks!
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.