1. Ti diamo il benvenuto
Grazie per aver partecipato al codelab Istio Multi Cloud Burst di Google.Questo codelab richiede esperienza pratica di livello principiante con Kubernetes, Node e Go. Cosa ti serve
|
|
Cosa imparerai
- Come creare un cluster Kubernetes su GKE
- Come installare Istio su un cluster Kubernetes con Helm
- Come installare Istio multicluster con Helm
- Deployment di un'applicazione web dal codice sorgente a Kubernetes
- Scrittura e applicazione di regole di routing del traffico a Istio
- Metriche di Prometheus
- Crea ed esegui il push di immagini container all'interno di un cluster Kubernetes
2. Preparazione
Puoi seguire questo codelab su:
- Google Cloud Shell (consigliato): shell nel browser, con strumenti installati
- il tuo laptop (segui le istruzioni riportate di seguito)
Inizia con Google Cloud Platform
- Se non hai un account GCP, ritira la scheda dell'account utente senza costi dall'istruttore.
- Vai alla console Google Cloud e fai clic su "Seleziona un progetto":

- Prendi nota dell'ID del progetto e fai clic sul progetto per sceglierlo:

Opzione 1: utilizzare Google Cloud Shell (consigliata)
Cloud Shell fornisce una shell a riga di comando all'interno del browser con gli strumenti necessari installati e autenticati automaticamente nel tuo account Google Cloud Platform. Se non vuoi eseguire questo esercizio su Cloud Shell, vai alla sezione successiva.
Vai alla console Cloud e fai clic su "Attiva Cloud Shell" nella barra degli strumenti in alto a destra:

Aggiungere strumenti a Cloud Shell
- Installa
kubectx****: scarica gli script bash da qui in una posizione in $PATH. - Installa
helm**** seguendo queste istruzioni.
In alternativa, esegui questi comandi per installare entrambi in ~/.bin e aggiungerli a $PATH:
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}
Ecco alcuni suggerimenti rapidi che possono semplificare l'utilizzo di Cloud Shell:
1. Stacca la shell in una nuova finestra: |
|
2. Utilizzo dell'editor di file: fai clic sull'icona a forma di matita in alto a destra per avviare un editor di file nel browser. Ti sarà utile perché copieremo gli snippet di codice nei file. |
|
3. Avvia nuove schede: se hai bisogno di più prompt del terminale. |
|
4. Ingrandisci il testo: le dimensioni predefinite del carattere in Cloud Shell potrebbero essere troppo piccole per essere lette. | Ctrl + - su Linux/Windows⌘ + - su macOS. |
Opzione 2: configura il laptop (non consigliata)
Se preferisci utilizzare il tuo ambiente workstation anziché Cloud Shell, configura i seguenti strumenti:
- Installa
gcloud:(preinstallato su Cloud Shell). Segui le istruzioni per installaregcloudsulla tua piattaforma. Lo utilizzeremo per creare un cluster Kubernetes. - Installa
kubectl:(preinstallato su Cloud Shell). Esegui questo comando per installare:
gcloud components install kubectl
Esegui questo comando per autenticare gcloud. Ti verrà chiesto di accedere con il tuo Account Google. Poi scegli il progetto pre-creato (mostrato sopra) come progetto predefinito. (Puoi saltare la configurazione di una zona di computing):
gcloud init
- Installazione di
curl:preinstallato sulla maggior parte dei sistemi Linux/macOS. Probabilmente ce l'hai già. In caso contrario, cerca su internet come installarlo. - Installa
kubectx****: scaricando gli script bash da qui in una posizione in $PATH - Installa
helm**** seguendo queste istruzioni.
3. Configura progetto Google Cloud
Abilita le API GKE (Google Kubernetes Engine), GCR (Google Container Registry) e GCB (Google Cloud Build) nel tuo progetto:
gcloud services enable \ cloudapis.googleapis.com \ container.googleapis.com \ containerregistry.googleapis.com \ cloudbuild.googleapis.com
Configura le variabili di ambiente
Durante la configurazione lavoreremo molto con il nostro progetto Google Cloud, quindi impostiamo una variabile di ambiente per riferimento rapido
export GCLOUD_PROJECT=$(gcloud config get-value project)
Durante questo workshop creeremo alcuni file di codice e di configurazione, quindi creiamo una directory di progetto e passiamo a questa directory
mkdir -p src/istio-burst && \ cd src/istio-burst && \ export proj=$(pwd)
4. Crea il cluster Kubernetes "principale"
Puoi creare facilmente un cluster Kubernetes gestito con Google Kubernetes Engine (GKE).
Il comando seguente creerà un cluster Kubernetes:
- denominata "primary",
- nella zona us-west1-a,
- L'ultima versione di Kubernetes disponibile.
- con 4 nodi iniziali
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
L'operazione potrebbe richiedere circa 5 minuti. Puoi osservare la creazione del cluster nella console Google Cloud.
Dopo la creazione del cluster Kubernetes, gcloud configura kubectl con le credenziali che puntano al cluster.
gcloud container clusters get-credentials $cluster --zone=$zone
Ora dovresti essere in grado di utilizzare kubectl con il nuovo cluster.
Esegui questo comando per elencare i nodi Kubernetes del tuo cluster (dovrebbero mostrare lo stato "Pronto"):
kubectl get nodes
Modificare i nomi di Kubeconfig per facilità d'uso
Passeremo spesso da un contesto all'altro, quindi avere un alias breve per i nostri cluster è utile.
Questo comando rinomina la voce kubeconfig appena creata in primary
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Imposta le autorizzazioni:
Per eseguire il deployment di Istio devi essere un amministratore del cluster. Questo comando imposterà l'email associata al tuo account Google Cloud come amministratore del cluster
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
5. Crea cluster "burst"
Il comando seguente creerà un cluster Kubernetes:
- denominato "burst",
- nella zona us-west1-a,
- L'ultima versione di Kubernetes disponibile.
- Con 1 nodo iniziale
- Scalabilità automatica abilitata fino a 5 nodi
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
L'operazione potrebbe richiedere circa 5 minuti. Puoi osservare la creazione del cluster nella console Google Cloud.
Dopo la creazione del cluster Kubernetes, gcloud configura kubectl con le credenziali che puntano al cluster.
gcloud container clusters get-credentials $cluster --zone=$zone
Ora dovresti essere in grado di utilizzare kubectl con il nuovo cluster.
Esegui questo comando per elencare i nodi Kubernetes del tuo cluster (dovrebbero mostrare lo stato "Pronto"):
kubectl get nodes
Modificare i nomi di Kubeconfig per facilità d'uso
Questo comando modificherà la voce kubeconfig appena creata in burst
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Imposta le autorizzazioni:
Per eseguire il deployment di Istio Remote devi essere un amministratore del cluster. Questo comando imposterà l'email associata al tuo account Google Cloud come amministratore del cluster
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
6. Applica regole firewall
Affinché i due cluster possano comunicare tra loro, dobbiamo creare una regola firewall.
Esegui questi comandi per creare una regola firewall in Google Cloud che consenta ai nostri cluster di comunicare
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
Entrambi i cluster sono configurati e pronti per il deployment dell'applicazione e di Istio.
7. Introduzione a Istio
Che cos'è Istio?
Istio è un piano di controllo del service mesh che mira a "connettere, proteggere, controllare e osservare i servizi". Lo fa in vari modi, ma principalmente inserendo un container proxy ( Envoy) in ogni pod Kubernetes di cui è stato eseguito il deployment. Il container proxy controlla tutte le comunicazioni di rete tra i microservizi in tandem con un hub di criteri e telemetria generico ( Mixer).

