# Create a service with an external IP

In 
Published 2022-12-03

This tutorial explains how we can expose a service in Kubernetes using a specific IP.

# Services - introduction

The pods don't have stable IPs and this is a problem for an external service to call the services inside pods.

A Kubernetes service group the pods (by using labels and selectors) and give them a fix

  • IP
  • DNS name
  • port

We can access the services inside these pods through this service, which acts as a load balancer as well. Each Service that is created, automatically gets an associated Endpoint object. This Endpoint object is a dynamic list of all the healthy Pods on the cluster that match the Service’s label selector.

The services could be of several types:

  • ClusterIP
  • NodePort
  • LoadBalancer

ClusterIP service type (the default service type)

All the services inside cluster can communicate by using the Cluster IP (or the name of the cluster which is resolved to the Cluster IP). This IP address is accessible only inside Kubernetes cluster.

# NodePort Service - introduction

NodePort service type

The NodePort Service type add a new layer over the ClusterIP Service type. This layer let you access the service on each node on a particular port (defined during the NodePort service definition).

With this type of service, you can access the services we have in pods by using node_ip:nodePort, where node_ip is the IP of any node, and nodePort is a port defined during the service definition. If there are multiple nodes, then multiple IP addresses with the same port will be exposed.

# Create a NodePort service

The following example is has a prerequisite the Deployment from Create, View and Destroy a Deployment

Now we can create the yaml file for creating the new service:

kind: Service 
apiVersion: v1 
metadata:
  name: http-server-service2 
spec:
  # This service works only with pods labeled as below
  selector:
    app: app1

  ports:
      - name: http
        protocol: TCP
        port: 8081 # On the clusterIP level (for inter-pods communication) & for external IP
        targetPort: 80 #On the pod level
  externalIPs:
    - 192.168.72.3

The following command will create the new service:

kubectl apply -f my-first-service-with-external-ip.yml

We can run the following command in order to see if the new service is created:

kubectl get services

Here is the result:


NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP    PORT(S)    AGE
http-server-service2   ClusterIP   10.105.247.113   192.168.72.3   8081/TCP   4s
kubernetes             ClusterIP   10.96.0.1        <none>         443/TCP    4d4h

If you want to get more information on "http-server-service" service you can run:

kubectl describe service http-server-service2

Here is the result:

Name:              http-server-service2
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=app1
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.105.247.113
IPs:               10.105.247.113
External IPs:      192.168.72.3
Port:              http  8081/TCP
TargetPort:        80/TCP
Endpoints:         10.244.0.26:80,10.244.0.27:80,10.244.0.30:80 + 1 more...
Session Affinity:  None
Events:            <none>

If you want to test that the service is accessible, you can on a machine which has access to 192.168.72.3 virtual IP and run the command curl 192.168.72.3:8081 :

curl 192.168.72.3:8081

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

IF you want to see the nodes IPs, you can run the following command:

kubectl get nodes -o wide

Here is the result in my case:

NAME       STATUS   ROLES           AGE    VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION                      CONTAINER-RUNTIME
minikube   Ready    control-plane   4d4h   v1.26.1   192.168.49.2   <none>        Ubuntu 20.04.5 LTS   5.10.16.3-microsoft-standard-WSL2   docker://20.10.23

# Delete a Service in Kubernetes

Delete the service created above:

kubectl delete service http-server-service2