1. Bienvenue
Merci d'avoir participé à l'atelier de programmation Google sur le bursting multicloud Istio.Cet atelier de programmation nécessite une expérience pratique de niveau débutant avec Kubernetes, Node et Go. Ce dont vous aurez besoin
|
|
Points abordés
- Créer un cluster Kubernetes sur GKE
- Installer Istio sur un cluster Kubernetes avec Helm
- Installer Istio Multicluster avec Helm
- Déployer une application Web à partir de la source vers Kubernetes
- Écrire et appliquer des règles de routage du trafic à Istio
- Métriques Prometheus
- Créer et transférer des images de conteneurs dans un cluster Kubernetes
2. Configuration
Vous pouvez suivre cet atelier de programmation sur :
- Google Cloud Shell (recommandé) : shell intégré au navigateur, avec outils installés
- votre ordinateur portable (suivez les instructions ci-dessous)
Premiers pas avec Google Cloud Platform
- Si vous n'avez pas de compte GCP, demandez à votre instructeur de vous fournir une carte de compte utilisateur sans frais.
- Accédez à la console Google Cloud et cliquez sur "Sélectionner un projet" :
. - Notez l'ID du projet quelque part, puis cliquez sur le projet pour le sélectionner :

Option 1 : Utiliser Google Cloud Shell (recommandé)
Cloud Shell fournit un shell de ligne de commande dans votre navigateur, avec les outils dont vous avez besoin installés et automatiquement authentifiés sur votre compte Google Cloud Platform. (Si vous ne souhaitez pas exécuter cet exercice sur Cloud Shell, passez à la section suivante.)
Accédez à la console Cloud et cliquez sur "Activer Cloud Shell" dans la barre d'outils en haut à droite :

Ajouter des outils à Cloud Shell
- Installez
kubectx**** en téléchargeant les scripts Bash depuis ce lien vers un emplacement dans $PATH. - Installez
helm**** en suivant ces instructions.
Vous pouvez également exécuter ces commandes pour installer les deux à ~/.bin et les ajouter à votre $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}
Voici quelques conseils rapides qui peuvent vous aider à utiliser Cloud Shell :
1. Détachez le shell dans une nouvelle fenêtre : |
|
2. Utiliser l'éditeur de fichiers : cliquez sur l'icône en forme de crayon en haut à droite pour lancer un éditeur de fichiers dans le navigateur. Cela vous sera utile, car nous allons copier des extraits de code dans des fichiers. |
|
3. Ouvrez de nouveaux onglets : si vous avez besoin de plusieurs invites de terminal. |
|
4. Agrandissez le texte : la taille de police par défaut dans Cloud Shell peut être trop petite pour être lue. | Ctrl+ + sur Linux/Windows ou ⌘+ + sur macOS |
Option 2 : Configurer votre ordinateur portable (non recommandé)
Si vous préférez utiliser votre propre environnement de poste de travail plutôt que Cloud Shell, configurez les outils suivants :
- Installez
gcloud:(préinstallé sur Cloud Shell). Suivez les instructions pour installergcloudsur votre plate-forme. Nous l'utiliserons pour créer un cluster Kubernetes. - Installez
kubectl:(préinstallé sur Cloud Shell). Exécutez la commande suivante pour installer :
gcloud components install kubectl
Exécutez la commande suivante pour authentifier gcloud. Vous serez invité à vous connecter avec votre compte Google. Ensuite, choisissez le projet pré-créé (voir ci-dessus) comme projet par défaut. (Vous pouvez ignorer la configuration d'une zone de calcul) :
gcloud init
- Installer
curl:: préinstallé sur la plupart des systèmes Linux/macOS. Vous l'avez probablement déjà. Sinon, recherchez sur Internet comment l'installer. - Installez
kubectx**** en téléchargeant les scripts Bash depuis ce lien vers un emplacement dans $PATH. - Installez
helm**** en suivant ces instructions.
3. Configurer un projet GCP
Activez les API GKE (Google Kubernetes Engine), GCR (Google Container Registry) et GCB (Google Cloud Build) dans votre projet :
gcloud services enable \ cloudapis.googleapis.com \ container.googleapis.com \ containerregistry.googleapis.com \ cloudbuild.googleapis.com
Configurer des variables d'environnement
Nous allons travailler intensivement avec notre projet Google Cloud lors de la configuration. Définissons une variable d'environnement pour une référence rapide.
export GCLOUD_PROJECT=$(gcloud config get-value project)
Nous allons créer des fichiers de code et de configuration au cours de cet atelier. Créons donc un répertoire de projet et accédons-y.
mkdir -p src/istio-burst && \ cd src/istio-burst && \ export proj=$(pwd)
4. Créer le cluster Kubernetes "primary"
Vous pouvez facilement créer un cluster Kubernetes géré avec Google Kubernetes Engine (GKE).
La commande suivante crée un cluster Kubernetes :
- nommée "primary",
- dans la zone us-west1-a,
- La dernière version de Kubernetes disponible,
- avec quatre nœuds initiaux.
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
(Cette opération peut prendre environ cinq minutes. Vous pouvez observer la création du cluster dans la console Cloud.)
Une fois le cluster Kubernetes créé, gcloud configure kubectl avec les identifiants pointant vers le cluster.
gcloud container clusters get-credentials $cluster --zone=$zone
Vous devriez maintenant pouvoir utiliser kubectl avec votre nouveau cluster.
Exécutez la commande suivante pour lister les nœuds Kubernetes de votre cluster (leur état doit être "Prêt") :
kubectl get nodes
Modifier les noms Kubeconfig pour faciliter l'utilisation
Nous allons souvent changer de contexte. Il est donc pratique d'avoir un alias court pour nos clusters.
Cette commande renomme l'entrée kubeconfig que vous venez de créer en primary.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Définissez les autorisations :
Pour déployer Istio, vous devez être administrateur de cluster. Cette commande définit l'adresse e-mail associée à votre compte Google Cloud comme administrateur du cluster.
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
5. Créer un cluster "burst"
La commande suivante crée un cluster Kubernetes :
- nommé "burst",
- dans la zone us-west1-a,
- La dernière version de Kubernetes disponible,
- Avec un nœud initial
- Autoscaling activé jusqu'à cinq nœuds
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
(Cette opération peut prendre environ cinq minutes. Vous pouvez observer la création du cluster dans la console Cloud.)
Une fois le cluster Kubernetes créé, gcloud configure kubectl avec les identifiants pointant vers le cluster.
gcloud container clusters get-credentials $cluster --zone=$zone
Vous devriez maintenant pouvoir utiliser kubectl avec votre nouveau cluster.
Exécutez la commande suivante pour lister les nœuds Kubernetes de votre cluster (leur état doit être "Prêt") :
kubectl get nodes
Modifier les noms Kubeconfig pour faciliter l'utilisation
Cette commande modifie l'entrée kubeconfig que vous venez de créer en burst.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Définissez les autorisations :
Pour déployer Istio Remote, vous devez être administrateur de cluster. Cette commande définit l'adresse e-mail associée à votre compte Google Cloud comme administrateur du cluster.
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
6. Appliquer des règles de pare-feu
Pour que nos deux clusters puissent communiquer entre eux, nous devons créer une règle de pare-feu.
Exécutez les commandes suivantes pour créer une règle de pare-feu dans Google Cloud Platform qui permettra à nos clusters de communiquer.
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
Nos deux clusters sont configurés et prêts à accueillir le déploiement de notre application et d'Istio.
7. Présentation d'Istio
Qu'est-ce qu'Istio ?
Istio est un plan de contrôle de maillage de services qui vise à "connecter, sécuriser, contrôler et observer les services". Pour ce faire, il utilise différentes méthodes, mais principalement en ajoutant un conteneur proxy ( Envoy) à chaque pod Kubernetes déployé. Le conteneur de proxy contrôle toutes les communications réseau entre les microservices en tandem avec un hub de télémétrie et de règles à usage général ( Mixer).

Ces règles peuvent être appliquées indépendamment de vos déploiements et services Kubernetes, ce qui signifie que l'opérateur réseau peut observer l'activité réseau, restreindre, rediriger ou réécrire les règles réseau sans redéployer les applications associées.
Voici quelques-unes des fonctionnalités de gestion du trafic compatibles avec Istio :
- Disjoncteurs
- Répartition du trafic en fonction d'un pourcentage
- Réécriture d'URL
- terminaison TLS
- Vérifications d'état
- Équilibrage de charge
Pour cet atelier, nous allons nous concentrer sur la répartition du trafic en pourcentage.
Termes Istio que nous allons utiliser
VirtualService
Un VirtualService définit un ensemble de règles de routage du trafic à appliquer lorsqu'un hôte est adressé.
Passerelle
Une passerelle est un équilibreur de charge qui fonctionne à la périphérie du réseau maillé et reçoit des connexions HTTP/TCP entrantes ou sortantes. Les passerelles peuvent spécifier des ports, des configurations SNI, etc.
DestinationRule
Une DestinationRule définit les règles qui s'appliquent au trafic destiné à un service après le routage. Ils spécifient la configuration de l'équilibrage de charge, la taille du pool de connexions à partir du side-car et les paramètres de détection des valeurs aberrantes.
Istio Multicluster
Vous avez peut-être remarqué que lorsque nous avons créé nos deux clusters, notre cluster primary comportait quatre nœuds sans autoscaling, et notre cluster burst comportait un nœud avec autoscaling jusqu'à cinq nœuds.
Cette configuration est nécessaire pour deux raisons.
Tout d'abord, nous voulons simuler un scénario "sur site" vers le cloud. Dans un environnement sur site, vous n'avez pas accès aux clusters d'autoscaling, car votre infrastructure est fixe.
Deuxièmement, une configuration à quatre nœuds (telle que définie ci-dessus) est la configuration minimale requise pour exécuter Istio. Cela soulève une question : si Istio nécessite au moins quatre nœuds, comment notre cluster burst peut-il exécuter Istio avec un seul nœud ? La réponse est qu'Istio Multicluster installe un ensemble beaucoup plus petit de services Istio et communique avec l'installation Istio dans le cluster principal pour récupérer les règles de stratégie et publier les informations de télémétrie.
8. Présentation de l'architecture de l'application
Présentation des composants
Nous allons déployer une application à trois niveaux à l'aide de NodeJS et Redis.
Worker
L'application Worker est écrite en NodeJS et écoute les requêtes HTTP POST entrantes. Elle effectue une opération de hachage sur ces requêtes et, si une variable d'environnement nommée PREFIX est définie, elle ajoute cette valeur au hachage. Une fois le hachage calculé, l'application envoie le résultat sur le canal "calculation" du serveur Redis spécifié.
Nous utiliserons la variable d'environnement PREFIX plus tard pour illustrer la fonctionnalité multicluster.
Pour référence, voici les packages utilisés par l'application.
body-parser:Nous permet d'analyser nos requêtes HTTPcors:Permet l'utilisation du partage des ressources entre origines multiplesdotenv:Analyse facile des variables d'environnementexpress:Hébergement de sites Web facile- Bibliothèque cliente
ioredis:pour communiquer avec les bases de données Redis morgan:Fournit un journal structuré
Frontend
Notre interface est également une application NodeJS qui héberge une page Web à l'aide d'express. Il prend en compte la fréquence saisie par l'utilisateur et envoie des requêtes à notre application worker à ce rythme. Cette application s'abonne également aux messages sur un canal Redis nommé "calculation" et affiche les résultats sur une page Web.
L'application utilise les dépendances suivantes.
body-parser:Nous permet d'analyser nos requêtes HTTPdotenv:Analyse facile des variables d'environnementexpress:Hébergement de sites Web facile- Bibliothèque cliente
ioredis:pour communiquer avec les bases de données Redis morgan:Fournit des journaux structurésrequest:Permet d'effectuer des requêtes HTTPsocket.io:Permet une communication bidirectionnelle entre la page Web et le serveur
Cette page Web utilise Bootstrap pour la mise en forme et, une fois exécutée, ressemble à ce qui suit :

Schéma d'architecture

Diagramme de déploiement
Nous allons déployer notre application finale sur les deux clusters que nous avons créés. Le cluster primary aura tous les composants (frontend, worker et Redis) déployés, mais le cluster burst n'aura que l'application worker déployée.
Voici un schéma décrivant les deux clusters. Les zones encadrées en rouge sont des services Kubernetes, celles en bleu sont des déploiements Kubernetes. Les zones jaunes indiquent l'installation d'Istio.
Notez que le cluster burst dispose toujours d'un service pour Redis, même s'il n'y a aucun déploiement pour Redis dans le cluster. Nous devons disposer de ce service dans le cluster pour que Kubernetes DNS puisse résoudre la requête. Toutefois, lorsque la requête est réellement effectuée, le proxy Istio la redirige vers le déploiement Redis dans le cluster primary.
L'application finale comportera un déploiement supplémentaire exécuté dans le cluster primary nommé istiowatcher.. C'est ce qui nous permettra de rediriger dynamiquement le trafic vers burst automatiquement lorsque notre trafic dépassera un certain seuil.

9. Créer des fichiers de déploiement d'application
Nous devons créer un ensemble de fichiers manifestes Kubernetes pour déployer notre application.
Accédez au répertoire racine du projet et créez un dossier nommé kubernetes.
mkdir ${proj}/kubernetes && cd ${proj}/kubernetes
Écrire frontend.yaml
Cela créera un déploiement et un service Kubernetes pour accéder à notre image d'interface.
Insérez le code suivant dans 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
Points clés à noter dans Deployment
- Nous avons spécifié que l'application s'exécutera sur le port
8080. - Nous avons défini l'adresse du nœud de calcul sur "
http://worker-service" et nous utiliserons la fonctionnalité DNS intégrée de Kubernetes pour résoudre le service résultant. - Nous avons défini l'adresse de notre
REDIS_URLsur "redis-cache-service:6379" et nous utiliserons la fonctionnalité DNS intégrée de Kubernetes pour résoudre les adresses IP résultantes. - Nous avons également défini des vérifications
livenessetreadinesspour le conteneur afin d'informer Kubernetes lorsque le conteneur est opérationnel.
Écrire worker-service.yaml
Nous allons écrire la définition du service Kubernetes dans un fichier distinct de la définition du déploiement, car nous allons réutiliser ce service sur plusieurs clusters, mais nous allons écrire un déploiement différent pour chaque cluster.
Insérez le code suivant dans worker-service.yaml
apiVersion: v1
kind: Service
metadata:
name: worker-service
spec:
type: ClusterIP
selector:
app: worker
ports:
- name: http
port: 80
targetPort: 8081
Écrire worker-primary.yaml
Il s'agit du déploiement de worker que nous allons transférer vers le cluster principal.
Insérez le code suivant dans 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"
Notez que nous suivons le même modèle pour fournir les sondes liveness et readiness, et pour spécifier les variables d'environnement PORT et REDIS_URL que notre application doit utiliser.
Un autre point à noter dans ce déploiement est l'absence de la variable d'environnement PREFIX. Cela signifie que les résultats de nos calculs seront des hachages bruts (sans préfixe).
Le dernier point clé de ce déploiement est le libellé cluster-type: primary-cluster. Nous l'utiliserons plus tard pour le routage du trafic sur Istio Multicluster.
Écrire redis.yaml
La communication de notre nœud de calcul avec l'interface s'effectue via un canal Redis. Nous devons donc déployer une application Redis dans notre cluster.
Insérez le code suivant dans 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: {}
Il s'agit d'un déploiement semi-standard d'une application Redis. Il crée un conteneur basé sur l'image redis:alpine, expose les ports appropriés et définit des limites de ressources raisonnables.
Écrire redis-service.yaml
Nous avons besoin d'un service Kubernetes pour communiquer avec notre application Redis.
Insérez le code suivant dans redis-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-cache-service
spec:
type: ClusterIP
selector:
app: redis-cache
ports:
- port: 6379
targetPort: 6379
Cela fournit un service nommé redis-cache-service pour accéder à notre déploiement Redis.
10. Déployer l'application
Maintenant que nos images sont transférées vers GCR et que nos fichiers manifestes Kubernetes sont écrits, c'est le bon moment pour déployer notre application et voir comment elle fonctionne.
Exécutez les commandes suivantes pour déployer l'application.
- Assurez-vous que nous sommes dans le bon cluster.
kubectx primary
- Déployer le cache Redis
kubectl apply -f redis.yaml
- Déployer le service Redis
kubectl apply -f redis-service.yaml
- Déployer l'interface
kubectl apply -f frontend.yaml
- Déployer le nœud de calcul
kubectl apply -f worker-primary.yaml
- Déployer le service Worker
kubectl apply -f worker-service.yaml
Nous avons déployé notre application sur GKE. Félicitations !
Tester
Attendez que les pods soient en ligne.
kubectl get pods -w
Une fois que tous les pods sont en cours d'exécution, appuyez sur 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
Vous remarquerez que nous n'avons pas exposé notre frontend via un équilibreur de charge. En effet, nous accéderons à l'application via Istio ultérieurement. Pour vérifier que tout fonctionne correctement, nous allons utiliser kubectl port-forward.. Exécutez la commande suivante pour transférer le port 8080 sur votre machine locale (ou Cloud Shell) vers le port 8080 exécutant le déploiement frontend.
kubectl port-forward \
$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}') \
8080:8080
Si vous exécutez l'application en local : ouvrez un navigateur Web et accédez à http://localhost:8080.
Si vous exécutez le code dans Cloud Shell, cliquez sur le bouton "Aperçu sur le Web" et sélectionnez "Prévisualiser sur le port 8080".

L'interface utilisateur doit s'afficher. Si vous saisissez un nombre dans la zone "Fréquence", des hachures devraient commencer à apparaître.

Félicitations, tout est opérationnel !
Appuyez sur Ctrl+C pour arrêter le transfert du port.
11. Nettoyer l'application déployée
Nous allons appliquer Istio à notre cluster, puis redéployer notre application. Commençons donc par nettoyer notre application actuelle.
Exécutez les commandes suivantes pour supprimer tous les déploiements et services que vous venez de créer.
- Supprimer
redis-cache-service
kubectl delete -f redis-service.yaml
- Supprimer
redis
kubectl delete -f redis.yaml
- Supprimer
frontend
kubectl delete -f frontend.yaml
- Supprimer
worker
kubectl delete -f worker-primary.yaml
- Supprimer
worker-service
kubectl delete -f worker-service.yaml
12. Installer Istio sur le cluster principal
Obtenir Istio
Les versions d'Istio sont hébergées sur GitHub. Les commandes suivantes téléchargeront la version 1.0.0 d'Istio et la décompresseront.
- Accédez à la racine de votre projet.
cd ${proj}
- Télécharger l'archive
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
- Extraire et supprimer l'archive
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz
Créer un modèle Istio
L'exécution de la commande Helm suivante créera le modèle permettant d'installer Istio sur votre 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
Cette commande crée un fichier nommé istio-primary.yaml dans votre répertoire actuel. Il contient toutes les définitions et spécifications nécessaires au déploiement et à l'exécution d'Istio.
Notez les deux paramètres --set. Ces modules complémentaires ajoutent la compatibilité avec Prometheus et ServiceGraph au système Istio. Nous utiliserons le service Prometheus plus loin dans l'atelier.
Déployer Istio
Pour déployer Istio, nous devons d'abord créer un espace de noms appelé istio-system dans lequel les déploiements et services Istio peuvent s'exécuter.
kubectl create namespace istio-system
Enfin, appliquez le fichier istio-primary.yaml que nous avons créé avec Helm.
kubectl apply -f istio-primary.yaml
Espace de noms par défaut des libellés
Istio fonctionne en injectant un service de proxy side-car dans chacun de vos déploiements. Cette opération est effectuée sur la base d'un consentement. Nous devons donc ajouter le libellé istio-injection=enabled à notre espace de noms default pour qu'Istio puisse injecter automatiquement le side-car.
kubectl label namespace default istio-injection=enabled
Félicitations ! Nous avons un cluster opérationnel avec Istio prêt à déployer notre application.
13. Déployer notre application avec la gestion du trafic Istio
Créer des fichiers de configuration de gestion du trafic Istio
Istio fonctionne de la même manière que Kubernetes, car il utilise des fichiers YAML pour la configuration. Dans cette optique, nous devons créer un ensemble de fichiers pour indiquer à Istio comment exposer et acheminer notre trafic.
Créez un répertoire nommé istio-manifests et accédez-y.
mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests
Écrire frontend-gateway.yaml
Ce fichier exposera notre cluster Kubernetes de manière semblable à un équilibreur de charge GKE et acheminera tout le trafic entrant vers notre service de frontend.
Créez un fichier appelé frontend-gateway.yaml et insérez-y le contenu suivant.
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
Écrire redis-virtualservice.yaml
Créez un fichier nommé redis-virtualservice.yaml et insérez-y les éléments suivants :
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
Écrire worker-virtualservice.yaml
Créez un fichier nommé worker-virtualservice.yaml et insérez-y les éléments suivants :
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
Déployer les règles de gestion du trafic Istio
Le déploiement des règles Istio s'effectue de la même manière que pour les autres ressources Kubernetes, avec kubectl apply.
- Appliquer notre passerelle
kubectl apply -f frontend-gateway.yaml
- Appliquer notre VirtualService Redis
kubectl apply -f redis-virtualservice.yaml
- Appliquer notre VirtualService Worker
kubectl apply -f worker-virtualservice.yaml
Déployer l'application
- Revenir à notre répertoire
kubernetes
cd ${proj}/kubernetes
- Déployer le cache Redis
kubectl apply -f redis.yaml
- Déployer le service Redis
kubectl apply -f redis-service.yaml
- Déployer l'interface
kubectl apply -f frontend.yaml
- Déployer le nœud de calcul
kubectl apply -f worker-primary.yaml
- Déployer le service Worker
kubectl apply -f worker-service.yaml
Valider
À ce stade, nous avons redéployé notre application sur un cluster avec des règles de gestion du trafic et Istio.
Attendons que toutes nos charges de travail soient en ligne.
Une fois qu'ils sont tous en ligne, récupérez l'IngressGateway que nous avons configuré dans 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,
Accédez à l'adresse <EXTERNAL-IP> ou envoyez une requête cURL. L'interface utilisateur devrait s'afficher.
$ curl 35.199.158.10
<!doctype html>
<html>
<head>
<title>String Hashr</title>
<!-- Bootstrap -->
...
14. Installer Istio sur le cluster "burst"
Nous avons passé beaucoup de temps à configurer et à déployer notre cluster primary, mais nous avons un autre cluster entier à déployer !
Dans cette section, nous devrons récupérer les variables de configuration dans les deux clusters. Faites donc bien attention au cluster vers lequel nous sommes dirigés pour chaque commande.
Créer le fichier manifeste Istio Remote
Comme lorsque nous avons déployé Istio sur le cluster primary, nous allons utiliser Helm pour créer un modèle de notre déploiement d'Istio Remote sur le cluster primary.burst Avant de pouvoir le faire, nous devons obtenir des informations sur notre cluster primary.
Recueillir des informations sur le cluster principal
Passer au cluster primary
kubectx primary
Les commandes suivantes récupèrent les adresses IP de différents pods du cluster principal. Elles sont utilisées par Istio Remote pour communiquer avec le cluster principal.
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}')
Créer un modèle distant
Nous allons maintenant utiliser helm pour créer un fichier nommé istio-remote-burst.yaml, que nous pourrons ensuite déployer sur le cluster burst.
Accéder à la racine du projet
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
Installer Istio Remote sur le cluster burst
Pour installer Istio sur notre cluster burst, nous devons suivre les mêmes étapes que pour l'installation sur le cluster primary, mais nous devons utiliser le fichier istio-remote-burst.yaml.
Modifier le kubecontext pour le mode rafale
kubectx burst
Créer l'espace de noms istio-system
kubectl create ns istio-system
Appliquer istio-burst.yaml
kubectl apply -f istio-remote-burst.yaml
Espace de noms par défaut du libellé
Une fois de plus, nous devons ajouter un libellé à l'espace de noms default pour que le proxy puisse être injecté automatiquement.
kubectl label namespace default istio-injection=enabled
Félicitations ! À ce stade, nous avons configuré Istio Remote sur le cluster burst. Toutefois, à ce stade, les clusters ne peuvent toujours pas communiquer. Nous devons générer un fichier kubeconfig pour le cluster burst que nous pouvons déployer sur le cluster primary pour les associer.
Créer un fichier kubeconfig pour le cluster "burst"
Passer à un cluster de pics
kubectx burst
Configurer l'environnement
Nous devons recueillir des informations sur le cluster pour pouvoir créer un fichier kubeconfig.
- Obtenir le nom du cluster
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
- Obtenir le nom du serveur de cluster
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
- Obtenez le nom du secret pour l'autorité de certification du compte de service
istio-multi.
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
- Obtenir les données de l'autorité de certification stockées dans le secret précédent
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
- Récupérer le jeton stocké dans le secret précédent
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)
Créer un fichier kubeconfig
Une fois toutes ces variables d'environnement définies, nous devons créer notre fichier 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
Un fichier burst-kubeconfig est alors créé dans votre répertoire actuel. Il peut être utilisé par le cluster primary pour authentifier et gérer le cluster burst.
Revenir au cluster principal
kubectx primary
Appliquez le fichier kubeconfig pour "burst" en créant un secret et en lui attribuant un libellé.
kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system
Attribuez un libellé au secret pour qu'Istio sache l'utiliser pour l'authentification multicluster.
kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system
Félicitations ! Les deux clusters sont authentifiés et communiquent entre eux via Istio Multicluster. Déployons notre application sur plusieurs clusters.
15. Déployer une application multicluster
Créer des déploiements
Accédez au répertoire kubernetes.
cd ${proj}/kubernetes
Créez un déploiement de nœuds de calcul pour le cluster "burst" : worker-burst.yaml
Créez un fichier nommé worker-burst.yaml et insérez-y les éléments suivants :
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-"
Notez que ce fichier est presque identique à celui de worker-primary.yaml que nous avons créé précédemment. Il existe deux différences principales.
La première différence clé est que nous avons ajouté la variable d'environnement PREFIX avec la valeur "bursty-".
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
Cela signifie que notre worker du cluster burst préfixera tous les hachages qu'il envoie avec "bursty-". Nous pouvons l'utiliser pour savoir si notre application est réellement multicluster.
La deuxième différence clé est que nous avons remplacé le libellé cluster-type de ce déploiement par burst-cluster au lieu de primary-cluster.
labels:
app: worker
cluster-type: burst-cluster
Nous utiliserons ce libellé ultérieurement lorsque nous mettrons à jour notre VirtualService.
Modifier les services Istio
Pour le moment, nos services Istio ne tirent pas parti de nos deux déploiements. 100 % de notre trafic est acheminé vers le cluster "principal". Remédions à cela.
Accédez à notre répertoire istio-manifests.
cd ${proj}/istio-manifests
Modifiez worker-virtualservice.yaml pour inclure 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
Vous pouvez voir que nous avons ajouté une deuxième destination à notre VirtualService. Il fait toujours référence au même hôte (worker-service.default.svc.cluster.local)), mais 50 % du trafic sont acheminés vers le sous-ensemble primary et les 50 % restants vers le sous-ensemble burst.
Nous avons défini le sous-ensemble primary comme étant les déploiements qui ont le libellé cluster-type: primary-cluster et le sous-ensemble burst comme étant les déploiements qui ont le libellé cluster-type: burst-cluster.
Cela répartit efficacement notre trafic à 50/50 entre les deux clusters.
Déployer sur le cluster
Déployer redis-service.yaml sur le cluster burst
Passer au fichier kubeconfig burst
kubectx burst
Accéder à la racine de notre projet
cd ${proj}
Déployez ensuite
Déployez redis-service.yaml sur le cluster de pics de charge.
kubectl apply -f kubernetes/redis-service.yaml
Déployer worker-burst.yaml sur le cluster burst
kubectl apply -f kubernetes/worker-burst.yaml
Déployez worker-service.yaml sur le cluster de pics de charge.
kubectl apply -f kubernetes/worker-service.yaml
Appliquer les VirtualServices Istio
Passer au fichier kubeconfig primary
kubectx primary
Déployer
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Vérifier que tout fonctionne
Pour vérifier que cela fonctionne, accédez à votre point d'entrée Istio Ingress et notez qu'environ 50 % des hachages sont précédés de "burst-".

Cela signifie que nous communiquons bien entre les clusters. Essayez de modifier les pondérations des différents services et d'appliquer le fichier worker-virtualservice.yaml. C'est un excellent moyen d'équilibrer le trafic entre les clusters, mais que se passerait-il si nous pouvions le faire automatiquement ?
16. Exploiter les métriques Prometheus
Présentation de Prometheus
Prometheus est une boîte à outils Open Source de surveillance et d'alerte pour les systèmes, initialement conçue chez SoundCloud. Il gère un modèle de données multidimensionnel avec des données de séries temporelles identifiées par le nom de la métrique et des paires clé/valeur.
Pour référence, voici le schéma de l'architecture Prometheus :

Lorsqu'Istio est déployé avec Prometheus, il signale automatiquement diverses métriques au serveur Prometheus. Nous pouvons utiliser ces métriques pour gérer nos clusters à la volée.
Explorer nos métriques Prometheus
Pour commencer, nous devons exposer le déploiement Prometheus.
Accédez à l'onglet "Charges de travail" dans GKE, puis accédez à la charge de travail "prometheus".

Une fois que vous affichez les détails du déploiement, accédez à Actions > Exposer.

Choisissez de transférer vers le port 9090, puis saisissez "Équilibreur de charge".

Choisissez "Exposer".
Cela créera un service sur une adresse IP accessible au public que nous pourrons utiliser pour explorer nos métriques Prometheus.
Attendez que le point de terminaison devienne opérationnel, puis cliquez sur l'adresse IP à côté de "Points de terminaison externes"
.
Vous devriez maintenant voir l'interface utilisateur de Prometheus.

Prometheus fournit suffisamment de métriques pour être son propre atelier. Pour l'instant, nous allons commencer par explorer la métrique istio_requests_total.
L'exécution de cette requête renvoie un grand nombre de données. Il s'agit de métriques sur toutes les requêtes qui transitent par le maillage de services Istio, et il y en a beaucoup ! Nous allons modifier notre expression pour filtrer les résultats et ne conserver que ce qui nous intéresse vraiment :
Requêtes dont le service de destination est worker-service.default.svc.cluster.local et dont la source est frontend-deployment, limitées aux 15 dernières secondes
Cette requête se présente comme suit :
istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]
et nous donne un ensemble de données beaucoup plus facile à gérer.

mais il reste un peu dense. Nous voulons connaître les requêtes par seconde, et non toutes les requêtes.
Pour ce faire, nous pouvons utiliser la fonction rate intégrée.
rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])

Nous nous en approchons, mais nous devons encore réduire ces métriques pour les regrouper de manière logique.
Pour ce faire, nous pouvons utiliser les mots clés sum et by pour regrouper et additionner nos résultats.
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)

Parfait ! Nous pouvons obtenir les métriques exactes dont nous avons besoin à partir de Prometheus.
Notre requête Prometheus finale
Avec tout ce que nous avons appris, la requête finale que nous devons envoyer à Prometheus est
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)
Nous pouvons maintenant utiliser leur API HTTP pour obtenir la métrique.
Nous pouvons interroger leur API avec notre requête en effectuant une requête HTTP GET comme suit. Remplacez <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\)
Voici un exemple de réponse :
{
"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"
]
}
]
}
}
Nous pouvons maintenant extraire la valeur de notre métrique du JSON.
Effectuer un nettoyage
Nous devons supprimer le service que nous venons d'utiliser pour exposer Prometheus. Dans la console Google Cloud, accédez en haut du service que nous venons de créer, puis cliquez sur "Supprimer".

Prochaines étapes :
Maintenant que nous avons trouvé un moyen de découvrir comment le trafic se déplace dans le cluster et à quelle vitesse, notre prochaine étape consiste à écrire un petit binaire qui interroge périodiquement Prometheus. Si les requêtes par seconde vers worker dépassent un certain seuil, nous appliquerons différentes pondérations de destination sur notre service virtuel de nœud de calcul pour envoyer tout le trafic vers le cluster burst. Une fois que les requêtes par seconde sont inférieures à un seuil bas, renvoyez tout le trafic vers primary.
17. Créer un burst cross-cluster
Configuration
Définir tout le trafic pour le service de nœud de calcul sur le cluster principal
Nous considérerons que tout le trafic destiné au cluster worker-service est acheminé vers le cluster primary, ce qui correspond à l'état "par défaut" de notre application.
Modifiez $proj/istio-manifests/worker-virtualservice.yaml comme suit :
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
Assurez-vous d'être connecté au cluster primary.
kubectx primary
Appliquer istio-manifests/worker-virtualservice.yaml
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Écrire le daemon istiowatcher
Nous utiliserons Go pour écrire ce service en raison de sa rapidité et de sa portabilité. Le flux global de l'application consiste à démarrer et à interroger Prometheus toutes les secondes.
Créez un répertoire nommé "istiowatcher" dans "src".
mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher
Nous allons appeler istioctl depuis notre conteneur afin de manipuler le plan de contrôle Istio depuis le cluster.
Écrire istiowatcher.go
Créez un fichier nommé istiowatcher.go dans ce répertoire et insérez-y le code suivant :
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)
}
}
Écrire un fichier Dockerfile
Créez un fichier nommé Dockerfile et insérez-y le code suivant.
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"]
Ce Dockerfile en plusieurs étapes télécharge et extrait la version 1.0.0 d'Istio lors de la première étape. La deuxième étape consiste à copier tout le contenu de notre répertoire dans l'image, puis à copier istioctl de l'étape de compilation vers /usr/local/bin (afin qu'il puisse être appelé par notre application), à obtenir les dépendances, à compiler le code et à définir CMD sur "istiowatcher".
Écrire burst.yaml
Il s'agit du fichier istiowatcher qui s'appliquera lorsque le nombre de requêtes par seconde envoyées à worker depuis frontend dépassera 15.
Créez un fichier nommé burst.yaml et insérez-y le code suivant.
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
Écrire natural.yaml
Nous considérerons qu'il s'agit de l'état "naturel" auquel nous revenons lorsque le nombre de requêtes par seconde de frontend à worker tombe en dessous de 10. Dans cet état, 100 % du trafic est acheminé vers le cluster primary.
Créez un fichier nommé natural.yaml et insérez-y le code suivant :
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
Compiler et envoyer istiowatcher
Exécutez la commande suivante pour envoyer le répertoire actuel à Google Cloud Build (GCB), qui créera l'image et lui attribuera un tag dans GCR.
gcloud builds submit -t gcr.io/${GCLOUD_PROJECT}/istiowatcher
Déployer istiowatcher
Accédez à notre répertoire kubernetes.
cd ${proj}/kubernetes/
Écrivez un fichier de déploiement : istiowatcher.yaml
Créez un fichier nommé istiowatcher.yaml et insérez le contenu suivant (remplacez <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
Déployer
Assurez-vous que nous sommes en cours d'exécution dans le cluster principal.
kubectx primary
Déployer istiowatcher.yaml dans l'espace de noms istio-system
kubectl apply -n istio-system -f istiowatcher.yaml
Il est important de noter les directives serviceAccountName et automountServiceAccountToken dans le fichier YAML. Cela nous donne les identifiants nécessaires pour exécuter istioctl depuis le cluster.
Nous devons également déployer cela dans l'espace de noms istio-system pour nous assurer d'avoir les identifiants pour istio-pilot-service-account. (il n'existe pas dans l'espace de noms default).
Regardez le trafic basculer automatiquement !
Passons maintenant au moment magique ! Passons à notre frontend et augmentons le nombre de requêtes par seconde à 20.
Vous remarquerez que cela prend quelques secondes, mais que tous nos hachages sont précédés du préfixe "bursty-".
En effet, nous échantillonnons Prometheus sur une plage de 15s, ce qui retarde un peu notre temps de réponse. Si nous voulions une bande beaucoup plus étroite, nous pourrions modifier notre requête Prometheus pour qu'elle soit 5s..
18. Étape suivante
Effectuer un nettoyage
Vous n'avez pas besoin d'effectuer de nettoyage si vous utilisez un compte temporaire fourni pour cet atelier.
Vous pouvez supprimer vos clusters Kubernetes, la règle de pare-feu et les images dans 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
Et après ?
- Assistez à des conférences Istio !
- Obtenir la certification : Créer votre prochaine application avec Kubernetes et Istio
- Keynote : Kubernetes, Istio, Knative : la nouvelle pile cloud ouverte – Aparna Sinha, Group Product Manager pour Kubernetes, Google
- Tutoriel : Utiliser Istio – Lee Calcote et Girish Ranganathan, SolarWinds
- Istio : la vue du paquet – Matt Turner, Tetrate
- Istio est-il le pare-feu nouvelle génération le plus avancé jamais créé ? - John Morello, Twistlock
- Consultez la documentation Istio.
- Rejoindre les groupes de travail Istio
- Suivez @IstioMesh sur Twitter.




