Kubernetes: Exposing Services through NodePort

There are different ways to expose a kubernetes cluster container that you are running; ClusterIP, NodePort, Ingress, LoadBalancer. In this tutorial, I will be discussing NodePort using the deployment template;

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app: webserver
  ports:
  - name: http
    protocol: TCP
    port: 8080
    targetPort: 80
  - name: redis
    protocol: TCP
    port: 6379
    targetPort: 6379
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx-redis-deployment
  labels:
        app: webserver
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: webserver
    spec:
      containers:
       - name: nginx
         image: nginx:1.9.1
         livenessProbe:
           tcpSocket:
             port: 80
       - name: redis
         imagePullPolicy: IfNotPresent
         image: redis
         livenessProbe:
           tcpSocket:
             port: 6379

If you run kubectl create -f deployment.yml, it creates both service and deployment.  Go ahead and run kubectl describe svc my-service;

Name:			my-service
Namespace:		default
Labels:			
Annotations:		kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"my-service","namespace":"default"},"spec":{"ports":[{"name":"http","port":8080...
Selector:		app=webserver
Type:			NodePort
IP:			10.0.0.188
Port:			http	8080/TCP
NodePort:		http	32044/TCP
Endpoints:		172.17.0.4:80,172.17.0.5:80,172.17.0.6:80
Port:			redis	6379/TCP
NodePort:		redis	31977/TCP
Endpoints:		172.17.0.4:6379,172.17.0.5:6379,172.17.0.6:6379
Session Affinity:	None
Events:

As you can see, the NodeType creates a nodePort on the clusterNode, maps those ports to corresponding Endpoints Pod port(32044 -> 80 and 31977->6379). Next is lets get the node IP and make calls to port 32044 and 31977; kubectl describe nodes

...
Addresses:
  InternalIP:	192.168.99.100
  Hostname:	minikube
Capacity:
 cpu:		2
 memory:	2048076Ki
 pods:		110
...

From above, the cluster node IP is 192.168.99.100. Lets curl port 32044 and telnet 31977.

$ curl 192.168.99.100:32044



Welcome to nginx!

    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }




<h1>Welcome to nginx!</h1>
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.

For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.

Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.

<em>Thank you for using nginx.</em>



$ telnet 192.168.99.100 31977
Trying 192.168.99.100...
Connected to 192.168.99.100.
Escape character is '^]'.
SET hello 5
+OK
quit
+OK
Connection closed by foreign host.
$

You will acheve the same result using the service ip and the service port run from directly on the node where your pods are running;




Welcome to nginx!

    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }




<h1>Welcome to nginx!</h1>
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.

For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.

Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.

<em>Thank you for using nginx.</em>



$ telnet 10.0.0.188 6379
SET hello 87
+OK
quit
+OK
Connection closed by foreign host
$

As you can see, kube-proxy handles the job of mapping the NodePort(can be generated for you or you specify) to the pods targetPort.