Zum Inhalt springen
BlogContainer (Kubernetes, Docker)Skalierung von Kubernetes über Regionen hinweg

Regionsübergreifende Skalierung von Kubernetes

Grafik zur regionsübergreifenden Skalierung von Kubernetes

Dieser Beitrag ist Teil unserer Serie zur Skalierung von Kubernetes. Registrieren Sie sich um ihn live zu sehen oder auf die Aufzeichnung zuzugreifen, und sehen Sie sich unsere anderen Beiträge in dieser Serie an:

Eine interessante Herausforderung bei Kubernetes ist die Bereitstellung von Workloads über mehrere Regionen hinweg. Obwohl Sie technisch gesehen einen Cluster mit mehreren Knoten in verschiedenen Regionen haben können, wird dies im Allgemeinen als etwas angesehen, das Sie aufgrund der zusätzlichen Latenzzeit vermeiden sollten.

Eine beliebte Alternative ist die Bereitstellung eines Clusters für jede Region und die Suche nach einer Möglichkeit, diese zu orchestrieren.

Diagramm eines Kubernetes-Clusters mit Knoten in mehreren Regionen (nicht immer eine gute Idee) im Vergleich zu einem Cluster in jeder Region, in der Sie bereitstellen müssen (der fortschrittlichere Ansatz)
Sie könnten einen Cluster mit Knoten haben, die sich über mehrere Regionen erstrecken, oder Sie könnten einen Cluster für jede Region haben.

In diesem Beitrag werden Sie:

  1. Bilden Sie drei Cluster: einen in Nordamerika, einen in Europa und einen in Südostasien.
  2. Erstellen Sie einen vierten Cluster, der als Orchestrator für die anderen fungieren wird.
  3. Richten Sie ein einziges Netz aus den drei Clusternetzen ein, um eine nahtlose Kommunikation zu ermöglichen.

Dieser Beitrag wurde mit einem Skript versehen, das mit Terraform funktioniert und nur minimale Interaktion erfordert. Sie können den Code dafür auf LearnK8s GitHub finden.

Erstellen des Cluster-Managers

Beginnen wir mit der Erstellung des Clusters, der den Rest verwalten wird. Die folgenden Befehle können verwendet werden, um den Cluster zu erstellen und die kubeconfig-Datei zu speichern.

bash
$ linode-cli lke cluster-create \
 --label cluster-manager \
 --region eu-west \
 --k8s_version 1.23
 
$ linode-cli lke kubeconfig-view "insert cluster id here" --text | tail +2 | base64 -d > kubeconfig-cluster-manager

Mit können Sie überprüfen, ob die Installation erfolgreich war:

bash
$ kubectl get pods -A --kubeconfig=kubeconfig-cluster-manager

Ausgezeichnet!

Im Clustermanager installieren Sie Karmada, ein Verwaltungssystem, mit dem Sie Ihre Cloud-nativen Anwendungen über mehrere Kubernetes-Cluster und Clouds hinweg ausführen können. Karmada verfügt über eine Steuerebene, die im Cluster-Manager installiert ist, und den Agenten, der in jedem anderen Cluster installiert ist.

Die Steuerungsebene besteht aus drei Komponenten:

  1. Ein API-Server;
  2. Ein Controller Manager; und
  3. Ein Planer
Diagramm der Karmada-Kontrollebene, bestehend aus einem Karmada-API-Server, Controller-Manager, etcd und Scheduler.
Karmadas Steuerungsebene.

Wenn Ihnen das bekannt vorkommt, liegt das daran, dass die Kubernetes-Kontrollebene die gleichen Komponenten enthält! Karmada musste sie kopieren und erweitern, um mit mehreren Clustern arbeiten zu können.

Das ist genug Theorie. Kommen wir zum Code.
Sie werden Helm verwenden, um den Karmada-API-Server zu installieren. Fügen wir das Helm-Repository mit hinzu:

bash
$ helm repo add karmada-charts https://raw.githubusercontent.com/karmada-io/karmada/master/charts
$ helm repo list
NAME            URL
karmada-charts   https://raw.githubusercontent.com/karmada-io/karmada/master/charts

Da der Karmada API Server von allen anderen Clustern erreichbar sein muss, müssen Sie

  • es vom Knoten aus freizulegen; und
  • stellen Sie sicher, dass die Verbindung vertrauenswürdig ist.

