Kubernetes: what is Endpoints
0 (0)

By | 03/13/2021
Click to rate this post!
[Total: 0 Average: 0]

Usually, we don’t see Endpoints objects when using Kubernetes Services, as they are working under the hood, similarly to ReplicaSets which are “hidden” behind Kubernetes Deployments.

Kubernetes Service

So, Service is a Kubernetes abstraction that uses labels to chose pods to route traffic to, see the Kubernetes: ClusterIP vs NodePort vs LoadBalancer, Services, and Ingress – an overview with examples and  Kubernetes: Service, load balancing, kube-proxy, and iptables:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

As soon as a new pod appear in a cluster, with labels matching with Service’s selector,  the app=MyApp in the example above – Service will start sending traffic to it.

This is achieved by adding an IP address of this Pod to the Endpoints list of this Service.

Let’s create a simple example:

---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
    - name: nginx-container
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

Here, we are creating a Pod with NGINX, and a Service with the default type ClusterIP.

Apply the manifest:

[simterm]

$ kubectl apply -f svc-example.yaml 
pod/nginx-pod created
service/nginx-svc created

[/simterm]

Check the Service:

[simterm]

$ kubectl get service nginx-svc
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
nginx-svc   ClusterIP   172.20.69.253   <none>        80/TCP    26s

[/simterm]

Kubernetes Endpoints

Now, let’s take a closer look at it:

[simterm]

$ kubectl describe service nginx-svc
Name:              nginx-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP Families:       <none>
IP:                172.20.69.253
IPs:               <none>
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.21.56.143:80

[/simterm]

In the end, we can the Endpoints of this Service – the IP od the pod.

Check this Pod:

[simterm]

$ kubectl describe pod nginx-pod
Name:         nginx-pod
Namespace:    default
Priority:     0
Node:         ip-10-21-49-33.us-east-2.compute.internal/10.21.49.33
Start Time:   Sat, 13 Mar 2021 08:37:55 +0200
Labels:       app=nginx
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Running
IP:           10.21.56.143
...

[/simterm]

Here is the IP mentioned above.

And now, let’s check the Ednpointds, which are dedicated API-objects and which can be observed in the same way as Services and Pods:

[simterm]

$ kubectl get endpoints nginx-svc
NAME        ENDPOINTS         AGE
nginx-svc   10.21.56.143:80   18m

[/simterm]

If we will add other pods with the same labels by describing them as additional objects in the manifest file or by creating a Deployment – those pods will be added as Endpoints for the Service:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx-container
        image: nginx
        ports:
          - name: web
            containerPort: 80
            protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

Create the Deployment:

[simterm]

$ kubectl apply -f svc-example.yaml 
deployment.apps/nginx-deploy created
service/nginx-svc unchanged

[/simterm]

And check the Endpoints:

[simterm]

$ kubectl get endpoints nginx-svc
NAME        ENDPOINTS                                        AGE
nginx-svc   10.21.37.55:80,10.21.54.174:80,10.21.56.143:80   21m

[/simterm]

Here we can see our 10.21.56.143:80 from the previous pod, and two new – from the pods specified in the replicas of the Deployment above.

Find those pods by using the --selector, similarly, as a Service looks for pods to add them to its Endpoints:

[simterm]

$ kubectl get pod --selector=app=nginx -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP          
nginx-deploy-7fcd954c94-gbm6d   1/1     Running   0          2m28s   10.21.54.174
nginx-deploy-7fcd954c94-mg8kr   1/1     Running   0          2m28s   10.21.37.55 
nginx-pod                       1/1     Running   0          23m     10.21.56.143

[/simterm]

Custom Endpoint

We also can create a custom endpoint that will be pointed to any desired resource.

For example, describe a new Service:

kind: Service
apiVersion: v1
metadata:
  name: external-svc
spec:
  ports:
    - name: web
      protocol: TCP
      port: 80
      targetPort: 80

Pay attention, that in this case, we didn’t add the selector field.

And describe the Endpoints object:

kind: Endpoints
apiVersion: v1
metadata:
  name: external-svc
subsets: 
  - addresses:
        - ip: 139.59.205.180
    ports:
      - port: 80
        name: web

Here:

  1. name: must be the same as the Service
  2. addresses: an address to send traffic to, in this example this an IP address of a server in the DigitalOcean cloud where the rtfm.co.ua is leaving, but you can set multiply address so the Service will do load-balancing between them as described in the Kubernetes: Service, load balancing, kube-proxy, and iptables
  3. ports.port and ports.name also must be the same as the corresponding Service

Create them:

[simterm]

$ kubectl apply -f external-endpoint.yaml 
service/external-svc created
endpoints/external-svc created

[/simterm]

Check the Service and its Endpoints:

[simterm]

$ kubectl describe svc external-svc
Name:              external-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP Families:       <none>
IP:                172.20.45.77
IPs:               <none>
Port:              web  80/TCP
TargetPort:        80/TCP
Endpoints:         139.59.205.180:80

[/simterm]

Run a Pod to check if this Service working:

[simterm]

$ kubectl run pod --rm -i --tty --image ubuntu -- bash

[/simterm]

Install the curl in this pod:

[simterm]

root@pod:/# apt update && apt -y install curl

[/simterm]

And check the Service by its name:

[simterm]

root@pod:/# curl -Ls external-svc | grep \<title\>
<title>RTFM: Linux, DevOps, and system administration</title>

[/simterm]

Or by using its FQDN:

[simterm]

root@pod:/# curl -Ls external-svc.default.svc.cluster.local | grep \<title\>
<title>RTFM: Linux, DevOps, and system administration</title>

[/simterm]

externalName

Another solution to access an external resource can be using a Service with the externalName type:

---
apiVersion: v1
kind: Service
metadata:
  name: rtfm-service
spec:
  ports:
    - port: 80
  type: ExternalName
  externalName: rtfm.co.ua

Apply, and check:

[simterm]

root@pod:/# curl -Ls rtfm-service | grep \<title\>
<title>RTFM: Linux, DevOps, and system administration</title>

[/simterm]

Done.

Loading