Próbowałem znaleźć sposób na zdefiniowanie usługi w jednej przestrzeni nazw, która łączy się z Pod działającym w innej przestrzeni nazw. Wiem, że kontenery w uruchomionym Podowie namespaceA
mogą uzyskać dostęp do serviceX
zdefiniowanego w namespaceB
, odwołując się do niego w DNS klastra jako serviceX.namespaceB.svc.cluster.local
, ale wolałbym, aby kod wewnątrz kontenera nie musiał wiedzieć o lokalizacji serviceX
. Oznacza to, że chcę, aby kod po prostu wyszukał, serviceX
a następnie miał do niego dostęp.
Dokumentacja Kubernetes sugeruje, że jest to możliwe. Mówi się, że jednym z powodów, dla których zdefiniowałbyś usługę bez selektora, jest to, że chcesz skierować swoją usługę do usługi w innej przestrzeni nazw lub w innym klastrze .
To sugeruje mi, że powinienem:
- Zdefiniuj
serviceX
usługę wnamespaceA
, bez selektora (ponieważ POD, który chcę wybrać, nie manamespaceA
). - Zdefiniuj usługę (do której również zadzwoniłem
serviceX
)namespaceB
, a następnie - Zdefiniuj obiekt Endpoints w,
namespaceA
aby wskazywałserviceX
wnamespaceB
.
To trzeci krok, którego nie byłem w stanie wykonać.
Najpierw próbowałem zdefiniować obiekt Endpoints w ten sposób:
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
To wydawało się logiczne podejście i oczywiście do czego służyłotargetRef
. Ale to prowadziło do błędu mówiącego, że ip
pole w addresses
tablicy jest obowiązkowe. Tak więc moją następną próbą było przypisanie stałego adresu ClusterIP do serviceX
in namespaceB
i umieszczenie go w polu IP (zauważ, że service_cluster_ip_range
jest skonfigurowany jako 192.168.0.0/16
, i 192.168.1.1
został przypisany jako ClusterIP dla serviceX
in namespaceB
; serviceX
w namespaceA
automatycznie przypisano inny ClusterIP w 192.168.0.0/16
podsieci) :
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
Który został przyjęty, ale zejściówki serviceX
w namespaceA
nie dostać przekazane Pod w namespaceB
- oni timed out. Patrząc na konfigurację iptables, wygląda na to, że aby to osiągnąć, musiałby dwukrotnie wykonać routing wstępny NAT.
Jedyną rzeczą, jaką znaleźliśmy, który pracował - ale nie jest to zadowalające rozwiązanie - do wyszukiwania rzeczywisty adres IP Pod zapewniając serviceX
w namespaceB
i umieścić ten adres w obiekcie punktów końcowych w namespaceA
. To oczywiście nie jest satysfakcjonujące, ponieważ adres IP Poda może się zmieniać w czasie. Oto problem z adresami IP usług do rozwiązania.
Czy jest więc sposób, aby spełnić to, co wydaje się być obietnicą zawartą w dokumentacji, że mogę skierować usługę w jednej przestrzeni nazw do usługi działającej w innej przestrzeni nazw?
Komentator zapytał, dlaczego chcesz to zrobić - oto przypadek użycia, który ma dla mnie przynajmniej sens:
Załóżmy, że masz system z wieloma dzierżawcami, który obejmuje również wspólną funkcję dostępu do danych, którą można współdzielić między dzierżawcami. Teraz wyobraź sobie, że istnieją różne odmiany tej funkcji dostępu do danych z typowymi interfejsami API, ale różne charakterystyki wydajności. Niektórzy najemcy uzyskują dostęp do jednego z nich, inni do drugiego.
Podsystemy każdego dzierżawcy działają we własnych przestrzeniach nazw, ale każdy z nich musi uzyskać dostęp do jednej z tych wspólnych usług dostępu do danych, która z konieczności będzie znajdować się w innej przestrzeni nazw (ponieważ jest dostępna dla wielu dzierżawców). Ale nie chcesz, aby dzierżawca musiał zmieniać swój kod, jeśli jego subskrypcja ulegnie zmianie, aby uzyskać dostęp do usługi o wyższej wydajności.
Potencjalnym rozwiązaniem (najczystszym, jakie przychodzi mi do głowy, gdyby tylko zadziałało) jest uwzględnienie definicji usługi w przestrzeni nazw każdego dzierżawcy dla usługi dostępu do danych, z każdą skonfigurowaną dla odpowiedniego punktu końcowego. Ta definicja usługi byłaby skonfigurowana tak, aby wskazywała odpowiednią usługę dostępu do danych, z której może korzystać każdy dzierżawca.
źródło
Odpowiedzi:
Natknąłem się na ten sam problem i znalazłem fajne rozwiązanie, które nie wymaga żadnej statycznej konfiguracji IP:
Możesz uzyskać dostęp do usługi za pośrednictwem jej nazwy DNS (jak wspomniałeś): nazwa usługi.namespace.svc.cluster.local
Możesz użyć tej nazwy DNS, aby odwołać się do niej w innej przestrzeni nazw za pośrednictwem usługi lokalnej :
źródło
To takie proste
jeśli chcesz go używać jako hosta i chcesz go rozwiązać
Jeśli używasz ambasadora do dowolnej innej bramy API dla usługi znajdującej się w innej przestrzeni nazw, zawsze zaleca się użycie:
będzie jak:
servicename.namespacename.svc.cluster.local
spowoduje to wysłanie żądania do określonej usługi w przestrzeni nazw, o której wspomniałeś.
przykład:
W tym miejscu zastąp
<servicename>
i<namespace>
odpowiednią wartością.W Kubernetes przestrzenie nazw są używane do tworzenia środowiska wirtualnego, ale wszystkie są ze sobą połączone.
źródło
.svc.cluster.local
jest domyślnie obsługiwane przy rozwiązywaniu usługi wewnętrznie.Możesz to osiągnąć, wdrażając coś na wyższym poziomie niż usługi w przestrzeni nazw, takie jak usługa loadbalancer https://github.com/kubernetes/contrib/tree/master/service-loadbalancer . Jeśli chcesz ograniczyć to do jednej przestrzeni nazw, użyj argumentu „--namespace = ns” (domyślnie wszystkie przestrzenie nazw: https://github.com/kubernetes/contrib/blob/master/service-loadbalancer/service_loadbalancer.go # L715 ). Działa to dobrze dla L7, ale jest trochę bałagan w L4.
źródło