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. Occorrente
|
|
Cosa imparerai
- Come creare un cluster Kubernetes su GKE
- Come installare Istio su un cluster Kubernetes con Helm
- Come installare Istio Multicluster con Helm
- Eseguire il deployment di un'applicazione web dal codice sorgente a Kubernetes
- Scrivere e applicare 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 in-browser con strumenti installati
- il tuo laptop (segui le istruzioni riportate di seguito)
Iniziare con Google Cloud
- Se non hai un account Google Cloud, ritira la scheda dell'account utente senza costi dall'insegnante.
- Vai alla console Google Cloud e fai clic su "Seleziona un progetto":

- Prendi nota dell'"ID" del progetto da qualche parte, quindi fai clic sul progetto per sceglierlo:

Opzione 1: utilizza Google Cloud Shell (opzione 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. Se non vuoi eseguire questo esercizio su Cloud Shell, vai alla sezione successiva.
Vai a Cloud Console 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****: segui 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. Scollega 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. Aumentare le dimensioni del testo: le dimensioni del carattere predefinite su Cloud Shell possono essere troppo piccole per essere lette. | Ctrl+ su Linux/Windows⌘+ su macOS. |
Opzione 2: configura il laptop (non consigliata)
Se ti senti più a tuo agio a utilizzare il tuo ambiente di workstation rispetto a 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 il seguente comando per l'installazione:
gcloud components install kubectl
Esegui il seguente comando per autenticare gcloud. Ti verrà chiesto di accedere con il tuo Account Google. Poi, scegli il progetto predefinito (vedi sopra) come progetto predefinito. (puoi saltare la configurazione di una zona di calcolo):
gcloud init
- Installa
curl:Preinstallato sulla maggior parte dei sistemi Linux/macOS. Probabilmente ce l'hai già. In caso contrario, cerca su internet come installarlo. - Installa
kubectx****: scarica gli script bash da qui in una posizione in $PATH - Installa
helm****: segui queste istruzioni.
3. Configura il 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
Configurare 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 del codice e file di configurazione, quindi creiamo una directory del progetto e passiamoci
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:
- denominato "principale",
- 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 monitorare la creazione del cluster in Cloud Console.
Dopo aver creato il cluster Kubernetes, gcloud configura kubectl con le credenziali che rimandano al cluster.
gcloud container clusters get-credentials $cluster --zone=$zone
Ora dovresti essere in grado di utilizzare kubectl con il nuovo cluster.
Esegui il comando seguente per elencare i nodi Kubernetes del tuo cluster (dovrebbero mostrare lo stato "Ready"):
kubectl get nodes
Modificare i nomi dei file Kubeconfig per facilitarne l'utilizzo
Passeremo spesso da un contesto all'altro, quindi è utile avere un alias breve per i nostri cluster.
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 imposta l'indirizzo email associato 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 un 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 monitorare la creazione del cluster in Cloud Console.
Dopo aver creato il cluster Kubernetes, gcloud configura kubectl con le credenziali che rimandano al cluster.
gcloud container clusters get-credentials $cluster --zone=$zone
Ora dovresti essere in grado di utilizzare kubectl con il nuovo cluster.
Esegui il comando seguente per elencare i nodi Kubernetes del tuo cluster (dovrebbero mostrare lo stato "Ready"):
kubectl get nodes
Modificare i nomi del file Kubeconfig per facilitarne l'utilizzo
Questo comando modificherà la voce kubeconfig che hai appena creato 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 imposta l'indirizzo email associato 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 i seguenti comandi per creare una regola firewall nella piattaforma 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
Abbiamo configurato entrambi i cluster e siamo pronti per eseguire il deployment della nostra applicazione e di Istio su di essi.
7. Introduzione a Istio
Che cos'è Istio?
Istio è un piano di controllo del mesh di servizi che mira a "connettere, proteggere, controllare e osservare i servizi". Lo fa in diversi modi, ma principalmente inserendo un container proxy ( Envoy) in ogni pod Kubernetes di cui è stato eseguito il deployment. Il contenitore proxy controlla tutte le comunicazioni di rete tra i microservizi in tandem con un hub di telemetria e criteri di uso generale ( Mixer).

Questi criteri possono essere applicati 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 i criteri 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 in base alla 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 instradamento del traffico da applicare quando viene indirizzato un host.
Gateway
Un gateway è un bilanciatore del carico che opera all'estremità della 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 i criteri da applicare 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
Quando abbiamo creato i due cluster, potresti aver notato che il cluster primary era composto da 4 nodi senza scalabilità automatica e il cluster burst da 1 nodo con scalabilità automatica fino a 5 nodi.
Questa configurazione è dovuta a due motivi.
Innanzitutto, vogliamo simulare uno scenario "on-premise" to Cloud. In un ambiente on-premise non hai accesso ai cluster con scalabilità automatica perché hai un'infrastruttura fissa.
In secondo luogo, una configurazione di 4 nodi (come definito sopra) è il requisito minimo per eseguire Istio. Questo ci porta alla domanda: se Istio richiede un minimo di 4 nodi, come può il nostro cluster burst eseguire Istio con un solo 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.
Lavoratore
L'applicazione di lavoro è scritta in NodeJS e ascolta le richieste HTTP POST in entrata, esegue su di esse un'operazione di hashing e, se è definita una variabile di ambiente denominata PREFIX, antepone l'hash a quel 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.
Come riferimento: questi sono i pacchetti utilizzati dall'applicazione.
body-parser:Ci consente di analizzare le richieste HTTPcors:Consente l'utilizzo della Condivisione delle risorse tra origini (CORS)dotenv:Analisi facile delle variabili di ambienteexpress:Hosting di siti web sempliciioredis:Libreria client per comunicare con i database Redismorgan:Fornisce un log ben 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 frequenza. 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 richieste HTTPdotenv:Analisi facile delle variabili di ambienteexpress:Hosting di siti web sempliciioredis:Libreria client per comunicare con i database Redismorgan:Fornisce log ben 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. Nel cluster primary verranno eseguiti il deployment di tutti i componenti (frontend, worker e Redis), mentre nel cluster burst verrà eseguita solo l'applicazione worker.
Ecco un diagramma che descrive i due cluster. Le caselle delineate in rosso sono servizi Kubernetes, quelle in blu sono deployment Kubernetes. Le caselle gialle indicano la nostra installazione di Istio.
Notare che nel cluster burst è ancora presente un servizio per Redis anche se non è presente alcun deployment per Redis nel cluster. Dobbiamo avere questo servizio nel cluster in modo che Kubernetes DNS possa risolvere la richiesta, ma quando la richiesta viene effettivamente effettuata, il proxy Istio reindirizzerà la richiesta al deployment di Redis nel cluster primary.
L'applicazione finale avrà un deployment aggiuntivo in esecuzione nel cluster primary denominato istiowatcher.. Questo ci consentirà di reindirizzare automaticamente il traffico a burst quando il traffico supera una determinata soglia.

9. Creare file di deployment dell'applicazione
Dobbiamo creare un insieme di manifest Kubernetes per eseguire il deployment della nostra applicazione
Vai alla directory principale del progetto e crea una nuova cartella denominata kubernetes
mkdir ${proj}/kubernetes && cd ${proj}/kubernetes
Scrivere 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 chiave 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 contenitore per aiutare Kubernetes a capire quando il contenitore è attivo e funzionante.
Scrivere worker-service.yaml
Stiamo scrivendo la definizione del servizio Kubernetes in un file separato rispetto alla definizione del deployment perché 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
Scrivere worker-primary.yaml
Questo sarà il deployment di worker che eseguiremo nel 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"
Tieni presente che in questo caso seguiamo lo stesso schema di fornitura di sonde liveness e readiness, nonché di specificazione 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 calcolo saranno hash non elaborati (senza prefisso).
L'ultimo punto chiave di questo deployment è l'etichetta cluster-type: primary-cluster. Lo utilizzeremo più avanti quando eseguiremo il routing del traffico su Istio Multicluster
Scrivere redis.yaml
La comunicazione dal nostro worker al frontend avviene tramite un canale Redis, 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 contenitore basato sull'immagine redis:alpine, espone le porte appropriate e imposta limiti di risorse ragionevoli.
Scrivere 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
Questo fornisce il servizio denominato redis-cache-service per accedere al nostro deployment Redis.
10. Esegui il deployment dell'applicazione
Ora che le nostre immagini sono state caricate su GCR e i manifest Kubernetes sono stati scritti, è un buon momento per eseguire il deployment della nostra applicazione e vedere come funziona.
Esegui i seguenti comandi per eseguire il deployment dell'applicazione
- Assicurati che siamo 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 worker
kubectl apply -f worker-primary.yaml
- Esegui il deployment del servizio worker
kubectl apply -f worker-service.yaml
Abbiamo eseguito il deployment della nostra applicazione in GKE. Complimenti!
Test
Attendi che i pod vengano attivati online
kubectl get pods -w
Una volta che tutti i pod sono in stato "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 attivo e funzionante, utilizzeremo kubectl port-forward. Esegui il seguente comando per inoltrare la porta 8080 sulla tua macchina locale (o Cloud Shell) alla porta 8080 su cui è in esecuzione il deployment 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 alla pagina http://localhost:8080
Se esegui l'operazione 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 vedere gli hash.

Congratulazioni, è tutto pronto.
Premi Ctrl+C per interrompere il port forwarding.
11. Ripulire l'applicazione di cui è stato eseguito il deployment
Applicheremo Istio al nostro cluster e poi eseguiremo nuovamente il deployment della nostra applicazione, quindi iniziamo a ripulire l'applicazione attuale.
Esegui i seguenti comandi per eliminare tutti i deployment e i servizi appena creati
- 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 principale
Ottieni Istio
Le release di Istio sono ospitate su GitHub. I comandi seguenti scaricano e decomprimono la versione 1.0.0 di Istio.
- Passa alla radice del progetto
cd ${proj}
- Scarica 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 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. Aggiungono il supporto di Prometheus e ServiceGraph al 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 su base di attivazione, quindi dobbiamo etichettare il nostro spazio dei nomi default con istio-injection=enabled in modo che Istio possa iniettare automaticamente il sidecar.
kubectl label namespace default istio-injection=enabled
Complimenti! Abbiamo un cluster funzionante con Istio pronto per il deployment della nostra applicazione.
13. Esegui il deployment della nostra applicazione con la gestione del traffico Istio
Creare file di configurazione per la gestione del traffico Istio
Istio funziona in modo simile a Kubernetes in quanto utilizza file YAML per la configurazione. In questo senso, 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 quella directory
mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests
Scrivere 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
Scrivere 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
Esegui il deployment delle norme di gestione del traffico Istio
Il deployment dei criteri Istio viene eseguito nello 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 VirtualService di Worker
kubectl apply -f worker-virtualservice.yaml
Esegui il deployment dell'applicazione
- Torna alla nostra 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 worker
kubectl apply -f worker-primary.yaml
- Esegui il deployment del servizio worker
kubectl apply -f worker-service.yaml
Verifica
A questo punto abbiamo eseguito nuovamente il deployment della nostra applicazione su un cluster con Istio e criteri di gestione del traffico.
Aspettiamo che tutti i nostri carichi di lavoro vengano attivati
Una volta che sono tutti online, recupera 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 esegui curl e dovresti vedere il frontend.
$ curl 35.199.158.10
<!doctype html>
<html>
<head>
<title>String Hashr</title>
<!-- Bootstrap -->
...
14. Installa Istio su un cluster "burst"
Abbiamo impiegato molto tempo per la configurazione e il deployment nel nostro cluster primary, ma abbiamo un altro intero cluster su cui eseguire il deployment.
In questa sezione dovremo acquisire le variabili di configurazione di entrambi i cluster, quindi presta molta attenzione al cluster a cui facciamo riferimento per ogni comando.
Crea il manifest Istio Remote
Come quando abbiamo eseguito il deployment di Istio nel cluster primary, utilizzeremo Helm per creare un modello del deployment di Istio Remote nel cluster burst. Tuttavia, prima di poter procedere, abbiamo bisogno di 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 principale. Questi vengono utilizzati da Istio Remote per comunicare nuovamente 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}')
Creare un modello remoto
Ora utilizzeremo helm per creare un file denominato istio-remote-burst.yaml che potremo poi eseguire 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 nel nostro cluster burst, dobbiamo seguire gli stessi passaggi eseguiti per l'installazione nel 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. Tuttavia, a questo punto i cluster non sono ancora in grado di comunicare. Dobbiamo generare un file kubeconfig per il cluster burst che possiamo eseguire nel cluster primary per collegarli.
Creare il file kubeconfig per il cluster "burst"
Passare al cluster burst
kubectx burst
Configurare l'ambiente
Dobbiamo raccogliere alcune informazioni sul cluster per creare un file kubeconfig.
- 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 dell'account di servizio
istio-multi
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
- Recupera i dati dell'autorità di certificazione memorizzati nel segreto precedente
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
- Recupera 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
Dopo aver impostato tutte le variabili di ambiente, 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 e assegnandogli un'etichetta
kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system
Etichetta il segreto in modo che Istio sappia di utilizzarlo per l'autenticazione multicluster
kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system
Complimenti! Entrambi i cluster sono autenticati e comunicano tra loro tramite Istio Multicluster. Eseguiamo il deployment dell'applicazione in più cluster
15. Esegui il deployment di un'applicazione tra cluster
Creare deployment
Passa alla directory kubernetes
cd ${proj}/kubernetes
Crea il deployment dei worker per il cluster "burst": worker-burst.yaml
Crea un file denominato worker-burst.yaml e inserisci 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-"
Tieni presente che questo file è quasi identico a worker-primary.yaml che abbiamo creato in precedenza. Esistono due differenze principali.
La prima differenza principale è 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 inviati il prefisso "bursty-". Possiamo utilizzare questo valore per sapere che la nostra applicazione è veramente cross-cluster.
La seconda differenza principale è che abbiamo modificato l'etichetta cluster-type di questo deployment da primary-cluster a burst-cluster
labels:
app: worker
cluster-type: burst-cluster
Utilizzeremo questa etichetta in seguito quando aggiorneremo il nostro VirtualService.
Modificare i servizi Istio
Al momento i nostri servizi Istio non sfruttano entrambi i deployment. Il 100% del nostro traffico viene indirizzato al cluster "principale". Cambiamolo.
Passa alla nostra directory istio-manifests
cd ${proj}/istio-manifests
Modifica il file 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
Puoi vedere che 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 efficace al 50% 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 directory principale 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
Applicare VirtualServices di Istio
Passa al file kubeconfig primary
kubectx primary
Quindi Esegui il deployment
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Verificare il funzionamento
Per verificare che funzioni, vai al punto di ingresso Istio e noterai che circa il 50% degli hash ha il prefisso "burst-".

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

