Unable to connect to minikube service in host - docker

I've gone through a fair few stackoverflow posts, none are working... So here's my issue:
I've got a simple node app running on broadcast 0.0.0.0 at port 5000, it's got a simple single endpoint at /.
I've got two k8s objects, here's my Deployment object:
### pf deployment
apiVersion: apps/v1
kind: Deployment
metadata:
# Unique key of the Deployment instance
name: pf-deployment
spec:
# 3 Pods should exist at all times.
replicas: 1
selector:
matchLabels:
app: public-facing
template:
metadata:
labels:
# Apply this label to pods and default
# the Deployment label selector to this value
app: public-facing
spec:
containers:
- name: public-facing
# Run this image
image: pf:ale8k
ports:
- containerPort: 5000
Next, here is my Service object:
### pf service
apiVersion: v1
kind: Service
metadata:
name: pf-service
labels:
run: pf-service-label
spec:
type: NodePort ### may be ommited as it is a default type
selector:
name: public-facing ### should match your labels defined for your angular pods
ports:
- protocol: TCP
targetPort: 5000 ### port your app listens on
port: 5000 ### port on which you want to expose it within your cluster
Finally, a very simple dockerfile:
### generic docker file
FROM node:12
WORKDIR /usr/src/app
COPY . .
RUN npm i
EXPOSE 5000
CMD ["npm", "run", "start"]
I have my image in the minikubes local docker registry, so that's not the issue...
When I try:
curl $(minikube service pf-service --url)
I get:
curl: (7) Failed to connect to 192.168.99.101 port 31753: Connection refused
When I try:
minikube service pf-service
I get a little further output:
Most likely you need to configure your SUID sandbox correctly
I have the hello-minikube image running, this works perfectly fine. So I presume it isn't my nacl?
I'm very new to kubernetes, so apologies in advance if it's very simple.
Thanks!

Service has got selector name: public-facing but pod has got label app: public-facing. They need to be same for Endpoints of the service to be populated with pod IPs.
If you execute below command
kubectl describe svc pf-service
You will see that Endpoints has got no IPs which is the cause of connection refused error.
Change the selector in service as below to make it work.
### pf service
apiVersion: v1
kind: Service
metadata:
name: pf-service
labels:
run: pf-service-label
spec:
type: NodePort ### may be ommited as it is a default type
selector:
app: public-facing ### should match your labels defined for your angular pods
ports:
- protocol: TCP
targetPort: 5000 ### port your app listens on
port: 5000 ### port on which you want to expose it within your cluster

Related

How can I correctly forward traffic from a container to a NodePort service with Kubernetes?

