martes, 15 de octubre de 2024

Service Mesh Istio


Imagina que tienes una aplicación la cual está construida por muchos microservicios, ¿Cómo la vas a monitorear/supervisar/optimizar el rendimiento y la comunicación de la aplicación entre todos estos microservicios?

Aquí es dónde te ayudan tener un service mesh:

- Administrar conexiones entre servicios
- Supervisión de tráfico
- Registro de tráfico
- Rastreo de tráfico
- Control de tráfico
- Escalabilidad y alta disponibilidad

En resumen un **service mesh** es una software dedicado a manejar la comunicación entre servicios.

Aquí te dejo el video para que lo sigas conmigo:






## Beneficios de una Service mesh

- Detección de servicios.
- Balanceador de carga
- Administración de tráfico
- División de tráfico
- Creación de reflejos de solicitudes
- Implementación de valores controlados
- Seguridad
- Supervisión

## Desventajas de una Service mesh

- Se incrementa el tiempo de ejecución
- Cada llamada primero se ejecuta en el proxy-sidecar (se agrega un paso adicional)
- Alguien debe integrar la Service Mesh en los flujos de trabajo y administrar su configuración

## Funcionamiento

Básicamente por medios de varios proxies dirige y rastrea la comunicación entre los servicios.

En donde el proxy es un gateway entre la red de la organización y el microservicio. Estos proxies se les llama sidecares, porque Istio agrega un contenedor junto al pod del microservicio. Y estos proxies son los que forman la **service mesh**.


Y dentro de cada Pod:

Dentro de la arquitectura hay dos componentes principales:


### Plano de datos

Cuando un servicio se quiere comunicar con otro, el proxy del sidecar hace lo siguiente:

1. El sidecar intercepta la solicitud.
2. La solicitud es encapsulada en una conexión de red independiente.
3. Levanta un canal seguro y cifrado entre los proxies de origen y destino.

### Plano de control.

Es la capa de administración y configuración de la service mesh.
La implementación suele incluir estas capacidades:

1. Registro de servicios: se hace seguimiento de todos los servicios en la service mesh.
2. Detección automática de nuevos servicios y eliminación de servicios inactivos.
3. Recopilación y agregación de datos de telemetría (métricas).

## Istio

Hoy instalaremos Istio que es una **service mesh** de Google, IBM y Lyft.

Istio: Es una solución muy popular para gestionar los diferentes microservicios que conforman una aplicación nativa de la nube.

Una recomendación es usar Istio con aplicaciones grandes, ya que puede ser un poco complejo dependiendo lo que queramos hacer.

## Instalación

1. Consta de un ejecutable que hay que colocar en el path:

```bash
curl -L https://istio.io/downloadIstio | sh -
```

2. Entramos en el directorio que descargamos y dentro hay una carpeta bin, movemos el ejecutable istioctl a una ruta de nuestro path en mi caso es, ejemplo:

```bash
cd istion-1.3.22/bin
mv istioctl $HOME/.local/bin
```

3. Instalamos Istio en nuestro cluster de kubernetes:

```bash
istioctl install
```

Podemos ver que nos ha creado un nuevo namespace:

Ahora para configurar Istio en todo un namespace de tu aplicación lo único que hay que hacer es ejecutar el siguiente comando:

```bash
kubectl label namespace TUNAMESPACE istio-injection=enabled
```

Para ver los labels que tiene el namespace:

```bash
kubectl get ns TUNAMESPACE --show-labels
```


**NOTA:** En el ejemplo se aplicará al namespace default, si ya tienes una aplicación ejecutándose en el namespace es necesario volver a desplegarla o cuando se haga un upgrade de la aplicación se le aplicará el label istio-injection=enabled.

## Monitoreo y Visualización de datos

Para el monitoreo contamos con los dos viejos conocidos Prometheus y Grafana (también cuenta soporte para Apache SkyWalking).
Para la Visualización de datos debemos instalar Jaeger y Kiali, Jaeger se hace cargo de realizar trazabilidad del sistema, permitiendo al usuario monitorear y ver problemas en sistemas distribuidos complejos y Kiali es el dashboard de observabilidad.

**NOTA:** Jaeger no es el único que existe también se puede utilizar Zipkin.

### Prometheus y Grafana

Hay dos escenarios:

- Prometheus y Grafana ya están instalados
- Prometheus y Grana no están instalados