Rufen wir also die IP-Adresse des Knotens ab, der die Steuerungsebene hostet:

bash
kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type==\"ExternalIP\")].address}' \
 --kubeconfig=kubeconfig-cluster-manager

Jetzt können Sie die Karmada-Kontrollebene mit installieren:

bash
$ helm install karmada karmada-charts/karmada \
 --kubeconfig=kubeconfig-cluster-manager \
 --create-namespace --namespace karmada-system \
 --version=1.2.0 \
 --set apiServer.hostNetwork=false \
 --set apiServer.serviceType=NodePort \
 --set apiServer.nodePort=32443 \
 --set certs.auto.hosts[0]="kubernetes.default.svc" \
 --set certs.auto.hosts[1]="*.etcd.karmada-system.svc.cluster.local" \
 --set certs.auto.hosts[2]="*.karmada-system.svc.cluster.local" \
 --set certs.auto.hosts[3]="*.karmada-system.svc" \
 --set certs.auto.hosts[4]="localhost" \
 --set certs.auto.hosts[5]="127.0.0.1" \
 --set certs.auto.hosts[6]="<insert the IP address of the node>"

Sobald die Installation abgeschlossen ist, können Sie die kubeconfig abrufen, mit der Sie sich mit der Karmada-API verbinden:

bash
kubectl get secret karmada-kubeconfig \
 --kubeconfig=kubeconfig-cluster-manager \
 -n karmada-system \
 -o jsonpath={.data.kubeconfig} | base64 -d > karmada-config

Aber Moment, warum noch eine kubeconfig-Datei?

Karmada API wurde entwickelt, um das standardmäßige Kubernetes-API zu ersetzen, behält aber dennoch alle Funktionen bei, die Sie gewohnt sind. Mit anderen Worten: Sie können mit kubectl Bereitstellungen erstellen, die mehrere Cluster umfassen.

Bevor Sie die Karmada-API und kubectl testen, sollten Sie die kubeconfig-Datei patchen. Standardmäßig kann die generierte kubeconfig nur innerhalb des Clusternetzwerks verwendet werden.

Sie können jedoch die folgende Zeile ersetzen, damit es funktioniert:

yaml
apiVersion: v1
kind: Config
clusters:
 - cluster:
     certificate-authority-data: LS0tLS1CRUdJTi…
     insecure-skip-tls-verify: false
     server: https://karmada-apiserver.karmada-system.svc.cluster.local:5443 # <- this works only in the cluster
   name: karmada-apiserver
# truncated

Ersetzen Sie sie durch die IP-Adresse des Knotens, die Sie zuvor abgerufen haben:

yaml
apiVersion: v1
kind: Config
clusters:
 - cluster:
     certificate-authority-data: LS0tLS1CRUdJTi…
     insecure-skip-tls-verify: false
     server: https://<node's IP address>:32443 # <- this works from the public internet
   name: karmada-apiserver
# truncated

Großartig, es ist an der Zeit, Karmada zu testen.

Installation des Karmada-Agenten

Geben Sie den folgenden Befehl ein, um alle Bereitstellungen und alle Cluster abzurufen:

bash
$ kubectl get clusters,deployments --kubeconfig=karmada-config
No resources found

Es überrascht nicht, dass es keine Bereitstellungen und keine zusätzlichen Cluster gibt. Fügen wir nun ein paar weitere Cluster hinzu und verbinden sie mit der Karmada-Kontrollebene.

Wiederholen Sie die folgenden Befehle dreimal:

bash
linode-cli lke cluster-create \
 --label <insert-cluster-name> \
 --region <insert-region> \
 --k8s_version 1.23
 
linode-cli lke kubeconfig-view "insert cluster id here" --text | tail +2 | base64 -d > kubeconfig-<insert-cluster-name>

Die Werte sollten die folgenden sein:

  • Name des Clusters euRegion eu-west und kubeconfig-Datei kubeconfig-eu
  • Name des Clusters apRegion ap-south und kubeconfig-Datei kubeconfig-ap
  • Name des Clusters usRegion us-west und kubeconfig-Datei kubeconfig-us

Mit können Sie überprüfen, ob die Cluster erfolgreich erstellt wurden:

bash
$ kubectl get pods -A --kubeconfig=kubeconfig-eu
$ kubectl get pods -A --kubeconfig=kubeconfig-ap
$ kubectl get pods -A --kubeconfig=kubeconfig-us

