1. Willkommen
Vielen Dank, dass Sie am Istio Multi Cloud Burst Codelab von Google teilnehmen.Für dieses Codelab benötigen Sie praktische Erfahrung mit Kubernetes, Node und Go auf Anfängerniveau. Voraussetzungen
|
|
Lerninhalte
- Kubernetes-Cluster in GKE erstellen
- Istio mit Helm in einem Kubernetes-Cluster installieren
- Istio Multicluster mit Helm installieren
- Webanwendung aus der Quelle in Kubernetes bereitstellen
- Traffic-Routing-Regeln für Istio schreiben und anwenden
- Prometheus-Messwerte
- Container-Images in einem Kubernetes-Cluster erstellen und per Push übertragen
2. Einrichtung
Sie können dieses Codelab auf einer der folgenden Plattformen ausführen:
- Google Cloud Shell (empfohlen): Browser-Shell mit vorinstallierten Tools
- auf Ihrem Laptop (folgen Sie der Anleitung unten)
Mit der Google Cloud Platform beginnen
- Wenn Sie noch kein GCP-Konto haben, holen Sie sich eine kostenlose Nutzerkontokarte vom Dozenten ab.
- Rufen Sie die Google Cloud Console auf und klicken Sie auf „Projekt auswählen“:

- Notieren Sie sich die ID des Projekts und klicken Sie dann darauf, um es auszuwählen:

Option 1: Google Cloud Shell verwenden (empfohlen)
Cloud Shell bietet eine Befehlszeile in Ihrem Browser mit den erforderlichen Tools, die automatisch in Ihrem Google Cloud-Konto authentifiziert werden. Wenn Sie diese Übung nicht in Cloud Shell ausführen möchten, fahren Sie mit dem nächsten Abschnitt fort.
Rufen Sie die Cloud Console auf und klicken Sie rechts oben in der Symbolleiste auf „Cloud Shell aktivieren“:

Cloud Shell Tools hinzufügen
- Installieren Sie
kubectx****, indem Sie die Bash-Scripts von hier an einen Ort in $PATH herunterladen. - Installieren Sie
helm****: Folgen Sie dazu dieser Anleitung.
Alternativ können Sie die folgenden Befehle ausführen, um beide in ~/.bin zu installieren und zu $PATH hinzuzufügen:
mkdir -p ~/.bin && \
cd ~/.bin && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubectx && \
chmod +x kubectx && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubens && \
chmod +x kubens && \
curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.12.0-linux-amd64.tar.gz && \
tar xzf helm-v2.12.0-linux-amd64.tar.gz && \
rm helm-v2.12.0-linux-amd64.tar.gz && \
mv linux-amd64/helm ./helm && \
rm -r linux-amd64 && \
export PATH=${HOME}/.bin:${PATH}
Einige praktische Tipps, die die Verwendung von Cloud Shell erleichtern:
1. Trennen Sie die Shell in einem neuen Fenster: |
|
2. Dateieditor verwenden : Klicken Sie oben rechts auf das Stiftsymbol, um einen Dateieditor im Browser zu starten. Das ist nützlich, da wir Code-Snippets in Dateien kopieren werden. |
|
3. Neue Tabs öffnen:Wenn Sie mehr als einen Terminalprompt benötigen. |
|
4. Text vergrößern : Die Standardschriftgröße in Cloud Shell ist möglicherweise zu klein zum Lesen. | Strg + unter Linux/Windows bzw.⌘ + unter macOS |
Option 2: Laptop einrichten (nicht empfohlen)
Wenn Sie Ihre eigene Workstation-Umgebung lieber als Cloud Shell verwenden, richten Sie die folgenden Tools ein:
- Installieren Sie
gcloud:(in Cloud Shell vorinstalliert). Folgen Sie der Anleitung, umgcloudauf Ihrer Plattform zu installieren. Damit erstellen wir einen Kubernetes-Cluster. - Installieren Sie
kubectl:(in Cloud Shell vorinstalliert). Führen Sie den folgenden Befehl aus, um Folgendes zu installieren:
gcloud components install kubectl
Führen Sie den folgenden Befehl aus, um gcloud zu authentifizieren. Sie werden aufgefordert, sich mit Ihrem Google-Konto anzumelden. Wählen Sie dann das vorab erstellte Projekt (siehe oben) als Standardprojekt aus. Sie können die Konfiguration einer Compute-Zone überspringen:
gcloud init
- Installieren Sie
curl:. Dieser ist auf den meisten Linux-/macOS-Systemen vorinstalliert. Sie haben es wahrscheinlich schon. Andernfalls können Sie im Internet nach einer Anleitung zur Installation suchen. - Installieren Sie
kubectx****, indem Sie die Bash-Scripts von hier an einen Ort in $PATH herunterladen. - Installieren Sie
helm****: Folgen Sie dazu dieser Anleitung.
3. GCP-Projekt einrichten
Aktivieren Sie die APIs GKE (Google Kubernetes Engine), GCR (Google Container Registry) und GCB (Google Cloud Build) in Ihrem Projekt:
gcloud services enable \ cloudapis.googleapis.com \ container.googleapis.com \ containerregistry.googleapis.com \ cloudbuild.googleapis.com
Umgebungsvariablen einrichten
Wir werden während der Einrichtung viel mit unserem Google Cloud-Projekt arbeiten. Legen Sie dazu eine Umgebungsvariable fest, die Sie schnell zur Hand haben.
export GCLOUD_PROJECT=$(gcloud config get-value project)
In diesem Workshop erstellen wir Code und Konfigurationsdateien. Erstellen wir also ein Projektverzeichnis und wechseln wir dorthin.
mkdir -p src/istio-burst && \ cd src/istio-burst && \ export proj=$(pwd)
4. „Primären“ Kubernetes-Cluster erstellen
Mit der Google Kubernetes Engine (GKE) können Sie ganz einfach verwaltete Kubernetes-Cluster erstellen.
Mit dem folgenden Befehl wird ein Kubernetes-Cluster erstellt:
- mit dem Namen „primary“,
- in der Zone „us-west1-a“,
- Die neueste verfügbare Kubernetes-Version,
- mit 4 ursprünglichen Knoten
export cluster=primary
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "4" --network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias
Das kann etwa 5 Minuten dauern. Sie können sich die Erstellung des Clusters in der Cloud Console ansehen.
Nachdem der Kubernetes-Cluster erstellt wurde, konfiguriert gcloud kubectl mit den Anmeldedaten, die auf den Cluster verweisen.
gcloud container clusters get-credentials $cluster --zone=$zone
Sie sollten kubectl jetzt mit Ihrem neuen Cluster verwenden können.
Führen Sie den folgenden Befehl aus, um die Kubernetes-Knoten Ihres Clusters aufzulisten. Sie sollten den Status „Bereit“ haben:
kubectl get nodes
Kubeconfig-Namen zur besseren Verwendung ändern
Wir wechseln häufig zwischen Kontexten, daher ist ein kurzer Alias für unsere Cluster praktisch.
Mit diesem Befehl wird der soeben erstellte kubeconfig-Eintrag in primary umbenannt.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Berechtigungen festlegen
Zum Bereitstellen von Istio müssen Sie Clusteradministrator sein. Mit diesem Befehl wird die E-Mail-Adresse, die mit Ihrem Google Cloud-Konto verknüpft ist, als Clusteradministrator festgelegt.
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
5. Burst-Cluster erstellen
Mit dem folgenden Befehl wird ein Kubernetes-Cluster erstellt:
- mit dem Namen „burst“,
- in der Zone „us-west1-a“,
- Die neueste verfügbare Kubernetes-Version,
- Mit 1 Anfangsknoten
- Autoscaling für bis zu 5 Knoten aktiviert
export cluster=burst
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "1" --enable-autoscaling --min-nodes=1 --max-nodes=5 \
--network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias
Das kann etwa 5 Minuten dauern. Sie können sich die Erstellung des Clusters in der Cloud Console ansehen.
Nachdem der Kubernetes-Cluster erstellt wurde, konfiguriert gcloud kubectl mit den Anmeldedaten, die auf den Cluster verweisen.
gcloud container clusters get-credentials $cluster --zone=$zone
Sie sollten kubectl jetzt mit Ihrem neuen Cluster verwenden können.
Führen Sie den folgenden Befehl aus, um die Kubernetes-Knoten Ihres Clusters aufzulisten. Sie sollten den Status „Bereit“ haben:
kubectl get nodes
Kubeconfig-Namen zur besseren Nutzung ändern
Mit diesem Befehl wird der gerade erstellte kubeconfig-Eintrag in burst geändert.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Berechtigungen festlegen
Zum Bereitstellen von Istio Remote müssen Sie Clusteradministrator sein. Mit diesem Befehl wird die E-Mail-Adresse, die mit Ihrem Google Cloud-Konto verknüpft ist, als Clusteradministrator festgelegt.
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
6. Firewallregeln anwenden
Damit unsere beiden Cluster miteinander kommunizieren können, müssen wir eine Firewallregel erstellen.
Führen Sie die folgenden Befehle aus, um eine Firewallregel in der Google Cloud-Plattform zu erstellen, die es unseren Clustern ermöglicht, zu kommunizieren.
function join_by { local IFS="$1"; shift; echo "$*"; }
ALL_CLUSTER_CIDRS=$(gcloud container clusters list \
--filter="(name=burst OR name=primary) AND zone=$zone" \
--format='value(clusterIpv4Cidr)' | sort | uniq)
ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}"))
ALL_CLUSTER_NETTAGS=$(gcloud compute instances list \
--filter="(metadata.cluster-name=burst OR metadata.cluster-name=primary) AND metadata.cluster-location=us-west1-a" \
--format='value(tags.items.[0])' | sort | uniq)
ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
gcloud compute firewall-rules create istio-multicluster-test-pods \
--allow=tcp,udp,icmp,esp,ah,sctp \
--direction=INGRESS \
--priority=900 \
--source-ranges="${ALL_CLUSTER_CIDRS}" \
--target-tags="${ALL_CLUSTER_NETTAGS}" --quiet
Wir haben beide Cluster eingerichtet und können unsere Anwendung und Istio darauf bereitstellen.
7. Einführung in Istio
Was ist Istio?
Istio ist eine Service Mesh-Steuerungsebene, die Dienste „verbinden, schützen, steuern und beobachten“ soll. Dies geschieht auf unterschiedliche Weise, vor allem aber durch das Einfügen eines Proxy-Containers ( Envoy) als Sidecar in jeden Ihrer bereitgestellten Kubernetes-Pods. Der Proxy-Container steuert die gesamte Netzwerkkommunikation zwischen Mikrodiensten in Kombination mit einem allgemeinen Richtlinien- und Telemetrie-Hub ( Mixer).