Queste norme possono essere applicate indipendentemente dai deployment e dai servizi Kubernetes, il che significa che l'operatore di rete può osservare l'attività di rete, limitare, reindirizzare o riscrivere le norme di rete senza eseguire nuovamente il deployment delle applicazioni associate.
Alcune delle funzionalità di gestione del traffico supportate da Istio sono:
- Interruttori di sicurezza
- Suddivisione del traffico basata sulla percentuale
- Riscrittura URL
- terminazione TLS
- Controlli di integrità
- Bilanciamento del carico
Ai fini di questo workshop, ci concentreremo sulla suddivisione del traffico in base alla percentuale.
Termini di Istio con cui lavoreremo
VirtualService
Un VirtualService definisce un insieme di regole di routing del traffico da applicare quando viene indirizzato un host.
Gateway
Un gateway è un bilanciatore del carico che opera al limite del mesh e riceve connessioni HTTP/TCP in entrata o in uscita. I gateway possono specificare porte, configurazioni SNI e così via.
DestinationRule
Una DestinationRule definisce le policy che si applicano al traffico destinato a un servizio dopo l'instradamento. Specificano la configurazione per il bilanciamento del carico, le dimensioni del pool di connessioni dal sidecar e le impostazioni di rilevamento degli outlier.
Istio multicluster
Potresti aver notato che, quando abbiamo creato i due cluster, il cluster primary era composto da 4 nodi senza scalabilità automatica, mentre il cluster burst era composto da 1 nodo con scalabilità automatica fino a 5 nodi.
Esistono due motivi per questa configurazione.
Innanzitutto, vogliamo simulare uno scenario "on-premise" nel cloud. In un ambiente on-premise non hai accesso ai cluster di scalabilità automatica perché hai un'infrastruttura fissa.
In secondo luogo, una configurazione a 4 nodi (come definita sopra) è il requisito minimo per eseguire Istio. Sorge quindi la domanda: se Istio richiede un minimo di 4 nodi, come può il nostro cluster burst eseguire Istio con 1 nodo? La risposta è che Istio Multicluster installa un insieme molto più piccolo di servizi Istio e comunica con l'installazione di Istio nel cluster principale per recuperare le regole dei criteri e pubblicare le informazioni di telemetria.
8. Panoramica dell'architettura dell'applicazione
Panoramica dei componenti
Eseguiremo il deployment di un'applicazione a tre livelli utilizzando NodeJS e Redis.
Worker
L'applicazione di lavoro è scritta in NodeJS e ascolterà le richieste HTTP POST in entrata, eseguirà un'operazione di hashing e, se è definita una variabile di ambiente denominata PREFIX, anteporrà l'hash a questo valore. Una volta calcolato l'hash, l'applicazione invia il risultato sul canale "calculation" sul server Redis specificato.
Utilizzeremo la variabile di ambiente PREFIX in un secondo momento per dimostrare la funzionalità multicluster.
Per riferimento, questi sono i pacchetti utilizzati dall'applicazione.
body-parser:Ci consente di analizzare le nostre richieste HTTPcors:Consente l'utilizzo della condivisione delle risorse tra origini (CORS)dotenv:Analisi semplice delle variabili di ambienteexpress:Hosting di siti web semplice- Libreria client
ioredis:per comunicare con i database Redis morgan:Fornisce un log strutturato
Frontend
Il nostro frontend è anche un'applicazione NodeJS che ospita una pagina web utilizzando express. Prende una frequenza inserita dall'utente e invia richieste alla nostra applicazione worker a quella velocità. Questa applicazione si iscrive anche ai messaggi su un canale Redis denominato "calculation" e mostra i risultati in una pagina web.
L'applicazione utilizza le seguenti dipendenze.
body-parser:Ci consente di analizzare le nostre richieste HTTPdotenv:Analisi semplice delle variabili di ambienteexpress:Hosting di siti web semplice- Libreria client
ioredis:per comunicare con i database Redis morgan:Fornisce log strutturatirequest:Consente di effettuare richieste HTTPsocket.io:Consente la comunicazione bidirezionale dalla pagina web al server
Questa pagina web utilizza Bootstrap per lo stile e, quando viene eseguita, ha il seguente aspetto