Jetzt ist es an der Zeit, dass sie sich dem Karmada-Cluster anschließen.

Karmada verwendet einen Agenten auf jedem anderen Cluster, um die Bereitstellung mit der Steuerungsebene zu koordinieren.

Diagramm des Karmada-Agenten, der sich mit der Clusterkontrollebene (API-Server, Controller-Manager und Scheduler) in Kubernetes-Cluster 1 verbindet.
Der Karmada-Agent.

Sie werden Helm verwenden, um den Karmada-Agenten zu installieren und ihn mit dem Cluster-Manager zu verbinden:

bash
$ helm install karmada karmada-charts/karmada \
 --kubeconfig=kubeconfig-<insert-cluster-name> \
 --create-namespace --namespace karmada-system \
 --version=1.2.0 \
 --set installMode=agent \
 --set agent.clusterName=<insert-cluster-name> \
 --set agent.kubeconfig.caCrt=<karmada kubeconfig certificate authority> \
 --set agent.kubeconfig.crt=<karmada kubeconfig client certificate data> \
 --set agent.kubeconfig.key=<karmada kubeconfig client key data> \
 --set agent.kubeconfig.server=https://<insert node's IP address>:32443 \

Sie müssen den obigen Befehl dreimal wiederholen und die folgenden Variablen einfügen:

  • Der Name des Clusters. Dieser ist entweder eu, ap, oder us
  • Die Zertifizierungsstelle des Clustermanagers. Sie finden diesen Wert in der Datei karmada-config Datei under clusters[0].cluster['certificate-authority-data'].
    Sie können den Wert entschlüsseln aus base64.
  • Die Daten des Client-Zertifikats des Benutzers. Sie finden diesen Wert in der Datei karmada-config ablegen unter users[0].user['client-certificate-data'].
    Sie können den Wert aus base64 dekodieren.
  • Die Daten des Client-Zertifikats des Benutzers. Sie finden diesen Wert in der Datei karmada-config ablegen unter users[0].user['client-key-data'].
    Sie können den Wert aus base64 dekodieren.
  • Die IP-Adresse des Karmada-Kontrollzentrums.

Um zu überprüfen, ob die Installation abgeschlossen ist, können Sie den folgenden Befehl eingeben:

bash
$ kubectl get clusters --kubeconfig=karmada-config
NAME   VERSION   MODE   READY
eu     v1.23.8   Pull   True
ap     v1.23.8   Pull   True
us     v1.23.8   Pull   True

Ausgezeichnet!

Orchestrierung der Multicluster-Bereitstellung mit Karmada-Richtlinien

Bei der derzeitigen Konfiguration übermitteln Sie eine Arbeitslast an Karmada, das sie dann auf die anderen Cluster verteilt.

Testen wir dies, indem wir eine Bereitstellung erstellen:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: hello
spec:
 replicas: 3
 selector:
   matchLabels:
     app: hello
 template:
   metadata:
     labels:
       app: hello
   spec:
     containers:
       - image: stefanprodan/podinfo
         name: hello
---
apiVersion: v1
kind: Service
metadata:
 name: hello
spec:
 ports:
   - port: 5000
     targetPort: 9898
 selector:
   app: hello

Sie können die Bereitstellung an den Karmada-API-Server mit übermitteln:

bash
$ kubectl apply -f deployment.yaml --kubeconfig=karmada-config

Dieser Einsatz hat drei Replikate - werden diese gleichmäßig auf die drei Cluster verteilt?

Schauen wir nach:

bash
$ kubectl get deployments --kubeconfig=karmada-config
NAME    READY   UP-TO-DATE   AVAILABLE
hello   0/3     0            0

Warum schafft Karmada die Pods nicht?

Lassen Sie uns den Einsatz beschreiben:

bash
$ kubectl describe deployment hello --kubeconfig=karmada-config
Name:                   hello
Namespace:              default
Selector:               app=hello
Replicas:               3 desired | 0 updated | 0 total | 0 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Events:
 Type     Reason             From               Message
 ----     ------             ----               -------
 Warning  ApplyPolicyFailed  resource-detector  No policy match for resource

Karmada weiß nicht, was es mit den Bereitstellungen machen soll, weil Sie keine Richtlinie angegeben haben.

Der Karmada-Scheduler verwendet Richtlinien für die Zuweisung von Workloads zu Clustern.