I am running Minikube on an m1 mac with the docker daemon. I have a container in a pod serving HTTP on port 7777; according to the documentation, I can use a combination of a nodeport and the minikube service command to expose it to the local machine. My configuration yaml file is pretty simple as well:
apiVersion: v1
kind: Pod
metadata:
name: door-controls
labels:
type: door-controls
spec:
containers:
- image: door_controls
name: door-controls
imagePullPolicy: Never
ports:
- containerPort: 7777
name: httpz
---
apiVersion: v1
kind: Service
metadata:
name: door-control-service
spec:
type: NodePort
selector:
type: door-controls
ports:
- name: svc-http
protocol: TCP
port: 80
targetPort: httpz
Running this in minikube and then attempting to use minikube service will expose the running process on a random port. From a machine inside the network, I can wget the pod IP on port 7777 and get data back, so I know the pod is correctly serving traffic. I also can wget the door-control-service nodeport service from inside the network on port 80 and get traffic back, so I know that the door-control-service configuration is working. But no amount of futzing will allow me to access the door-control-service inside the network via the nodeport (which is randomly generated in the port ~30k range, and the browser launched by minikube service never returns data so I can't access it outside of that range either.
What am I doing wrong? Or more generally, how can I debug this issue? I am new to kubernetes and not sure where in the logs I should be looking for errors in the first place.

How to route test traffic through kubernetes cluster (minikube)?

I have a minikube cluster with two pods (with ubuntu containers). What I need to do is route test traffic from one port to another through this minikube cluster. This traffic should be sent through these two pods like in the picture. I am a beginner in this Kubernetes stuff so I really don't know how to do this and which way to go... Please, help me or give me some hints.
I am working on ubuntu server ver. 18.04.
enter image description here
I agree with an answer provided by #Harsh Manvar and I would also like to expand a little bit on this topic.
There already is an answer with a similar setup. I encourage you to check it out:
Stackoverflow.com: Questions: How to access a service from other machine in LAN
There are different drivers that could be used to run your minikube. They will have differences when it comes to dealing with inbound traffic. I missed the part that was telling about the driver used in the setup (comment). If it's the Docker shown in the tags, you could follow below example.
Example
Steps:
Spawn nginx-one and nginx-two Deployments to imitate Pods from the image
Create a service that will be used to send traffic from nginx-one to nginx-two
Create a service that will allow you to connect to nginx-one from LAN
Test the setup
Spawn nginx-one and nginx-two Deployments to imitate Pods from the image
You can use following definitions to spawn two Deployments where each one will have a single Pod:
nginx-one.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-one
spec:
selector:
matchLabels:
app: nginx-one
replicas: 1
template:
metadata:
labels:
app: nginx-one
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
nginx-two.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-two
spec:
selector:
matchLabels:
app: nginx-two
replicas: 1
template:
metadata:
labels:
app: nginx-two
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Create a service that will be used to send traffic from nginx-one to nginx-two
You will need to use a Service to send the traffic from nginx-one to nginx-two. Example of such Service could be following:
apiVersion: v1
kind: Service
metadata:
name: nginx-two-service
spec:
type: ClusterIP # could be changed to NodePort
selector:
app: nginx-two # IMPORTANT
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
After applying this definition you will be able to send the traffic to nginx-two by using the service name (nginx-two-service)
A side note!
You can use the IP of the Pod without the Service but this is not a recommended way.
Create a service that will allow you to connect to nginx-one from LAN
Assuming that you want to expose your minikube instance to LAN with Docker driver you will need to create a service and expose it. Example of such setup could be the following:
apiVersion: v1
kind: Service
metadata:
name: nginx-one-service
spec:
type: ClusterIP # could be changed to NodePort
selector:
app: nginx-one # IMPORTANT
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
You will also need to run:
$ kubectl port-forward --address 0.0.0.0 service/nginx-one-service 8000:80
Above command (ran on your minikube host!) will expose your nginx-one-service to be available on LAN. It will map port 8000 on the machine that ran this command to the port 80 of this service. You can check it by executing from another machine at LAN:
curl IP_ADDRESS_OF_MINIKUBE_HOST:8000
A side note!
You will need root access to have your inbound traffic enter on ports lesser than 1024.
Test the setup
You will need to check if there is a communication between the objects as shown in below "connection diagram".
PC -> nginx-one -> nginx-two -> example.com
The testing methodology could be following:
PC -> nginx-one:
Run on a machine in your LAN:
curl MINIKUBE_IP_ADDRESS:8000
nginx-one -> nginx-two:
Exec into your nginx-one Pod and run command:
$ kubectl exec -it NGINX_POD_ONE_NAME -- /bin/bash
$ curl nginx-two-service
nginx-two -> example.com:
Exec into your nginx-two Pod and run command:
$ kubectl exec -it NGINX_POD_TWO_NAME -- /bin/bash
$ curl example.com
If you completed above steps you can swap nginx Pods for your own software.
Additional notes and resources:
I encourage you to check kubeadm as it's the tool to create your own Kubernetes clusters:
Kubernetes.io: Docs: Setup: Production environment: Tools: Kubeadm: Create cluster kubeadm
As you said:
I am a beginner in this Kubernetes stuff so I really don't know how to do this and which way to go... Please, help me or give me some hints.
You could check following links for more resources:
Kubernetes.io
Kubernetes: Docs: Concepts: Workloads: Controllers: Deployment
Kubernetes.io: Docs: Concepts: Services networking: Service
There are multiple options you can follow:
As you have two PODs you can expose one via service,
so service-1 is exposed and sending traffic to POD-1
POD-1 will send a request to service-2 of Kubernetes
This way traffic will get forwarded to POD-2 and from there it will Go out of cluster
There is also a container to container communication possibility if you can run both applications in a single POD.
POD-1 to POD-2 communication you can use the service option or POD URI.

Can't access a pod from another pod using NodePort service

I have a very simple setup. I'm running Kubernetes using the Docker Desktop Kubernetes feature on my PC.
There are 2 pods running from the yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
labels:
app: my-nginx
spec:
replicas: 2
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: my-nginx
image: nginx:alpine
There is another pod running from the command: kubectl run nginx-standalone --image nginx:alpine
There is a service from yaml:
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: my-nginx
ports:
- port: 80
targetPort: 80
nodePort: 31000
Basically, the service is "connected" only to the pods that come from yaml deployment, due to labels selector.
What I'm doing:
I "ssh" into nginx-standalone
I installed curl (inside of nginx-standalone)
I tried the following (inside of nginx-standalone):
curl nginx-nodeport - works well, I get the proper response
curl nginx-nodeport:31000 - does not work, I get curl: (7) Failed to connect to nginx-nodeport port 31000: Connection refused
I do not understand why the 2nd command does not return a successful HTTP response. I know that the 31000 port works, because I can do curl nginx-nodeport:31000 from my host PC. Why it does not work from the nginx-standalone pod?
That's expected behavior because the nodePort 31000 is listening on the nodes network interface and does not exist in pod's network interface. If you want to access a pod from another pod via kubernetes service use clusterIP type service instead of NodePort type. NodePort type service should be used for exposing a kubernetes pod to consumers outside the kubernetes cluster.

Accessing app outside kubernetes cluster with minikube

i'm new to kubernetes , i'm trying to learn it using minikube and i'm facing a problem with accessing apps outside the cluster. i created a deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 8080
To access it i need to expose it decoratively or imperatively. In the imperative way it works :
kubectl expose deployment nginx-deployment --port 80 --type NodePort
When i create a service declaratively i always end up with a connection refused error :
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
type : NodePort
ports:
- port : 8080
nodePort : 30018
protocol : TCP
selector:
app: nginx
curl -k http://NodeIP:NodePort returns :
curl: (7) Failed to connect to Node IP port NodePORT: Connection
refused
As #Ansil suggested, your nginx should be configured to listen on port 8080 if you want to refer to this port in your Service definition. By default it listens on port 80.
You cannot make it listen on different port like 8080 simply by specifying different containerPort in your Deployment definition as in your example:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 8080
You can easily verify it on your own by attaching to such Pod:
kubectl exec -ti <nginx-pod-name> -- /bin/bash
Once you're there, run:
ss -ntlp
And you should see on which port your nginx actually listens on.
Additionally you may:
cat /etc/nginx/conf.d/default.conf
It will also tell you on which port your nginx is configured to listen. That's all. It's really simple. You changed containerPort to 8080 but inside your container nothing actually listens on such port.
You can still expose it as a Service (no matter declaratively or imperatively) but it won't change anything as eventually it points to the wrong port on your container, on which nothing listens and you'll see message similar to this one:
curl: (7) Failed to connect to 10.1.2.3 port 30080: Connection refused
Once you create a service in minikube you can expose the service to the outside of the minikube VM (host machine) using the command
minikube service SERVICE_NAME
Refer: https://minikube.sigs.k8s.io/docs/reference/commands/service/

Can't access an Express.js service via a Kubernetes NodePort service in a MicroK8s cluster

I have a simple Express.js server Dockerized and when I run it like:
docker run -p 3000:3000 mytag:my-build-id
http://localhost:3000/ responds just fine and also if I use the LAN IP of my workstation like http://10.44.103.60:3000/
Now if I deploy this to MicroK8s with a service deployment declaration like:
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
name: my-service
spec:
type: NodePort
ports:
- name: "3000"
port: 3000
targetPort: 3000
status:
loadBalancer: {}
and pod specification like so (update 2019-11-05):
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
name: my-service
spec:
replicas: 1
selector:
matchLabels:
name: my-service
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
name: my-service
spec:
containers:
- image: mytag:my-build-id
name: my-service
ports:
- containerPort: 3000
resources: {}
restartPolicy: Always
status: {}
and obtain the exposed NodePort via kubectl get services to be 32750 and try to visit it on the MicroK8s host machine like so:
curl http://127.0.0.1:32750
then the request just hangs and if I try to visit the LAN IP of the MicroK8s host from my workstation at
http://192.168.191.248:32750/
then the request is immediately refused.
But, if I try to port forward into the pod with
kubectl port-forward my-service-5db955f57f-q869q 3000:3000
then http://localhost:3000/ works just fine.
So the pod deployment seems to be working fine and example services like the microbot-service work just fine on that cluster.
I've made sure the Express.js server listens on all IPs with
app.listen(port, '0.0.0.0', () => ...
So what can be the issue?
You need to add a selector to your service. This will tell Kubernetes how to find your deployment. Additionally you can use nodePort to specify the port number of your service. After doing that you will be able to curl your MicroK8s IP.
Your Service YAML should look like this:
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
name: my-service
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30001
selector:
name: my-service
status:
loadBalancer: {}
the LAN IP of the MicroK8s host from my workstation
That is the central source of your misunderstanding; localhost, 127.0.0.1, and your machine's LAN IP have nothing to do with what is apparently a virtual machine running microk8s (which it would have been infinitely valuable to actually include that information in your question, rather than us having to deduce it from one buried sentence)
I've made sure the Express.js server listens on all IPs with
Based on what you reported later:
at http://192.168.191.248:32750/ then the request is immediately refused.
then it appears that your express server is not, in fact, listening on all interfaces. That explains why you can successfully port-forward into the Pod (which causes traffic to appear on the Pod's localhost) but not reach it from "outside" the Pod
You can also test that theory by using another Pod inside the cluster to curl its Pod IP on port 3000 (in order to side-step the Service and thus NodePort parts)
There is a small chance that you have misconfigured your Pod and Service relationship, but since you didn't post your PodSpec, and the behavior you are describing sounds a lot more like an express misconfiguration, we'll go with that until we have evidence to the contrary

Resources