Kubernetes service not able to curl itself inside docker - docker

Background
I am testing the Kubernetes setting on Minikube. I have two simple services successfully setup and they are backed by simple docker image. Below is an example of my service configuration. I use NodePort to expose the service on port 80.
# service 1
kind: Service
apiVersion: v1
metadata:
name: service1
spec:
selector:
app: service1
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: service1-deployment
labels:
app: service1
spec:
replicas: 1
selector:
matchLabels:
app: service1
template:
metadata:
labels:
app: service1
spec:
containers:
- name: service1
image: service1
imagePullPolicy: Never
ports:
- containerPort: 8080
---
# service 2
kind: Service
apiVersion: v1
metadata:
name: service2
spec:
selector:
app: service2
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: service2-deployment
labels:
app: service2
spec:
replicas: 1
selector:
matchLabels:
app: service2
template:
metadata:
labels:
app: service2
spec:
containers:
- name: service2
image: service2
imagePullPolicy: Never
ports:
- containerPort: 8080
Issue
I use docker exec -it to go inside docker container. I can curl service1 from service2 container without any issue. However, if I try to curl service2 from service2 container, it gets a timeout connection error.
Results from curl -v service2
Rebuilt URL to: service2/
Trying 10.101.116.46...
TCP_NODELAY set
connect to 10.101.116.46 port 80 failed: Connection timed out
Failed to connect to service2 port 80: Connection timed out
Closing connection 0
curl: (7) Failed to connect to service2 port 80: Connection timed out
I guess the DNS records gets resolved correctly, because 10.101.116.46 is the correct IP attached to service2. Then what could be the issue cause this problem?
More Followup Tests
From my understanding, the Kubernetes service internally maps the port to container port, so in my case it maps service port 80 to pod port 8080. From service2 container, I am able to curl <service2 pod ip>:8080 successfully, but I am not able to curl <service2 ip>, which resolves connection time out error. And this happens exactly the same inside the service1 container that it can access pod but no service. I do not understand is there any internal setting that I miss?

This could be any of these:
The pod servicing service2 has a service that is listening on 127.0.0.1 or not listening on 0.0.0.0 (Any IP address)
service2 has a redirect and your service only listen on port 80. You would have to enable the other port (possibly 443) and run curl with the -L option to follow the link.
The pod servicing service2 is not even listening on port 80.

Related

Can't access my node in k8s via browser (with service & deployment) [duplicate]

This question already has an answer here:
Kubernetes services are not accessible through nodeport with Desktop Docker setup
(1 answer)
Closed 2 years ago.
There is the deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-task-tracker-deployment
spec:
selector:
matchLabels:
app: my-task-tracker
replicas: 5
template:
metadata:
labels:
app: my-task-tracker
spec:
containers:
- name: hello-world
image: shaikezam/task-tracker:1.0
ports:
- containerPort: 8080
protocol: TCP
This is the service (NodePort):
apiVersion: v1
kind: Service
metadata:
name: my-task-tracker-service
labels:
app: my-task-tracker
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8085
nodePort: 30001
protocol: TCP
selector:
app: my-task-tracker
Now, I try to access localhost:8085 or localhost:30001, and nothing happened.
I'm running using K8S in docker desktop.
Any suggestion what I'm doing wrong?
Target port should be 8080 in service yaml if that is what your container runs on as per your deployment yaml file.
apiVersion: v1
kind: Service
metadata:
name: my-task-tracker-service
labels:
app: my-task-tracker
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
nodePort: 30001
protocol: TCP
selector:
app: my-task-tracker
=======
port exposes the Kubernetes service on the specified port within the cluster. Other pods within the cluster can communicate with this server on the specified port.
TargetPort is the port on which the service will send requests to, that your pod will be listening on. Your application in the container will need to be listening on this port also.
NodePort exposes a service externally to the cluster by means of the target nodes IP address and the NodePort. NodePort is the default setting if the port field is not specified. You should be able to use your application on Nodeport as well.
In your case target port should be 8080 that is what is important for app to run ,you can listen to your app on port 8085 within your cluster by changing the port field in the yaml and externally by changing the Nodeport.

Why I can't access my web service from the kubernetes cluster?

I'm trying to execute an application inside a kubernetes cluster.
I used to launch the application with docker-compose without problems, but when I create
my kubernetes deployment files, I am not able to access the service inside the cluster even after exposing them. here is my deployment file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
# type: LoadBalancer
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: jksun12/vdsaipro
# command: ["/run.sh"]
ports:
- containerPort: 80
- containerPort: 3306
# volumeMounts:
# - name: myapp-pv-claim
# mountPath: /var/lib/mysql
# volumes:
# - name: myapp-pv-claim
# persistentVolumeClaim:
# claimName: myapp-pv-claim
---
apiVersion: apps/v1
kind: PersistentVolumeClaim
metadata:
name: myapp-pv-claim
labels:
app: myapp
spec:
accesModes:
- ReadWriteMany
resources:
requests:
storage: 4Gi
Here is the result of
kubectl describe service myapp-service
:
Name: myapp-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=myapp
Type: NodePort
IP: 10.109.12.113
Port: port-1 80/TCP
TargetPort: 80/TCP
NodePort: port-1 31892/TCP
Endpoints: 172.18.0.5:80,172.18.0.8:80,172.18.0.9:80
Port: port-2 3306/TCP
TargetPort: 3306/TCP
NodePort: port-2 32393/TCP
Endpoints: 172.18.0.5:3306,172.18.0.8:3306,172.18.0.9:3306
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
And here are the errors that I get when I try to access them:
curl 172.17.0.2:32393
curl: (1) Received HTTP/0.9 when not allowed
And here is the next result when I try to access the other port
curl 172.17.0.2:31892
curl: (7) Failed to connect to 172.17.0.2 port 31892: Connection refused
curl: (7) Failed to connect to 172.17.0.2 port 31892: Connection refused
I'm running ubuntu server 20.04.1 LTS. The manip is on top of minikube.
Thanks for your help.
If you are accessing the service from inside the cluster use ClusterIP as the IP. So curl should be 10.109.12.113:80 and 10.109.12.113:3306
In case accessing it from outside the cluster then use NODEIP and NODEPORT. So curl should be on <NODEIP>:32393 and <NODEIP>:31892
From inside the cluster I would also use POD IPs directly to understand if the issue is at service level or pod level.
You need to make sure that the application is listening on port 80 and port 3306. Only mentioning containerPort as 80 and 3306 does not make the application listen on those ports.
Also make sure that the application code inside the pod is listening on 0.0.0.0 instead of 127.0.0.1

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/

How to use kube-proxy to forward https serivce in k8s?

As we know ,kube-proxy is used to proxy serive that could be accessed from external network via apiserver, does kube-proxy support to proxy https service in k8s or any other solution so that we could access it via apiserver ?
You need to expose your https pods via a service of type Nodeport, then you can access the https via the defined port on any node in the cluster (master or worker) because kube-proxy will forward the requests to your pods that are part of the service. NodePorts can be in the range of 30000-32767 by default.
Example configuration for an https service and deployment with nginx:
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
name: nginx
labels:
app: nginx
spec:
type: NodePort
ports:
- port: 443
name: nginx
targetPort: 443
nodePort: 32756
selector:
app: nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginxdeployment
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: Always
ports:
- containerPort: 443
kube-proxy iptables mode works on IP layer(Networking layer), it does not care if the packet is http or https.

Resources