Definieren wir eine einfache Richtlinie, die jedem Cluster ein Replikat zuweist:

yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
 name: hello-propagation
spec:
 resourceSelectors:
   - apiVersion: apps/v1
     kind: Deployment
     name: hello
   - apiVersion: v1
     kind: Service
     name: hello
 placement:
   clusterAffinity:
     clusterNames:
       - eu
       - ap
       - us
   replicaScheduling:
     replicaDivisionPreference: Weighted
     replicaSchedulingType: Divided
     weightPreference:
       staticWeightList:
         - targetCluster:
             clusterNames:
               - us
           weight: 1
         - targetCluster:
             clusterNames:
               - ap
           weight: 1
         - targetCluster:
             clusterNames:
               - eu
           weight: 1

Sie können die Richtlinie mit an den Cluster übermitteln:

bash
$ kubectl apply -f policy.yaml --kubeconfig=karmada-config

Schauen wir uns die Bereitstellungen und Pods an:

bash
$ kubectl get deployments --kubeconfig=karmada-config
NAME    READY   UP-TO-DATE   AVAILABLE
hello   3/3     3            3
 
$ kubectl get pods --kubeconfig=kubeconfig-eu
NAME                    READY   STATUS    RESTARTS
hello-5d857996f-hjfqq   1/1     Running   0
 
$ kubectl get pods --kubeconfig=kubeconfig-ap
NAME                    READY   STATUS    RESTARTS
hello-5d857996f-xr6hr   1/1     Running   0
 
$ kubectl get pods --kubeconfig=kubeconfig-us
NAME                    READY   STATUS    RESTARTS
hello-5d857996f-nbz48   1/1     Running   0
Kartengrafik mit Kubernetes-Clustern in jeder Region (Fremont, CA, London und Singapur)
Karmada hat jedem Cluster einen Pod zugewiesen.

Karmada hat jedem Cluster einen Pod zugewiesen, da Ihre Richtlinie für jeden Cluster eine gleiche Gewichtung vorsieht.

Skalieren wir die Bereitstellung auf 10 Replikate mit:

bash
$ kubectl scale deployment/hello --replicas=10 --kubeconfig=karmada-config

Wenn Sie die Hülsen untersuchen, können Sie Folgendes feststellen:

bash
$ kubectl get deployments --kubeconfig=karmada-config
NAME    READY   UP-TO-DATE   AVAILABLE
hello   10/10   10           10
$ kubectl get pods --kubeconfig=kubeconfig-eu
NAME                    READY   STATUS    RESTARTS
hello-5d857996f-dzfzm   1/1     Running   0
hello-5d857996f-hjfqq   1/1     Running   0
hello-5d857996f-kw2rt   1/1     Running   0
hello-5d857996f-nz7qz   1/1     Running   0
 
$ kubectl get pods --kubeconfig=kubeconfig-ap
NAME                    READY   STATUS    RESTARTS
hello-5d857996f-pd9t6   1/1     Running   0
hello-5d857996f-r7bmp   1/1     Running   0
hello-5d857996f-xr6hr   1/1     Running   0
 
$ kubectl get pods --kubeconfig=kubeconfig-us
NAME                    READY   STATUS    RESTARTS
hello-5d857996f-nbz48   1/1     Running   0
hello-5d857996f-nzgpn   1/1     Running   0
hello-5d857996f-rsp7k   1/1     Running   0

Wir sollten die Politik dahingehend ändern, dass die EU- und US-Cluster 40 % der Hülsen besitzen und nur 20 % dem AP-Cluster überlassen werden.

yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
 name: hello-propagation
spec:
 resourceSelectors:
   - apiVersion: apps/v1
     kind: Deployment
     name: hello
   - apiVersion: v1
     kind: Service
     name: hello
 placement:
   clusterAffinity:
     clusterNames:
       - eu
       - ap
       - us
   replicaScheduling:
     replicaDivisionPreference: Weighted
     replicaSchedulingType: Divided
     weightPreference:
       staticWeightList:
         - targetCluster:
             clusterNames:
               - us
           weight: 2
         - targetCluster:
             clusterNames:
               - ap
           weight: 1
         - targetCluster:
             clusterNames:
               - eu
           weight: 2

Sie können die Police mit einreichen:

bash
$ kubectl apply -f policy.yaml --kubeconfig=karmada-config

Sie können beobachten, wie sich die Verteilung Ihres Pods entsprechend verändert:

bash
$ kubectl get pods --kubeconfig=kubeconfig-eu
NAME                    READY   STATUS    RESTARTS   AGE
hello-5d857996f-hjfqq   1/1     Running   0          6m5s
hello-5d857996f-kw2rt   1/1     Running   0          2m27s
 
$ kubectl get pods --kubeconfig=kubeconfig-ap
hello-5d857996f-k9hsm   1/1     Running   0          51s
hello-5d857996f-pd9t6   1/1     Running   0          2m41s
hello-5d857996f-r7bmp   1/1     Running   0          2m41s
hello-5d857996f-xr6hr   1/1     Running   0          6m19s
 
$ kubectl get pods --kubeconfig=kubeconfig-us
hello-5d857996f-nbz48   1/1     Running   0          6m29s
hello-5d857996f-nzgpn   1/1     Running   0          2m51s
hello-5d857996f-rgj9t   1/1     Running   0          61s
hello-5d857996f-rsp7k   1/1     Running   0          2m51s
Das Kartendiagramm zeigt die Verteilung der Pods auf die Regionen gemäß der von Karmada Controller festgelegten Politik - 40% in Fremont, CA, 40% in London und 20% in Singapur.
Die Pods werden entsprechend der Richtlinie verteilt.

Großartig!

Karmada unterstützt verschiedene Richtlinien zur Verteilung Ihrer Arbeitslasten. Sie können die Dokumentation für fortgeschrittene Anwendungsfälle einsehen.

Die Pods laufen in den drei Clustern, aber wie kann man auf sie zugreifen?

Schauen wir uns den Service in Karmada an:

bash
$ kubectl describe service hello --kubeconfig=karmada-config
Name:              hello
Namespace:         default
Labels:            propagationpolicy.karmada.io/name=hello-propagation
                  propagationpolicy.karmada.io/namespace=default
Selector:          app=hello
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.105.24.193
IPs:               10.105.24.193
Port:              <unset>  5000/TCP
TargetPort:        9898/TCP
Events:
 Type     Reason                  Message
 ----     ------                  -------
 Normal   SyncSucceed             Successfully applied resource(default/hello) to cluster ap
 Normal   SyncSucceed             Successfully applied resource(default/hello) to cluster us
 Normal   SyncSucceed             Successfully applied resource(default/hello) to cluster eu
 Normal   AggregateStatusSucceed  Update resourceBinding(default/hello-service) with AggregatedStatus successfully.
 Normal   ScheduleBindingSucceed  Binding has been scheduled
 Normal   SyncWorkSucceed         Sync work of resourceBinding(default/hello-service) successful.

Der Dienst ist in allen drei Clustern implementiert, aber sie sind nicht miteinander verbunden.

Auch wenn Karmada mehrere Cluster verwalten kann, bietet es keinen Netzwerkmechanismus , der sicherstellt, dass die drei Cluster miteinander verbunden sind. Mit anderen Worten: Karmada ist ein hervorragendes Werkzeug zur Orchestrierung von Bereitstellungen über Cluster hinweg, aber Sie brauchen etwas anderes, um sicherzustellen, dass diese Cluster miteinander kommunizieren können.

Verbinden von mehreren Clustern mit Istio

Istio wird in der Regel verwendet, um den Netzwerkverkehr zwischen Anwendungen im selben Cluster zu kontrollieren. Es funktioniert, indem es alle ausgehenden und eingehenden Anfragen abfängt und sie durch Envoy weiterleitet.

Diagramm, das zeigt, wie Envoy-Proxys den Datenverkehr abfangen und an andere Pods weiterleiten.
Die Proxys von Envoy fangen den gesamten Datenverkehr ab.

Die Istio-Kontrollebene ist für die Aktualisierung und das Sammeln von Metriken von diesen Proxys zuständig und kann auch Anweisungen zur Umleitung des Datenverkehrs geben.

Das Diagramm zeigt, wie die Istio-Kontrollebene die Proxys im laufenden Betrieb rekonfigurieren kann, und Sie können eine Regel haben, um den Verkehr zwischen Pods zu verweigern.
Mit Istio können Sie Richtlinien zur Verwaltung des Datenverkehrs in Ihrem Cluster definieren.

Sie könnten also Istio verwenden, um den gesamten Datenverkehr zu einem bestimmten Dienst abzufangen und ihn an einen der drei Cluster zu leiten. Das ist die Idee hinter dem Multicluster-Setup von Istio.

