Tenho tentado encontrar uma maneira de definir um serviço em um namespace que se vincule a um pod executado em outro namespace. Eu sei que os contêineres em um pod em execução namespaceA
podem acessar serviceX
definido em namespaceB
referenciando-o no DNS do cluster como serviceX.namespaceB.svc.cluster.local
, mas prefiro não ter o código dentro do contêiner preciso saber sobre a localização de serviceX
. Ou seja, quero que o código apenas procure serviceX
e possa acessá-lo.
A documentação do Kubernetes sugere que isso é possível. Ele diz que um dos motivos pelos quais você definiria um serviço sem um seletor é que você deseja apontar seu serviço para um serviço em outro namespace ou em outro cluster .
Isso me sugere que eu deveria:
- Defina um
serviceX
serviço emnamespaceA
, sem um seletor (já que o POD que desejo selecionar não está emnamespaceA
). - Defina um serviço (que também chamei
serviceX
)namespaceB
e, em seguida, - Definir um objecto Endpoints em
namespaceA
que ponto aserviceX
emnamespaceB
.
É esta terceira etapa que não fui capaz de realizar.
Primeiro, tentei definir o objeto Endpoints desta maneira:
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
Essa parecia a abordagem lógica e, obviamente, para que serviatargetRef
. Mas, isso levou a um erro dizendo que o ip
campo na addresses
matriz era obrigatório. Então, minha próxima tentativa foi atribuir um endereço IP fixo de Cluster a serviceX
in namespaceB
e colocá-lo no campo IP (observe que o service_cluster_ip_range
está configurado como 192.168.0.0/16
e 192.168.1.1
foi atribuído como ClusterIP para serviceX
in namespaceB
; serviceX
em namespaceA
foi atribuído automaticamente um ClusterIP diferente na 192.168.0.0/16
sub - rede) :
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
Isso foi aceito, mas os acessos ao serviceX
in namespaceA
não foram encaminhados ao pod in namespaceB
- eles expiraram. Olhando a configuração do iptables, parece que teria que fazer o pré-roteamento NAT duas vezes para conseguir isso.
A única coisa que eu achei que funcionou - mas não é uma solução satisfatória - é pesquisar o endereço IP real do Pod fornecendo serviceX
em namespaceB
e colocar esse endereço no objeto Endpoints em namespaceA
. Isso não é satisfatório, é claro, porque o endereço IP do pod pode mudar com o tempo. Esse é o problema que os IPs de serviço estão aí para resolver.
Então, há uma maneira de cumprir o que parece ser a promessa da documentação de que posso apontar um serviço em um namespace para um serviço executado em um namespace diferente?
Um comentarista questionou por que você faria isso - aqui está um caso de uso que faz sentido para mim, pelo menos:
Digamos que você tenha um sistema multilocatário, que também inclui uma função comum de acesso a dados que pode ser compartilhada entre os locatários. Agora imagine que existem diferentes sabores dessa função de acesso a dados com APIs comuns, mas com características de desempenho diferentes. Alguns inquilinos têm acesso a um deles, outros inquilinos têm acesso a outro.
Os pods de cada locatário são executados em seus próprios namespaces, mas cada um precisa acessar um desses serviços comuns de acesso a dados, que estarão necessariamente em outro namespace (já que é acessado por vários locatários). Porém, você não gostaria que o locatário tivesse que alterar seu código se sua assinatura fosse alterada para acessar o serviço de alto desempenho.
Uma solução potencial (a mais limpa que posso imaginar, se ao menos funcionasse) é incluir uma definição de serviço no namespace de cada locatário para o serviço de acesso a dados, com cada um configurado para o endpoint apropriado. Essa definição de serviço seria configurada para apontar para o serviço de acesso a dados adequado que cada locatário tem direito de usar.
fonte
Respostas:
Eu tropecei no mesmo problema e encontrei uma boa solução que não precisa de nenhuma configuração de ip estático:
Você pode acessar um serviço por meio de seu nome DNS (conforme mencionado por você): servicename.namespace.svc.cluster.local
Você pode usar esse nome DNS para referenciá-lo em outro namespace por meio de um serviço local :
fonte
É tão simples de fazer
se você quiser usá-lo como host e resolver isso
Se você estiver usando embaixador para qualquer outro gateway de API para serviço localizado em outro namespace, é sempre recomendável usar:
será como:
servicename.namespacename.svc.cluster.local
isso enviará uma solicitação a um serviço específico dentro do namespace que você mencionou.
exemplo:
Substitua aqui o
<servicename>
e<namespace>
pelo valor apropriado.No Kubernetes, os namespaces são usados para criar um ambiente virtual, mas todos estão conectados uns aos outros.
fonte
.svc.cluster.local
é, por padrão, suportado para resolver o serviço internamente.Você pode conseguir isso implantando algo em uma camada mais alta do que os serviços com namespace, como o loadbalancer de serviço https://github.com/kubernetes/contrib/tree/master/service-loadbalancer . Se você quiser restringi-lo a um único namespace, use o argumento "--namespace = ns" (o padrão é todos os namespaces: https://github.com/kubernetes/contrib/blob/master/service-loadbalancer/service_loadbalancer.go # L715 ). Isso funciona bem para L7, mas é um pouco confuso para L4.
fonte