Quando viene eseguito il deployment di Istio con Prometheus, vengono registrate automaticamente varie metriche sul server Prometheus. Possiamo utilizzare queste metriche per gestire i nostri cluster in tempo reale.
Esplorazione delle nostre metriche di Prometheus
Per iniziare, dobbiamo esporre il deployment di Prometheus.
Vai alla scheda Workload in GKE, vai al 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 "Mostra"
Verrà creato un servizio su un indirizzo IP accessibile pubblicamente che potremo utilizzare per esplorare le nostre metriche Prometheus
Attendi che l'endpoint diventi operativo, quindi fai clic sull'indirizzo IP accanto a "Endpoint esterni" 
A questo punto dovresti vedere l'interfaccia utente di Prometheus.

Prometheus fornisce metriche sufficienti per essere un proprio laboratorio. Per il momento, però, inizieremo esplorando 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 mesh di servizi Istio, e sono molte. Modificheremo l'espressione per filtrare i risultati in base a 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 ha il seguente aspetto:
istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]
e ci offre un insieme di dati molto più gestibile

Ma è ancora un po' confuso. Vogliamo conoscere le richieste al secondo, non tutte le richieste.
Per farlo, possiamo utilizzare la funzione incorporata 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 le metriche esatte di cui abbiamo bisogno da Prometheus.
La nostra query Prometheus finale
Con tutto ciò che abbiamo appreso, l'ultima query che dobbiamo chiedere 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 sull'API con la nostra query inviando una richiesta GET HTTP come questa. 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 nella parte superiore del servizio che abbiamo appena creato e fai clic su "Elimina".