Genug der Theorie - machen wir uns die Hände schmutzig. Der erste Schritt besteht darin, Istio in den drei Clustern zu installieren.

Es gibt zwar mehrere Möglichkeiten, Istio zu installieren, aber ich bevorzuge normalerweise Helm:

bash
$ helm repo add istio https://istio-release.storage.googleapis.com/charts
$ helm repo list
NAME            URL
istio                 https://istio-release.storage.googleapis.com/charts

Sie können Istio in den drei Clustern mit installieren:

bash
$ helm install istio-base istio/base \
 --kubeconfig=kubeconfig-<insert-cluster-name> \
 --create-namespace --namespace istio-system \
 --version=1.14.1

Sie sollten die cluster-name mit ap, eu und us und führen Sie den Befehl für jeden aus.

Das Basisdiagramm installiert vor allem allgemeine Ressourcen wie Rollen und RoleBindings.

Die eigentliche Installation ist im Paket mit dem istiod Karte. Doch bevor Sie damit fortfahren, müssen Sie Konfiguration der Istio-Zertifizierungsstelle (CA) um sicherzustellen, dass die drei Cluster miteinander in Verbindung treten und sich gegenseitig vertrauen können.

Klonen Sie das Istio-Repository mit in ein neues Verzeichnis:

bash
$ git clone https://github.com/istio/istio

Erstellen einer certs und wechseln Sie in dieses Verzeichnis:

bash
$ mkdir certs
$ cd certs

Erstellen Sie das Stammzertifikat mit:

bash
$ make -f ../istio/tools/certs/Makefile.selfsigned.mk root-ca

Der Befehl erzeugte die folgenden Dateien:

  • root-cert.pem: das erzeugte Stammzertifikat
  • root-key.pem: der generierte Root-Schlüssel
  • root-ca.confdie Konfiguration für OpenSSL, um das Stammzertifikat zu erzeugen
  • root-cert.csr: die generierte CSR für das Stammzertifikat

Generieren Sie für jeden Cluster ein Zwischenzertifikat und einen Schlüssel für die Istio-Zertifizierungsstelle:

bash
$ make -f ../istio/tools/certs/Makefile.selfsigned.mk cluster1-cacerts
$ make -f ../istio/tools/certs/Makefile.selfsigned.mk cluster2-cacerts
$ make -f ../istio/tools/certs/Makefile.selfsigned.mk cluster3-cacerts

Die Befehle erzeugen die folgenden Dateien in einem Verzeichnis namens cluster1, cluster2, und cluster3:

bash
$ kubectl create secret generic cacerts -n istio-system \
 --kubeconfig=kubeconfig-<cluster-name>
 --from-file=<cluster-folder>/ca-cert.pem \
 --from-file=<cluster-folder>/ca-key.pem \
 --from-file=<cluster-folder>/root-cert.pem \
 --from-file=<cluster-folder>/cert-chain.pem

Sie sollten die Befehle mit den folgenden Variablen ausführen:

| cluster name | folder name |
| :----------: | :---------: |
|      ap      |  cluster1   |
|      us      |  cluster2   |
|      eu      |  cluster3   |

Damit sind Sie endlich bereit, istiod zu installieren:

bash
$ helm install istiod istio/istiod \
 --kubeconfig=kubeconfig-<insert-cluster-name> \
 --namespace istio-system \
 --version=1.14.1 \
 --set global.meshID=mesh1 \
 --set global.multiCluster.clusterName=<insert-cluster-name> \
 --set global.network=<insert-network-name>

Wiederholen Sie den Befehl dreimal mit den folgenden Variablen:

| cluster name | network name |
| :----------: | :----------: |
|      ap      |   network1   |
|      us      |   network2   |
|      eu      |   network3   |

Sie sollten auch den Istio-Namensraum mit einer Topologie-Annotation versehen:

bash
$ kubectl label namespace istio-system topology.istio.io/network=network1 --kubeconfig=kubeconfig-ap
$ kubectl label namespace istio-system topology.istio.io/network=network2 --kubeconfig=kubeconfig-us
$ kubectl label namespace istio-system topology.istio.io/network=network3 --kubeconfig=kubeconfig-eu

Ist das alles?

Fast.

Tunneln des Datenverkehrs mit einem Ost-West-Gateway

Sie brauchen noch:

  • ein Gateway, um den Verkehr von einem Cluster zum anderen zu leiten; und
  • einen Mechanismus zur Ermittlung von IP-Adressen in anderen Clustern.
Das Diagramm zeigt, wie der Istio-Multicluster die Endpunkte erkennt und das Ost-West-Gateway zwischen den Pods installiert.
Istio-Multicluster: Erkennen von Endpunkten und Installieren des Ost-West-Gateways.

Für das Gateway können Sie Helm verwenden, um es zu installieren:

bash
$ helm install eastwest-gateway istio/gateway \
 --kubeconfig=kubeconfig-<insert-cluster-name> \
 --namespace istio-system \
 --version=1.14.1 \
 --set labels.istio=eastwestgateway \
 --set labels.app=istio-eastwestgateway \
 --set labels.topology.istio.io/network=istio-eastwestgateway \
 --set labels.topology.istio.io/network=istio-eastwestgateway \
 --set networkGateway=<insert-network-name> \
 --set service.ports[0].name=status-port \
 --set service.ports[0].port=15021 \
 --set service.ports[0].targetPort=15021 \
 --set service.ports[1].name=tls \
 --set service.ports[1].port=15443 \
 --set service.ports[1].targetPort=15443 \
 --set service.ports[2].name=tls-istiod \
 --set service.ports[2].port=15012 \
 --set service.ports[2].targetPort=15012 \
 --set service.ports[3].name=tls-webhook \
 --set service.ports[3].port=15017 \
 --set service.ports[3].targetPort=15017 \

Wiederholen Sie den Befehl dreimal mit den folgenden Variablen:

| cluster name | network name |
| :----------: | :----------: |
|      ap      |   network1   |
|      us      |   network2   |
|      eu      |   network3   |

Stellen Sie dann für jeden Cluster ein Gateway mit der folgenden Ressource bereit:

yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: cross-network-gateway
spec:
 selector:
   istio: eastwestgateway
 servers:
   - port:
       number: 15443
       name: tls
       protocol: TLS
     tls:
       mode: AUTO_PASSTHROUGH
     hosts:
       - "*.local"

Sie können die Datei den Clustern mit übergeben:

bash
$ kubectl apply -f expose.yaml --kubeconfig=kubeconfig-eu
$ kubectl apply -f expose.yaml --kubeconfig=kubeconfig-ap
$ kubectl apply -f expose.yaml --kubeconfig=kubeconfig-us

Für die Erkennungsmechanismen müssen Sie die Anmeldedaten jedes Clusters gemeinsam nutzen. Dies ist notwendig, da die Cluster einander nicht kennen.

Um andere IP-Adressen zu ermitteln, müssen sie auf andere Cluster zugreifen und diese als mögliche Ziele für den Datenverkehr registrieren. Zu diesem Zweck müssen Sie ein Kubernetes-Geheimnis mit der kubeconfig-Datei für die anderen Cluster erstellen.

Istio verwendet diese, um sich mit den anderen Clustern zu verbinden, die Endpunkte zu erkennen und die Envoy-Proxys anzuweisen, den Datenverkehr weiterzuleiten.

Sie benötigen drei Geheimnisse:

yaml
apiVersion: v1
kind: Secret
metadata:
 labels:
   istio/multiCluster: true
 annotations:
   networking.istio.io/cluster: <insert cluster name>
 name: "istio-remote-secret-<insert cluster name>"
type: Opaque
data:
 <insert cluster name>: <insert cluster kubeconfig as base64>

Sie sollten die drei Geheimnisse mit den folgenden Variablen erstellen:

| cluster name | secret filename |  kubeconfig   |
| :----------: | :-------------: | :-----------: |
|      ap      |  secret1.yaml   | kubeconfig-ap |
|      us      |  secret2.yaml   | kubeconfig-us |
|      eu      |  secret3.yaml   | kubeconfig-eu |

Nun sollten Sie die Geheimnisse an den Cluster übermitteln und dabei darauf achten, dass das AP-Geheimnis nicht an den AP-Cluster übermittelt wird.

Die Befehle sollten die folgenden sein:

bash
$ kubectl apply -f secret2.yaml -n istio-system --kubeconfig=kubeconfig-ap
$ kubectl apply -f secret3.yaml -n istio-system --kubeconfig=kubeconfig-ap
 
