Sometimes we need to access services in our cluster via network which are not yet part of the cluster, but we plan on migrating them at some point. Or there are webservices still running on some old piece of junk, but we'd like to have all the comforts of an ingress controller in place, before we are touching that old damn thing.
Luckily, there are at least two ways (network plugins such as cilium offer even further ways) to reflect such things in native kubernetes resources, which, although simple, are not that well known as one would expect.
Endpoint + Service
Usually when working with services, we use labels to select pods. In the background, kubernetes then creates an Endpoint object bearing the same name as our service, which is then regularly updated depending on the type of the service and contains the ports and IPs of the, well, endpoints.
But we can also simply create our own Endpoint object. The following would create and Endpoint and a Service, allowing us to access the ips and named ports in the Endpoint via the service.
---
apiVersion: v1
kind: Endpoints
metadata:
name: example
subsets:
- addresses:
- ip: 10.0.0.1
- ip: 10.0.0.2
ports:
- port: 80
name: http
- port: 9100
name: metrics
Now this endpoint would be created in the default namespace and point at the
ips 10.0.0.1
and 10.0.0.2
, exposing port 80 under the name http and 9100
under the name metrics.
To have it accessible via a service, we now need a service with the same name
in the same namespace.
There is no magic using labels involved.
---
apiVersion: v1
kind: Service
metadata:
name: example
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
name: http
- port: 9100
protocol: TCP
targetPort: 9100
name: metrics
ExternalName Service
When we already have a DNS name we can use, we can use a Service
of type ExternalName
.
This also could just be a service in another namespace, such as
example.another-namespace.svc
!
---
kind: Service
apiVersion: v1
metadata:
name: external-example
spec:
type: ExternalName
externalName: example.org
ports:
- protocol: TCP
port: 80
targetPort: 80
name: http
- protocol: TCP
port: 9100
targetPort: 9100
name: http
In both instances we now have a Service example
in our default namespace,
exposing port 80 and 9100 of some, possibly external, entity.