Diese Richtlinien können unabhängig von Ihren Kubernetes-Bereitstellungen und ‑Diensten angewendet werden. Das bedeutet, dass der Netzwerkbetreiber die Netzwerkaktivitäten beobachten, Netzwerkrichtlinien einschränken, umleiten oder neu schreiben kann, ohne die zugehörigen Anwendungen neu bereitzustellen.
Zu den von Istio unterstützten Funktionen zur Trafficverwaltung gehören:
- Schutzschalter
- Prozentuale Trafficaufteilung
- URL-Umschreibung
- TLS-Terminierung
- Systemdiagnosen
- Load Balancing
In diesem Workshop konzentrieren wir uns auf die prozentuale Aufteilung des Traffics.
Istio-Begriffe, mit denen wir arbeiten werden
VirtualService
Ein VirtualService definiert eine Reihe von Traffic-Routingregeln, die angewendet werden sollen, wenn ein Host adressiert wird.
Gateway
Ein Gateway ist ein Load Balancer, der am Rand des Mesh-Netzwerks ausgeführt wird und eingehende oder ausgehende HTTP/TCP-Verbindungen empfängt. Gateways können Ports, SNI-Konfigurationen usw. angeben.
DestinationRule
Mit einer DestinationRule werden Richtlinien definiert, die auf Traffic angewendet werden, der nach dem Routing für einen Dienst bestimmt ist. Sie geben die Konfiguration für das Load Balancing, die Größe des Verbindungspools aus dem Sidecar und die Einstellungen für die Anomalieerkennung an.
Istio Multicluster
Sie haben vielleicht beim Erstellen unserer beiden Cluster bemerkt, dass unser primary-Cluster 4 Knoten ohne Autoscaling und unser burst-Cluster 1 Knoten mit Autoscaling auf bis zu 5 Knoten hatte.
Dafür gibt es zwei Gründe.
Zuerst möchten wir ein On-Premise-zu-Cloud-Szenario simulieren. In einer On-Premise-Umgebung haben Sie keinen Zugriff auf Autoscaling-Cluster, da Sie eine feste Infrastruktur haben.
Zweitens: Für die Ausführung von Istio ist eine Konfiguration mit vier Knoten (wie oben definiert) die Mindestanforderung. Das wirft die Frage auf: Wenn Istio mindestens vier Knoten erfordert, wie kann unser burst-Cluster Istio mit nur einem Knoten ausführen? Die Antwort ist, dass bei Istio Multicluster ein viel kleinerer Teil der Istio-Dienste installiert wird und mit der Istio-Installation im primären Cluster kommuniziert wird, um die Richtlinienregeln abzurufen und Telemetrieinformationen zu veröffentlichen.
8. Anwendungsarchitektur – Übersicht
Komponenten – Übersicht
Wir stellen eine dreistufige Anwendung mit NodeJS und Redis bereit.
Arbeiter
Die Worker-Anwendung ist in NodeJS geschrieben und überwacht eingehende POST-HTTP-Anfragen. Sie führt einen Hash-Vorgang darauf aus und fügt dem Hash, falls eine Umgebungsvariable namens PREFIX definiert ist, diesen Wert vorangestellt hinzu. Nachdem der Hash berechnet wurde, sendet die Anwendung das Ergebnis über den Kanal „calculation“ an den angegebenen Redis-Server.
Wir verwenden die Umgebungsvariable PREFIX später, um die Multicluster-Funktion zu demonstrieren.
Zur Information: Dies sind die Pakete, die von der Anwendung verwendet werden.
body-parser:Ermöglicht das Parsen von HTTP-Anfragencors:Ermöglicht die Verwendung von Cross-Origin Resource Sharingdotenv:Einfaches Parsen von Umgebungsvariablenexpress:Einfaches Websitehostingioredis:Clientbibliothek zur Kommunikation mit Redis-Datenbankenmorgan:Bietet ein gut strukturiertes Protokoll
Frontend
Unser Front-End ist ebenfalls eine NodeJS-Anwendung, die eine Webseite mit Express hostet. Es wird eine vom Nutzer eingegebene Häufigkeit verwendet und Anfragen werden mit dieser Rate an unsere worker-Anwendung gesendet. Diese Anwendung abonniert auch Nachrichten auf einem Redis-Kanal namens „calculation“ und zeigt die Ergebnisse auf einer Webseite an.
Die Anwendung verwendet die folgenden Abhängigkeiten.
body-parser:Ermöglicht das Parsen von HTTP-Anfragendotenv:Einfaches Parsen von Umgebungsvariablenexpress:Einfaches Websitehostingioredis:Clientbibliothek zur Kommunikation mit Redis-Datenbankenmorgan:Bietet gut strukturierte Protokollerequest:Ermöglicht das Stellen von HTTP-Anfragensocket.io:Ermöglicht die bidirektionale Kommunikation von der Webseite zum Server
Auf dieser Webseite wird Bootstrap für das Styling verwendet. Sie sieht dann so aus:

Architekturdiagramm

Bereitstellungsdiagramm
Wir stellen unsere endgültige Anwendung in den beiden von uns erstellten Clustern bereit. Im Cluster primary sind alle Komponenten (frontend, worker und Redis) bereitgestellt, im Cluster burst jedoch nur die Anwendung worker.
Das folgende Diagramm zeigt die beiden Cluster. Die rot umrandeten Felder sind Kubernetes-Dienste, die blauen Felder sind Kubernetes-Bereitstellungen. Die gelben Felder stehen für unsere Istio-Installation.
Beachten Sie, dass im Cluster burst noch immer ein Dienst für Redis bereitgestellt wird, obwohl es im Cluster kein Redis-Deployment gibt. Dieser Dienst muss sich im Cluster befinden, damit Kubernetes DNS die Anfrage auflösen kann. Wenn die Anfrage jedoch tatsächlich gestellt wird, leitet der Istio-Proxy die Anfrage an die Redis-Bereitstellung im primary-Cluster weiter.
Die endgültige Anwendung hat ein zusätzliches Deployment, das im primary-Cluster namens istiowatcher. ausgeführt wird. So können wir den Traffic automatisch auf die burst umleiten, wenn er einen bestimmten Grenzwert überschreitet.

9. Anwendungsbereitstellungsdateien erstellen
Wir müssen eine Reihe von Kubernetes-Manifesten erstellen, um unsere Anwendung bereitzustellen.
Wechseln Sie in das Stammverzeichnis des Projekts und erstellen Sie einen neuen Ordner mit dem Namen kubernetes.
mkdir ${proj}/kubernetes && cd ${proj}/kubernetes
frontend.yaml schreiben
Dadurch werden sowohl ein Kubernetes-Deployment als auch ein Dienst zum Zugriff auf unser Frontend-Image erstellt.
Fügen Sie Folgendes in frontend.yaml ein:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend-deployment
labels:
app: frontend
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: gcr.io/istio-burst-workshop/frontend
ports:
- containerPort: 8080
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8080
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/"
port: 8080
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-liveness-probe"
env:
- name: PORT
value: "8080"
- name: PROCESSOR_URL
value: "http://worker-service"
- name: REDIS_URL
value: "redis-cache-service:6379"
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080
Wichtige Informationen in der Deployment
- Wir haben den Port, auf dem die Anwendung ausgeführt wird, als
8080festgelegt. - Wir haben die Adresse für den Worker auf „
http://worker-service“ festgelegt und verwenden die integrierte DNS-Funktion von Kubernetes, um den resultierenden Dienst aufzulösen. - Wir haben die Adresse für unsere
REDIS_URLauf „redis-cache-service:6379“ festgelegt und verwenden die integrierte DNS-Funktion von Kubernetes, um die resultierenden IP-Adressen aufzulösen. - Außerdem haben wir
liveness- undreadiness-Prüfungen für den Container festgelegt, damit Kubernetes weiß, wann der Container einsatzbereit ist.
worker-service.yaml schreiben
Wir schreiben die Kubernetes-Dienstdefinition in einer separaten Datei als die Bereitstellungsdefinition, da wir diesen Dienst in mehreren Clustern wiederverwenden, aber für jeden Cluster eine andere Bereitstellung schreiben.
Fügen Sie Folgendes in worker-service.yaml ein:
apiVersion: v1
kind: Service
metadata:
name: worker-service
spec:
type: ClusterIP
selector:
app: worker
ports:
- name: http
port: 80
targetPort: 8081
worker-primary.yaml schreiben
Das ist die Bereitstellung von worker, die wir an den primären Cluster pushen.
Fügen Sie Folgendes in worker-primary.yaml ein:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: worker-deployment
labels:
app: worker
spec:
replicas: 1
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
cluster-type: primary-cluster
spec:
containers:
- name: worker
image: gcr.io/istio-burst-workshop/worker
imagePullPolicy: Always
ports:
- containerPort: 8081
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-liveness-probe"
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
Beachten Sie, dass wir hier dasselbe Muster verfolgen, indem wir liveness- und readiness-Sonden bereitstellen und die Umgebungsvariablen PORT und REDIS_URL für unsere Anwendung angeben.
Bei dieser Bereitstellung fällt außerdem auf, dass die Umgebungsvariable PREFIX fehlt. Das bedeutet, dass unsere Berechnungsergebnisse Roh-Hashes sind, also ohne Präfix.
Der letzte wichtige Punkt dieser Bereitstellung ist das cluster-type: primary-cluster-Label. Das verwenden wir später, wenn wir das Traffic-Routing in Istio Multicluster behandeln.
redis.yaml schreiben
Die Kommunikation von unserem Worker zurück zum Frontend erfolgt über einen Redis-Kanal. Daher müssen wir eine Redis-Anwendung in unserem Cluster bereitstellen.
Fügen Sie Folgendes in redis.yaml ein:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: redis-cache
spec:
template:
metadata:
labels:
app: redis-cache
spec:
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
readinessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
livenessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
volumeMounts:
- mountPath: /data
name: redis-data
resources:
limits:
memory: 256Mi
cpu: 125m
requests:
cpu: 70m
memory: 200Mi
volumes:
- name: redis-data
emptyDir: {}
Dies ist eine semi-standardmäßige Bereitstellung einer Redis-Anwendung. Es richtet einen Container auf Grundlage des redis:alpine-Images ein, stellt die entsprechenden Ports bereit und legt sinnvolle Ressourcenlimits fest.
redis-service.yaml schreiben
Wir benötigen einen Kubernetes-Dienst, um mit unserer Redis-Anwendung zu kommunizieren.
Fügen Sie Folgendes in redis-service.yaml ein:
apiVersion: v1
kind: Service
metadata:
name: redis-cache-service
spec:
type: ClusterIP
selector:
app: redis-cache
ports:
- port: 6379
targetPort: 6379
Dadurch wird der Dienst redis-cache-service für den Zugriff auf unsere Redis-Bereitstellung bereitgestellt.
10. Anwendung bereitstellen
Nachdem unsere Images in GCR gepusht und unsere Kubernetes-Manifeste geschrieben wurden, ist es an der Zeit, unsere Anwendung bereitzustellen und zu sehen, wie sie funktioniert.
Führen Sie die folgenden Befehle aus, um die Anwendung bereitzustellen.
- Prüfen, ob wir uns im richtigen Cluster befinden
kubectx primary
- Redis-Cache bereitstellen
kubectl apply -f redis.yaml
- Redis-Dienst bereitstellen
kubectl apply -f redis-service.yaml
- Frontend bereitstellen
kubectl apply -f frontend.yaml
- Worker bereitstellen
kubectl apply -f worker-primary.yaml
- Worker-Dienst bereitstellen
kubectl apply -f worker-service.yaml
Wir haben unsere Anwendung in GKE bereitgestellt. Glückwunsch!
Testen
Warten, bis die Pods online sind
kubectl get pods -w
Sobald alle Pods den Status „Running“ (Laufend) haben, drücken Sie Strg + C.
NAME READY STATUS RESTARTS AGE frontend-deployment-695d95fbf7-76sd8 1/1 Running 0 2m redis-cache-7475999bf5-nxj8x 1/1 Running 0 2m worker-deployment-5b9cf9956d-g975p 1/1 Running 0 2m
Wie Sie sehen, haben wir unser Frontend nicht über einen Load Balancer freigegeben. Das liegt daran, dass wir später über Istio auf die Anwendung zugreifen. Um zu testen, ob alles funktioniert, verwenden wir kubectl port-forward.. Führen Sie den folgenden Befehl aus, um Port 8080 auf Ihrem lokalen Computer (oder in Cloud Shell) an Port 8080 weiterzuleiten, auf dem die frontend-Bereitstellung ausgeführt wird.
kubectl port-forward \
$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}') \
8080:8080
Lokaler Betrieb: Öffnen Sie einen Webbrowser und rufen Sie http://localhost:8080 auf.
Wenn Sie die Anwendung in Cloud Shell ausführen:Klicken Sie auf die Schaltfläche „Webvorschau“ und wählen Sie „Vorschau auf Port 8080“ aus.

