1. Te damos la bienvenida
Gracias por acompañarnos en el codelab de Istio Multi Cloud Burst de Google.Este codelab requiere experiencia práctica de nivel principiante con Kubernetes, Node y Go. Lo que necesitarás
|
|
Qué aprenderás
- Cómo crear un clúster de Kubernetes en GKE
- Cómo instalar Istio en un clúster de Kubernetes con Helm
- Cómo instalar Istio Multicluster con Helm
- Implementa una aplicación web desde el código fuente en Kubernetes
- Cómo escribir y aplicar reglas de enrutamiento de tráfico a Istio
- Métricas de Prometheus
- Compila y envía imágenes de contenedores dentro de un clúster de Kubernetes
2. Cómo prepararte
Puedes seguir este codelab en cualquiera de las siguientes opciones:
- Google Cloud Shell (recomendado): Shell en el navegador que incluye herramientas instaladas
- Tu laptop (sigue las instrucciones que se indican a continuación)
Comienza a usar Google Cloud Platform
- Si no tienes una cuenta de GCP, retira la tarjeta de cuenta de usuario gratuita con el instructor.
- Ve a la consola de Google Cloud y haz clic en "Seleccionar un proyecto":

- Toma nota del "ID" del proyecto en algún lugar y, luego, haz clic en el proyecto para elegirlo:

Opción 1: Usa Google Cloud Shell (recomendado)
Cloud Shell proporciona un shell de línea de comandos dentro de tu navegador con las herramientas que necesitas instaladas y autenticadas automáticamente en tu cuenta de Google Cloud Platform. (Si no deseas ejecutar este ejercicio en Cloud Shell, pasa a la siguiente sección).
Ve a Cloud Console y haz clic en "Activar Cloud Shell" en la barra de herramientas de la esquina superior derecha:

Agrega herramientas a Cloud Shell
- Instala
kubectx****: Para ello, descarga las secuencias de comandos de Bash desde aquí a una ubicación en $PATH. - Instala
helm****: Sigue estas instrucciones.
Como alternativa, ejecuta estos comandos para instalar ambos en ~/.bin y agregarlos a tu $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}
A continuación, se incluyen algunas sugerencias rápidas que pueden facilitar el uso de Cloud Shell:
1. Desconecta el shell en una ventana nueva: |
|
2. Usa el editor de archivos: Haz clic en el ícono de lápiz en la parte superior derecha para iniciar un editor de archivos en el navegador. Esto te resultará útil, ya que copiaremos fragmentos de código en archivos. |
|
3. Iniciar pestañas nuevas: Si necesitas más de una instrucción de terminal. |
|
4. Aumenta el tamaño del texto: El tamaño de fuente predeterminado en Cloud Shell puede ser demasiado pequeño para leerlo. | Ctrl + en Linux o Windows, y ⌘ + en macOS |
Opción 2: Configura tu laptop (no recomendado)
Si te sientes más cómodo usando tu propio entorno de estación de trabajo que Cloud Shell, configura las siguientes herramientas:
- Instala
gcloud:(preinstalado en Cloud Shell). Sigue las instrucciones para instalargclouden tu plataforma. Lo usaremos para crear un clúster de Kubernetes. - Instala
kubectl:(preinstalado en Cloud Shell). Ejecuta el siguiente comando para instalarlo:
gcloud components install kubectl
Ejecuta el siguiente comando para autenticar gcloud. Se te pedirá que accedas con tu Cuenta de Google. Luego, elige el proyecto creado previamente (que se muestra arriba) como proyecto predeterminado. (Puedes omitir la configuración de una zona de procesamiento):
gcloud init
- Instalación
curl:Preinstalado en la mayoría de los sistemas Linux/macOS. Es probable que ya la tengas. De lo contrario, busca en Internet cómo instalarlo. - Instala
kubectx****: Para ello, descarga las secuencias de comandos de Bash desde aquí a una ubicación en $PATH. - Instala
helm****: Sigue estas instrucciones.
3. Configura el proyecto de GCP
Habilita las APIs de GKE (Google Kubernetes Engine), GCR (Google Container Registry) y GCB (Google Cloud Build) en tu proyecto:
gcloud services enable \ cloudapis.googleapis.com \ container.googleapis.com \ containerregistry.googleapis.com \ cloudbuild.googleapis.com
Configura las variables de entorno
Trabajaremos mucho con nuestro proyecto de Google Cloud durante la configuración, así que estableceremos una variable de entorno para consultarla rápidamente.
export GCLOUD_PROJECT=$(gcloud config get-value project)
Durante este taller, crearemos algunos archivos de código y configuración, por lo que crearemos un directorio de proyecto y lo cambiaremos.
mkdir -p src/istio-burst && \ cd src/istio-burst && \ export proj=$(pwd)
4. Crea el clúster de Kubernetes "principal"
Puedes crear fácilmente un clúster de Kubernetes administrado con Google Kubernetes Engine (GKE).
El siguiente comando creará un clúster de Kubernetes:
- llamado "principal",
- en la zona us-west1-a
- La versión más reciente de Kubernetes disponible
- con 4 nodos iniciales
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
(Este proceso puede tardar alrededor de 5 minutos. Puedes ver cómo se crea el clúster en Cloud Console.
Después de crear el clúster de Kubernetes, gcloud configura kubectl con las credenciales que apuntan al clúster.
gcloud container clusters get-credentials $cluster --zone=$zone
Ahora deberías poder usar kubectl con tu clúster nuevo.
Ejecuta el siguiente comando para enumerar los nodos de Kubernetes de tu clúster (deben mostrar el estado "Ready"):
kubectl get nodes
Modifica los nombres de Kubeconfig para facilitar su uso
Cambiaremos de contexto con frecuencia, por lo que tener un alias corto para nuestros clústeres es útil.
Este comando cambiará el nombre de la entrada de kubeconfig que acabas de crear a primary.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Cómo establecer permisos:
Para implementar Istio, debes ser administrador del clúster. Este comando establecerá el correo electrónico asociado con tu cuenta de Google Cloud como administrador del clúster.
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
5. Crea un clúster de "ráfaga"
El siguiente comando creará un clúster de Kubernetes:
- llamado "burst",
- en la zona us-west1-a
- La versión más reciente de Kubernetes disponible
- Con 1 nodo inicial
- Ajuste de escala automático habilitado hasta 5 nodos
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
(Este proceso puede tardar alrededor de 5 minutos. Puedes ver cómo se crea el clúster en Cloud Console.
Después de crear el clúster de Kubernetes, gcloud configura kubectl con las credenciales que apuntan al clúster.
gcloud container clusters get-credentials $cluster --zone=$zone
Ahora deberías poder usar kubectl con tu clúster nuevo.
Ejecuta el siguiente comando para enumerar los nodos de Kubernetes de tu clúster (deben mostrar el estado "Ready"):
kubectl get nodes
Modifica los nombres de Kubeconfig para facilitar su uso
Este comando modificará la entrada de kubeconfig que acabas de crear en burst.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Cómo establecer permisos:
Para implementar Istio Remote, debes ser administrador del clúster. Este comando establecerá el correo electrónico asociado con tu cuenta de Google Cloud como administrador del clúster.
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
6. Aplica reglas de firewall
Para que nuestros dos clústeres se comuniquen entre sí, deberemos crear una regla de firewall.
Ejecuta los siguientes comandos para crear una regla de firewall en Google Cloud que permita que nuestros clústeres se comuniquen.
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
Tenemos ambos clústeres configurados y listos para implementar nuestra aplicación e Istio en ellos.
7. Introducción a Istio
¿Qué es Istio?
Istio es un plano de control de malla de servicios que tiene como objetivo "conectar, proteger, controlar y observar servicios". Lo hace de varias maneras, pero principalmente agregando un contenedor de proxy ( Envoy) como archivo adicional a cada uno de los Pods de Kubernetes implementados. El contenedor de proxy controla toda la comunicación de red entre microservicios en conjunto con un centro de telemetría y políticas de uso general ( Mixer).

Estas políticas se pueden aplicar de forma independiente de tus implementaciones y servicios de Kubernetes, lo que significa que el operador de red puede observar la actividad de la red, restringir, redireccionar o reescribir las políticas de red sin volver a implementar las aplicaciones asociadas.
Estas son algunas de las funciones de administración de tráfico que admite Istio:
- Disyuntores
- División de tráfico basada en porcentajes
- Reescritura de URLs
- finalización de TLS
- Verificaciones de estado
- Balanceo de cargas
Para los fines de este taller, nos enfocaremos en la división del tráfico basada en porcentajes.
Términos de Istio con los que trabajaremos
VirtualService
Un VirtualService define un conjunto de reglas de enrutamiento de tráfico que se aplican cuando se dirige un host.
Puerta de enlace
Una puerta de enlace es un balanceador de cargas que opera en el perímetro de la malla y recibe conexiones HTTP/TCP entrantes o salientes. Las puertas de enlace pueden especificar puertos, configuraciones de SNI, etcétera.
Regla del destino
Un objeto DestinationRule define políticas que se aplican al tráfico destinado a un servicio después de que se haya producido el enrutamiento. Especifican la configuración del balanceo de cargas, el tamaño del grupo de conexiones del sidecar y la configuración de detección de valores atípicos.
Istio Multicluster
Es posible que hayas notado que, cuando creamos nuestros dos clústeres, nuestro clúster primary tenía 4 nodos sin ajuste de escala automático, y nuestro clúster burst tenía 1 nodo con ajuste de escala automático de hasta 5 nodos.
Esta configuración tiene dos motivos.
Primero, queremos simular una situación de "local" a la nube. En un entorno local, no tienes acceso a clústeres con ajuste de escala automático, ya que tienes una infraestructura fija.
En segundo lugar, una configuración de 4 nodos (como se definió anteriormente) es el requisito mínimo para ejecutar Istio. Esto plantea la siguiente pregunta: Si Istio requiere un mínimo de 4 nodos, ¿cómo puede nuestro clúster burst ejecutar Istio con 1 nodo? La respuesta es que Istio Multicluster instala un conjunto mucho más pequeño de los servicios de Istio y se comunica con la instalación de Istio en el clúster principal para recuperar las reglas de política y publicar información de telemetría.
8. Descripción general de la arquitectura de la aplicación
Descripción general de los componentes
Implementaremos una aplicación de tres niveles con NodeJS y Redis.
Trabajador
La aplicación de trabajador está escrita en NodeJS y detectará las solicitudes HTTP POST entrantes, realizará una operación de hash en ellas y, si se define una variable de entorno llamada PREFIX, antepondrá el hash con ese valor. Una vez que se calcula el hash, la aplicación envía el resultado al canal "calculation" en el servidor de Redis especificado.
Usaremos la variable de entorno PREFIX más adelante para demostrar la funcionalidad de varios clústeres.
A modo de referencia, estos son los paquetes que usa la aplicación.
body-parser:Nos permite analizar nuestras solicitudes HTTPcors:Permite el uso de Cross Origin Resource Sharingdotenv:Análisis sencillo de las variables de entornoexpress:Hosting de sitios web sencilloioredis:Biblioteca cliente para comunicarse con bases de datos de Redismorgan:Proporciona un registro estructurado agradable
Frontend
Nuestro frontend también es una aplicación de NodeJS que aloja una página web con express. Toma una frecuencia ingresada por el usuario y envía solicitudes a nuestra aplicación worker a esa velocidad. Esta aplicación también se suscribe a los mensajes en un canal de Redis llamado "calculation" y muestra los resultados en una página web.
La aplicación usa las siguientes dependencias.
body-parser:Nos permite analizar nuestras solicitudes HTTPdotenv:Análisis sencillo de las variables de entornoexpress:Hosting de sitios web sencilloioredis:Biblioteca cliente para comunicarse con bases de datos de Redismorgan:Proporciona registros estructurados útilesrequest:Permite realizar solicitudes HTTPsocket.io:Permite la comunicación bidireccional desde la página web al servidor
Esta página web usa Bootstrap para el diseño y, cuando se ejecuta, se ve de la siguiente manera:

Diagrama de arquitectura

Diagrama de implementación
Implementaremos nuestra aplicación final en los dos clústeres que creamos. El clúster primary tendrá todos los componentes (frontend, worker y Redis) implementados en él, pero el clúster burst solo tendrá implementada la aplicación worker.
A continuación, se muestra un diagrama que describe los dos clústeres. Los cuadros delineados en rojo son servicios de Kubernetes, y los que están en azul son implementaciones de Kubernetes. Los cuadros amarillos indican nuestra instalación de Istio.
Observa cómo el clúster burst aún tiene un servicio para Redis implementado, aunque no haya ninguna implementación para Redis en el clúster. Necesitamos tener este servicio en el clúster para que el DNS de Kubernetes pueda resolver la solicitud, pero cuando se realice la solicitud, el proxy de Istio la redireccionará a la implementación de Redis en el clúster primary.
La aplicación final tendrá una implementación adicional que se ejecutará en el clúster primary llamado istiowatcher.. Esto es lo que nos permitirá redireccionar el tráfico de forma dinámica al clúster burst automáticamente cuando nuestro tráfico supere un cierto umbral.

9. Crea archivos de implementación de la aplicación
Debemos crear un conjunto de manifiestos de Kubernetes para implementar nuestra aplicación.
Cambia al directorio raíz del proyecto y crea una carpeta nueva llamada kubernetes.
mkdir ${proj}/kubernetes && cd ${proj}/kubernetes
Escribe frontend.yaml
Esto creará un Deployment y un Service de Kubernetes para acceder a nuestra imagen de frontend.
Inserta lo siguiente en 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
Aspectos clave que se deben tener en cuenta en Deployment
- Especificamos que el puerto en el que se ejecutará la aplicación será
8080. - Establecimos la dirección del trabajador como "
http://worker-service" y usaremos la función de DNS integrada de Kubernetes para resolver el servicio resultante. - Establecimos la dirección de nuestro
REDIS_URLcomo "redis-cache-service:6379" y usaremos la función de DNS integrada de Kubernetes para resolver las direcciones IP resultantes. - También configuramos sondeos de
livenessyreadinessen el contenedor para ayudar a informar a Kubernetes cuando el contenedor esté en funcionamiento.
Escribe worker-service.yaml
Escribimos la definición del servicio de Kubernetes en un archivo separado de la definición de Deployment, ya que volveremos a usar este servicio en varios clústeres, pero escribiremos un Deployment diferente para cada clúster.
Inserta lo siguiente en worker-service.yaml
apiVersion: v1
kind: Service
metadata:
name: worker-service
spec:
type: ClusterIP
selector:
app: worker
ports:
- name: http
port: 80
targetPort: 8081
Escribe worker-primary.yaml
Esta será la implementación de worker que enviaremos al clúster principal.
Inserta lo siguiente en 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"
Observa que, en este caso, seguimos el mismo patrón de proporcionar sondas liveness y readiness, además de especificar las variables de entorno PORT y REDIS_URL para que las use nuestra aplicación.
Otro aspecto que se debe tener en cuenta en esta implementación es la falta de la variable de entorno PREFIX. Esto significa que los resultados de nuestros cálculos serán hashes sin procesar (sin prefijos).
El último punto clave de esta implementación es la etiqueta cluster-type: primary-cluster. Lo usaremos más adelante cuando hagamos el enrutamiento de tráfico en Istio Multicluster.
Escribe redis.yaml
La comunicación de nuestro trabajador con el frontend se realiza a través de un canal de Redis, por lo que debemos implementar una aplicación de Redis en nuestro clúster.
Inserta lo siguiente en 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: {}
Esta es una implementación semiestándar de una aplicación de Redis. Inicia un contenedor basado en la imagen redis:alpine, expone los puertos adecuados y establece límites de recursos razonables.
Escribe redis-service.yaml
Necesitamos un servicio de Kubernetes para comunicarnos con nuestra aplicación de Redis
Inserta lo siguiente en redis-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-cache-service
spec:
type: ClusterIP
selector:
app: redis-cache
ports:
- port: 6379
targetPort: 6379
Esto proporciona un servicio llamado redis-cache-service para acceder a nuestra implementación de Redis.
10. Implementa la aplicación
Ahora que nuestras imágenes se enviaron a GCR y nuestros manifiestos de Kubernetes están escritos, es un buen momento para implementar nuestra aplicación y ver cómo funciona.
Ejecuta los siguientes comandos para implementar la aplicación
- Asegúrate de que estamos en el clúster correcto
kubectx primary
- Implementa la caché de Redis
kubectl apply -f redis.yaml
- Implementa el servicio de Redis
kubectl apply -f redis-service.yaml
- Implementa el frontend
kubectl apply -f frontend.yaml
- Implementar Worker
kubectl apply -f worker-primary.yaml
- Implementa el servicio de Worker
kubectl apply -f worker-service.yaml
Implementamos nuestra aplicación en GKE. ¡Felicitaciones!
Prueba
Espera a que los Pods se conecten.
kubectl get pods -w
Una vez que todos los Pods estén en "Running", presiona 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
Notarás que no expusimos nuestro frontend a través de un LoadBalancer. Esto se debe a que, más adelante, accederemos a la aplicación a través de Istio. Para probar que todo esté en funcionamiento, usaremos kubectl port-forward. Ejecuta el siguiente comando para reenviar el puerto 8080 en tu máquina local (o de Cloud Shell) al puerto 8080 que ejecuta la implementación de frontend.
kubectl port-forward \
$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}') \
8080:8080
Si ejecutas el servidor de forma local, abre un navegador web y navega a http://localhost:8080.
Si ejecutas el programa en Cloud Shell, haz clic en el botón "Vista previa en la Web" y selecciona "Vista previa en el puerto 8080".

Deberías ver el frontend. Si ingresas un número en el cuadro "Frecuencia", deberías ver que comienzan a aparecer hashes.

¡Felicitaciones! Ya está todo listo.
Presiona Ctrl+C para detener la redirección del puerto.
11. Limpia la aplicación implementada
Aplicaremos Istio a nuestro clúster y, luego, volveremos a implementar nuestra aplicación, por lo que primero limpiaremos nuestra aplicación actual.
Ejecuta los siguientes comandos para borrar todas las implementaciones y los servicios que acabas de crear.
- Borrar
redis-cache-service
kubectl delete -f redis-service.yaml
- Borrar
redis
kubectl delete -f redis.yaml
- Borrar
frontend
kubectl delete -f frontend.yaml
- Borrar
worker
kubectl delete -f worker-primary.yaml
- Borrar
worker-service
kubectl delete -f worker-service.yaml
12. Instala Istio en el clúster principal
Obtener Istio
Los lanzamientos de Istio se alojan en GitHub. Con los siguientes comandos, se descargará y descomprimirá la versión 1.0.0 de Istio.
- Cambia a la raíz de tu proyecto
cd ${proj}
- Descarga el archivo
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
- Cómo extraer y quitar el archivo
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz
Create Istio Template
Ejecutar el siguiente comando de Helm creará la plantilla para instalar Istio en tu clúster.
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
Esto crea un archivo llamado istio-primary.yaml en tu directorio actual que contiene todas las definiciones y especificaciones necesarias para implementar y ejecutar Istio.
Observa los dos parámetros --set. Estos complementos agregan compatibilidad con Prometheus y ServiceGraph al sistema de Istio. Usaremos el servicio de Prometheus más adelante en el lab.
Implementa Istio
Para implementar Istio, primero debemos crear un espacio de nombres llamado istio-system en el que se puedan ejecutar las implementaciones y los servicios de Istio.
kubectl create namespace istio-system
Por último, aplica el archivo istio-primary.yaml que creamos con Helm.
kubectl apply -f istio-primary.yaml
Etiqueta el espacio de nombres predeterminado
Istio funciona inyectando un servicio de proxy de sidecar en cada una de tus implementaciones. Esto se hace de forma opcional, por lo que debemos etiquetar nuestro espacio de nombres default con istio-injection=enabled para que Istio pueda insertar automáticamente el sidecar por nosotros.
kubectl label namespace default istio-injection=enabled
¡Felicitaciones! Tenemos un clúster en funcionamiento con Istio listo para que implementemos nuestra aplicación.
13. Implementa nuestra aplicación con la administración del tráfico de Istio
Crea archivos de configuración de administración de tráfico de Istio
Istio funciona de manera similar a Kubernetes, ya que usa archivos YAML para la configuración. En ese sentido, debemos crear un conjunto de archivos que le indiquen a Istio cómo exponer y enrutar nuestro tráfico.
Crea un directorio llamado istio-manifests y cámbiate a él.
mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests
Escribe frontend-gateway.yaml
Este archivo expondrá nuestro clúster de Kubernetes de una manera similar a un LoadBalancer de GKE y enrutará todo el tráfico entrante a nuestro servicio de frontend.
Crea un archivo llamado frontend-gateway.yaml y, luego, inserta lo siguiente.
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
Escribe redis-virtualservice.yaml
Crea un archivo llamado redis-virtualservice.yaml y, luego, inserta lo siguiente:
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
Escribe worker-virtualservice.yaml
Crea un archivo llamado worker-virtualservice.yaml y, luego, inserta lo siguiente:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
port:
number: 80
Implementa políticas de administración de tráfico de Istio
La implementación de las políticas de Istio se realiza de la misma manera que otros recursos de Kubernetes, con kubectl apply
- Aplica nuestra puerta de enlace
kubectl apply -f frontend-gateway.yaml
- Aplica nuestro VirtualService de Redis
kubectl apply -f redis-virtualservice.yaml
- Aplica nuestro VirtualService de Worker
kubectl apply -f worker-virtualservice.yaml
Implementar la aplicación
- Vuelve a nuestro directorio
kubernetes.
cd ${proj}/kubernetes
- Implementa la caché de Redis
kubectl apply -f redis.yaml
- Implementa el servicio de Redis
kubectl apply -f redis-service.yaml
- Implementa el frontend
kubectl apply -f frontend.yaml
- Implementar Worker
kubectl apply -f worker-primary.yaml
- Implementa el servicio de Worker
kubectl apply -f worker-service.yaml
Verificar
En este punto, volvimos a implementar nuestra aplicación en un clúster con Istio y políticas de administración del tráfico.
Esperemos a que todas nuestras cargas de trabajo se conecten.
Una vez que todos estén en línea, obtén el IngressGateway que configuramos en 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,
Navega a la dirección <EXTERNAL-IP> o ejecútala con curl, y deberías ver el frontend.
$ curl 35.199.158.10
<!doctype html>
<html>
<head>
<title>String Hashr</title>
<!-- Bootstrap -->
...
14. Instala Istio en el clúster "burst"
Hemos dedicado mucho tiempo a configurar e implementar en nuestro clúster primary, pero tenemos otro clúster completo para implementar.
En esta sección, deberemos obtener variables de configuración en ambos clústeres, por lo que deberás prestar mucha atención al clúster al que se hace referencia en cada comando.
Crea el manifiesto remoto de Istio
Al igual que cuando implementamos Istio en el clúster primary, usaremos Helm para crear una plantilla de nuestra implementación de Istio remoto en el clúster burst. Sin embargo, antes de hacerlo, necesitamos obtener información sobre nuestro clúster de primary.
Recopila información del clúster principal
Cambiar al clúster primary
kubectx primary
Los siguientes comandos recuperan las direcciones IP de varios Pods en el clúster principal. Istio Remote los usa para comunicarse con el clúster 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}')
Create Remote Template
Ahora usaremos helm para crear un archivo llamado istio-remote-burst.yaml que luego podremos implementar en el clúster burst.
Cambia a la raíz del proyecto
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
Instala Istio Remote en el clúster de ráfagas
Para instalar Istio en nuestro clúster burst, debemos seguir los mismos pasos que cuando lo instalamos en el clúster primary, pero debemos usar el archivo istio-remote-burst.yaml.
Cambia kubecontext a burst
kubectx burst
Crea el espacio de nombres istio-system
kubectl create ns istio-system
Aplica istio-burst.yaml
kubectl apply -f istio-remote-burst.yaml
Etiqueta el espacio de nombres predeterminado
Una vez más, debemos etiquetar el espacio de nombres default para que el proxy se pueda insertar automáticamente.
kubectl label namespace default istio-injection=enabled
¡Felicitaciones! En este punto, configuramos Istio Remote en el clúster burst. Sin embargo, en este punto, los clústeres aún no pueden comunicarse. Debemos generar un archivo kubeconfig para el clúster burst que podamos implementar en el clúster primary para vincularlos.
Crea kubeconfig para el clúster "burst"
Cambiar a clúster de ráfaga
kubectx burst
Configura el entorno
Necesitamos recopilar información sobre el clúster para crear un archivo kubeconfig.
- Obtén el nombre del clúster
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
- Obtén el nombre del servidor del clúster
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
- Obtén el nombre del secreto de la autoridad de certificación de la cuenta de servicio
istio-multi.
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
- Obtén los datos de la entidad certificadora almacenados en el secreto anterior.
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
- Obtén el token almacenado en el secreto anterior.
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)
Crea el archivo kubeconfig
Con todas esas variables de entorno configuradas, debemos crear nuestro archivo 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
Esto creará un archivo nuevo llamado burst-kubeconfig en tu directorio actual, que el clúster primary puede usar para autenticar y administrar el clúster burst.
Cómo volver al clúster principal
kubectx primary
Aplica el kubeconfig para "ráfaga" creando un secreto y etiquetándolo
kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system
Etiqueta el secreto para que Istio sepa que debe usarlo para la autenticación de varios clústeres
kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system
¡Felicitaciones! Ambos clústeres están autenticados y se comunican entre sí a través de Istio Multicluster. Implementemos nuestra aplicación entre clústeres
15. Implementa una aplicación entre clústeres
Crea Deployments
Cambia al directorio kubernetes.
cd ${proj}/kubernetes
Crea una implementación de trabajador para el clúster "burst": worker-burst.yaml
Crea un archivo llamado worker-burst.yaml y, luego, inserta el siguiente contenido:
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-"
Observa que es casi idéntico al archivo worker-primary.yaml que creamos antes. Existen dos diferencias clave.
La primera diferencia clave es que agregamos la variable de entorno PREFIX con el valor "bursty-".
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
Esto significa que nuestro trabajador en el clúster burst antepondrá el prefijo "bursty-" a todos los hashes que envíe. Podemos usar esto para saber que nuestra aplicación es realmente entre clústeres.
La segunda diferencia clave es que cambiamos la etiqueta cluster-type en esta implementación de primary-cluster a burst-cluster.
labels:
app: worker
cluster-type: burst-cluster
Usaremos esta etiqueta más adelante cuando actualicemos nuestro VirtualService.
Cómo modificar servicios de Istio
En este momento, nuestros servicios de Istio no aprovechan ambas implementaciones. El 100% de nuestro tráfico se enruta al clúster "principal". Cambiemos eso.
Cambia a nuestro directorio istio-manifests.
cd ${proj}/istio-manifests
Edita worker-virtualservice.yaml para incluir 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
Puedes ver que agregamos un segundo destino a nuestro VirtualService. Aún hace referencia al mismo host (worker-service.default.svc.cluster.local)), pero el 50% del tráfico se enruta al subconjunto primary y el otro 50% se enruta al subconjunto burst.
Definimos el subconjunto primary como las implementaciones que tienen la etiqueta cluster-type: primary-cluster y el subconjunto burst como las implementaciones que tienen la etiqueta cluster-type: burst-cluster.
Esto divide nuestro tráfico de manera efectiva en un 50% para cada clúster.
Implementar en el clúster
Implementa redis-service.yaml en el clúster de Burst
Cambia a burst kubeconfig
kubectx burst
Cambia a la raíz de nuestro proyecto
cd ${proj}
Luego, implementa
Implementa redis-service.yaml en el clúster de ráfagas
kubectl apply -f kubernetes/redis-service.yaml
Implementa worker-burst.yaml en el clúster de ráfagas
kubectl apply -f kubernetes/worker-burst.yaml
Implementa worker-service.yaml en el clúster de ráfagas
kubectl apply -f kubernetes/worker-service.yaml
Aplica VirtualServices de Istio
Cambia a primary kubeconfig
kubectx primary
Luego, implementa
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Verifica que funcione
Para verificar que funcione, navega a tu punto de entrada de Istio y observa que aproximadamente el 50% de los hashes tienen el prefijo "burst-".

Esto significa que la comunicación entre clústeres se realizó correctamente. Intenta cambiar los pesos en los diferentes servicios y aplicar el archivo worker-virtualservice.yaml. Esta es una excelente manera de equilibrar el tráfico entre los clústeres, pero ¿qué sucede si podemos hacerlo automáticamente?
16. Aprovecha las métricas de Prometheus
Introducción a Prometheus
Prometheus es un kit de herramientas de supervisión y alertas de sistemas de código abierto que se creó originalmente en SoundCloud. Mantiene un modelo de datos multidimensional con datos de series temporales identificados por el nombre de la métrica y los pares clave-valor.
A modo de referencia, aquí se muestra el diagrama de la arquitectura de Prometheus:

Cuando se implementa Istio con Prometheus, se registran automáticamente varias métricas en el servidor de Prometheus. Podemos usar estas métricas para administrar nuestros clústeres sobre la marcha.
Explora nuestras métricas de Prometheus
Para comenzar, debemos exponer la implementación de Prometheus.
Navega a la pestaña Cargas de trabajo en GKE y explora en detalle la carga de trabajo "prometheus".

Una vez que veas los detalles de la implementación, ve a Actions -> Expose.

Elige reenviar al puerto 9090 y escribe "Balanceador de cargas".

Y elige "Exponer".
Esto creará un servicio en una dirección IP de acceso público que podemos usar para explorar nuestras métricas de Prometheus.
Espera a que el extremo esté operativo y, luego, haz clic en la dirección IP junto a "Extremos externos"
.
Ahora deberías ver la IU de Prometheus.