Diagramma dell'architettura

Diagramma di deployment
Eseguiremo il deployment dell'applicazione finale nei due cluster che abbiamo creato. Il cluster primary avrà tutti i componenti (frontend, worker e Redis) di cui è stato eseguito il deployment, mentre il cluster burst avrà solo l'applicazione worker di cui è stato eseguito il deployment.
Di seguito è riportato un diagramma che descrive i due cluster. I riquadri evidenziati in rosso sono servizi Kubernetes, quelli in blu sono deployment Kubernetes. I riquadri gialli indicano l'installazione di Istio.
Nota come il cluster burst abbia ancora un servizio per Redis di cui è stato eseguito il deployment, anche se non esiste un deployment per Redis nel cluster. Abbiamo bisogno di questo servizio nel cluster in modo che Kubernetes DNS possa risolvere la richiesta, ma quando la richiesta viene effettivamente effettuata, il proxy Istio la reindirizza al deployment Redis nel cluster primary.
L'applicazione finale avrà un deployment aggiuntivo in esecuzione nel cluster primary denominato istiowatcher.. Questo ci consentirà di reindirizzare dinamicamente il traffico a burst automaticamente quando il traffico supera una determinata soglia.

9. Crea file di deployment dell'applicazione
Dobbiamo creare un insieme di manifest Kubernetes per eseguire il deployment della nostra applicazione
Passa alla directory principale del progetto e crea una nuova cartella denominata kubernetes.
mkdir ${proj}/kubernetes && cd ${proj}/kubernetes
Scrivi frontend.yaml
Verranno creati sia un deployment che un servizio Kubernetes per accedere all'immagine frontend.
Inserisci quanto segue in frontend.yaml.
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
Aspetti importanti da notare in Deployment
- Abbiamo specificato che la porta su cui verrà eseguita l'applicazione è
8080 - Abbiamo impostato l'indirizzo del worker su "
http://worker-service" e utilizzeremo la funzionalità DNS integrata di Kubernetes per risolvere il servizio risultante. - Abbiamo impostato l'indirizzo del nostro
REDIS_URLsu "redis-cache-service:6379" e utilizzeremo la funzionalità DNS integrata di Kubernetes per risolvere gli indirizzi IP risultanti. - Abbiamo anche impostato i probe
livenessereadinesssul container per aiutare Kubernetes a sapere quando il container è attivo e in esecuzione.
Scrivi worker-service.yaml
Stiamo scrivendo la definizione del servizio Kubernetes in un file separato rispetto alla definizione del deployment, in quanto riutilizzeremo questo servizio in più cluster, ma scriveremo un deployment diverso per ogni cluster.
Inserisci quanto segue in worker-service.yaml
apiVersion: v1
kind: Service
metadata:
name: worker-service
spec:
type: ClusterIP
selector:
app: worker
ports:
- name: http
port: 80
targetPort: 8081
Scrivi worker-primary.yaml
Questo sarà il deployment di worker che verrà eseguito sul cluster principale.
Inserisci quanto segue in worker-primary.yaml.
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"
Nota che seguiamo lo stesso pattern di fornitura dei probe liveness e readiness, nonché di specifica delle variabili di ambiente PORT e REDIS_URL da utilizzare per la nostra applicazione.
Un'altra cosa da notare in questo deployment è la mancanza della variabile di ambiente PREFIX. Ciò significa che i risultati del nostro calcolo saranno hash non elaborati (senza prefisso).
L'ultimo punto chiave di questo deployment è l'etichetta cluster-type: primary-cluster. Lo utilizzeremo in seguito quando eseguiremo il routing del traffico su Istio multicluster
Scrivi redis.yaml
La comunicazione dal worker al frontend avviene tramite un canale Redis e, pertanto, dobbiamo eseguire il deployment di un'applicazione Redis nel nostro cluster.
Inserisci quanto segue in redis.yaml
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: {}
Si tratta di un deployment semi-standard di un'applicazione Redis. Crea un container basato sull'immagine redis:alpine, espone le porte appropriate e imposta limiti di risorse ragionevoli.
Scrivi redis-service.yaml
Abbiamo bisogno di un servizio Kubernetes per comunicare con la nostra applicazione Redis
Inserisci quanto segue in redis-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-cache-service
spec:
type: ClusterIP
selector:
app: redis-cache
ports:
- port: 6379
targetPort: 6379
In questo modo, il servizio denominato redis-cache-service può accedere al nostro deployment Redis.
10. Esegui il deployment dell'applicazione
Ora che le nostre immagini sono state inviate a GCR e i nostri manifest Kubernetes sono stati scritti, è il momento di eseguire il deployment della nostra applicazione e vedere come funziona.
Esegui i seguenti comandi per eseguire il deployment dell'applicazione
- Assicurati di trovarti nel cluster giusto
kubectx primary
- Esegui il deployment della cache Redis
kubectl apply -f redis.yaml
- Esegui il deployment del servizio Redis
kubectl apply -f redis-service.yaml
- Esegui il deployment del frontend
kubectl apply -f frontend.yaml
- Esegui il deployment del lavoratore
kubectl apply -f worker-primary.yaml
- Esegui il deployment del servizio di lavoro
kubectl apply -f worker-service.yaml
Abbiamo eseguito il deployment della nostra applicazione su GKE. Complimenti!
Test
Attendi che i pod siano online
kubectl get pods -w
Quando tutti i pod sono in esecuzione, premi Ctrl + 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
Noterai che non abbiamo esposto il nostro frontend tramite un bilanciatore del carico. Questo perché in seguito accederemo all'applicazione tramite Istio. Per verificare che tutto sia in esecuzione, utilizzeremo kubectl port-forward. Esegui il comando seguente per inoltrare la porta 8080 sulla tua macchina locale (o Cloud Shell) alla porta 8080 che esegue il deployment di frontend.
kubectl port-forward \
$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}') \
8080:8080
Se esegui l'app localmente: apri un browser web e vai all'indirizzo http://localhost:8080.
Se esegui l'applicazione in Cloud Shell, fai clic sul pulsante "Anteprima web" e seleziona "Anteprima sulla porta 8080".