Das Frontend sollte angezeigt werden. Wenn Sie in das Feld „Häufigkeit“ eine Zahl eingeben, sollten Hash-Werte angezeigt werden.

Herzlichen Glückwunsch, alles ist eingerichtet.
Drücken Sie Ctrl+C, um die Portweiterleitung zu beenden.
11. Bereitgestellte Anwendung bereinigen
Wir wenden Istio auf unseren Cluster an und stellen dann unsere Anwendung neu bereit. Bereinigen wir also zuerst unsere aktuelle Anwendung.
Führen Sie die folgenden Befehle aus, um alle gerade erstellten Bereitstellungen und Dienste zu löschen.
redis-cache-servicelöschen
kubectl delete -f redis-service.yaml
redislöschen
kubectl delete -f redis.yaml
frontendlöschen
kubectl delete -f frontend.yaml
workerlöschen
kubectl delete -f worker-primary.yaml
worker-servicelöschen
kubectl delete -f worker-service.yaml
12. Istio im primären Cluster installieren
Istio abrufen
Die Istio-Releases werden auf GitHub gehostet. Mit den folgenden Befehlen wird die Version 1.0.0 von Istio heruntergeladen und entpackt.
- Zum Stammverzeichnis des Projekts wechseln
cd ${proj}
- Archiv herunterladen
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
- Archiv extrahieren und entfernen
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz
Istio-Vorlage erstellen
Mit dem folgenden Helm-Befehl wird die Vorlage erstellt, mit der Istio in Ihrem Cluster installiert wird.
helm template istio-1.0.0/install/kubernetes/helm/istio \ --name istio --namespace istio-system \ --set prometheus.enabled=true \ --set servicegraph.enabled=true > istio-primary.yaml
Dadurch wird im aktuellen Verzeichnis eine Datei mit dem Namen istio-primary.yaml erstellt, die alle Definitionen und Spezifikationen enthält, die zum Bereitstellen und Ausführen von Istio erforderlich sind.
Beachten Sie die beiden --set-Parameter. Dadurch wird dem Istio-System Prometheus- und ServiceGraph-Unterstützung hinzugefügt. Wir verwenden den Prometheus-Dienst später im Lab.
Istio bereitstellen
Um Istio bereitzustellen, müssen wir zuerst einen Namespace mit dem Namen istio-system erstellen, in dem die Istio-Bereitstellungen und ‑Dienste ausgeführt werden können.
kubectl create namespace istio-system
Und schließlich wenden wir die istio-primary.yaml-Datei an, die wir mit Helm erstellt haben.
kubectl apply -f istio-primary.yaml
Standard-Namespace für Label
Istio fügt jedem Ihrer Deployments einen Sidecar-Proxydienst hinzu. Dies geschieht auf Opt-in-Basis. Wir müssen also unseren Namespace default mit istio-injection=enabled labeln, damit Istio den Sidecar automatisch für uns einfügen kann.
kubectl label namespace default istio-injection=enabled
Glückwunsch! Wir haben einen Cluster mit Istio eingerichtet, in dem wir unsere Anwendung bereitstellen können.
13. Anwendung mit Istio-Traffic-Management bereitstellen
Istio-Konfigurationsdateien für die Trafficverwaltung erstellen
Istio funktioniert ähnlich wie Kubernetes, da auch hier YAML-Dateien zur Konfiguration verwendet werden. Daher müssen wir eine Reihe von Dateien erstellen, in denen Istio mitgeteilt wird, wie der Traffic freigegeben und weitergeleitet werden soll.
Erstellen Sie ein Verzeichnis mit dem Namen istio-manifests und wechseln Sie dorthin.
mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests
frontend-gateway.yaml schreiben
Mit dieser Datei wird unser Kubernetes-Cluster ähnlich wie ein GKE-Load Balancer freigegeben und der gesamte eingehende Traffic wird an unseren Frontend-Dienst weitergeleitet.
Erstellen Sie eine Datei mit dem Namen frontend-gateway.yaml und fügen Sie Folgendes ein:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: frontend-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: frontend-ingress-virtual-service
spec:
hosts:
- "*"
gateways:
- frontend-gateway
http:
- route:
- destination:
host: frontend-service
port:
number: 80
redis-virtualservice.yaml schreiben
Erstellen Sie eine Datei mit dem Namen redis-virtualservice.yaml und fügen Sie Folgendes ein:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: redis-virtual-service
spec:
hosts:
- redis-cache-service
gateways:
- mesh
tcp:
- route:
- destination:
host: redis-cache-service.default.svc.cluster.local
worker-virtualservice.yaml schreiben
Erstellen Sie eine Datei mit dem Namen worker-virtualservice.yaml und fügen Sie Folgendes ein:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
port:
number: 80
Istio-Richtlinien für die Trafficverwaltung bereitstellen
Die Bereitstellung der Istio-Richtlinien erfolgt auf die gleiche Weise wie bei anderen Kubernetes-Ressourcen, wobei kubectl apply
- Unser Gateway anwenden
kubectl apply -f frontend-gateway.yaml
- Redis-VirtualService anwenden
kubectl apply -f redis-virtualservice.yaml
- Worker-VirtualService anwenden
kubectl apply -f worker-virtualservice.yaml
Anwendung bereitstellen
- Kehren Sie zum Verzeichnis
kuberneteszurück.
cd ${proj}/kubernetes
- Redis-Cache bereitstellen
kubectl apply -f redis.yaml
- Redis-Dienst bereitstellen
kubectl apply -f redis-service.yaml
- Frontend bereitstellen
kubectl apply -f frontend.yaml
- Worker bereitstellen
kubectl apply -f worker-primary.yaml
- Worker-Dienst bereitstellen
kubectl apply -f worker-service.yaml
Bestätigen
Wir haben unsere Anwendung in einem Cluster mit Istio und Traffic-Management-Richtlinien neu bereitgestellt.
Warten Sie, bis alle Arbeitslasten online sind
Sobald alle online sind, rufen Sie das Ingress-Gateway ab, das wir in frontend-ingressgateway.yaml konfiguriert haben.
$ kubectl -n istio-system get svc istio-ingressgateway NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.36.3.112 35.199.158.10 80:31380/TCP,
Rufen Sie entweder die Adresse <EXTERNAL-IP> auf oder curlen Sie sie. Das Frontend sollte angezeigt werden.
$ curl 35.199.158.10
<!doctype html>
<html>
<head>
<title>String Hashr</title>
<!-- Bootstrap -->
...
14. Istio in einem Burst-Cluster installieren
Wir haben viel Zeit damit verbracht, unseren primary-Cluster einzurichten und bereitzustellen. Aber wir haben noch einen ganzen anderen Cluster, in dem wir unsere Anwendung bereitstellen müssen.
In diesem Abschnitt müssen wir Konfigurationsvariablen aus beiden Clustern abrufen. Achten Sie daher genau darauf, auf welchen Cluster sich die einzelnen Befehle beziehen.
Istio-Remote-Manifest erstellen
Ähnlich wie bei der Bereitstellung von Istio im primary-Cluster verwenden wir Helm, um die Bereitstellung von Istio remote im burst-Cluster zu modellieren. Bevor wir das tun können, benötigen wir jedoch einige Informationen zu unserem primary-Cluster.
Informationen zum primären Cluster erfassen
Zum primary-Cluster wechseln
kubectx primary
Mit den folgenden Befehlen werden die IP-Adressen verschiedener Pods im primären Cluster abgerufen. Diese werden von Istio Remote verwendet, um mit dem primären Cluster zu kommunizieren.
export PILOT_POD_IP=$(kubectl -n istio-system get pod -l istio=pilot -o jsonpath='{.items[0].status.podIP}')
export POLICY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=policy -o jsonpath='{.items[0].status.podIP}')
export STATSD_POD_IP=$(kubectl -n istio-system get pod -l istio=statsd-prom-bridge -o jsonpath='{.items[0].status.podIP}')
export TELEMETRY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=telemetry -o jsonpath='{.items[0].status.podIP}')
export ZIPKIN_POD_IP=$(kubectl -n istio-system get pod -l app=jaeger -o jsonpath='{range .items[*]}{.status.podIP}{end}')
Remote-Vorlage erstellen
Jetzt erstellen wir mit helm eine Datei namens istio-remote-burst.yaml, die wir dann im Cluster burst bereitstellen können.
Zum Projektstamm wechseln
cd $proj
helm template istio-1.0.0/install/kubernetes/helm/istio-remote --namespace istio-system \
--name istio-remote \
--set global.remotePilotAddress=${PILOT_POD_IP} \
--set global.remotePolicyAddress=${POLICY_POD_IP} \
--set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \
--set global.proxy.envoyStatsd.enabled=true \
--set global.proxy.envoyStatsd.host=${STATSD_POD_IP} \
--set global.remoteZipkinAddress=${ZIPKIN_POD_IP} > istio-remote-burst.yaml
Istio Remote im Burst-Cluster installieren
Um Istio in unserem burst-Cluster zu installieren, müssen wir dieselben Schritte ausführen wie bei der Installation im primary-Cluster, aber stattdessen die Datei istio-remote-burst.yaml verwenden.
Kubecontext in „burst“ ändern
kubectx burst
Namespace „istio-system“ erstellen
kubectl create ns istio-system
Istio-burst.yaml anwenden
kubectl apply -f istio-remote-burst.yaml
Standard-Namespace für Labels
Wir müssen dem Namespace default wieder ein Label hinzufügen, damit der Proxy automatisch eingefügt werden kann.
kubectl label namespace default istio-injection=enabled
Glückwunsch! Wir haben Istio Remote jetzt auf dem Cluster burst eingerichtet. Zu diesem Zeitpunkt können die Cluster jedoch noch nicht miteinander kommunizieren. Wir müssen eine kubeconfig-Datei für den Cluster burst generieren, die wir im Cluster primary bereitstellen können, um sie miteinander zu verknüpfen.
Kubeconfig für Burst-Cluster erstellen
Zu Burst-Cluster wechseln
kubectx burst
Umgebung einrichten
Wir benötigen einige Informationen zum Cluster, um eine kubeconfig-Datei dafür zu erstellen.
- Name des Clusters abrufen
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
- Clusterservernamen abrufen
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
- Name des Secrets für die Zertifizierungsstelle des Dienstkontos
istio-multiabrufen
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
- Daten der Zertifizierungsstelle abrufen, die im vorherigen Secret gespeichert sind
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
- Im vorherigen Secret gespeichertes Token abrufen
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)
Kubeconfig-Datei erstellen
Nachdem alle Umgebungsvariablen festgelegt sind, müssen wir die kubeconfig-Datei erstellen.
cat <<EOF > burst-kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ${CA_DATA}
server: ${SERVER}
name: ${CLUSTER_NAME}
contexts:
- context:
cluster: ${CLUSTER_NAME}
user: ${CLUSTER_NAME}
name: ${CLUSTER_NAME}
current-context: ${CLUSTER_NAME}
kind: Config
preferences: {}
users:
- name: ${CLUSTER_NAME}
user:
token: ${TOKEN}
EOF
Dadurch wird im aktuellen Verzeichnis eine neue Datei namens burst-kubeconfig erstellt, die vom Cluster primary zur Authentifizierung und Verwaltung des Clusters burst verwendet werden kann.
Zurück zum primären Cluster wechseln
kubectx primary
Kubeconfig für „burst“ anwenden, indem Sie ein Secret erstellen und ein Label hinzufügen
kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system
Labeln Sie das Secret, damit Istio weiß, dass es für die Multicluster-Authentifizierung verwendet werden soll.
kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system
Glückwunsch! Wir haben beide Cluster authentifiziert und sie kommunizieren über Istio Multicluster miteinander. Clusterübergreifende Bereitstellung unserer Anwendung
15. Clusterübergreifende Anwendung bereitstellen
Deployments erstellen
Wechseln Sie zum Verzeichnis kubernetes.
cd ${proj}/kubernetes
Arbeiterbereitstellung für „Burst“-Cluster erstellen: worker-burst.yaml
Erstellen Sie eine Datei mit dem Namen worker-burst.yaml und fügen Sie Folgendes ein:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: worker-deployment
labels:
app: worker
spec:
replicas: 1
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
cluster-type: burst-cluster
spec:
containers:
- name: worker
image: gcr.io/istio-burst-workshop/worker
imagePullPolicy: Always
ports:
- containerPort: 8081
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-liveness-probe"
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
Beachten Sie, dass diese Datei fast identisch mit der Datei „worker-primary.yaml“ ist, die wir zuvor erstellt haben. Es gibt zwei Hauptunterschiede.
Der erste wichtige Unterschied besteht darin, dass wir die Umgebungsvariable PREFIX mit dem Wert „bursty-“ hinzugefügt haben.
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
Das bedeutet, dass unser Worker im Cluster burst allen gesendeten Hashes das Präfix „bursty-“ vorangestellt. So können wir erkennen, dass unsere Anwendung wirklich clusterübergreifend ist.
Der zweite wichtige Unterschied besteht darin, dass wir das cluster-type-Label dieser Bereitstellung von primary-cluster in burst-cluster geändert haben.
labels:
app: worker
cluster-type: burst-cluster
Dieses Label verwenden wir später, wenn wir unseren VirtualService aktualisieren.
Istio-Dienste ändern
Derzeit nutzen unsere Istio-Dienste nicht beide Bereitstellungen. 100% des Traffics werden an den „primären“ Cluster weitergeleitet. Das wollen wir ändern.
Wechseln Sie in das Verzeichnis istio-manifests.
cd ${proj}/istio-manifests
worker-virtualservice.yaml bearbeiten, um DestinationRules einzufügen
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 50
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 50
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: worker-destination-rule
spec:
host: worker-service
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: primary
labels:
cluster-type: primary-cluster
- name: burst
labels:
cluster-type: burst-cluster
Wie Sie sehen, haben wir unserem VirtualService ein zweites Ziel hinzugefügt. Er verweist weiterhin auf denselben Host (worker-service.default.svc.cluster.local)), aber 50% des Traffics werden an die primary-Untergruppe und die anderen 50% an die burst-Untergruppe weitergeleitet.
Wir haben die Teilmenge primary als Bereitstellungen mit dem Label cluster-type: primary-cluster und die Teilmenge burst als Bereitstellungen mit dem Label cluster-type: burst-cluster definiert.
Dadurch wird der Traffic effektiv zu 50 % auf die beiden Cluster aufgeteilt.
Im Cluster bereitstellen
redis-service.yaml im Burst-Cluster bereitstellen
Zu burst-kubeconfig wechseln
kubectx burst
Zum Projektstamm wechseln
cd ${proj}
Dann bereitstellen
redis-service.yaml im Burst-Cluster bereitstellen
kubectl apply -f kubernetes/redis-service.yaml
worker-burst.yaml im Burst-Cluster bereitstellen
kubectl apply -f kubernetes/worker-burst.yaml
worker-service.yaml im Burst-Cluster bereitstellen
kubectl apply -f kubernetes/worker-service.yaml
Istio VirtualServices anwenden
Zu primary-kubeconfig wechseln
kubectx primary
Dann bereitstellen
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Funktion prüfen
Rufen Sie dazu Ihren Istio-Ingress-Punkt auf. Sie sehen dann, dass etwa 50% der Hashes mit „burst-“ beginnen.