Prometheus proporciona suficientes métricas como para ser su propio taller. Por ahora, comenzaremos explorando la métrica istio_requests_total.
La ejecución de esa consulta devuelve una gran cantidad de datos. Son métricas sobre todas las solicitudes que pasan por la malla de servicios de Istio, ¡y son muchas! Cambiaremos nuestra expresión para filtrar los resultados y obtener lo que realmente nos interesa:
Solicitudes en las que el servicio de destino es worker-service.default.svc.cluster.local y cuya fuente es frontend-deployment, limitadas a los últimos 15 segundos
Esa consulta se ve de la siguiente manera:
istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]
Y nos proporciona un conjunto de datos mucho más manejable con el que trabajar

Pero sigue siendo un poco denso. Queremos conocer las solicitudes por segundo, no todas las solicitudes.
Para obtenerlo, podemos usar la función integrada rate.
rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])

Esto nos acerca más, pero necesitamos reducir esas métricas un poco más en un grupo lógico.
Para ello, podemos usar las palabras clave sum y by para agrupar y sumar nuestros resultados.
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)

¡Perfecto! Podemos obtener las métricas exactas que necesitamos de Prometheus.
Nuestra consulta final de Prometheus
Con todo lo que aprendimos, la consulta final que debemos hacerle a Prometheus es
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)
Ahora podemos usar su API de HTTP para obtener la métrica.
Podemos consultar su API con nuestra consulta realizando una solicitud GET de HTTP de la siguiente manera. Reemplaza <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\)
Esta es una respuesta de ejemplo:
{
"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"
]
}
]
}
}
Ahora, podemos extraer el valor de nuestra métrica del JSON.
Haz limpieza
Debemos borrar el servicio que acabamos de usar para exponer Prometheus. En la consola de Google Cloud, ve a la parte superior del servicio que acabamos de crear y haz clic en "Borrar".

