I've a simple HelloWorld ReactJs application Docker image and I created the deployment as:
kind: Deployment
apiVersion: apps/v1
metadata:
name: minikube-react-app
spec:
replicas: 2
selector:
matchLabels:
app: minikube-react-app
template:
metadata:
labels:
app: minikube-react-app
spec:
containers:
- name: minikube-react-app
image: hello-react:1.0.1
imagePullPolicy: Never
ports:
- containerPort: 80
resources:
requests:
memory: "100Mi"
cpu: "300m"
limits:
memory: "200Mi"
cpu: "600m"
restartPolicy: Always
---
kind: Service
apiVersion: v1
metadata:
name: minikube-react-app
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
protocol: TCP
nodePort: 31000
selector:
app: minikube-react-app
I ran, kubectl apply -f deployent.yaml
But when I access http://localhost:31000 it's not working(This site can’t be reached).
Can someone help me with this please?
Run the following command to get the actual address to connect with your app from host machine.
minikube service --url <service-name>
Ref: https://minikube.sigs.k8s.io/docs/handbook/accessing/
Should use 'node ip' instead of 'localhost' to acccess node port.
Run shell minikube ip to obtain ip of minikube node.
Check the service type: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
Related
When I'm trying to run SQL Server in kubernetes with the mcr.microsoft.com/mssql/server image in minikube cluster in several seconds I'm getting the following in logs:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Pulling 38h (x77 over 47h) kubelet Pulling image "mcr.microsoft.com/mssql/server"
Normal BackOff 38h (x1658 over 47h) kubelet Back-off pulling image "mcr.microsoft.com/mssql/server"
Warning Failed 38h (x79 over 47h) kubelet Failed to pull image "mcr.microsoft.com/mssql/server": rpc error: code = Unknown desc = context deadline exceeded
Pulling and running the image in docker desktop works fine.
What I've already tried:
Specifying a tag like :2019-latest;
Specifying an imagePullPolicy like IfNotPresent or Never. Seems like even after pulling the image via powershell directly kubernetes doesn't see it locally (but docker does).
I suspect the reason is that the image is too large and kubernetes has too short timeout settings by default. But I'm a newbie with kubernetes and haven't checked this yet. At least, I don't see anything about it in SQL Server examples.
Here's the deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mssql-deployment
namespace: mynamespace
spec:
replicas: 1
selector:
matchLabels:
app: mssql
strategy:
type: Recreate
template:
metadata:
labels:
app: mssql
spec:
terminationGracePeriodSeconds: 10
containers:
- image: mcr.microsoft.com/mssql/server
name: mssql
env:
- name: ACCEPT_EULA
value: "Y"
- name: SA_PASSWORD
valueFrom:
secretKeyRef:
name: mssql
key: SA_PASSWORD
ports:
- containerPort: 1433
name: mssql
securityContext:
privileged: true
volumeMounts:
- name: mssqldb
mountPath: /var/opt/mssql
volumes:
- name: mssqldb
persistentVolumeClaim:
claimName: mysql-pv-claim
service.yaml
apiVersion: v1
kind: Service
metadata:
name: mssql-deployment
namespace: mynamespace
spec:
ports:
- protocol: TCP
port: 1433
targetPort: 1433
selector:
app: mssql
type: LoadBalancer
pvc.yaml:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
Could you, please, help me figure out what I'm doing wrong? Let me know if you need more details.
Thank you!
I'm trying to access my SQL Server Express database hosted on my local machine from inside a minikube pod. I tried to follow the idea describe on kubernetes official doc. While I am inspecting my container I found out that my application got crashed every time I am creating POD because the application is unable to connect to the local database.
This is my config:
apiVersion: v1
kind: Service
metadata:
name: sqlserver-svc
spec:
ports:
- protocol: TCP
port: 1443
targetPort: 1433
===========================
apiVersion: v1
kind: Endpoints
metadata:
name: sqlserver-svc
subsets:
- addresses:
- ip: 192.168.0.101
ports:
- port: 1433
======== Application container ==========
apiVersion: v1
kind: Pod # object type -> that will reside kubernetes cluster
metadata:
name: api-pod
labels:
component: web
spec:
containers:
- name: api
image: nayan2/simptekapi
ports:
- containerPort: 5000
env:
- name: DATABASE_HOST
value: "sqlserver-svc:1443\\SQLEXPRESS"
- name: DATABASE_PORT
value: '1433'
- name: DATABASE_USER
value: sa
- name: DATABASE_PW
value: 1234
- name: JWT_SECRET
value: sec
- name: NODE_ENV
value: production
================================
apiVersion: v1
kind: Service
metadata:
name: api-node-port
spec:
type: NodePort
ports:
- port: 4200
targetPort: 5000
nodePort: 31515
selector:
component: web
It is obvious that I am doing something wrong. I am relatively new with docker/container and Kubernetes technology. Still learning. Can anybody help me with this??
Error while trying to connect React frontend web to nodejs express api server into kubernetes cluster.
Can navigate in browser to http:localhost:3000 and web site is ok.
But can't navigate to http:localhost:3008 as expected (should not be exposed)
My goal is to pass REACT_APP_API_URL environment variable to frontend in order to set axios baseURL and be able to establish communication between front and it's api server.
deploy-front.yml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: gbpd-front
spec:
selector:
matchLabels:
app: gbpd-api
tier: frontend
track: stable
replicas: 2
template:
metadata:
labels:
app: gbpd-api
tier: frontend
track: stable
spec:
containers:
- name: react
image: binomio/gbpd-front:k8s-3
ports:
- containerPort: 3000
resources:
limits:
memory: "150Mi"
requests:
memory: "100Mi"
imagePullPolicy: Always
service-front.yaml
apiVersion: v1
kind: Service
metadata:
name: gbpd-front
spec:
selector:
app: gbpd-api
tier: frontend
ports:
- protocol: "TCP"
port: 3000
targetPort: 3000
type: LoadBalancer
Deploy-back.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: gbpd-api
spec:
selector:
matchLabels:
app: gbpd-api
tier: backend
track: stable
replicas: 3 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: gbpd-api
tier: backend
track: stable
spec:
containers:
- name: gbpd-api
image: binomio/gbpd-back:dev
ports:
- name: http
containerPort: 3008
service-back.yaml
apiVersion: v1
kind: Service
metadata:
name: gbpd-api
spec:
selector:
app: gbpd-api
tier: backend
ports:
- protocol: "TCP"
port: 3008
targetPort: http
I tried many combinations, also tried adding "LoadBalancer" to backservice but nothing...
I can connect perfecto to localhost:3000 and use frontend but frontend can't connect to backend service.
Question 1: What's is the ip/name to use in order to pass REACT_APP_API_URL to fronten correctly?
Question 2: Why is curl localhost:3008 not answering?
After 2 days trying almost everything in k8s official docs... can't figure out what's happening here, so any help will be much appreciated.
kubectl describe svc gbpd-api
Response:
kubectl describe svc gbpd-api
Name: gbpd-api
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"gbpd-api","namespace":"default"},"spec":{"ports":[{"port":3008,"p...
Selector: app=gbpd-api,tier=backend
Type: LoadBalancer
IP: 10.107.145.227
LoadBalancer Ingress: localhost
Port: <unset> 3008/TCP
TargetPort: http/TCP
NodePort: <unset> 31464/TCP
Endpoints: 10.1.1.48:3008,10.1.1.49:3008,10.1.1.50:3008
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
I tested your environment, and it worked when using a Nginx image, let's review the environment:
The front-deployment is correctly described.
The front-service exposes it as loadbalancer, meaning your frontend is accessible from outside, perfect.
The back deployment is also correctly described.
The backend-service stays with as ClusterIP in order to be only accessible from inside the cluster, great.
Below I'll demonstrate the communication between front-end and back end.
I'm using the same yamls you provided, just changed the image to Nginx for example purposes, and since it's a http server I'm changing containerport to 80.
Question 1: What's is the ip/name to use in order to pass REACT_APP_API_URL to fronten correctly?
I added the ENV variable to the front deploy as requested, and I'll use it to demonstrate also. You must use the service name to curl, I used the short version because we are working in the same namespace. you can also use the full name: http://gbpd-api.default.svc.cluster.local:3008
Reproduction:
Create the yamls and applied them:
$ cat deploy-front.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gbpd-front
spec:
selector:
matchLabels:
app: gbpd-api
tier: frontend
track: stable
replicas: 2
template:
metadata:
labels:
app: gbpd-api
tier: frontend
track: stable
spec:
containers:
- name: react
image: nginx
env:
- name: REACT_APP_API_URL
value: http://gbpd-api:3008
ports:
- containerPort: 80
resources:
limits:
memory: "150Mi"
requests:
memory: "100Mi"
imagePullPolicy: Always
$ cat service-front.yaml
cat: cat: No such file or directory
apiVersion: v1
kind: Service
metadata:
name: gbpd-front
spec:
selector:
app: gbpd-api
tier: frontend
ports:
- protocol: "TCP"
port: 3000
targetPort: 80
type: LoadBalancer
$ cat deploy-back.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gbpd-api
spec:
selector:
matchLabels:
app: gbpd-api
tier: backend
track: stable
replicas: 3
template:
metadata:
labels:
app: gbpd-api
tier: backend
track: stable
spec:
containers:
- name: gbpd-api
image: nginx
ports:
- name: http
containerPort: 80
$ cat service-back.yaml
apiVersion: v1
kind: Service
metadata:
name: gbpd-api
spec:
selector:
app: gbpd-api
tier: backend
ports:
- protocol: "TCP"
port: 3008
targetPort: http
$ kubectl apply -f deploy-front.yaml
deployment.apps/gbpd-front created
$ kubectl apply -f service-front.yaml
service/gbpd-front created
$ kubectl apply -f deploy-back.yaml
deployment.apps/gbpd-api created
$ kubectl apply -f service-back.yaml
service/gbpd-api created
Remember, in Kubernetes the communication is designed to be made between services, because the pods are always recreated when there is a change in the deployment or when the pod fail.
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/gbpd-api-dc5b4b74b-kktb9 1/1 Running 0 41m
pod/gbpd-api-dc5b4b74b-mzpbg 1/1 Running 0 41m
pod/gbpd-api-dc5b4b74b-t6qxh 1/1 Running 0 41m
pod/gbpd-front-66b48f8b7c-4zstv 1/1 Running 0 30m
pod/gbpd-front-66b48f8b7c-h58ds 1/1 Running 0 31m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/gbpd-api ClusterIP 10.0.10.166 <none> 3008/TCP 40m
service/gbpd-front LoadBalancer 10.0.11.78 35.223.4.218 3000:32411/TCP 42m
The pods are the workers, and since they are replaceable by nature, we will connect to a frontend pod to simulate his behaviour and try to connect to the backend service (which is the network layer that will direct the traffic to one of the backend pods).
The nginx image does not come with curl preinstalled, so I will have to install it for demonstration purposes:
$ kubectl exec -it pod/gbpd-front-66b48f8b7c-4zstv -- /bin/bash
root#gbpd-front-66b48f8b7c-4zstv:/# apt update && apt install curl -y
done.
root#gbpd-front-66b48f8b7c-4zstv:/# curl gbpd-api:3008
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
Now let's try using the environment variable that was defined:
root#gbpd-front-66b48f8b7c-4zstv:/# printenv | grep REACT
REACT_APP_API_URL=http://gbpd-api:3008
root#gbpd-front-66b48f8b7c-4zstv:/# curl $REACT_APP_API_URL
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
Considerations:
Question 2: Why is curl localhost:3008 not answering?
Since all yamls are correctly described you must check if image: binomio/gbpd-back:dev is correctly serving on port 3008 as intended.
Since it's not a public image, I can't test it, so I'll give you troubleshooting steps:
just like we logged inside the front-end pod you will have to log into this backend-pod and test curl localhost:3008.
If it's based on a linux distro with apt-get, you can run the commands just like I did on my demo:
get the pod name from backend deploy (example: gbpd-api-6676c7695c-6bs5n)
run kubectl exec -it pod/<POD_NAME> -- /bin/bash
then run apt update && apt install curl -y
and test curl localhost:3008
if no answer run `apt update && apt install net-tools
and test netstat -nlpt, it will have to show you the output of the services running and the respective port, example:
root#gbpd-api-585df9cb4d-xr6nk:/# netstat -nlpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginx: master pro
If the pod does not return nothing even on this approach, you will have to check the code in the image.
Let me know if you need help after that!
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
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.
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
I'm trying to deploy my Dockerized React app to Kubernetes. I believe I've dockerized it correctly, but i'm having trouble accessing the exposed pod.
I don't have experience in Docker or Kubernetes, so any help would be appreciated.
My React app is just static files (from npm run build) being served from Tomcat.
My Dockerfile is below. In summary, I put my app in the Tomcat folder and expose port 8080.
FROM private-docker-registry.com/repo/tomcat:latest
EXPOSE 8080:8080
# Copy build directory to Tomcat webapps directory
RUN mkdir -p /tomcat/webapps/app
COPY /build/sample-app /tomcat/webapps/app
# Create a symbolic link to ROOT -- this way app starts at root path
(localhost:8080)
RUN ln -s /tomcat/webapps/app /tomcat/webapps/ROOT
# Start Tomcat
ENTRYPOINT ["catalina.sh", "run"]
I build and pushed the Docker image to the Private Docker Registry.
I verified that container runs correctly by running it like this:
docker run -p 8080:8080 private-docker-registry.com/repo/sample-app:latest
Then, if I go to localhost:8080, I see the homepage of my React app.
Now, the trouble I'm having is deploying to Kubernetes and accessing the app externally.
Here's my deployment.yaml file:
kind: Deployment
apiVersion: apps/v1beta2
metadata:
name: sample-app
namespace: dev
labels:
app: sample-app
spec:
replicas: 1
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: sample-app
image: private-docker-registry.com/repo/sample-app:latest
ports:
- containerPort: 8080
protocol: TCP
nodeSelector:
TNTRole: luxkube
---
kind: Service
apiVersion: v1
metadata:
name: sample-app
labels:
app: sample-app
spec:
selector:
app: sample-app
type: NodePort
ports:
- port: 80
targetPort: 8080
protocol: TCP
I created the deployment and service by running
kubectl --namespace=dev create -f deployment.yaml
Output of 'describe deployment'
Name: sample-app
Namespace: dev
CreationTimestamp: Sat, 21 Jul 2018 12:27:30 -0400
Labels: app=sample-app
Annotations: deployment.kubernetes.io/revision=1
Selector: app=sample-app
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=sample-app
Containers:
sample-app:
Image: private-docker-registry.com/repo/sample-app:latest
Port: 8080/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: sample-app-bb6f59b9 (1/1 replicas created)
Events: <none>
Output of 'describe service'
Name: sample-app
Namespace: fab-dev
Labels: app=sample-app
Annotations: <none>
Selector: app=sample-app
Type: NodePort
IP: 10.96.29.199
Port: <unset> 80/TCP
TargetPort: 8080/TCP
NodePort: <unset> 34604/TCP
Endpoints: 192.168.138.145:8080
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
Now I don't know which IP and port I should be using to access the app.
I have tried every combination but none has loaded my app. I believe the port should be 80, so if I just have the IP, i shuold be able to go to the browser and access the React app by going to http://.
Does anyone have suggestions?
The short version is that the Service is listening on the same TCP/IP port on every Node in your cluster (34604) as is shown in the output of describe service:
NodePort: <unset> 34604
If you wish to access the application through a "nice" URL, you'll want a load balancer that can translate the hostname into the in-cluster IP and port combination. That's what an Ingress controller is designed to do, but it isn't the only way -- changing the Service to be type: LoadBalancer will do that for you, if you're running in a cloud environment where Kubernetes knows how to programmatically create load balancers for you.
I believe you found the answer by now :), I landed here as I was facing this issue. Solved for self, hope this helps everyone.
Here's what can help:
Deploy your app (say: react-app).
Run below command:
kubectl expose deployment <workload> --namespace=app-dev --name=react-app --type=NodePort --port=3000 output: service/notesui-app exposed
Publish the service port as 3000, Target Port 3000, Node Port (auto selected 32250)
kubectl get svc react-app --namespace=notesui-dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
react-app NodePort 10.23.22.55 <none> 3000:32250/TCP 48m
Yaml: (sample)
apiVersion: v1
kind: Service
name: react-app
namespace: app-dev
spec:
selector: <workload>
ports:
- nodePort: 32250
port: 3000
protocol: TCP
targetPort: 3000
type: NodePort
status: {}
Access the app on browser:
http://<Host>:32250/index
is your node ip where pod is running.
If you have app running in multiple nodes (scaled). It is a NodePort setting on every node.
App can be accessed:
http://<Host1>:32250/index
http://<Host2>:32250/index