I am using kubernetes and run one service. Service is running and is showing in service. But i am not able to access it from the public ip of the instance. Below is my deployment file.
apiVersion: v1
kind: Service
metadata:
name: apache-service
spec:
selector:
app: apache
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: apache-deployment
spec:
selector:
matchLabels:
app: apache
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: apache
spec:
containers:
- name: apache
image: mobingi/ubuntu-apache2-php7:7.2
ports:
- containerPort: 80
Here is my list of service.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apache-service NodePort 10.106.242.181 <none> 80:31807/TCP 9m5s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 11m
But when i check the same service from the follwing telnet with the public ip of cluster and node. It is not responding.
telnet public-ip:31807
Any type of help will be appreciable.
What do you mean by cluster IP? Do you mean the node that acts as kunernetes master? It won't work if you use master IP. Because masters don't have deployments scheduled due to security concerns.
Exposing a service via nodeport means that the service listens to a particular port in each of the worker nodes. So you can access the kunernetes worker nodes with the nodeports and get response. However if you created the cluster using cloud providers like aws, the worker nodes security groups are secured. Probably, you need to edit the security groups of worker nodes to access the service.
Related
I think that you can configure this in the -service.yaml. For example I have a frontend and a backend. The frontend should be public and my backend should be private. So how do you set up two microservices that communicate with each other, one being public and one private, using Kubernetes?
frontend-service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: frontend
name: frontend
spec:
ports:
- port: 8081
protocol: TCP
targetPort: 8081
selector:
app: frontend
type: LoadBalancer
status:
loadBalancer: {}
backend-service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: backend
name: backend
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: backend
type: LoadBalancer
status:
loadBalancer: {}
What I tried
kubectl apply -f frontend-deploy.yaml
kubectl get pods
kubectl apply -f frontend-service.yaml
kubectl get service
kubectl apply -f backend-deploy.yaml
kubectl get pods
kubectl apply -f backend-service.yaml
kubectl get service
kubectl expose deployment frontend --type=LoadBalancer --name=frontend-service.yaml
You should use ClusterIP type for the private / internal services which will make your application only available within the cluster:
ClusterIP: Exposes the Service on a cluster-internal IP. Choosing this value makes the Service only reachable from within the cluster. This is the default ServiceType
...and LoadBalancer type for the public services which are designed to receive requests from the outside the cluster:
LoadBalancer: Exposes the Service externally using a cloud provider's load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.
Example:
Let's say that I have created frontend and backend deployments - frontend on 8081 port and backend on 8080. Services yamls are similar to yours (I used LoadBalancer for the frontend, and ClusterIP for the backend). Fronted service is available at the 80 port, backend at the 8080:
apiVersion: v1
kind: Service
metadata:
labels:
app: frontend
name: frontend
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8081
selector:
app: frontend
type: LoadBalancer
---
apiVersion: v1
kind: Service
metadata:
labels:
app: backend
name: backend
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: backend
type: ClusterIP
Let's check the services:
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
backend ClusterIP 10.36.9.41 <none> 8080/TCP 19m
frontend LoadBalancer 10.36.4.172 xx.xxx.xxx.xxx 80:32126/TCP 19m
As can see, both services have ClusterIP (used for communication inside the cluster) and frontend service has a LoadBalancer with public IP.
Let's exec into a pod and send request to the frontend and backend using just a service name:
root#my-nginx-deployment-5bbb68bb8f-jgvrk:/# curl backend:8080
"hello world backend"
root#my-nginx-deployment-5bbb68bb8f-jgvrk:/# curl frontend:80
"hello world frontend"
It's working properly, because the pod that I exec into is in the same namespace (default). For communication between different namespaces you should use <service-name>.<namespace>.svc.cluster.local or ClusterIP:
root#my-nginx-deployment-5bbb68bb8f-jgvrk:/# curl backend.default.svc.cluster.local:8080
"hello world backend"
root#my-nginx-deployment-5bbb68bb8f-jgvrk:/# curl 10.36.9.41:8080
"hello world backend"
This is how communication inside cluster works in Kubernetes
For requests outside the cluster use LoadBalancer IP (EXTERNAL-IP in the kubectl get svc command):
user#shell-outside-the-cluster:~$ curl xx.xxx.xxx.xxx
"hello world frontend"
Consider using Ingress when you have multiple applications which you want to expose publicly.
Also check these:
Access Services Running on Clusters | Kubernetes
Service | Kubernetes
Debug Services | Kubernetes
DNS for Services and Pods | Kubernetes
I create RabbitMQ cluster inside Kubernetes. I am trying to add loadbalancer. But I cant get the loadbalancer External-IP it is still pending.
apiVersion: v1
kind: Service
metadata:
name: rabbitmq
labels:
run: rabbitmq
spec:
type: NodePort
ports:
- port: 5672
protocol: TCP
name: mqtt
- port: 15672
protocol: TCP
name: ui
selector:
run: rabbitmq
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rabbitmq
spec:
replicas: 1
selector:
matchLabels:
run: rabbitmq
template:
metadata:
labels:
run: rabbitmq
spec:
containers:
- name: rabbitmq
image: rabbitmq:latest
imagePullPolicy: Always
And My load balancer is below. I gave loadbalancer
nodePort is random,
port number is from kubernetes created RabbitMQ mqtt port number,
target port number is from kubernetes created RabbitMQ UI port number
apiVersion: v1
kind: Service
metadata:
name: loadbalanceservice
labels:
app: rabbitmq
spec:
selector:
app: rabbitmq
type: LoadBalancer
ports:
- nodePort: 31022
port: 30601
targetPort: 31533
service type Loadbalancer only works on cloud providers which support external load balancers.Setting the type field to LoadBalancer provisions a load balancer for your Service.It's pending because the environment that you are in is not supporting Loadbalancer type of service.In a non cloud environment an easier option would be to use nodeport type service. Here is a guide on using Nodeport to access service from outside the cluster.
LoadBalancer service doesn't work on bare metal clusters. Your LoadBalancer service will act as NodePort service as well. You can use nodeIP:nodePort combination to access your service from outside the cluster.
If you do want an external IP with custom port combination to access your service, then look into metallb which implements support for LoadBalancer type services on bare metal clusters.
I have created a simple php application trying to access from kubernetes cluster but I am unable access the application
my deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: phpdeployment
spec:
replicas: 3
selector:
matchLabels:
app: phpapp
template:
metadata:
labels:
app: phpapp
spec:
containers:
- image: rajendar38/myhtmlapp
name: myhtmlapp
ports:
- containerPort: 80
my service.yml
apiVersion: v1
kind: Service
metadata:
name: php-service
spec:
selector:
app: myhtmlapp
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 31000
type: NodePort
rajendar#HP-EliteBook:~/Desktop/work$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 26h
my-service ClusterIP 10.102.235.244 <none> 4000/TCP 24h
php-service NodePort 10.110.73.30 <none> 80:31000/TCP 22m
I am using minikube for this application
when I am trying to connect to http:127.0.0.1:31000/test.html
I unable to connect to application
Thanks
Rajendar
Minikube is using a virtual machine to provide the single node cluster.
When exposing a NodePort service it is local from the perspective of the VM, which is usually not the same as your local machine.
Use minikube ip to determine the IP of the machine and use that IP instead of localhost or 127.0.0.1 to access NodePort services on the minikube cluster.
The target port and port are same 80 therefore the services is using port 80 for both
try
port: 8000
targetPort: 80
As say #Thomas, you must find the IP of the VM with:
minikube ip
and after launch the service with this IP and the port 31000, in your case.
I've developed a containerized Flask application and I want to deploy it with Kubernetes. However, I can't connect the ports of the Container with the Service correctly.
Here is my Deployment file:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: <my-app-name>
spec:
replicas: 1
template:
metadata:
labels:
app: flaskapp
spec:
containers:
- name: <container-name>
image: <container-image>
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5000
name: http-port
---
apiVersion: v1
kind: Service
metadata:
name: <service-name>
spec:
selector:
app: flaskapp
ports:
- name: http
protocol: TCP
targetPort: 5000
port: 5000
nodePort: 30013
type: NodePort
When I run kubectl get pods, everything seems to work fine:
NAME READY STATUS RESTARTS AGE
<pod-id> 1/1 Running 0 7m
When I run kubectl get services, I get the following:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
<service-name> NodePort 10.105.247.63 <none> 5000:30013/TCP
...
However, when I give the following URL to the browser: 10.105.247.63:30013, the browser keeps loading but never returns the data from the application.
Does anyone know where the problem could be? It seems that the service is not connected to the container's port.
30013 is the port on the Node not in the cluster IP. To get a reply you would have to connect to <IP-address-of-the-node>:30013. To get the list of nodes you can:
kubectl get nodes -o=wide
You can also go through the CLUSTER-IP but you'll have to use the exposed port 5000: 10.105.247.63:5000
I'm trying to expose my api so I can send request to it. However when I used the command minikube service api --url I get nothing. All my pods are running fine according to kubectl get pods so I'm abit stuck about what this could be.
api-1007925651-0rt1n 1/1 Running 0 26m
auth-1671920045-0f85w 1/1 Running 0 26m
blankit-app 1/1 Running 5 5d
logging-2525807854-2gfwz 1/1 Running 0 26m
mongo-1361605738-0fdq4 1/1 Running 0 26m
jwl:.build jakewlace$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
api 10.0.0.194 <none> 3001/TCP 23m
auth 10.0.0.36 <none> 3100/TCP 23m
kubernetes 10.0.0.1 <none> 443/TCP 5d
logging 10.0.0.118 <none> 3200/TCP 23m
mongo 10.0.0.132 <none> 27017/TCP 23m
jwl:.build jakewlace$
jwl:.build jakewlace$ minikube service api --url
jwl:.build jakewlace$
Any help would be massively appreciated, thank you.
I realised that the question here could be perceived as being minimal, but that is because I'm not sure what more information I could show from the tutorials I've been following it should just work. If you need more information please do let me know I will let you know.
EDIT:
api-service.yml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
io.kompose.service: api
name: api
spec:
ports:
- name: "3001"
port: 3001
targetPort: 3001
selector:
io.kompose.service: api
status:
loadBalancer: {}
api-deployment.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
creationTimestamp: null
labels:
io.kompose.service: api
name: api
spec:
replicas: 1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: api
spec:
containers:
- image: blankit/web:0.0.1
name: api
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3001
resources: {}
restartPolicy: Always
status: {}
Your configuration is fine, but only missing one thing.
There are many types of Services in Kubernetes, but in this case you should know about two of them:
ClusterIP Services:
Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster. This is the default.
NodePort:
Exposes the service on each Node’s IP at a static port (the NodePort). A ClusterIP service, to which the NodePort service will route, is automatically created. You’ll be able to contact the NodePort service, from outside the cluster, by requesting <NodeIP>:<NodePort>.
Note:
If you have a multi-node cluster and you've exposed a NodePort Service, you can access is from any other node on the same port, not necessarily the same node the pod is deployed onto.
So, getting back to your service, you should specify the service type in your spec:
kind: Service
apiVersion: v1
metadata:
...
spec:
type: NodePort
selector:
...
ports:
- protocol: TCP
port: 3001
Now if you minikube service api --url, it should return a URL like http://<NodeIP>:<NodePort>.
Note: The default Kubernetes configuration will chose a random port from 30000-32767. But you can override that if needed.
Useful references:
Kubernetes / Publishing services - service types
Kubernetes / Connect a Front End to a Back End Using a Service