Próximos pasos:
Después de encontrar una forma de descubrir cómo se mueve el tráfico por el clúster y a qué velocidad, el siguiente paso es escribir un pequeño archivo binario que consulte Prometheus de forma periódica y, si las solicitudes por segundo a worker superan un umbral determinado, aplique diferentes pesos de destino en nuestro servicio virtual de trabajadores para enviar todo el tráfico al clúster burst. Una vez que las solicitudes por segundo se encuentren por debajo de un umbral inferior, envía todo el tráfico de vuelta a primary.
17. Crea una ráfaga entre clústeres
Configuración
Establece todo el tráfico de worker-service en el clúster principal
Consideraremos que todo el tráfico destinado a worker-service se enruta al clúster primary como el estado "predeterminado" de nuestra aplicación.
Edita $proj/istio-manifests/worker-virtualservice.yaml para que se vea de la siguiente manera:
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
Asegúrate de estar conectado al clúster primary.
kubectx primary
Aplica istio-manifests/worker-virtualservice.yaml
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Escribe el daemon de Istiowatcher
Usaremos Go para escribir este servicio por su velocidad y portabilidad. El flujo general de la aplicación será iniciarse y, cada segundo, consultar Prometheus.
Crea un directorio nuevo en src llamado istiowatcher.
mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher
Llamaremos a istioctl desde nuestro contenedor para manipular el plano de control de Istio desde el clúster.
Escribe istiowatcher.go
Crea un archivo en ese directorio llamado istiowatcher.go y, luego, inserta lo siguiente en él:
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)
}
}
Escribe el Dockerfile
Crea un archivo nuevo llamado Dockerfile y, luego, inserta el siguiente contenido:
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"]
Este Dockerfile de varias etapas descarga y extrae la versión 1.0.0 de Istio en la primera etapa. La segunda etapa copia todo desde nuestro directorio a la imagen, luego copia istioctl desde la etapa de compilación a /usr/local/bin (para que nuestra aplicación pueda llamarlo), obtiene las dependencias, compila el código y establece CMD como "istiowatcher".
Escribe burst.yaml
Este es el archivo istiowatcher que se aplicará cuando las solicitudes por segundo a worker desde frontend superen las 15.
Crea un archivo nuevo llamado burst.yaml y, luego, inserta el siguiente contenido:
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
Escribe natural.yaml
Consideraremos que este es el estado "natural" al que volvemos cuando las solicitudes por segundo de frontend a worker son inferiores a 10. En este estado, el 100% del tráfico se enruta al clúster primary.
Crea un archivo nuevo llamado natural.yaml y, luego, inserta lo siguiente en él:
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
Compila y envía istiowatcher
Ejecuta el siguiente comando para enviar el directorio actual a Google Cloud Build (GCB), que compilará y etiquetará la imagen en GCR.
gcloud builds submit -t gcr.io/${GCLOUD_PROJECT}/istiowatcher
Implementa istiowatcher
Cambia a nuestro directorio kubernetes.
cd ${proj}/kubernetes/
Escribe un archivo de implementación: istiowatcher.yaml
Crea un archivo llamado istiowatcher.yaml y, luego, inserta lo siguiente (reemplaza <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
Implementar
Asegúrate de que estemos ejecutando el clúster principal
kubectx primary
Implementa istiowatcher.yaml en el espacio de nombres istio-system
kubectl apply -n istio-system -f istiowatcher.yaml
Es importante tener en cuenta las directivas serviceAccountName y automountServiceAccountToken en el archivo YAML. Esto nos proporciona las credenciales necesarias para ejecutar istioctl desde el clúster.
También debemos implementar esto en el espacio de nombres istio-system para asegurarnos de tener las credenciales del istio-pilot-service-account. (no existe en el espacio de nombres default).
Mira cómo cambia el tráfico automáticamente.
Ahora, ¡el momento mágico! Vamos a nuestro frontend y aumentemos las solicitudes por segundo a 20.
Observa que tarda unos segundos, pero se acelera y todos nuestros hashes tienen el prefijo "bursty-".
Esto se debe a que tomamos muestras de Prometheus en un rango de 15s, lo que hace que nuestro tiempo de respuesta se retrase un poco. Si quisiéramos una banda mucho más ajustada, podríamos cambiar nuestra consulta a Prometheus a 5s..
18. Próximos pasos
Haz limpieza
No es necesario que realices una limpieza si usas una cuenta temporal proporcionada para este taller.
Puedes borrar tus clústeres de Kubernetes, la regla de firewall y las imágenes en 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
Going Forward (Próximos pasos)
- Asiste a algunas charlas sobre Istio.
- Get the Cert: Build Your Next App With Kubernetes + Istio
- Conferencia magistral: Kubernetes, Istio y Knative: La nueva pila de código abierto de Cloud - Aparna Sinha, gerente de Producto de Grupo de Kubernetes, Google
- Instructivo: Cómo usar Istio (Lee Calcote y Girish Ranganathan, SolarWinds)
- Istio - The Packet's-Eye View - Matt Turner, Tetrate
- Is Istio the Most Next Gen Next Gen Firewall Ever Created? - John Morello, Twistlock
- Lee la documentación de Istio.
- Únete a los Grupos de trabajo de Istio
- Sigue a @IstioMesh en Twitter




