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 appears 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:
$ kubectl apply -f svc-example.yaml
pod/nginx-pod created
service/nginx-svc created
Check the Service:
$ 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
Kubernetes Endpoints
Now, let’s take a closer look at it:
$ 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
In the end, we can the Endpoints of this Service — the IP of the pod.
Check this Pod:
$ 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
…
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:
$ kubectl get endpoints nginx-svc
NAME ENDPOINTS AGE
nginx-svc 10.21.56.143:80 18m
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:
$ kubectl apply -f svc-example.yaml
deployment.apps/nginx-deploy created
service/nginx-svc unchanged
And check the Endpoints:
$ 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
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:
$ 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
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:
-
name
: must be the same as the Service -
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 -
ports.port
andports.name
also must be the same as the corresponding Service
Create them:
$ kubectl apply -f external-endpoint.yaml
service/external-svc created
endpoints/external-svc created
Check the Service and its Endpoints:
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
Run a Pod to check if this Service working:
$ kubectl run pod — rm -i — tty — image ubuntu — bash
Install the curl
in this pod:
root@pod:/# apt update && apt -y install curl
And check the Service by its name:
root@pod:/# curl -Ls external-svc | grep \<title\>
<title>RTFM: Linux, DevOps, and system administration</title>
Or by using its FQDN:
root@pod:/# curl -Ls external-svc.default.svc.cluster.local | grep \<title\>
<title>RTFM: Linux, DevOps, and system administration</title>
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:
$ root@pod:/# curl -Ls rtfm-service | grep \<title\>
<title>RTFM: Linux, DevOps, and system administration</title>
Done.
Originally published at RTFM: Linux, DevOps и системное администрирование.
Top comments (0)