Das bedeutet, dass wir jetzt clusterübergreifend kommunizieren. Versuchen Sie, die Gewichte für die verschiedenen Dienste zu ändern und die worker-virtualservice.yaml-Datei anzuwenden. Das ist eine gute Möglichkeit, den Traffic zwischen Clustern auszugleichen. Aber was wäre, wenn wir das automatisch tun könnten?
16. Prometheus-Messwerte nutzen
Einführung in Prometheus
Prometheus ist ein Open-Source-Toolkit für die Überwachung und Benachrichtigung von Systemen, das ursprünglich bei SoundCloud entwickelt wurde. Es wird ein mehrdimensionales Datenmodell mit Zeitreihendaten verwaltet, die anhand des Messwertnamens und Schlüssel/Wert-Paaren identifiziert werden.
Hier ist das Prometheus-Architekturdiagramm als Referenz:

Wenn Istio mit Prometheus bereitgestellt wird, meldet es automatisch verschiedene Messwerte an den Prometheus-Server. Mit diesen Messwerten können wir unsere Cluster im laufenden Betrieb verwalten.
Prometheus-Messwerte
Zuerst müssen wir die Prometheus-Bereitstellung freigeben.
Rufen Sie in GKE den Tab „Arbeitslasten“ auf und gehen Sie zur Arbeitslast „prometheus“.