En este post nos vamos a enfocar en el primer escenario, ya que no hay mucha documentación de cómo hacerlo mientras que el segundo escenario hay por montones y es el escenario que nadie suele tener.

En nuestros manifest de Prometheus, buscamos el configmap de Prometheus y agregamos lo siguiente, en la sección de scrape_configs (también puedes editar el configmap de Prometheus claro está):

Vamos a agregar la configuración para exportar las stats de Istiod:

```yaml
---
- job_name: "istiod"
  kubernetes_sd_configs:
    - role: endpoints
      namespaces:
        names:
          - istio-system
  relabel_configs:
    - source_labels:
        [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
      action: keep
      regex: istiod;http-monitoring
```

Para exportar las stats de Envoy proxy-sidecar y gateway proxies agregamos lo siguiente (seguimos en el configmap de Prometheus).

```yaml
- job_name: "envoy-stats"
  metrics_path: /stats/prometheus
  kubernetes_sd_configs:
    - role: pod

  relabel_configs:
    - source_labels: [__meta_kubernetes_pod_container_port_name]
      action: keep
      regex: ".*-envoy-prom"
```

**Nota:** después de aplicar estos cambios entramos a la consola de Prometheus en el menú damos click en Status-> Service Discovery, y veremos las dos nuevas métricas que son: envoy-stats y istiod, corresponden a las dos configuraciones que hemos agregado en la parte de arriba.


Si quieres ver desde grafana estas métricas puedes ir al panel de la izquierda -> Metrics y en Search Metrics escribes istio.


Listo ya puedes entrar en Grafana y agregar el dashboard de Istio Control Plane Dashboard (ID: 7645), si te vas al panel izquierdo->Metrics podrás seleccionar las métricas que quieras ver de Istio.

Algunos Dashboards que te pueden interesar:

7639 11829 7636 7630 13277

## Aplicación de Prueba

Ahora vamos a probar nuestra service mesh con una aplicación, si ya tienes una aplicación solo debes agregar el label istio-injection=enabled

- Creamos un namespace para nuestra aplicación de ejemplo:

```bash
kubectl create namespace bookinfo
```

- Aplicamos el label en el namespace, esto hará que Istio cree el sidecar en el pod:

```bash
kubectl label namespace bookinfo istio-injection=enabled 
```

- Instalamos la aplicación:

```bash
kubectl -n bookinfo apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/bookinfo/platform/kube/bookinfo.yaml
```

Ingress y Gateway

Actualmente Istio cuenta con su propio Ingress pero están migrando a usar el Gateway de Kubernetes el cual por default no está instalado, por lo que debe realizar primero el siguiente comando:

```bash
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
```

- Istio cuenta con su propio ingress, por lo que para acceder a la aplicación lo haremos con el siguiente manifest:

**gateway-bookinfo.yaml**

```yaml
    ---
	apiVersion: gateway.networking.k8s.io/v1beta1
	kind: Gateway
	metadata:
	  name: bookinfo-gateway
	spec:
	  gatewayClassName: istio
	  listeners:
	  - name: http
	    port: 80
    	protocol: HTTP
	    allowedRoutes:
	      namespaces:
	        from: Same
```

Y también creamos una configuración de las rutas:

**route-bookinfo.yaml**

```yaml
    ---
	apiVersion: gateway.networking.k8s.io/v1beta1
	kind: HTTPRoute
	metadata:
	  name: bookinfo
	spec:
	  parentRefs:
	  - name: bookinfo-gateway
	  rules:
	  - matches:
	    - path:
	        type: Exact
	        value: /productpage
	    - path:
	        type: PathPrefix
	        value: /static
	    - path:
	        type: Exact
	        value: /login
	    - path:
	        type: Exact
	        value: /logout
	    - path:
	        type: PathPrefix
	        value: /api/v1/products
	    backendRefs:
	    - name: productpage
	      port: 9080
```

Instalamos ambos manifest:

```bash
kubectl -n bookinfo apply -f gateway-bookinfo.yaml
kubectl -n bookinfo apply -f route-bookinfo.yaml
```

Ahora podemos acceder a nuestra aplicación en caso que cuentes con metallb solo haces lo siguiente:

```bash
kubectl -n bookinfo get gateway
```

De lo contrario tendrás que realizar un port-forward:

```bash
kubect -n bookinfo port-forward svc/bookinfo-gateway-istio 8080:80
```


La URL es:

http://IP/productpage

Si es port-forward podrá ser:

http://IP:8080/productpage

Una vez hayas entrado a la página, la aplicación se verá así:

## Jaeger para el rastreo (tracing)

Como mencioné anteriormente Jaeger tiene tareas interesantes como:

- Monitoreo de las transacciones entre microservicios.
- Análisis de la causa raíz
- Análisis de la trazabilidad de los microservicios
- Análisis de la dependencia de servicios
- Optimización de rendimiento / latencia

Para instalarlo ejecutamos el siguiente comando:

```bash
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/addons/jaeger.yaml
```

## Kiali el Dashboard de Istio

Para instalarlo ejecutamos el siguiente comando:

```bash
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/addons/kiali.yaml
```

Pero como nosotros tenemos instalado Prometheus y Grafana en diferentes namespaces (monitoring y grafana respectivamente), tenemos que editar el manifest kiali.yaml por lo que te recomiendo que lo bajes o puedes configurar el configmap de kiali en el namespace de istio-systems:

Configmap de kiali:

```bash
kubectl -n istio edit configmaps kiali
```

En ambos casos debemos buscar la línea que dice external_services, y agregamos lo siguiente:

```yaml
external_services:
  prometheus: # prometheus-service es el servicio de prometheus, monitoring es el namespace donde está prometheus instalado.
    url: "http://prometheus-service.monitoring.svc.cluster.local:8082/"
  grafana:
    in_cluster_url: "http://grafana.grafana.svc.cluster.local"
    url: "http://grafana.ahioros.homelab.local"
..
..
..
  tracing:
    enabled: true
```

Este último parámentro (tracing) es para el jaeger.

Espera hasta que el pod este en estado Running, para realizar el siguiente comando:

```bash
istioctl dashboard kiali
```

Esto te abrirá una página en tu navegador.

O puedes crear un manifest loadbalancer para acceder a kiali.

## Generación de tráfico

Vamos a crear tráfico para poder analizar con Istio la trazabilidad de los microservicios.

Ejecuta:

```bash
for i in $(seq 1 100); do curl -s -o /dev/null "http://istio.ahioros.homelab.local/productpage"; done
```

Recuerda cambiar istio.ahioros.homelab.local por la IP que tienes para acceder al servicio.

Dale click al menú de la izquierda donde dice "Traffic Grap", selecciona el namespace "bookinfo", y en la esquina superior derecha te recomiendo que pongas Last 1h y que se actualice Every 1m.

Debes poder ver algo como esto:


Ahora dale click al menú de la izquierda -> "Mesh" aquí podrás ver los componentes de Istio (Los configs que hicimos de Prometheus, Grafana y Jaeger):


## Seguridad en Istio

Por default Istio cifra el comunicado entre los proxies de los microservicios, esto lo puedes comprobar dando click en el menú de la izquierda -> "Traficc Graph", busca la opción que debajo de Namespace, dale click en Display, hasta abajo está la opción Securitty dale click a la casilla.

Ahora verás como aparece un candado en la línea de comunicacion de los microservicios, y si seleccionas dicha línea en el gráfico, verás que te aparecerá en las configuraciones de la derecha una nueva opción que dice: ** mTLS Enabled**. También te recomiendo que le des click en la casilla de Traffic Animation, Response Time, Throughput y Traffic Distribution (esta última es excelente cuando haces despliegues de un microservicio nuevo y quieres ver cómo se comporta después de crear una política donde le enviés X cantidad del tráfico).

**Nota:** Recuerda generar tráfico en la aplicación.

Se verá algo más o menos así:


## Final

Hasta aquí dejamos este tutorial.

## Desinstalación de Istio

Ejecuta:

```bash
istioctl uninstall -y --purge
```

Recuerda borrar el namespace de Istio:

```bash
kubectl delete namespace istio-system
```

Eliminar la aplicación de bookinfo y sus componentes:

```bash
kubectl -n bookinfo delete -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/bookinfo/platform/kube/bookinfo.yaml
```

```bash
kubectl -n bookinfo delete -f gateway-bookinfo.yaml
kubectl -n bookinfo delete -f route-bookinfo.yaml
```

Y también recuerda eliminar el namespace de la aplicación:

```bash
kubectl delete namespace bookinfo
```

Y para eliminar el Gateway de kubernetes (opcional):

```bash
kubectl delete -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
```

No hay comentarios.: