Cannot access NodePort service outside Kubernetes cluster - docker

I am on Windows and used Docker Desktop to deploy a local Kubernetes cluster using WSL 2. I tried to deploy a pod and expose it through a NodePort service so I could access it outside the cluster, but it is not working.
Here are the commands to reproduce the scenario:
kubectl create deployment echoserver --image=k8s.gcr.io/echoserver:1.4
kubectl expose deployment echoserver --type=NodePort --port=8080
Trying to open NODE_IP:EXPOSED_PORT in the browser or running the netcat command nc NODE_IP EXPOSED_PORT and trying to send a message (from either WSL or Windows) does not work.
NODE_IP is the internal IP of the Docker Desktop K8S node (obtained by seeing the INTERNAL-IP column on the command kubectl get nodes -o wide)
EXPOSED_PORT is the node port exposed by the service (obtained by seeing the field NodePort on command kubectl describe service echoserver)
Opening the URL on the browser should be met with this page. However, you will get a generic error response saying the browser couldn't reach the URL.
Sending a message with the netcat command should be met with a 400 Bad Request response, as it will not be a properly formatted HTTP request. However, you will not get any response at all or the TCP connection may not even be made in the 1st place.
Trying to communicate with the service and/or the pod from inside the cluster, for example, through another pod, works perfectly.
Using the command kubectl port-forward deployment/echoserver 2311:8080 to port forward the deployment locally and then either accessing localhost:2311 in the browser or through netcat also work perfectly (in both WSL and Windows).

If you want to access it not using localhost you should use your <windows_hosts's_IP:NodePort>.
So having your deployment and service deployed:
$kubectl get svc,deploy
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/echoserver NodePort 10.105.169.2 <none> 8080:31570/TCP 4m12s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5m3s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/echoserver 1/1 1 1 4m19s
You can either access it by using localhost:31570 or <windows_hosts's_IP:NodePort>.
In my case 192.168.0.29 is my Windows host's IP:
curl.exe 192.168.0.29:31570
CLIENT VALUES:
client_address=192.168.65.3
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://192.168.0.29:8080/

Related

Container docker & Kubernetes apache tomcat 8.5.56 http status 404

please I'm running a .war application on apache tomcat 8.5.56 in a docker container and everything work well, but when I create deploy the container on Kubernetes I can access my application welcome page: I have the error message
HTTP Status 404 – Not Found
Type Status Report
Message The requested resource [/SmartClass] is not available
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Apache Tomcat/8.5.56
Please anyone knows how to solve it?
For the deployment I have just copied the .war file into
/opt/apache-tomcat/webapps/ and I have copied my server.xml file into /opt/apache-tomcat/conf/
It looks like the problem is related to the connection to the application.
Create a Service object that exposes your Tomcat deployment:
kubectl expose deployment tomcat-example --type=NodePort --name=example-service
Display information about the Service:
kubectl describe services example-service
The output is similar to this:
Name: example-service
Namespace: default
Labels: run=lexample
Annotations: <none>
Selector: run=example
Type: NodePort
IP: 10.32.0.16
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 30000/TCP
Endpoints: 10.200.1.4:8080,10.200.2.5:8080
Session Affinity: None
Events: <none>
Make a note of the NodePort value for the service. For example, in the preceding output, the NodePort value is 30000.
List the pods that are running the Tomcat application:
kubectl get pods --selector="run=example" --output=wide
The output is similar to this:
NAME READY STATUS ... IP NODE
tomcat-2895499144-bsbk5 1/1 Running ... 10.200.1.4 worker1
tomcat-2895499144-m1pwt 1/1 Running ... 10.200.2.5 worker2
Get the public IP address of one of your nodes that is running a Tomcat pod. How you get this address depends on how you set up your cluster. For example, if you are using Minikube, you can see the node address by running kubectl cluster-info. If you are using Google Compute Engine instances, you can use the gcloud compute instances list command to see the public addresses of your nodes.
On your chosen node, create a firewall rule that allows TCP traffic on your node port. For example, if your Service has a NodePort value of 31568, create a firewall rule that allows TCP traffic on port 30000. Different cloud providers offer different ways of configuring firewall rules.
Use the node address and node port to access the Hello World application:
curl http://<public-node-ip>:<node-port>
where <public-node-ip> is the public IP address of your node, and <node-port> is the NodePort value for your service.
Please adjust above command according to proper names and values you have used.

Unable to access to service from kubernetes master node

