Servizio situato in un altro spazio dei nomi


108

Ho cercato di trovare un modo per definire un servizio in uno spazio dei nomi che si collega a un pod in esecuzione in un altro spazio dei nomi. So che i contenitori in un pod in esecuzione namespaceApossono accedere serviceXdefiniti in namespaceBreferenziandolo nel cluster DNS come serviceX.namespaceB.svc.cluster.local, ma preferirei che il codice all'interno del contenitore non avesse bisogno di conoscere la posizione di serviceX. Cioè, voglio che il codice cerchi serviceXe poi sia in grado di accedervi.

La documentazione di Kubernetes suggerisce che ciò è possibile. Dice che uno dei motivi per cui definiresti un servizio senza un selettore è che vuoi puntare il tuo servizio a un servizio in un altro Namespace o su un altro cluster .

Questo mi suggerisce che dovrei:

  1. Definisci un serviceXservizio in namespaceA, senza un selettore (poiché il POD che voglio selezionare non è in namespaceA).
  2. Definisci un servizio (che ho anche chiamato serviceX) namespaceBe poi
  3. Definire un oggetto endpoint namespaceAa punto serviceXa namespaceB.

È questo terzo passaggio che non sono stato in grado di compiere.

Innanzitutto, ho provato a definire l'oggetto Endpoint in questo modo:

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

Sembrava l'approccio logico, e ovviamente a cosa servivatargetRef . Tuttavia, questo ha portato a un errore che diceva che il ipcampo addressesnell'array era obbligatorio. Quindi, il mio tentativo successivo è stato quello di assegnare un indirizzo ClusterIP fisso a serviceXin namespaceBe inserirlo nel campo IP (si noti che service_cluster_ip_rangeè configurato come 192.168.0.0/16, ed è 192.168.1.1stato assegnato come ClusterIP per serviceXin namespaceB; serviceXin è namespaceAstato assegnato automaticamente un ClusterIP diverso sulla 192.168.0.0/16sottorete) :

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

È stato accettato, ma gli accessi a serviceXin namespaceAnon sono stati inoltrati al Pod in namespaceB: sono scaduti. Guardando la configurazione di iptables, sembra che avrebbe dovuto eseguire due volte il pre-routing NAT per ottenere ciò.

L'unica cosa che ho trovato che ha funzionato - ma non è una soluzione soddisfacente - è di ricercare l'indirizzo IP effettivo del Pod fornire serviceXin namespaceBe mettere quell'indirizzo nell'oggetto Endpoint in namespaceA. Ciò non è soddisfacente, ovviamente, perché l'indirizzo IP del Pod potrebbe cambiare nel tempo. Questo è il problema che gli IP del servizio sono lì per risolvere.

Quindi, c'è un modo per soddisfare quella che sembra essere la promessa della documentazione che posso indirizzare un servizio in uno spazio dei nomi a un servizio in esecuzione in uno spazio dei nomi diverso?

Un commentatore ha chiesto perché vorresti farlo: ecco un caso d'uso che ha senso per me, almeno:

Supponiamo di avere un sistema multi-tenant, che include anche una funzione di accesso ai dati comune che può essere condivisa tra i tenant. Ora immagina che esistano versioni diverse di questa funzione di accesso ai dati con API comuni, ma caratteristiche di prestazioni diverse. Alcuni inquilini hanno accesso a uno di essi, altri hanno accesso a un altro.

I pod di ogni tenant vengono eseguiti nei propri spazi dei nomi, ma ognuno deve accedere a uno di questi servizi di accesso ai dati comuni, che sarà necessariamente in un altro spazio dei nomi (poiché è accessibile da più tenant). Tuttavia, non si vorrebbe che l'inquilino debba modificare il proprio codice se l'abbonamento cambia per accedere al servizio con prestazioni più elevate.

Una potenziale soluzione (la più pulita a cui riesco a pensare, se solo funzionasse) è includere una definizione del servizio nello spazio dei nomi di ogni tenant per il servizio di accesso ai dati, con ciascuno configurato per l'endpoint appropriato. Questa definizione di servizio sarebbe configurata in modo da puntare al servizio di accesso ai dati appropriato che ogni tenant è autorizzato a utilizzare.


lo scopo degli spazi dei nomi è isolare, quindi penso che se hai bisogno di attraversare gli spazi dei nomi devi sapere almeno dove si trova!
MrE

Quindi, cosa significa la documentazione quando suggerisce che è possibile indirizzare un servizio definito in uno spazio dei nomi per accedere a un servizio in uno spazio dei nomi diverso non definendo un selettore e, implicitamente, definendo un endpoint? Ci sono certamente casi d'uso validi per questo, uno dei quali ho aggiunto alla domanda. La documentazione è solo fuorviante o c'è un modo per farlo che non ho ancora capito?
David McKinley

