J'ai essayé de trouver un moyen de définir un service dans un espace de noms lié à un pod fonctionnant dans un autre espace de noms. Je sais que les conteneurs d'un pod en cours d'exécution namespaceA
peuvent accéder serviceX
définis dans namespaceB
en le référençant dans le DNS du cluster comme serviceX.namespaceB.svc.cluster.local
, mais je préfère ne pas avoir le code à l'intérieur du conteneur besoin de connaître l'emplacement de serviceX
. Autrement dit, je veux que le code recherche simplement serviceX
et puisse y accéder.
La documentation Kubernetes suggère que cela est possible. Il indique que l'une des raisons pour lesquelles vous définiriez un service sans sélecteur est que vous souhaitez pointer votre service vers un service dans un autre espace de noms ou sur un autre cluster .
Cela me suggère que je devrais:
- Définissez un
serviceX
service dansnamespaceA
, sans sélecteur (puisque le POD que je souhaite sélectionner n'est pas dansnamespaceA
). - Définissez un service (que j'ai également appelé
serviceX
) dansnamespaceB
, puis - Définir un objet de points de terminaison
namespaceA
pour pointer versserviceX
dansnamespaceB
.
C'est cette troisième étape que je n'ai pas pu accomplir.
Tout d'abord, j'ai essayé de définir l'objet Endpoints de cette façon:
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 l'approche logique, et évidemment à quoi cela targetRef
servait. Mais cela a conduit à une erreur disant que le ip
champ dans le addresses
tableau était obligatoire. Donc, mon prochain essai a été d'attribuer une adresse ClusterIP fixe à serviceX
in namespaceB
, et de la mettre dans le champ IP (notez que le service_cluster_ip_range
est configuré en tant que 192.168.0.0/16
et a 192.168.1.1
été attribué en tant que ClusterIP pour serviceX
in namespaceB
; serviceX
in a namespaceA
été automatiquement attribué un ClusterIP différent sur le 192.168.0.0/16
sous - réseau) :
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
in namespaceA
n'ont pas été transmis au pod in namespaceB
- ils ont expiré. En regardant la configuration d'iptables, il semble qu'il aurait fallu deux fois le pré-routage NAT pour y parvenir.
La seule chose que j'ai trouvé qui fonctionnait - mais pas une solution satisfaisante - est de rechercher l'adresse IP réelle du Pod fournissant serviceX
dans namespaceB
et de mettre cette adresse dans l'objet Endpoints 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 adresses IP de service doivent résoudre.
Alors, y a-t-il un moyen de répondre à ce qui semble être la promesse de la documentation que je peux pointer un service dans un espace de noms vers un service fonctionnant dans un espace de noms différent?
Un commentateur a demandé pourquoi vous voudriez faire cela - voici un cas d'utilisation qui me semble logique, au moins:
Supposons que vous ayez un système multi-locataire, qui comprend également une fonction d'accès aux données commune qui peut être partagée entre les locataires. Imaginez maintenant qu'il existe différentes saveurs 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 sera nécessairement dans un autre espace de noms (car il est accédé par plusieurs locataires). Mais vous ne voudriez pas que le locataire doive changer son code si son abonnement change pour accéder au service plus performant.
Une solution potentielle (la plus propre à laquelle je puisse penser, si seulement cela fonctionnait) consiste à inclure une définition de service dans l'espace de noms de chaque locataire pour le service d'accès aux données, chacun étant configuré pour le point de terminaison 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.
la source
Réponses:
Je suis tombé sur le même problème et j'ai trouvé une solution intéressante qui ne nécessite aucune configuration IP statique:
Vous pouvez accéder à un service via son nom DNS (comme vous l'avez mentionné): servicename.namespace.svc.cluster.local
Vous pouvez utiliser ce nom DNS pour le référencer dans un autre espace de noms via un service local :
la source
C'est si simple de le faire
si vous souhaitez l'utiliser comme hôte et souhaitez le résoudre
Si vous utilisez ambassador vers une autre passerelle API pour le service situé dans un autre espace de noms, il est toujours suggéré d'utiliser:
ce sera comme:
servicename.namespacename.svc.cluster.local
cela enverra une demande à un service particulier dans l'espace de noms que vous avez mentionné.
exemple:
Remplacez ici
<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.
la source
.svc.cluster.local
est prise en charge par défaut pour résoudre le service en interne.Vous pouvez y parvenir en déployant quelque chose à une couche plus élevée que les services à espace de noms, comme le service loadbalancer https://github.com/kubernetes/contrib/tree/master/service-loadbalancer . Si vous souhaitez le restreindre à un seul espace de noms, utilisez l'argument "--namespace = ns" (par défaut, 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.
la source