I have a frontend React application and a Go backend service as the API for the frontend. Both are Kubernetes services in the same namespace. How can I communicate with the Go backend service without having to use an external IP? I got it to work with an external ip, but, I can't get the fqdn to resolve correctly like it should. The frontend service is built from the nginx:1.15.2-alpine
docker image. How can I get the frontend React app to communicate with the backend Go server?
Frontend service.yaml:
apiVersion: v1
kind: Service
metadata:
name: ui
namespace: client
labels:
app: ui
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: http
- name: https
port: 443
targetPort: https
selector:
app: ui
Frontend deployment.yaml:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: ui
namespace: client
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 2
template:
metadata:
labels:
app: ui
spec:
containers:
- name: ui
image: #######
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
Backend service.yaml:
apiVersion: v1
kind: Service
metadata:
name: api
namespace: client
labels:
app: api
spec:
type: NodePort
ports:
- port: 8001
protocol: TCP
targetPort: http
name: http
selector:
app: api
Backend deployment.yaml:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: api
namespace: client
labels:
name: api
spec:
replicas: 1
revisionHistoryLimit: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: ####
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8001
There are many issues with the yamls. First, in service yamls, the targetPort should be port numbers(integers) and not string. So, the updated config will be,
apiVersion: v1
kind: Service
metadata:
name: ui
namespace: client
labels:
app: ui
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
selector:
app: ui
and
apiVersion: v1
kind: Service
metadata:
name: api
namespace: client
labels:
app: api
spec:
type: NodePort
ports:
- port: 8001
protocol: TCP
targetPort: 8001
name: http
selector:
app: api
After changing the targetPort in service yamls, I created a pod to do nslookup and it works as expected.
kubectl apply -f https://k8s.io/examples/admin/dns/busybox.yaml
kubectl exec -ti busybox -- nslookup api.client
produces the output
Defaulting container name to busybox.
Use 'kubectl describe pod/busybox -n default' to see all of the containers in this pod.
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: api.client
Address 1: 10.101.84.21 api.client.svc.cluster.local
The React application does not run in Kubernetes. Maybe you have a dev server running in Kubernetes, but it just serves up HTML and Javascript files to a browser running outside the cluster. The application in the browser has no idea about this "Kubernetes" thing and can't resolve the Kubernetes-internal ...svc.cluster.local
hostnames; it needs a way to talk back to the cluster.
Since you have the backend configured as a NodePort type service, you can look up the backend's externally visible port, then configure the backend URL in the served browser application to be that port number on some node in your cluster. This is a little bit messy and manual.
A better path is to configure an ingress so that, for example, https://.../
serves your browser application and https://.../api
goes to your back-end. Then the backend URL can just be the bare path /api
, and it will be interpreted with the same host name and scheme as the UI.