He estado tratando de encontrar una manera de definir un servicio en un espacio de nombres que se vincule a un Pod que se ejecuta en otro espacio de nombres. Sé que los contenedores en un Pod que se ejecutan namespaceA
pueden acceder serviceX
definido en namespaceB
al hacer referencia a él en el DNS del clúster como serviceX.namespaceB.svc.cluster.local
, pero prefiero no tener el código dentro del contenedor que necesito saber sobre la ubicación de serviceX
. Es decir, quiero que el código simplemente busque serviceX
y luego pueda acceder a él.
La documentación de Kubernetes sugiere que esto es posible. Dice que una de las razones por las que definiría un servicio sin un selector es que desea apuntar su servicio a un servicio en otro espacio de nombres o en otro clúster .
Eso me sugiere que debería:
- Definir un
serviceX
servicio ennamespaceA
, sin un selector (ya que el POD que quiero seleccionar no estánamespaceA
). - Definir un servicio (al que también llamé
serviceX
)namespaceB
y luego - Defina un objeto Endpoints en
namespaceA
para apuntar haciaserviceX
adentronamespaceB
.
Es este tercer paso el que no he podido realizar.
Primero, intenté definir el objeto Endpoints de esta manera:
kind: Endpoints
apiVersion: v1
metadata:
name: serviceX
namespace: namespaceA
subsets:
- addresses:
- targetRef:
kind: Service
namespace: namespaceB
name: serviceX
apiVersion: v1
ports:
- name: http
port: 3000
Ese parecía el enfoque lógico, y obviamente para qué targetRef
era. Pero, esto llevó a un error que decía que el ip
campo en la addresses
matriz era obligatorio. Entonces, mi siguiente intento fue asignar una dirección ClusterIP fija a serviceX
in namespaceB
, y ponerla en el campo IP (tenga en cuenta que service_cluster_ip_range
está configurado como 192.168.0.0/16
y 192.168.1.1
se asignó como ClusterIP para serviceX
in namespaceB
; serviceX
en namespaceA
se asignó automáticamente una ClusterIP diferente en la 192.168.0.0/16
subred) :
kind: Endpoints
apiVersion: v1
metadata:
name: serviceX
namespace: namespaceA
subsets:
- addresses:
- ip: 192.168.1.1
targetRef:
kind: Service
namespace: namespaceB
name: serviceX
apiVersion: v1
ports:
- name: http
port: 3000
Eso fue aceptado, pero los accesos a serviceX
in namespaceA
no se reenviaron al Pod in namespaceB
, se agotó el tiempo de espera. En cuanto a la configuración de iptables, parece que habría tenido que hacer un enrutamiento previo NAT dos veces para lograrlo.
Lo único que se encontró que funcionaba - pero no es una solución satisfactoria - es para buscar la dirección IP real de la vaina proporcionar serviceX
en namespaceB
y poner esa dirección en el objeto en puntos finales namespaceA
. Eso no es satisfactorio, por supuesto, porque la dirección IP del Pod puede cambiar con el tiempo. Ese es el problema que las IP de servicio están ahí para resolver.
Entonces, ¿hay alguna manera de cumplir con lo que parece ser la promesa de la documentación de que puedo apuntar un servicio en un espacio de nombres a un servicio que se ejecuta en un espacio de nombres diferente?
Un comentarista preguntó por qué querría hacer esto; aquí hay un caso de uso que tiene sentido para mí, al menos:
Supongamos que tiene un sistema de múltiples inquilinos, que también incluye una función común de acceso a datos que se puede compartir entre inquilinos. Ahora imagine que hay diferentes sabores de esta función de acceso a datos con API comunes, pero diferentes características de rendimiento. Algunos inquilinos tienen acceso a uno de ellos, otros inquilinos tienen acceso a otro.
Los pods de cada inquilino se ejecutan en sus propios espacios de nombres, pero cada uno necesita acceder a uno de estos servicios comunes de acceso a datos, que necesariamente estará en otro espacio de nombres (ya que varios inquilinos acceden a él). Pero, no querrá que el inquilino tenga que cambiar su código si cambia su suscripción para acceder al servicio de mayor rendimiento.
Una posible solución (la más limpia que se me ocurre, si tan solo funcionara) es incluir una definición de servicio en el espacio de nombres de cada inquilino para el servicio de acceso a datos, con cada uno configurado para el punto final apropiado. Esta definición de servicio se configuraría para apuntar al servicio de acceso a datos adecuado que cada inquilino tiene derecho a usar.
fuente
Respuestas:
Me encontré con el mismo problema y encontré una buena solución que no necesita ninguna configuración de IP estática:
Puede acceder a un servicio a través de su nombre DNS (como lo mencionó): servicename.namespace.svc.cluster.local
Puede usar ese nombre DNS para hacer referencia a él en otro espacio de nombres a través de un servicio local :
fuente
Es tan simple hacerlo
si quieres usarlo como host y quieres resolverlo
Si está utilizando embajador en cualquier otra puerta de enlace API para el servicio ubicado en otro espacio de nombres, siempre se sugiere usar:
será como:
servicename.namespacename.svc.cluster.local
esto enviará una solicitud a un servicio en particular dentro del espacio de nombres que ha mencionado.
ejemplo:
Aquí reemplace
<servicename>
y<namespace>
con el valor apropiado.En Kubernetes, los espacios de nombres se utilizan para crear un entorno virtual, pero todos se conectan entre sí.
fuente
.svc.cluster.local
es compatible de forma predeterminada para resolver el servicio internamente.Puede lograr esto implementando algo en una capa más alta que los Servicios con espacio de nombres, como el equilibrador de carga del servicio https://github.com/kubernetes/contrib/tree/master/service-loadbalancer . Si desea restringirlo a un solo espacio de nombres, use el argumento "--namespace = ns" (predeterminado para todos los espacios de nombres: https://github.com/kubernetes/contrib/blob/master/service-loadbalancer/service_loadbalancer.go # L715 ). Esto funciona bien para L7, pero es un poco complicado para L4.
fuente