Dovresti vedere il frontend. Se inserisci un numero nella casella "Frequenza", dovresti iniziare a visualizzare i segni di cancelletto.

Congratulazioni, tutto è pronto e funzionante.
Premi Ctrl+C per interrompere l'inoltro della porta.
11. Pulisci l'applicazione di cui è stato eseguito il deployment
Applicheremo Istio al nostro cluster e poi eseguiremo nuovamente il deployment della nostra applicazione, quindi puliamo prima l'applicazione attuale.
Esegui questi comandi per eliminare tutti i deployment e i servizi che hai appena creato
- Elimina
redis-cache-service
kubectl delete -f redis-service.yaml
- Elimina
redis
kubectl delete -f redis.yaml
- Elimina
frontend
kubectl delete -f frontend.yaml
- Elimina
worker
kubectl delete -f worker-primary.yaml
- Elimina
worker-service
kubectl delete -f worker-service.yaml
12. Installa Istio sul cluster primario
Scarica Istio
Le release di Istio sono ospitate su GitHub. I seguenti comandi scaricheranno la versione 1.0.0 di Istio e la decomprimeranno.
- Passa alla radice del progetto
cd ${proj}
- Scaricare l'archivio
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
- Estrai e rimuovi l'archivio
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz
Crea il modello Istio
L'esecuzione del seguente comando Helm creerà il modello per installare Istio nel cluster.
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
Viene creato un file denominato istio-primary.yaml nella directory corrente che contiene tutte le definizioni e le specifiche necessarie per eseguire il deployment e l'esecuzione di Istio.
Nota i due parametri --set. Questi componenti aggiuntivi supportano Prometheus e ServiceGraph nel sistema Istio. Utilizzeremo il servizio Prometheus più avanti nel lab.
Esegui il deployment di Istio
Per eseguire il deployment di Istio, dobbiamo prima creare uno spazio dei nomi denominato istio-system in cui possono essere eseguiti i deployment e i servizi Istio.
kubectl create namespace istio-system
Infine, applica il file istio-primary.yaml che abbiamo creato con Helm
kubectl apply -f istio-primary.yaml
Spazio dei nomi predefinito dell'etichetta
Istio funziona inserendo un servizio proxy sidecar in ogni deployment. Questa operazione viene eseguita in base all'attivazione, quindi dobbiamo etichettare lo spazio dei nomi default con istio-injection=enabled in modo che Istio possa inserire automaticamente il sidecar.
kubectl label namespace default istio-injection=enabled
Complimenti! Abbiamo un cluster in esecuzione con Istio pronto per il deployment della nostra applicazione.
13. Esegui il deployment della nostra applicazione con la gestione del traffico di Istio
Creare file di configurazione di gestione del traffico Istio
Istio funziona in modo simile a Kubernetes, in quanto utilizza file YAML per la configurazione. In quest'ottica, dobbiamo creare un insieme di file che indichino a Istio come esporre e instradare il nostro traffico.
Crea una directory denominata istio-manifests e passa a questa directory
mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests
Scrivi frontend-gateway.yaml
Questo file esporrà il nostro cluster Kubernetes in modo simile a un bilanciatore del carico GKE e indirizzerà tutto il traffico in entrata al nostro servizio frontend.
Crea un file denominato frontend-gateway.yaml e inserisci quanto segue.
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
Scrivi redis-virtualservice.yaml
Crea un file denominato redis-virtualservice.yaml e inserisci quanto segue:
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
Scrivi worker-virtualservice.yaml
Crea un file denominato worker-virtualservice.yaml e inserisci quanto segue:
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
Implementa le policy di gestione del traffico Istio
Il deployment dei criteri Istio viene eseguito allo stesso modo delle altre risorse Kubernetes, con kubectl apply
- Applica il nostro gateway
kubectl apply -f frontend-gateway.yaml
- Applica il nostro VirtualService Redis
kubectl apply -f redis-virtualservice.yaml
- Applica il nostro Worker VirtualService
kubectl apply -f worker-virtualservice.yaml
Esegui il deployment dell'applicazione
- Tornare alla directory
kubernetes
cd ${proj}/kubernetes
- Esegui il deployment della cache Redis
kubectl apply -f redis.yaml
- Esegui il deployment del servizio Redis
kubectl apply -f redis-service.yaml
- Esegui il deployment del frontend
kubectl apply -f frontend.yaml
- Esegui il deployment del lavoratore
kubectl apply -f worker-primary.yaml
- Esegui il deployment del servizio di lavoro
kubectl apply -f worker-service.yaml
Verifica
A questo punto abbiamo eseguito nuovamente il deployment della nostra applicazione su un cluster con Istio e policy di gestione del traffico.
Attendiamo che tutti i nostri workload vengano attivati.
Una volta che sono tutti online, recupera l'IngressGateway che abbiamo configurato in frontend-ingressgateway.yaml
$ 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,
Vai all'indirizzo <EXTERNAL-IP> o invia una richiesta curl e dovresti visualizzare il frontend.
$ curl 35.199.158.10
<!doctype html>
<html>
<head>
<title>String Hashr</title>
<!-- Bootstrap -->
...
14. Installare Istio sul cluster "burst"
Abbiamo dedicato molto tempo alla configurazione e al deployment sul nostro cluster primary, ma abbiamo un altro cluster completo su cui eseguire il deployment.
In questa sezione dovremo recuperare le variabili di configurazione in entrambi i cluster, quindi presta molta attenzione al cluster a cui è indirizzato ogni comando.
Crea il manifest remoto di Istio
Come quando abbiamo eseguito il deployment di Istio nel cluster primary, utilizzeremo Helm per creare un modello del deployment di Istio remoto nel cluster burst. Prima di poterlo fare, però, dobbiamo ottenere alcune informazioni sul nostro cluster primary
Raccogliere informazioni sul cluster principale
Passa al cluster primary
kubectx primary
I seguenti comandi recuperano gli indirizzi IP di vari pod nel cluster primario. Questi vengono utilizzati da Istio Remote per comunicare con il cluster principale.
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}')
Crea modello remoto
Ora utilizzeremo helm per creare un file denominato istio-remote-burst.yaml, che potremo poi eseguire il deployment nel cluster burst.
Passa alla radice del progetto
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
Installa Istio Remote sul cluster burst
Per installare Istio sul nostro cluster burst, dobbiamo seguire gli stessi passaggi eseguiti per l'installazione sul cluster primary, ma dobbiamo utilizzare il file istio-remote-burst.yaml.
Modificare kubecontext in burst
kubectx burst
Crea lo spazio dei nomi istio-system
kubectl create ns istio-system
Applica istio-burst.yaml
kubectl apply -f istio-remote-burst.yaml
Spazio dei nomi predefinito dell'etichetta
Ancora una volta, dobbiamo etichettare lo spazio dei nomi default in modo che il proxy possa essere inserito automaticamente.
kubectl label namespace default istio-injection=enabled
Complimenti! A questo punto abbiamo configurato Istio Remote sul cluster burst. A questo punto, tuttavia, i cluster non sono ancora in grado di comunicare. Dobbiamo generare un file kubeconfig per il cluster burst che possiamo distribuire nel cluster primary per collegarli.
Crea kubeconfig per il cluster "burst"
Passare al cluster di scatto a raffica
kubectx burst
Configura l'ambiente
Per creare un file kubeconfig per il cluster, dobbiamo raccogliere alcune informazioni.
- Recupera il nome del cluster
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
- Ottenere il nome del server del cluster
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
- Recupera il nome del secret per l'autorità di certificazione del service account
istio-multi
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
- Recupera i dati dell'autorità di certificazione archiviati nel segreto precedente
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
- Ottieni il token memorizzato nel segreto precedente
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)
Creare il file kubeconfig
Con tutte queste variabili di ambiente impostate, dobbiamo creare il file kubeconfig
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
Verrà creato un nuovo file denominato burst-kubeconfig nella directory corrente, che può essere utilizzato dal cluster primary per autenticare e gestire il cluster burst.
Tornare al cluster principale
kubectx primary
Applica il file kubeconfig per "burst" creando un secret ed etichettandolo
kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system
Etichetta il secret in modo che Istio sappia di utilizzarlo per l'autenticazione multicluster
kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system
Complimenti! Abbiamo autenticato entrambi i cluster e li abbiamo fatti comunicare tra loro tramite Istio Multicluster. Eseguiamo il deployment della nostra applicazione cross-cluster
15. Eseguire il deployment di un'applicazione cross-cluster
Crea deployment
Passa alla directory kubernetes
cd ${proj}/kubernetes
Crea il deployment del worker per il cluster "burst": worker-burst.yaml
Crea un file denominato worker-burst.yaml e inserisci al suo interno quanto segue:
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-"
Nota che è quasi identico a worker-primary.yaml che abbiamo creato in precedenza. Esistono due differenze principali.
La prima differenza fondamentale è che abbiamo aggiunto la variabile di ambiente PREFIX con il valore "bursty-".
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
Ciò significa che il nostro worker nel cluster burst anteporrà a tutti gli hash che invia il prefisso "bursty-", che possiamo utilizzare per sapere che la nostra applicazione è effettivamente cross-cluster.
La seconda differenza fondamentale è che abbiamo modificato l'etichetta cluster-type in questo deployment da primary-cluster a burst-cluster
labels:
app: worker
cluster-type: burst-cluster
Utilizzeremo questa etichetta in un secondo momento quando aggiorneremo il nostro VirtualService.
Modificare i servizi Istio
Al momento i nostri servizi Istio non sfruttano entrambi i nostri deployment. Il 100% del nostro traffico viene indirizzato al cluster "principale". Cambiamolo.
Passa alla directory istio-manifests
cd ${proj}/istio-manifests
Modifica worker-virtualservice.yaml per includere DestinationRules
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
Come puoi vedere, abbiamo aggiunto una seconda destinazione al nostro VirtualService. Fa ancora riferimento allo stesso host (worker-service.default.svc.cluster.local)), ma il 50% del traffico viene indirizzato al sottoinsieme primary e l'altro 50% al sottoinsieme burst.
Abbiamo definito il sottoinsieme primary come i deployment con l'etichetta cluster-type: primary-cluster e il sottoinsieme burst come i deployment con l'etichetta cluster-type: burst-cluster.
In questo modo, il traffico viene suddiviso in modo uniforme tra i due cluster.
Esegui il deployment nel cluster
Esegui il deployment di redis-service.yaml nel cluster burst
Passa a kubeconfig burst
kubectx burst
Passa alla radice del progetto
cd ${proj}
Quindi esegui il deployment
Esegui il deployment di redis-service.yaml nel cluster burst
kubectl apply -f kubernetes/redis-service.yaml
Esegui il deployment di worker-burst.yaml nel cluster burst
kubectl apply -f kubernetes/worker-burst.yaml
Esegui il deployment di worker-service.yaml nel cluster burst
kubectl apply -f kubernetes/worker-service.yaml
Applica i servizi virtuali Istio
Passa a kubeconfig primary
kubectx primary
Quindi, esegui il deployment.
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Verifica che funzioni
Per verificare che funzioni, vai al punto di ingresso Istio e nota che circa il 50% degli hash ha il prefisso "burst-".

Ciò significa che la comunicazione tra i cluster è riuscita. Prova a modificare i pesi sui diversi servizi e ad applicare il file worker-virtualservice.yaml. Questo è un ottimo modo per bilanciare il traffico tra i cluster, ma cosa succederebbe se potessimo farlo automaticamente?
16. Sfruttare le metriche di Prometheus
Introduzione a Prometheus
Prometheus è un toolkit di avviso e monitoraggio dei sistemi open source originariamente creato da SoundCloud. Mantiene un modello di dati multidimensionale con dati delle serie temporali identificati dal nome della metrica e dalle coppie chiave/valore.
Per riferimento, ecco il diagramma dell'architettura di Prometheus:

Istio, quando viene eseguito il deployment con Prometheus, invia automaticamente varie metriche al server Prometheus. Possiamo utilizzare queste metriche per gestire i nostri cluster al volo.
Esplorare le metriche di Prometheus
Per iniziare, dobbiamo esporre il deployment di Prometheus.
Vai alla scheda Workload in GKE e visualizza in dettaglio il workload "prometheus".

Una volta visualizzati i dettagli del deployment, vai ad Azioni -> Esponi.

Scegli di inoltrare alla porta 9090 e digita "Bilanciatore del carico".

e scegli "Esposizione".
In questo modo verrà creato un servizio su un indirizzo IP accessibile pubblicamente che possiamo utilizzare per esplorare le metriche di Prometheus
Attendi che l'endpoint diventi operativo e, una volta fatto, fai clic sull'indirizzo IP accanto a "Endpoint esterni" 
Ora dovresti visualizzare la UI di Prometheus.

