Reputation: 103
I am trying to learn Kubernetes.
I am trying to do this using Minikube and here is what I did:
1.) Write a simple server using Node
2.) Write a Dockerfile
for that particular Node server
3.) Create a Kubernetes deployment
4.) Create a service (of type ClusterIP)
5.) Create a service (of type NodePort) to expose the container so I can access from outside (browser, curl)
But when I try to connect to the NodePort
with the format of <NodePort>:<port>
and `:, it gives an error:
Failed to connect to 192.168.39.192 port 80: Connection refused
These are the files I created as steps mentioned above (1-5).
1.) server.js - Here only I have mentioned server.js
, relevent package.json
exists and they work as expected when I run the server locally (without deploying it in Docker), I mention this in case readers might ask whether my server works correctly.
'use strict';
const express = require('express');
// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
// App
const app = express();
app.get('/', (req, res) => {
res.send('Hello world\n');
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
2.) Dockerfile
FROM node:10
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
# Bundle app source
COPY . .
EXPOSE 8080
CMD [ "npm", "start" ]
3.) deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-web-app
spec:
replicas: 2
selector:
matchLabels:
name: node-web-app
template:
metadata:
labels:
# you can specify any labels you want here
name: node-web-app
spec:
containers:
- name: node-web-app
# image must be the same as you built before (name:tag)
image: banuka/node-web-app
ports:
- name: http
containerPort: 8080
protocol: TCP
imagePullPolicy: Never
terminationGracePeriodSeconds: 60
4.) clusterip.yaml
kind: Service
apiVersion: v1
metadata:
labels:
# these labels can be anything
name: node-web-app-clusterip
name: node-web-app-clusterip
spec:
selector:
app: node-web-app
ports:
- protocol: TCP
port: 80
# target is the port exposed by your containers (in our example 8080)
targetPort: 8080
5.) NodePort.yaml
kind: Service
apiVersion: v1
metadata:
labels:
name: node-server-nodeport
name: node-server-nodeport
spec:
# this will make the service a NodePort service
type: NodePort
selector:
app: node-app-web
ports:
- protocol: TCP
# new -> this will be the port used to reach it from outside
# if not specified, a random port will be used from a specific range (default: 30000-32767)
nodePort: 32555
port: 80
targetPort: 8080
And when I try to curl from outside or use my web browser it gives following error:
curl: (7) Failed to connect to 192.168.39.192 port 32555: Connection refused
PS: pods and containers are also working as expected.
Upvotes: 0
Views: 6379
Reputation: 716
Adding ways to check the label and add the label. Labelling pods is what fixed it for me.
kubectl get pods --show-labels -n mynamespace
kubectl label pod nginx-66bccddb68-8tjpk -n mynamespace app=webserver
Upvotes: 0
Reputation: 31
The Service's selector must match the Pod's label.
In your NodePort.yaml selector is app: node-app-web
, while in deployment.yaml label is node-web-app
.
Upvotes: 1
Reputation: 345
I had same problem always when I write wrong selectors to NodePort service spec
Upvotes: 3
Reputation: 12009
There are several possible reasons for this.
First: Are you using your local IP or the IP where the minikube VM is running? To verify use minikube ip
.
Second: The NodePort
service wants to use pods with label app: node-app-web
, but your pods only have the label name: node-web-app
Just to make sure the port that you assume is used, check with minikube service list
that the requested port was allocated. Check your firewall settings as well.
Upvotes: 3