Klicken Sie in den Bereitstellungsdetails auf „Aktionen“ -> „Freigeben“.

Wählen Sie die Weiterleitung an Port 9090 aus und geben Sie „Load Balancer“ ein.

Wählen Sie „Entwickeln“ aus.
Dadurch wird ein Dienst mit einer öffentlich zugänglichen IP-Adresse erstellt, mit der wir unsere Prometheus-Messwerte untersuchen können.
Warten Sie, bis der Endpunkt betriebsbereit ist, und klicken Sie dann auf die IP-Adresse neben „Externe Endpunkte“
.
Sie sollten jetzt die Prometheus-Benutzeroberfläche sehen.

Prometheus bietet genügend Messwerte, um ein eigener Workshop zu sein. Fürs Erste konzentrieren wir uns jedoch auf den Messwert istio_requests_total.
Die Ausführung dieser Abfrage gibt eine Menge Daten zurück. Es sind Messwerte zu allen Anfragen, die über das Istio Service Mesh laufen. Das sind eine Menge! Wir ändern den Ausdruck, um nur die Ergebnisse zu sehen, die uns wirklich interessieren:
Anfragen, bei denen der Zieldienst worker-service.default.svc.cluster.local und die Quelle frontend-deployment ist, auf die letzten 15 Sekunden beschränkt
Diese Abfrage sieht so aus:
istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]
Außerdem haben wir dann einen überschaubaren Datensatz, mit dem wir arbeiten können.