Prometheus fornisce metriche sufficienti per essere un workshop a sé stante. Per il momento, però, inizieremo a esplorare la metrica istio_requests_total.
L'esecuzione di questa query restituisce una serie di dati. Si tratta di metriche su tutte le richieste che passano attraverso il service mesh Istio, e sono molte. Modificheremo l'espressione per filtrare i risultati e visualizzare solo ciò che ci interessa davvero:
Richieste in cui il servizio di destinazione è worker-service.default.svc.cluster.local e la cui origine è frontend-deployment limitata agli ultimi 15 secondi
La query è simile alla seguente:
istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]
e ci fornisce un insieme di dati molto più gestibile su cui lavorare.

ma è ancora un po' denso. Vogliamo conoscere le richieste al secondo, non tutte le richieste.
Per ottenere questo risultato, possiamo utilizzare la funzione integrata rate
rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])

Ci stiamo avvicinando, ma dobbiamo ridurre ulteriormente queste metriche in un gruppo logico.
Per farlo, possiamo utilizzare le parole chiave sum e by per raggruppare e sommare i risultati.
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)

Perfetto! Possiamo ottenere da Prometheus le metriche esatte di cui abbiamo bisogno.
Query Prometheus finale
Con tutto ciò che abbiamo imparato, la query finale che dobbiamo porre a Prometheus è
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)
Ora possiamo utilizzare la relativa API HTTP per ottenere la metrica.
Possiamo eseguire query sulla loro API con la nostra query effettuando una richiesta GET HTTP come segue. Sostituisci <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\)
Ecco un esempio di risposta:
{
"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"
]
}
]
}
}
Ora possiamo estrarre il valore della metrica dal JSON
Pulizia
Dobbiamo eliminare il servizio che abbiamo appena utilizzato per esporre Prometheus. Nella console Google Cloud, vai in cima al servizio che abbiamo appena creato e fai clic su "Elimina".