[root#kubemaster ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod1deployment-c8b9c74cb-hkxmq 1/1 Running 0 12s 192.168.90.1 kubeworker1 <none> <none>
[root#kubemaster ~]# kubectl logs pod1deployment-c8b9c74cb-hkxmq
2020/05/16 23:29:56 Server listening on port 8080
[root#kubemaster ~]# kubectl get service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m <none>
pod1service ClusterIP 10.101.174.159 <none> 80/TCP 16s creator=sai
Curl on master node:
[root#kubemaster ~]# curl -m 2 -v -s http://10.101.174.159:80
* About to connect() to 10.101.174.159 port 80 (#0)
* Trying 10.101.174.159...
* Connection timed out after 2001 milliseconds
* Closing connection 0
Curl on worker node 1 is sucessfull for cluster IP ( this is the node where pod is running )
[root#kubemaster ~]# ssh kubeworker1 curl -m 2 -v -s http://10.101.174.159:80
Hello, world!
Version: 1.0.0
Hostname: pod1deployment-c8b9c74cb-hkxmq
Curl fails on other worker node as well :
[root#kubemaster ~]# ssh kubeworker2 curl -m 2 -v -s http://10.101.174.159:80
* About to connect() to 10.101.174.159 port 80 (#0)
* Trying 10.101.174.159...
* Connection timed out after 2001 milliseconds
* Closing connection 0
I was facing the same issue so this is what I did and it worked:
Brief: I am running 2 VMs for a 2 Node cluster. 1 Master Node and 1 Worker Node. A Deployment is running on the worker node. I wanted to curl from the master node so that I can get response from my application running inside a pod on the worker node. For that I deployed a service on the worker node which then exposed those set of pods inside the cluster.
Issue: After deploying the service and doing Kubectl get service, it provided me with ClusterIP of that service and a port (BTW I used NodePort instead of Cluster IP when writing the service.yaml). But when curling on that IP address and port it was just hanging and then after sometime giving timeout.
Solution: Then I tried to look at the hierarchy. First I need to contact the Node on which service is located then on the port given by the NodePort (i.e The one between 30000-32767) so first I did Kubectl get nodes -o wide to get the Internal IP address of the required Node (mine was 10.0.1.4) and then I did kubectl get service -o wide to get the port (the one between 30000-32767) and curled it. So my curl command was -> curl http://10.0.1.4:30669 and I was able to get the output.
First of all, you should always be using Service DNS instead of Cluster/dynamic IPs to access the application deployed. The service DNS would be < service-name >.< service-namespace >.svc.cluster.local, cluster.local is the default Kubernetes cluster name, if not changed otherwise.
Now coming to the service accessibility, it may be DNS issues. What you can do is try to check the kube-dns pod logs in kube-system namespace. Also, try to curl from a standalone pod. If that's working.
kubectl run --generator=run-pod/v1 bastion --image=busybox
kubectl exec -it bastion bash
curl -vvv pod1service.default.svc.cluster.local
If not the further questions would be, where is the cluster and how it was created?

Kubernetes hello-minikube Tutorial - Can't Connect to Pod

Apologies if this is a really simple question - I am following the hello-minikube the tutorial on the Kubernetes link below (running on Mac OS)
Minikube tutorial
I created a deployment on port 8380 as 8080 is in use,
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-node ClusterIP 10.100.248.81 <none> 8380/TCP 11s
I also exposed the deployment, but when I try to curl or open the app URL I get connection refused.
Failed to connect to localhost port 8380: Connection refused
Also if I specify --type=LoadBalancer during the expose step - that also fails to connect.
Any help would be much appreciated.
I've recreated all the steps from the tutorial you have mentioned.
Your error only occurs when you do not change the port from 8080 to 8380, in one of the steps provided in the documentation. After you change it in all 3 places, it works perfectly fine.
What I suggest is checking if you changed the port in the server.js file - as it is used by the Dockerfile in build phase:
var www = http.createServer(handleRequest);
www.listen(8080); #->8380
Then in the Dockerfile in EXPOSE 8080 # -> 8380.
And the last place is while running the deployment:
kubectl run hello-node --image=hello-node:v1 --port=8380 --image-pull-policy=Never
I've tested this with --type=LoadBalancer.

minikube : not able to connect a locally deployed nginx service

I have installed minikube on my ubuntu 16.04 machine and have started a cluster, with a message
"Kubernetes is available at https://192.168.99.100:443"
Next, I deployed nginx service with the following command
> kubectl.sh run my-nginx --image=nginx --replicas=2 --port=80 --expose
> kubectl.sh get pods -o wide
NAME READY STATUS RESTARTS AGE NODE
my-nginx-2494149703-8jnh4 1/1 Running 0 13m 127.0.0.1
my-nginx-2494149703-q09be 1/1 Running 0 13m 127.0.0.1
> kubectl.sh get services -o wide
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes 10.0.0.1 <none> 443/TCP 14m <none>
my-nginx 10.0.0.83 <none> 80/TCP 13m run=my-nginx
> kubectl.sh get nodes -o wide
NAME STATUS AGE
127.0.0.1 Ready 16m
Questions:
1) Is node 127.0.0.1 my local development machine? This has got me confused me the most.
2) Is my following understanding correct: The cluster (nodes, kubernetes API server) has internal IP addresses in 10.0.0.x and their corresponding external IP addresses are 192.168.99.x. The 2 pods will then have IPs in the range like 10.0.1.x and 10.0.2.x ?
3) Why is the external IP for the services not there? Not even, for the kubernetes service. Isn't the 192.168.99.43 an external IP here?
4) Most importantly, how do I connect to the nginx service from my laptop?
1) Is node 127.0.0.1 my local development machine? This has got me
confused me the most.
When a node registers, you provide the IP or name to register with. By default, the node is just registering 127.0.0.1. This is referencing your VM running linux, not your host machine.
2) Is my following understanding correct: The cluster (nodes,
kubernetes API server) has internal IP addresses in 10.0.0.x and their
corresponding external IP addresses are 192.168.99.x. The 2 pods will
then have IPs in the range like 10.0.1.x and 10.0.2.x ?
Yup, the 10.0.0.x network is your overlay network. The 192.168.99.x are your "public" addresses which are visible outside of the cluster.
3) Why is the external IP for the services not there? Not even, for
the kubernetes service. Isn't the 192.168.99.43 an external IP here?
The external IP is typically used to ingress traffic via a specific IP. The kubernetes service is using a clusterIP service type which means it's only visible to the internal cluster.
4) Most importantly, how do I connect to the nginx service from my
laptop?
The easiest way to view your nginx service is to make it type NodePort, then deploy the service. After that, describe the service to get the port that was assigned (or after you create it will tell you as well). Then hit the ip of your VM and provide the auto assigned NodePort.
e.g. http://192.168.99.100:30001

How can I access the Kubernetes service through ClusterIP

I am trying to create Kubernetes cluster using three VMs(Master – 10.x.x.4, Node1 – 10.x.x.150, Node2 – 10.x.x.160).
I was able to create the guestbook application successfully following this link: http://kubernetes.io/v1.0/examples/guestbook/. Only one change I made to frontend-service.yaml: to use NodePort. I can access the frontend service using nodes IP and port number(10.x.x.150:30724 or 10.x.x.160:30724). So everything is working as expected but I am not able to access the frontend service using ClusterIP address(in my case 10.x.x.79).
My understanding of NodePort is that the service can be accessed through cluster IP and also on a port on each node of the cluster. How can I access the service through ClusterIP so that I don’t have to access the each node? Am I missing something here?
service and pod details
$sudo kubectl describe service frontend
Name: frontend
Namespace: default
Labels: name=frontend
Selector: name=frontend
Type: NodePort
IP: 10.x.x.79
Port: <unnamed> 80/TCP
NodePort: <unnamed> 30724/TCP
Endpoints: 172.x.x.13:80,172.x.x.14:80,172.x.x.11:80
Session Affinity: None
No events.
$sudo kubectl describe pod frontend-2b5us
Name: frontend-2b5us
Namespace: default
Image(s): gcr.io/google_samples/gb-frontend:v3
Node: 10.x.x.150/10.x.x.150
Labels: name=frontend
Status: Running
Reason:
Message:
IP: 172.x.x.11
Replication Controllers: frontend (3/3 replicas created)
Containers:
php-redis:
Image: gcr.io/google_samples/gb-frontend:v3
State: Running
Started: Fri, 30 Oct 2015 04:00:40 -0500
Ready: True
Restart Count: 0
I tried to search but would not find any solution for my exact problem but I did find similar problem that looks like for GCE.
Why can't I access my Kubernetes service via its IP?
You do not have ClusterIP service. You do have a NodePort service. To access it, you connect to the NodePort on any of your nodes in the cluster, as you've already discovered. You do get load-balancing here. Even though you connect to a cluster node, the pod you get does not necessarily run on that particular node.
Read the relevant section in the documentation at https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types to learn about additional service types. You probably do not want NodePort on GCP.
Talking about ClusterIP. To access a ClusterIP service for debugging purposes, you can run kubectl port-forward. You will not actually access the service, but you will directly connect to one of the pods.
For example
kubectl port-forward frontend-2b5us 80 8080
Now connect to localhost:8080
More sophisticated command, which discovers the port on its own, given namespace -n weave and a selector. Taken from https://www.weave.works/docs/scope/latest/installing/
kubectl port-forward -n weave \
"$(kubectl get -n weave pod \
--selector=weave-scope-component=app \
-o jsonpath='{.items..metadata.name}')" \
4040
From where are you trying to access clusterIP? The clusterIP (by default) only works from within the cluster. It is a virtual IP, not routed.

Resources