Jak wyeksponować usługę bez głowy dla StatefulSet zewnętrznie w Kubernetes
Dzięki temu, że nie ma problemu, nie ma problemu.
Do wykrywania usług w klastrze używane są StatefulSet i usługa bez głowy.Celem jest ujawnienie poszczególnych brokerów Kafka zewnętrznie, które są wewnętrznie adresowane jako:
kafka-0.broker.kafka.svc.cluster.local:9092
kafka-1.broker.kafka.svc.cluster.local:9092
kafka-2.broker.kafka.svc.cluster.local:9092
Ograniczenie polega na tym, że ta usługa zewnętrzna jest w stanie zwrócić się konkretnie do brokerów.
Jaki jest właściwy (lub jeden możliwy) sposób na to? Czy możliwe jest wystawienie serwis zewnętrzny za kafka-x.broker.kafka.svc.cluster.local:9092
?
5 answers
Rozwiązaliśmy to w 1.7 zmieniając usługę headless na Type=NodePort
i ustawiając externalTrafficPolicy=Local
. To omija wewnętrzne równoważenie obciążenia usługi i ruchu przeznaczonego do określonego węzła na tym porcie węzła będzie działać tylko wtedy, gdy Kafka pod znajduje się na tym węźle.
apiVersion: v1
kind: Service
metadata:
name: broker
spec:
externalTrafficPolicy: Local
ports:
- nodePort: 30000
port: 30000
protocol: TCP
targetPort: 9092
selector:
app: broker
type: NodePort
Na przykład, mamy dwa węzły nodeA i nodeB, nodeB uruchamia Kafka pod. nodeA: 30000 nie połączy się, ale nodeB: 30000 połączy się z kafka pod działającym na nodeB.
Https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typenodeport
Uwaga To było również dostępne w 1.5 i 1.6 jako adnotacja beta, więcej można znaleźć tutaj na temat dostępności funkcji: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
Zauważ również, że chociaż wiąże to Kafkę pod z określoną zewnętrzną tożsamością sieci, nie upewnij się, że wolumin pamięci masowej będzie powiązany z tą tożsamością sieciową. Jeśli używasz VolumeClaimTemplates w zestawie Stanów, Twoje woluminy są powiązane z pod, podczas gdy kafka oczekuje, że wolumin będzie powiązany z tożsamością sieciową.
Na przykład, jeśli pod kafka-0 restartuje się i kafka-0 pojawia się na nodeC zamiast nodeA, kafka-0 ' S pvc (jeśli używa VolumeClaimTemplates) ma dane, które są dla nodeA, a broker działający na kafka-0 zaczyna odrzucać żądania myśląc, że jest nodeA nie nodeC.
Aby to naprawić, czekamy na lokalne stałe woluminy, ale teraz mamy pojedynczy PVC dla naszego Kafka StatefulSet i dane są przechowywane pod $NODENAME
na tym PVC, aby powiązać dane woluminów z konkretnym węzłem.
Https://github.com/kubernetes/features/issues/121 https://kubernetes.io/docs/concepts/storage/volumes/#local
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-14 12:35:32
Rozwiązania do tej pory nie były wystarczająco satysfakcjonujące dla mnie, więc zamierzam opublikować własną odpowiedź. Moje cele:
- Pods powinny być nadal dynamicznie zarządzane za pomocą StatefulSet tak bardzo, jak to możliwe.
- Utwórz zewnętrzną usługę dla Pod (tj. Kafka Broker) dla klientów producentów/konsumentów i unikaj równoważenia obciążenia.
- Stwórz wewnętrzną usługę bez głowy, aby każdy Broker mógł się ze sobą komunikować.
Zaczynając od yolean/kubernetes-kafka , brakuje tylko eksponowania serwisu Na zewnątrz i dwóch wyzwań w tym zakresie.
- generowanie unikalnych etykiet dla pod brokera, dzięki czemu możemy stworzyć zewnętrzną usługę dla każdego Pod brokera.
- powiedzenie pośrednikom, aby komunikowali się ze sobą za pomocą usługi wewnętrznej, konfigurując Kafka, aby powiedział producentowi / konsumentom, aby komunikowali się za pośrednictwem usługi zewnętrznej.
Na etykiety pod i zewnętrzne usługi:
Aby wygenerować etykiety dla pod, ten problem był naprawdę pomocny. Używając go jako przewodnika, dodajemy następującą linię do 10broker-config.yml init.sh
własność z:
kubectl label pods ${HOSTNAME} kafka-set-component=${HOSTNAME}
Zachowujemy istniejącą usługę bez głowy, ale generujemy również zewnętrzną Usługę dla pod za pomocą etykiety (dodałem je do 20dns.yml):
apiVersion: v1
kind: Service
metadata:
name: broker-0
namespace: kafka
spec:
type: NodePort
ports:
- port: 9093
nodePort: 30093
selector:
kafka-set-component: kafka-0
Konfiguracja Kafki z wewnętrznymi / zewnętrznymi słuchaczami
Znalazłem ten numer niezwykle przydatne w próbie zrozumienia, jak skonfigurować Kafka.
To ponownie wymaga aktualizacji właściwości init.sh
i server.properties
w 10broker-config.yml z następującym:
Dodaj do server.properties
, aby zaktualizować protokoły bezpieczeństwa (obecnie używające PLAINTEXT
):
listener.security.protocol.map=INTERNAL_PLAINTEXT:PLAINTEXT,EXTERNAL_PLAINTEXT:PLAINTEXT
inter.broker.listener.name=INTERNAL_PLAINTEXT
Dynamiczne określanie zewnętrznego IP i zewnętrznego portu dla każdego Pod w init.sh
:
EXTERNAL_LISTENER_IP=<your external addressable cluster ip>
EXTERNAL_LISTENER_PORT=$((30093 + ${HOSTNAME##*-}))
Następnie skonfiguruj listeners
i advertised.listeners
IPs dla EXTERNAL_LISTENER
i INTERNAL_LISTENER
(również w init.sh
własność):
sed -i "s/#listeners=PLAINTEXT:\/\/:9092/listeners=INTERNAL_PLAINTEXT:\/\/0.0.0.0:9092,EXTERNAL_PLAINTEXT:\/\/0.0.0.0:9093/" /etc/kafka/server.properties
sed -i "s/#advertised.listeners=PLAINTEXT:\/\/your.host.name:9092/advertised.listeners=INTERNAL_PLAINTEXT:\/\/$HOSTNAME.broker.kafka.svc.cluster.local:9092,EXTERNAL_PLAINTEXT:\/\/$EXTERNAL_LISTENER_IP:$EXTERNAL_LISTENER_PORT/" /etc/kafka/server.properties
Oczywiście nie jest to pełne rozwiązanie dla produkcji (na przykład dotyczące bezpieczeństwa zewnętrznych brokerów) i nadal doskonalę swoje zrozumienie, jak również pozwolić wewnętrznym producentom / konsumentom komunikować się z brokerami.
Jednak jak na razie jest to najlepsze podejście do mojego zrozumienia Kubernetes i Kafka.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 10:50:52
Chciałbym powiedzieć, że przeczytałem to pytanie i odpowiedziałem 3 razy wcześniej od próby owinięcia głowy wokół tego, co było Bezgłowe usługi/jaki był ich cel. (i nigdy w pełni nie rozumiałem usług bezgłowych, ani tego, o co chodziło w tym Q&A.)
i na 4 czytaniu (powracając do niego po dalszej edukacji) w końcu kliknęło/w końcu zrozumiałem.
tak więc celem tej odpowiedzi jest powtórzenie pytania/problemu / Nadira i odpowiedź tak, jakby wyjaśniając to uczniowi. Więc że inni, którzy się na to natkną, otrzymają znaczenie niesamowitego rozwiązania Nadira przy pierwszym czytaniu.
Przydatna Wiedza:
-
Istnieje usługa typu: ExternalName.
ExternalName Usługa po prostu wskazuje na adres DNS.
istnieją 2 smaki ExternalName Service:- BEZ IP klastra:
dobrym przypadkiem użycia byłoby umożliwienie klastrowi testowemu i klastrowi produkcyjnemu współdzielenia tyle kodu jako możliwe. (a w niektórych przypadkach dla prostego wygody) strąki w obu testy i produkcja wskazywałyby na ten sam adres DNS usługi Nazwa, to będzie przewidywalny kod wielokrotnego użytku. Różnica byłoby, że środowisko testujące będzie miało usługę, która wskazuje na usługę SQL, która istnieje wewnątrz klastra. Na klaster produkcyjny korzystałby z usługi ExternalName, która przekierowanie/wskaż adres DNS dostawcy chmury zarządzanego SQL rozwiązanie. - z gromadą IP:
jest to wersja usługi ExternalName, która jest kluczem do rozwiązania.
- BEZ IP klastra:
-
Zbiór stanów składa się z 3 części:
- Porządkowy
- Trwałe Przechowywanie
- uporczywy IP (ale to nie jest przewidywalne)
-
Są 3 ważne rzeczy do zapamiętania o Kube-Proxy:
- to sprawia, że wszystko ma unikalne IP.
- jest odpowiedzialny za implementację wirtualnych adresów IP klastra statycznego (wirtualne adresy IP klastra statycznego są uważane za wirtualne, ponieważ istnieją tylko w każdym węzle iptables w implementacji iptables Kube-Proxy, lub w tabeli Hash jądra w wersji IP-vs next-gen Kube-Proxy) i jest również odpowiedzialny za logiczny efekt równoważenia obciążenia, który występuje w normalnych usługach.
- KubeProxy jest odpowiedzialny za mapowanie ruchu, który przychodzi na NodePorts do odpowiednia normalna usługa.
-
Są 4 ważne rzeczy do zapamiętania o Bezgłowej służbie:
- tworzy przewidywalny Adres DNS.
- nie działa jako wewnętrzny cluster Load Balancer. Rozmawiasz bezpośrednio z pod zidentyfikowanym przez przewidywalny Adres DNS. (które jest bardzo pożądane dla obciążeń stateful)
- nie ma statycznego adresu IP klastra.
- jako efekt uboczny cech 2 i 3, jest poza sferą Kube-Proxy (która jest odpowiedzialna za kierowanie ruchem wchodzącym na Node Porty Do usług.parafrazuję to kilka razy, więc problem w tym, że NodePorts zazwyczaj nie może przekierowywać ruchu do Headless Usługi. Ruch zewnętrzny wchodzący do klastra zazwyczaj nie może być przekazane do Usługi Bezgłowe. Nie jest intuicyjne, jak na zewnątrz / align = "left" /
stąd pierwotne pytanie: w jaki sposób usługa Bezgłowa (która wskazuje na pojedynczego członka Państwowego zestawu) może być eksponowana zewnętrznie?
Przed dodaniem usługi bez głowy do zestawu Stateful, pods kafka - 0, kafka-1 i kafka-2 miałyby statyczne adresy IP, ale statycznego adresu IP nie można było przewidzieć.
Bezgłowy Serwis daje Stateful Set przewidywalne adresy DNS klastra wewnętrznego (a Stateful Set nie potrzebował statycznego adresu IP klastra, ponieważ miał już taki jako część swojej tożsamości jako zestaw Stateful)
Kafka-0.broker.kafka.svc.klaster.local: 9092
Kafka-1.broker.kafka.svc.klaster.local: 9092
Kafka-2.broker.kafka.svc.klaster.local: 9092
Rozwiązanie Część 1:
Przewidywalne adresy DNS klastra wewnętrznego rozwiązują dostęp klastra wewnętrznego do zestawów stanu. (pozwala to na pods w zestawie stanowym, aby rozmawiać między sobą i pozwala innym pods w klastrze, aby uzyskać do nich dostęp.)
Część Rozwiązania 2:
Drugie rozwiązanie jest potrzebne do rozwiązania zewnętrznego dostępu do zestawów/zasobów Stateful poza klastrem, aby móc uzyskać dostęp do zestawów stateful wewnątrz klastra.
dla każdego pod W Zestawie Stanowym tworzona jest usługa typu ExternalName z wirtualnym statycznym adresem ClusterIP zarządzanym przez Kube-Proxy. Każdy punkt aby / przekierowuje ruch na przewidywalny statyczny adres wewnętrzny klastra DNS zidentyfikowany w rozwiązaniu 1, A ponieważ ta usługa ExternalName ma wirtualny statyczny Klaster zarządzany przez Kube-Proxy, może być mapowanie z NodePorts do niego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-13 02:48:32
Zmień usługę z Bezgłowego klastra na NodePort, który przekierowałby żądanie do dowolnego z węzłów na ustawionym porcie (w moim przykładzie 30092) na port 9042 na Kafkas. Trafiłbyś losowo w jedną z kapsuł, ale myślę, że to jest w porządku.
20dns.YML staje się (coś takiego):
# A no longer headless service to create DNS records
---
apiVersion: v1
kind: Service
metadata:
name: broker
namespace: kafka
spec:
type: NodePort
ports:
- port: 9092
- nodePort: 30092
# [podname].broker.kafka.svc.cluster.local
selector:
app: kafka
Zastrzeżenie: możesz potrzebować dwóch usług. Jeden bezgłowy dla wewnętrznych nazw dns i jeden NodePort dla dostępu zewnętrznego. Sam tego nie próbowałem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-27 20:09:13
Z dokumentacji kubernetes kafka :
Zewnętrzny dostęp z hostport
Alternatywą jest użycie hostportu dla zewnętrznego dostępu. Kiedy korzystanie z tego tylko jednego brokera kafka może działać na każdym Hostie, co jest dobrym pomysł w każdym razie.
Aby przełączyć się na hostport adres reklamowy kafka musi być switched to the ExternalIP or ExternalDNS name of the node running the broker. w kafka/10broker-config.YML switch to
OUTSIDE_HOST=$(kubectl get node "$NODE_NAME" -o jsonpath='{.status.addresses[?(@.type=="ExternalIP")].address}') OUTSIDE_PORT=${OutsidePort}
I w kafka/50kafka.yml dodaj hostport:
- name: outside containerPort: 9094 hostPort: 9094
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-21 13:42:41