$ kubectl apply -f secret1.yaml -n istio-system --kubeconfig=kubeconfig-us
$ kubectl apply -f secret3.yaml -n istio-system --kubeconfig=kubeconfig-us
 
$ kubectl apply -f secret1.yaml -n istio-system --kubeconfig=kubeconfig-eu
$ kubectl apply -f secret2.yaml -n istio-system --kubeconfig=kubeconfig-eu

Und das ist alles!

Sie können die Einrichtung nun testen.

Testen der Multicluster-Vernetzung

Lassen Sie uns einen Einsatz für einen Schlaf-Pod erstellen.

Sie verwenden diesen Pod, um eine Anfrage an die zuvor erstellte Hello-Bereitstellung zu stellen:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: sleep
spec:
 selector:
   matchLabels:
     app: sleep
 template:
   metadata:
     labels:
       app: sleep
   spec:
     terminationGracePeriodSeconds: 0
     containers:
       - name: sleep
         image: curlimages/curl
         command: ["/bin/sleep", "3650d"]
         imagePullPolicy: IfNotPresent
         volumeMounts:
           - mountPath: /etc/sleep/tls
             name: secret-volume
     volumes:
       - name: secret-volume
         secret:
           secretName: sleep-secret
           optional: true

Sie können die Bereitstellung mit erstellen:

bash
$ kubectl apply -f sleep.yaml --kubeconfig=karmada-config

Da es für diese Bereitstellung keine Richtlinie gibt, wird Karmada sie nicht bearbeiten und in der Schwebe lassen. Sie können die Richtlinie ändern, um die Bereitstellung mit aufzunehmen:

yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
 name: hello-propagation
spec:
 resourceSelectors:
   - apiVersion: apps/v1
     kind: Deployment
     name: hello
   - apiVersion: v1
     kind: Service
     name: hello
   - apiVersion: apps/v1
     kind: Deployment
     name: sleep
 placement:
   clusterAffinity:
     clusterNames:
       - eu
       - ap
       - us
   replicaScheduling:
     replicaDivisionPreference: Weighted
     replicaSchedulingType: Divided
     weightPreference:
       staticWeightList:
         - targetCluster:
             clusterNames:
               - us
           weight: 2
         - targetCluster:
             clusterNames:
               - ap
           weight: 2
         - targetCluster:
             clusterNames:
               - eu
           weight: 1

Sie können die Richtlinie mit anwenden:

bash
$ kubectl apply -f policy.yaml --kubeconfig=karmada-config

Mit können Sie herausfinden, wo der Pod eingesetzt wurde:

bash
$ kubectl get pods --kubeconfig=kubeconfig-eu
$ kubectl get pods --kubeconfig=kubeconfig-ap
$ kubectl get pods --kubeconfig=kubeconfig-us

Angenommen, der Pod ist auf dem US-Cluster gelandet, führen Sie nun folgenden Befehl aus

Now, assuming the pod landed on the US cluster, execute the following command:
bash
for i in {1..10}
do
 kubectl exec --kubeconfig=kubeconfig-us -c sleep \
   "$(kubectl get pod --kubeconfig=kubeconfig-us -l \
   app=sleep -o jsonpath='{.items[0].metadata.name}')" \
   -- curl -sS hello:5000 | grep REGION
done

Sie werden feststellen, dass die Antwort von verschiedenen Schoten aus verschiedenen Regionen kommt!

Auftrag erledigt!

Wie geht es jetzt weiter?

Diese Konfiguration ist recht einfach und lässt einige weitere Funktionen vermissen, die Sie wahrscheinlich einbauen möchten:

Wir fassen zusammen, was wir in diesem Beitrag behandelt haben:

  • die Verwendung von Karmada zur Kontrolle mehrerer Cluster;
  • Festlegung von Richtlinien zur Planung von Workloads über mehrere Cluster hinweg;
  • Nutzung von Istio zur Überbrückung der Vernetzung von mehreren Clustern und
  • wie Istio den Datenverkehr abfängt und ihn an andere Cluster weiterleitet.

Sie können einen vollständigen Überblick über die Skalierung von Kubernetes über verschiedene Regionen hinweg sowie über andere Skalierungsmethoden erhalten, indem Sie sich für unsere Webinar-Reihe anmelden und diese auf Abruf ansehen.


Kommentare

Kommentar abgeben

Ihre E-Mail Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit *gekennzeichnet