web-dev-qa-db-fra.com

Service situé dans un autre espace de noms

J'ai essayé de trouver un moyen de définir un service dans un espace-noms lié à un pod s'exécutant dans un autre espace-noms. Je sais que les conteneurs d'un pod s'exécutant sous namespaceA peuvent accéder à serviceX défini dans namespaceB en le référençant dans le cluster DNS sous la forme serviceX.namespaceB.svc.cluster.local, mais je préférerais ne pas avoir le code. l'intérieur du conteneur doit connaître l'emplacement de serviceX. C’est-à-dire que je veux que le code cherche simplement serviceX et puisse ensuite y accéder.

La documentation de Kubernetes suggère que cela est possible. Il indique qu'une des raisons pour lesquelles vous définiriez un service sans sélecteur est que vous souhaitez diriger votre service vers un service situé dans un autre espace de noms ou sur un autre cluster .

Cela me suggère que je devrais:

  1. Définissez un service serviceX dans namespaceA, sans sélecteur (car le POD que je veux sélectionner ne se trouve pas dans namespaceA).
  2. Définissez un service (que j’ai aussi appelé serviceX) dans namespaceB, puis
  3. Définissez un objet Points de terminaison dans namespaceA pour qu'il pointe vers serviceX dans namespaceB.

C’est cette troisième étape que je n’ai pas pu accomplir.

J'ai d'abord essayé de définir l'objet Endpoints de la manière suivante:

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

Cela semblait être l’approche logique, et évidemment à quoi servait la targetRef. Mais cela a conduit à une erreur indiquant que le champ ip du tableau addresses était obligatoire. Donc, mon essai suivant a été d’affecter une adresse de cluster fixe à serviceX dans namespaceB et de la placer dans le champ IP (notez que le service_cluster_ip_range est configuré comme 192.168.0.0/16, et 192.168.1.1 a été affecté en tant que ClusterIP pour serviceX dans namespaceB; serviceX dans namespaceA a été automatiquement affecté à un autre ClusterIP sur le sous-réseau 192.168.0.0/16 :

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

Cela a été accepté, mais les accès à serviceX dans namespaceA n'ont pas été transmis au pod dans namespaceB - leur délai a expiré. En regardant la configuration d'iptables, on dirait qu'il aurait fallu effectuer deux fois le pré-routage NAT pour le faire.

La seule chose que j’ai trouvée qui a fonctionné - mais n’est pas une solution satisfaisante - consiste à rechercher l’adresse IP réelle du pod fournissant serviceX dans namespaceB et à mettre cette adresse dans l’objet Points de terminaison dans namespaceA. Ce n'est pas satisfaisant, bien sûr, car l'adresse IP du pod peut changer avec le temps. C’est le problème que les IPs de service sont là pour résoudre.

Alors, y a-t-il un moyen de respecter ce qui semble être la promesse de la documentation que je puisse diriger un service situé dans un espace de noms vers un service s'exécutant dans un espace de noms différent?

Un intervenant a demandé pourquoi vous voudriez faire cela - voici un cas d'utilisation qui a du sens pour moi, au moins:

Supposons que vous ayez un système multi-locataire, qui inclut également une fonction d'accès aux données commune pouvant être partagée entre les locataires. Imaginons maintenant qu’il existe différentes variantes de cette fonction d’accès aux données avec des API communes, mais des caractéristiques de performances différentes. Certains locataires ont accès à l'un d'entre eux, d'autres locataires ont accès à un autre.

Les pods de chaque locataire s'exécutent dans leurs propres espaces de noms, mais chacun doit accéder à l'un de ces services d'accès aux données communs, qui se trouveront nécessairement dans un autre espace de noms (car plusieurs locataires y ont accès). Cependant, vous ne voudriez pas que le locataire change de code si son abonnement change pour accéder au service le plus performant.

Une solution potentielle (la solution la plus propre à laquelle je puisse penser, si seulement elle fonctionnait) consiste à inclure une définition de service dans l'espace-noms de chaque client hébergé pour le service d'accès aux données, chaque configuration étant configurée pour le noeud final approprié. Cette définition de service serait configurée pour pointer vers le service d'accès aux données approprié que chaque locataire est autorisé à utiliser.

66
David McKinley

Je suis tombé sur le même problème et j'ai trouvé une solution intéressante ne nécessitant aucune configuration ip statique:

Vous pouvez accéder à un service via son nom DNS (comme indiqué par vous): nom_service.namespace.svc.cluster.local

Vous pouvez utiliser ce nom DNS pour le référencer dans n autre espace de noms via un service local :

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
138
Paul

C'est si simple de le faire

si vous voulez l'utiliser comme hôte et que vous voulez le résoudre

ce sera comme: servicename.namespacename.svc.cluster.local

cela enverra une demande à un service particulier à l'intérieur de l'espace de noms que vous avez mentionné.

Pour ex

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

Ici, remplacez <servicename> et <namespace> par la valeur appropriée.

Dans kubernetes, les espaces de noms sont utilisés pour créer un environnement virtuel, mais tous sont connectés les uns aux autres.

2
Harsh Manvar

Vous pouvez y parvenir en déployant quelque chose sur une couche supérieure aux services à espace de noms, comme le service loadbalancer https://github.com/kubernetes/contrib/tree/master/service-loadbalancer . Si vous souhaitez le limiter à un seul espace de noms, utilisez l'argument "--namespace = ns" (la valeur par défaut de tous les espaces de noms: https://github.com/kubernetes/contrib/blob/master/service-loadbalancer /service_loadbalancer.go#L715 ). Cela fonctionne bien pour L7, mais est un peu compliqué pour L4.

1
Prashanth B