Aber es ist immer noch etwas dicht. Wir möchten die Anfragen pro Sekunde wissen, nicht alle Anfragen.
Dazu können wir die vordefinierte Funktion rate verwenden.
rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])

Wir kommen dem Ziel näher, müssen diese Messwerte aber noch etwas weiter in eine logische Gruppe einteilen.
Dazu können wir die Keywords sum und by verwenden, um die Ergebnisse zu gruppieren und zu summieren.
sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)

Super! Wir können die genauen Messwerte, die wir benötigen, aus Prometheus abrufen.
Die endgültige Prometheus-Abfrage
Mit all dem, was wir gelernt haben, lautet die letzte Abfrage, die wir an Prometheus stellen müssen:
sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)
Jetzt können wir den Messwert über die HTTP API abrufen.
Wir können die API mit unserer Abfrage abfragen, indem wir eine HTTP-GET-Anfrage wie diese senden. Ersetzen Sie <prometheus-ip-here>
curl http://<prometheus-ip-here>/api/v1/query?query=sum\(rate\(istio_requests_total%7Breporter%3D%22destination%22%2C%0Adestination_service%3D%22worker-service.default.svc.cluster.local%22%2C%0Asource_workload%3D%22frontend-deployment%22%7D%5B15s%5D\)\)%20by%20\(source_workload%2C%0Asource_app%2C%20destination_service\)
Hier ist ein Beispiel:
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"destination_service": "worker-service.default.svc.cluster.local",
"source_app": "frontend",
"source_workload": "frontend-deployment"
},
"value": [
1544404907.503,
"18.892886390062788"
]
}
]
}
}
Jetzt können wir den Messwert aus dem JSON-Objekt extrahieren.
Clean-up
Wir müssen den Dienst löschen, den wir gerade zum Bereitstellen von Prometheus verwendet haben. Klicken Sie in der Google Cloud Console oben im Bereich des gerade erstellten Dienstes auf „Löschen“.

