Desacoplar servicios externos de tu Kubernetes

Una de nuestras obsesiones debería de ser que todo esté lo más desacoplado posible, tanto a nivel de código como de infraestructura. En el artículo anterior te mostré diferentes formas de alcanzar pods expuestos a través de servicios. En este quiero contarte dos maneras de desacoplar servicios externos, fuera de Kubernetes, con el objetivo de ser consumidos por tus aplicaciones dentro de este.

Desacoplar a través de endpoints

Cuando te hablé de los servicios te conté que estos suelen estar asociados a un despliegue, y por ende a los pods. Cuando esto ocurre, el servicio genera de manera automática un recurso llamado Endpoint que recoge todas las IPs de todos los pods que están disponibles. Este mismo sistema se puede utilizar para servicios externos. Para ello, lo primero que debemos hacer es crear un servicio sin selector:

#service-without-pod-selector.yaml
apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  ports:
    - port: 80    

Como ves, este servicio únicamente tiene un nombre y un puerto, pero ningún selector. Si creas dicho servicio y compruebas su descripción, veras que el mismo no tiene ningún endpoint al que apuntar:

kubectl create -f service-without-pod-selector.yaml
kubectl describe svc external-service
kubectl describe svc external-service

En este caso es necesario que seamos nosotros quienes creemos el recurso Endpoint, con las IPs que el servicio utilizará para enrutar las peticiones:

apiVersion: v1
kind: Endpoints
metadata:
  name: external-service #The name of the Endpoints object must match with the name of the service
subsets:
  - addresses: #The IPs of the endpoints that the service will forward connections to
    - ip: 11.11.11.11
    - ip: 22.22.22.22
    ports:
    - port: 90 # The target port of the endpoints

Una vez creado el mismo, si vuelves a comprobar la descripción de tu servicio, el cual tiene el mismo nombre que nuestro recurso endpoint, comprobarás que ya tiene asociadas las IPs que hemos elegido como prueba, además del puerto:

kubectl create -f external-service-endpoints.yaml
kubectl describe svc external-service
external-service con endpoints

De esta manera puedes quitar y poner IPs para tu servicio sin tener que tocar para nada los pods que lo consumen.

¿Y si quiero utilizar dominios?

En otras ocasiones, en lugar de trabajar directamente con IPs de servicios externos, es posible que debas hacer referencia a un dominio, con lo que el desacople sería incluso mayor. Para ello, en vez de apoyarte en el recurso endpoint, puedes utilizar el servicio del tipo ExternalName:

apiVersion: v1
kind: Service
metadata:
  name: external-svc-name
spec:
  type: ExternalName
  externalName: api.returngis.net
  ports:
  - port: 80

La configuración es mucho más sencilla y será ese servicio externo el que se encargue de gestionar las IPs que atienden a dicho dominio.

kubectl get svc

¡Saludos!