non sono sicuro, mi dispiace. quello che so è che accedo ai servizi in più spazi dei nomi usando il loro fqdn. Lo faccio soprattutto con vpn, poiché ho 1 pod vpn e mi connetto attraverso tutti i servizi da esso. tuttavia è necessario conoscere lo spazio dei nomi e fornire fqdn. ti suggerirei di chiedere sul canale slack.
MrE

L'utilizzo di fqdn è la soluzione che sto attualmente utilizzando. Il mio caso d'uso sarebbe servito meglio, però, (ora aggiunto alla domanda) se non fosse necessario.
David McKinley

Mi chiedo anche a cosa si riferisca la documentazione, tuttavia posso usare fqdn come soluzione soddisfacente per il mio caso d'uso.
Vincent De Smet

Risposte:


224

Mi sono imbattuto nello stesso problema e ho trovato una bella soluzione che non necessita di alcuna configurazione di ip statico:

Puoi accedere a un servizio tramite il suo nome DNS (come menzionato da te): servicename.namespace.svc.cluster.local

Puoi utilizzare quel nome DNS per farvi riferimento in un altro spazio dei nomi tramite un servizio locale :

kind: Service
apiVersion: v1
metadata:
  name: service-y
  namespace: namespace-a
spec:
  type: ExternalName
  externalName: service-x.namespace-b.svc.cluster.local
  ports:
  - port: 80

2
Questa è un'ottima soluzione! Non sono sicuro che il tipo "ExternalName" fosse disponibile per i servizi quando ho inizialmente posto la domanda, ma ora è supportato e risolve il problema in modo preciso. Grazie, Paul.
David McKinley

1
funziona? io dubito. qualcuno può confermare se questo ha funzionato davvero, non funziona per me.
debianmaster

2
Sì lo fa. Funziona per un pod per parlare con un servizio in un altro spazio dei nomi, ma non per un loadbalancer in ingresso.
Paul,

a causa della correzione della ricerca CNAME nel cluster di kubernetes , la vecchia versione potrebbe non funzionare.
赵浩翔

1
Funzionerebbe / dovrebbe funzionare anche per i servizi nello spazio dei nomi del sistema kube?
Nabheet

10

È così semplice farlo

se vuoi usarlo come host e vuoi risolverlo

Se stai utilizzando ambassador per qualsiasi altro gateway API per il servizio situato in un altro spazio dei nomi, è sempre consigliabile utilizzare:

            Use : <service name>
            Use : <service.name>.<namespace name>
            Not : <service.name>.<namespace name>.svc.cluster.local

sarà come: servicename.namespacename.svc.cluster.local

questo invierà una richiesta a un particolare servizio all'interno dello spazio dei nomi che hai menzionato.

esempio:

kind: Service
apiVersion: v1
metadata:
  name: service
spec:
  type: ExternalName
  externalName: <servicename>.<namespace>.svc.cluster.local

Qui sostituisci <servicename>e <namespace>con il valore appropriato.

In Kubernetes, gli spazi dei nomi vengono utilizzati per creare un ambiente virtuale, ma tutti sono connessi tra loro.


6
Potresti spiegare in che modo questa risposta è diversa da quella fornita da Paul quasi 2 anni prima?
Oliver

2
@Oliver non c'è differenza ma ho appena specificato cosa sostituire il nome del servizio e lo spazio dei nomi in quale luogo particolare. mentre ha usato lo spazio dei nomi, a mi sembra confuso.
Harsh Manvar

7
Un trucco utile su SO consiste nell'aggiungere un commento alla risposta e fare i necessari chiarimenti.
Oliver

4
La definirei come la soluzione migliore perché .svc.cluster.localè supportata per impostazione predefinita per la risoluzione del servizio internamente.
DrKNa

1
svegliato anche per me. grazie
vimal prakash

0

Puoi ottenere ciò distribuendo qualcosa a un livello superiore rispetto ai Servizi con spazio dei nomi, come il servizio loadbalancer https://github.com/kubernetes/contrib/tree/master/service-loadbalancer . Se desideri limitarlo a un singolo spazio dei nomi, utilizza l'argomento "--namespace = ns" (il valore predefinito è tutti gli spazi dei nomi: https://github.com/kubernetes/contrib/blob/master/service-loadbalancer/service_loadbalancer.go # L715 ). Funziona bene per L7, ma è un po 'disordinato per L4.


3
Questo progetto è deprecato ora (agosto 2018)
Nicola Ben

1
@Prashanth B: Potresti aggiornare la tua risposta di conseguenza!
chaosguru
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.