Vorgehensweise:
Nachdem wir herausgefunden haben, wie und mit welcher Geschwindigkeit sich der Traffic durch den Cluster bewegt, ist unser nächster Schritt, eine kleine Binärdatei zu schreiben, die Prometheus regelmäßig abfragt. Wenn die Anzahl der Anfragen pro Sekunde an worker einen bestimmten Grenzwert überschreitet, werden unterschiedliche Zielgewichte auf unseren virtuellen Worker-Dienst angewendet, um den gesamten Traffic an den burst-Cluster zu senden. Sobald die Anzahl der Anfragen pro Sekunde unter einen niedrigeren Grenzwert fällt, wird der gesamte Traffic an primary zurückgesendet.
17. Clusterübergreifenden Burst erstellen
Einrichtung
Allen Traffic für den Worker-Dienst an den primären Cluster weiterleiten
Wir betrachten den Zustand, in dem der gesamte Traffic für worker-service an den Cluster primary weitergeleitet wird, als „Standardstatus“ unserer Anwendung.
Bearbeiten Sie $proj/istio-manifests/worker-virtualservice.yaml so:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 100
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 0
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: worker-destination-rule
spec:
host: worker-service
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: primary
labels:
cluster-type: primary-cluster
- name: burst
labels:
cluster-type: burst-cluster
Prüfen, ob eine Verbindung zum primary-Cluster besteht
kubectx primary
Istio-Manifests/worker-virtualservice.yaml anwenden
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Istiowatcher-Daemon schreiben
Wir verwenden Go, um diesen Dienst zu schreiben, da es sich um eine schnelle und portable Sprache handelt. Der Ablauf der Anwendung besteht darin, dass sie gestartet wird und jede Sekunde Prometheus abfragt.
Erstellen Sie in „src“ ein neues Verzeichnis mit dem Namen „istiowatcher“.
mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher
Wir rufen istioctl von unserem Container aus auf, um die Istio-Steuerungsebene innerhalb des Clusters zu manipulieren.
„istiowatcher.go“ schreiben
Erstellen Sie in diesem Verzeichnis eine Datei mit dem Namen istiowatcher.go und fügen Sie Folgendes ein:
package main
import (
"github.com/tidwall/gjson"
"io/ioutil"
"log"
"net/http"
"os/exec"
"time"
)
func main() {
//These are in requests per second
var targetLow float64 = 10
var targetHigh float64 = 15
// This is for the ticker in milliseconds
ticker := time.NewTicker(1000 * time.Millisecond)
isBurst := false
// Our prometheus query
reqQuery := `/api/v1/query?query=sum(rate(istio_requests_total{reporter="destination",destination_service="worker-service.default.svc.cluster.local",source_workload="frontend-deployment"}[15s]))by(source_workload,source_app,destination_service)`
for t := range ticker.C {
log.Printf("Checking Prometheus at %v", t)
// Check prometheus
// Note that b/c we are querying over the past 5 minutes, we are getting a very SLOW ramp of our reqs/second
// If we wanted this to be a little "snappier" we can scale it down to say 30s
resp, err := http.Get("http://prometheus.istio-system.svc.cluster.local:9090" + reqQuery)
if err != nil {
log.Printf("Error: %v", err)
continue
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
val := gjson.Get(string(body), "data.result.0.value.1")
log.Printf("Value: %v", val)
currentReqPerSecond := val.Float()
log.Printf("Reqs per second %f", currentReqPerSecond)
if currentReqPerSecond > targetHigh && !isBurst {
applyIstio("burst.yaml")
log.Println("Entering burst mode")
isBurst = true
} else if currentReqPerSecond < targetLow && isBurst {
applyIstio("natural.yaml")
log.Println("Returning to natural state.")
isBurst = false
}
}
}
func applyIstio(filename string) {
cmd := exec.Command("istioctl", "replace", "-f", filename)
if err := cmd.Run(); err != nil {
log.Printf("Error hit applying istio manifests: %v", err)
}
}
Dockerfile schreiben
Erstellen Sie eine neue Datei mit dem Namen Dockerfile und fügen Sie Folgendes ein:
FROM golang:1.11.2-stretch as base
FROM base as builder
WORKDIR /workdir
RUN curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
RUN tar xzf istio-1.0.0-linux.tar.gz
RUN cp istio-1.0.0/bin/istioctl ./istioctl
FROM base
WORKDIR /go/src/istiowatcher
COPY . .
COPY --from=builder /workdir/istioctl /usr/local/bin/istioctl
RUN go get -d -v ./...
RUN go install -v ./...
CMD ["istiowatcher"]
In diesem mehrstufigen Dockerfile wird in der ersten Phase die Version 1.0.0 von Istio heruntergeladen und extrahiert. In der zweiten Phase wird alles aus unserem Verzeichnis in das Image kopiert. Anschließend wird istioctl aus der Build-Phase in /usr/local/bin kopiert, damit es von unserer Anwendung aufgerufen werden kann. Die Abhängigkeiten werden abgerufen, der Code wird kompiliert und CMD wird auf „istiowatcher“ gesetzt.
burst.yaml schreiben
Diese Datei wird von istiowatcher angewendet, wenn die Anzahl der Anfragen pro Sekunde an worker von frontend über 15 liegt.
Erstellen Sie eine neue Datei mit dem Namen burst.yaml und fügen Sie Folgendes ein:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 0
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 100
natural.yaml schreiben
Dies ist der „natürliche“ Zustand, zu dem wir zurückkehren, wenn die Anzahl der Anfragen pro Sekunde von frontend auf worker unter 10 fällt. In diesem Zustand wird 100% des Traffics an den Cluster primary weitergeleitet.
Erstellen Sie eine neue Datei mit dem Namen natural.yaml und fügen Sie Folgendes ein:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 100
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 0
Istiowatcher erstellen und pushen
Führen Sie den folgenden Befehl aus, um das aktuelle Verzeichnis an Google Cloud Build (GCB) zu senden. Dort wird das Image in GCR erstellt und getaggt.
gcloud builds submit -t gcr.io/${GCLOUD_PROJECT}/istiowatcher
Istiowatcher bereitstellen
Wechseln Sie in das Verzeichnis kubernetes.
cd ${proj}/kubernetes/
Bereitstellungsdatei schreiben: istiowatcher.yaml
Erstellen Sie eine Datei mit dem Namen istiowatcher.yaml und fügen Sie den folgenden Code ein. Ersetzen Sie dabei <your-project-id> durch Ihre Projekt-ID.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: istiowatcher-deployment
labels:
app: istiowatcher
spec:
replicas: 1
selector:
matchLabels:
app: istiowatcher
template:
metadata:
labels:
app: istiowatcher
spec:
serviceAccountName: istio-pilot-service-account
automountServiceAccountToken: true
containers:
- name: istiowatcher
image: gcr.io/<your-project-id>/istiowatcher
imagePullPolicy: Always
Bereitstellen
Prüfen, ob wir im primären Cluster ausgeführt werden
kubectx primary
istiowatcher.yaml im Namespace istio-system bereitstellen
kubectl apply -n istio-system -f istiowatcher.yaml
Beachten Sie die Anweisungen serviceAccountName und automountServiceAccountToken in der YAML-Datei. So erhalten wir die Anmeldedaten, die zum Ausführen von istioctl innerhalb des Clusters erforderlich sind.
Außerdem müssen wir es im Namespace istio-system bereitstellen, damit wir die Anmeldedaten für die istio-pilot-service-account haben. (Sie ist nicht im Namespace default vorhanden).
Sehen Sie sich an, wie der Traffic automatisch umgeleitet wird.
Jetzt kommt der magische Moment! Gehen wir zum Frontend und erhöhen die Anzahl der Anforderungen pro Sekunde auf 20.
Es dauert einige Sekunden, bis die Leistung erreicht wird. Alle Hashes haben das Präfix „bursty-“.
Das liegt daran, dass wir Prometheus in einem Bereich von 15s erfassen, was zu einer etwas längeren Antwortzeit führt. Wenn wir eine viel engere Bandbreite wünschen, könnten wir unsere Abfrage für Prometheus in 5s. ändern.
18. Nächste Schritte
Clean-up
Wenn Sie ein für diesen Workshop bereitgestelltes temporäres Konto verwenden, müssen Sie nichts bereinigen.
Sie können Ihre Kubernetes-Cluster, die Firewallregel und die Images in GCR löschen.
gcloud container clusters delete primary --zone=us-west1-a
gcloud container clusters delete burst --zone=us-west1-a
gcloud compute firewall-rules delete istio-multicluster-test-pods
gcloud container images delete gcr.io/$GCLOUD_PROJECT/istiowatcher
Ausblick
- Nehmen Sie an Istio-Vorträgen teil.
- Zertifizierung erwerben: Nächste App mit Kubernetes und Istio erstellen
- Keynote: Kubernetes, Istio, Knative: The New Open Cloud Stack – Aparna Sinha, Group Product Manager for Kubernetes, Google
- Anleitung: Istio verwenden – Lee Calcote und Girish Ranganathan, SolarWinds
- Istio – Die Sicht des Pakets – Matt Turner, Tetrate
- Ist Istio die Next-Gen-Firewall der nächsten Generation? – John Morello, Twistlock
- Istio-Dokumentation lesen
- Istio-Arbeitsgruppen beitreten
- Folgen Sie @IstioMesh auf Twitter.