Passaggi successivi:
Dopo aver trovato un modo per scoprire come si sposta il traffico nel cluster e a quale velocità, il passaggio successivo consiste nello scrivere un piccolo binario che esegue periodicamente query su Prometheus e, se le richieste al secondo a worker superano una determinata soglia, applica pesi di destinazione diversi al nostro servizio virtuale di worker per inviare tutto il traffico al cluster burst. Una volta che le richieste al secondo scendono al di sotto di una soglia inferiore, invia tutto il traffico di nuovo a primary.
17. Crea un burst cross-cluster
Configurazione
Imposta tutto il traffico per il servizio worker sul cluster principale
Considereremo tutto il traffico destinato a worker-service e indirizzato al cluster primary come lo stato "predefinito" della nostra applicazione
Modifica $proj/istio-manifests/worker-virtualservice.yaml in modo che sia simile a quanto segue
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
Assicurati di essere connesso al cluster primary
kubectx primary
Applica istio-manifests/worker-virtualservice.yaml
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Scrivi il daemon istiowatcher
Utilizzeremo Go per scrivere questo servizio per la sua velocità e portabilità. Il flusso generale dell'applicazione sarà di avviarsi e, ogni secondo, interrogare Prometheus,
Crea una nuova directory in src denominata istiowatcher
mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher
Chiameremo istioctl dall'interno del nostro container per manipolare il control plane Istio dall'interno del cluster.
Scrivi istiowatcher.go
Crea un file denominato istiowatcher.go in questa directory e inserisci il seguente contenuto:
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)
}
}
Scrivi Dockerfile
Crea un nuovo file denominato Dockerfile e inserisci al suo interno quanto segue.
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"]
Questo Dockerfile in più fasi scarica ed estrae la release 1.0.0 di Istio nella prima fase. La seconda fase copia tutto dalla nostra directory nell'immagine, quindi copia istioctl dalla fase di build a /usr/local/bin (in modo che possa essere chiamato dalla nostra applicazione), recupera le dipendenze, compila il codice e imposta CMD su "istiowatcher".
Scrivi burst.yaml
Questo è il file che istiowatcher applicherà quando le richieste al secondo a worker da frontend superano 15.
Crea un nuovo file denominato burst.yaml e inserisci al suo interno quanto segue.
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
Scrivere natural.yaml
Considereremo questo lo stato "naturale" a cui torniamo quando le richieste al secondo da frontend a worker scendono sotto 10. In questo stato, il 100% del traffico viene indirizzato al cluster primary.
Crea un nuovo file denominato natural.yaml e inserisci al suo interno quanto segue
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
Crea e invia istiowatcher
Esegui questo comando per inviare la directory corrente a Google Cloud Build (GCB), che creerà e taggherà l'immagine in GCR.
gcloud builds submit -t gcr.io/${GCLOUD_PROJECT}/istiowatcher
Esegui il deployment di istiowatcher
Passa alla directory kubernetes
cd ${proj}/kubernetes/
Scrivi un file di deployment: istiowatcher.yaml
Crea un file denominato istiowatcher.yaml e inserisci quanto segue (sostituisci <your-project-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
Esegui il deployment
Assicurati che l'operazione venga eseguita nel cluster principale
kubectx primary
Esegui il deployment di istiowatcher.yaml nello spazio dei nomi istio-system
kubectl apply -n istio-system -f istiowatcher.yaml
È importante notare le direttive serviceAccountName e automountServiceAccountToken nel file YAML. In questo modo otteniamo le credenziali necessarie per eseguire istioctl dall'interno del cluster.
Dobbiamo anche eseguire il deployment all'interno dello spazio dei nomi istio-system per assicurarci di disporre delle credenziali per istio-pilot-service-account. (non esiste nello spazio dei nomi default).
Guarda il traffico passare automaticamente da un'app all'altra.
Ora il momento magico. Andiamo al nostro frontend e aumentiamo le richieste al secondo a 20.
Nota che ci vogliono alcuni secondi, ma aumenta e tutti i nostri hash hanno il prefisso "bursty-".
Questo perché stiamo campionando Prometheus nell'intervallo 15s, il che rallenta un po' il nostro tempo di risposta. Se volessimo una banda molto più stretta, potremmo modificare la query in prometheus in modo che sia 5s.
18. Passaggi successivi
Pulizia
Non è necessario eseguire la pulizia se utilizzi un account temporaneo fornito per questo workshop.
Puoi eliminare i cluster Kubernetes, la regola firewall e le immagini in GCR
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
Prospettive future
- Partecipa ad alcune conferenze su Istio.
- Ottieni la certificazione: crea la tua prossima app con Kubernetes + Istio
- Keynote: Kubernetes, Istio, Knative: The New Open Cloud Stack - Aparna Sinha, Group Product Manager for Kubernetes, Google
- Tutorial: Using Istio - Lee Calcote & Girish Ranganathan, SolarWinds
- Istio - The Packet's-Eye View - Matt Turner, Tetrate
- Istio è il firewall di nuova generazione più avanzato mai creato? - John Morello, Twistlock
- Leggi la documentazione di Istio.
- Partecipa ai gruppi di lavoro di Istio
- Segui @IstioMesh su Twitter