Passaggi successivi:
Dopo aver trovato un modo per scoprire come si muove il traffico all'interno del cluster e a quale velocità, il passaggio successivo consiste nello scrivere un piccolo file binario che esegue query periodicamente su Prometheus e, se le richieste al secondo per worker superano una determinata soglia, applica pesi di destinazione diversi al nostro servizio virtuale di lavoro per inviare tutto il traffico al cluster burst. Quando le richieste al secondo scendono al di sotto di una soglia inferiore, invia tutto il traffico a primary.
17. Creare un'esplosione tra cluster
Configurazione
Impostare tutto il traffico per il servizio worker sul cluster principale
Considereremo tutto il traffico destinato a worker-service instradato al cluster primary come lo stato "predefinito" della nostra applicazione
Modifica $proj/istio-manifests/worker-virtualservice.yaml in modo che abbia il seguente aspetto
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
Scrivere il daemon istiowatcher
Per scrivere questo servizio utilizzeremo Go per la sua velocità e portabilità. Il flusso complessivo dell'applicazione sarà avviarsi ed eseguire ogni secondo una query su Prometheus.
Crea una nuova directory in src denominata istiowatcher
mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher
Chiameremo istioctl dal nostro contenitore per manipolare il piano di controllo Istio all'interno del cluster.
Scrivere istiowatcher.go
Crea un file nella directory denominato istiowatcher.go e inserisci quanto segue
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)
}
}
Scrivere il Dockerfile
Crea un nuovo file denominato Dockerfile e inserisci 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 multi-stadio scarica ed estrae la release 1.0.0 di Istio nella prima fase. Il secondo passaggio copia tutto dalla nostra directory nell'immagine, poi copia istioctl dalla fase di compilazione in /usr/local/bin (in modo che possa essere chiamato dalla nostra applicazione), recupera le dipendenze, compila il codice e imposta CMD su "istiowatcher"
Scrivere burst.yaml
Questo è il file che istiowatcher applicherà quando le richieste/secondo a worker da frontend superano 15.
Crea un nuovo file denominato burst.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
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
Lo considereremo lo stato "naturale" a cui torniamo quando le richieste/secondo da frontend a worker scendono al di sotto di 10. In questo stato, il 100% del traffico viene indirizzato al cluster primary.
Crea un nuovo file denominato natural.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
subset: primary
port:
number: 80
weight: 100
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 0
Crea e esegui il push di istiowatcher
Esegui il seguente 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 nostra directory kubernetes
cd ${proj}/kubernetes/
Scrivere 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'esecuzione sia 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 all'interno del cluster.
Inoltre, dobbiamo 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 passaggio automatico del traffico.
Ora è arrivato il momento magico. Andiamo al nostro frontend e aumentiamo le richieste/secondo a 20
Tieni presente che l'operazione richiede alcuni secondi, ma viene eseguita fino a quando tutti gli hash non hanno il prefisso "bursty-".
Questo perché stiamo campionando prometheus nell'intervallo 15s, il che rende un po' più lento il tempo di risposta. Se volessimo una banda molto più ristretta, potremmo modificare la query di Prometheus in modo che sia 5s.
18. Passaggi successivi
Pulizia
Non è necessario eseguire la pulizia se utilizzi un account temporaneo fornito per questo laboratorio.
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
Passaggi successivi
- Partecipa ad alcuni Istio Talks.
- Ottieni la certificazione: crea la tua prossima app con Kubernetes + Istio
- Keynote: Kubernetes, Istio, Knative: il nuovo stack cloud open - Aparna Sinha, Group Product Manager per Kubernetes, Google
- Tutorial: utilizzo di Istio - Lee Calcote e 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 Istio
- Segui @IstioMesh su Twitter




