Uso de Istio+Kiali para implementar y visualizar despliegues Canary

Artículos de este ciclo
- (este artículo)
- Despliegue Canary usando Jenkins-X Istio Flagger
Despliegue Canary
Esperamos que hayas leído , donde explicamos brevemente qué son los despliegues Canary y mostramos cómo implementarlo utilizando recursos estándar de Kubernetes.
Istio
Y suponemos que al leer este artículo, ya sabes qué es Istio. Si no, puedes leer sobre él .
Aplicación para pruebas

Cada pod contiene dos contenedores: nuestra aplicación e istio-proxy.
Usaremos una aplicación de prueba simple con pods frontend-nginx y backend en python. El pod con nginx simplemente redirigirá cada solicitud al pod con backend y funcionará como un proxy. Los detalles pueden verse más adelante en los siguientes archivos yaml:
Ejecutar la aplicación de prueba por tu cuenta
Si deseas seguir mi ejemplo y usar esta aplicación de prueba por tu cuenta, consulta .
Despliegue inicial
Al iniciar el primer despliegue, vemos que los pods de nuestra aplicación tienen solo 2 contenedores, es decir, el sidecar de Istio aún se está implementando:

Y también vemos el Loadbalancer de Istio Gateway en el namespace istio-system:

Generación de tráfico
Usaremos la siguiente IP para generar tráfico que será recibido por los pods de frontend y redirigido a los pods de backend:
while true; do curl -s --resolve 'frontend.istio-test:80:35.242.202.152' frontend.istio-test; sleep 0.1; done
También añadiremos frontend.istio-test a nuestro archivo hosts.
Visualización de Mesh a través de Kiali
Hemos instalado la aplicación de prueba e Istio junto con Tracing, Grafana, Prometheus y Kiali (ver más en ). Por lo tanto, podemos usar Kiali a través de:
istioctl dashboard kiali # admin:admin

Kiali visualiza el tráfico actual a través de Mesh
Como vemos, el 100% del tráfico llega al servicio frontend, luego al pod del frontend con la etiqueta v1, ya que utilizamos un proxy nginx simple que redirige las solicitudes al servicio backend, que a su vez las redirige a los pods de backend con la etiqueta v1.
Kiali funciona excelente junto con Istio y proporciona una solución lista para la visualización de Mesh. Es simplemente maravilloso.
Despliegue Canary
Nuestro backend ya tiene dos despliegues k8s, uno para v1 y otro para v2. Ahora solo necesitamos decirle a Istio que redirija un cierto porcentaje de solicitudes a v2.
Paso 1: 10%
Y todo lo que necesitamos hacer es ajustar el peso de VirtualService en :
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
gateways: []
hosts:
- "backend.default.svc.cluster.local"
http:
- match:
- {}
route:
- destination:
host: backend.default.svc.cluster.local
subset: v1
port:
number: 80
weight: 90
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 10 
Vemos que el 10% de las solicitudes se redirige a v2.
Paso 2: 50%
Y ahora, simplemente hay que aumentarlo al 50%:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
...
- destination:
host: backend.default.svc.cluster.local
subset: v1
port:
number: 80
weight: 50
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 50 
Paso 3: 100%
Ahora el despliegue Canary se considera completo y todo el tráfico se redirige a v2:

Pruebas manuales de Canary
Supongamos que ahora estamos enviando el 10% de todas las solicitudes al backend v2. ¿Qué pasa si queremos probar manualmente el v2 para asegurarnos de que todo funciona como esperamos?
Podemos añadir una regla de coincidencia especial basada en los encabezados HTTP:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
gateways: []
hosts:
- "backend.default.svc.cluster.local"
http:
- match:
- headers:
canary:
exact: "canary-tester"
route:
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 100
- match:
- {}
route:
- destination:
host: backend.default.svc.cluster.local
subset: v1
port:
number: 80
weight: 90
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 10Ahora, usando curl, podemos forzar una solicitud a v2 enviando el encabezado:
![]()
Las solicitudes sin encabezado aún serán manejadas en la proporción 1/10:

Canary para dos versiones dependientes
Ahora consideraremos el caso en el que tenemos la versión v2 tanto para el frontend como para el backend. Para ambos hemos especificado que el 10% del tráfico debe ir a v2:

Vemos que el frontend v1 y v2 redirigen tráfico en una proporción de 1/10 a los backend v1 y v2.
¿Y si necesitáramos redirigir el tráfico de frontend-v2 solo a backend-v2, porque no es compatible con v1? Para ello, estableceremos una proporción de 1/10 para el frontend, que controla qué tráfico llega a backend-v2 utilizando la coincidencia por sourceLabels :
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
gateways: []
hosts:
- "backend.default.svc.cluster.local"
http:
...
- match:
- sourceLabels:
app: frontend
version: v2
route:
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 100Como resultado, obtenemos lo que necesitamos:

Diferencias con el enfoque manual de Canary
En parte anterior realizábamos el despliegue de Canary manualmente, utilizando también dos despliegues de k8s. Allí gestionábamos la proporción de solicitudes, cambiando el número de réplicas. Este enfoque funciona, pero tiene serias desventajas.
Istio permite definir la proporción de solicitudes independientemente del número de réplicas. Esto significa, por ejemplo, que podemos utilizar HPAs (Horizontal Pod Autoscalers — escalado horizontal de pods) y no es necesario configurarlo de acuerdo con el estado actual del despliegue de Canary.
Summary
Istio funciona excelente y al usarlo junto con Kiali obtenemos una combinación muy poderosa. Lo siguiente en mi lista de intereses es la combinación de Spinnaker con Istio para la automatización y análisis de Canary.
Fuente: habr.com
