> minikube delete -p minikube 🔥 Eliminando "minikube" en docker... 🔥 Eliminando contenedor "minikube" ... 🔥 Eliminando C:\Users\whistler092\.minikube\machines\minikube... 💀 Removed all traces of the "minikube" cluster. > minikube start -p demo --network-plugin=cni --cni=calico -p demo 😄 minikube v1.34.0 en Microsoft Windows 11 Pro 10.0.26100.2605 Build 26100.2605 ✨ Controlador docker seleccionado automáticamente. Otras opciones: hyperv, ssh ❗ With --network-plugin=cni, you will need to provide your own CNI. See --cni flag as a user-friendly alternative 📌 Using Docker Desktop driver with root privileges 👍 Starting "minikube" primary control-plane node in"minikube" cluster 🚜 Pulling base image v0.0.45 ... 🔥 Creating docker container (CPUs=2, Memory=8100MB) ... ❗ Failing to connect to https://registry.k8s.io/ from inside the minikube container 💡 To pull new external images, you may need to configure a proxy: https://minikube.sigs.k8s.io/docs/reference/networking/proxy/ 🐳 Preparando Kubernetes v1.31.0 en Docker 27.2.0... ▪ Generando certificados y llaves ▪ Iniciando plano de control ▪ Configurando reglas RBAC... 🔗 Configurando CNI Calico ... 🔎 Verifying Kubernetes components... ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5 🌟 Complementos habilitados: storage-provisioner, default-storageclass 🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
Ahora el nuevo clúster está corriendo con Calico como plugin de red. Verifiquemos
Vamos a revisar el archivo kubernetes-microservices-3808182\02_03\learning-resources-api.yaml que contiene la definición de un deployment y un service.
> kubectl apply -f learning-resources-api.yaml deployment.apps/learning-resources created service/learning-service created > kubectl apply -f .\echo-server.yaml deployment.apps/echo-server created service/echo-service created
Ahora podemos ver los pods y los servicios
1 2 3 4 5 6 7
> kubectl get pods NAME READY STATUS RESTARTS AGE echo-server-6b4cb79dc5-gtjxj 1/1 Running 0 3m20s echo-server-6b4cb79dc5-x67c8 1/1 Running 0 3m20s learning-resources-5d986c647d-flxz9 1/1 Running 0 4m29s learning-resources-5d986c647d-g5tn9 1/1 Running 0 4m29s learning-resources-5d986c647d-zp6l6 1/1 Running 0 4m29s
1 2 3 4 5
> kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo-service NodePort 10.103.79.0 <none> 80:30076/TCP 4m kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 46m learning-service ClusterIP 10.102.219.228 <none> 80/TCP 5m9s
Aquí se desplegaron dos servicios de backend, uno de tipo NodePort y otro de tipo ClusterIP. Ahora vamos a desplegar el servicio de Frontend para poder interactuar con estos microservicios.
Con este yaml file, vamos a desplegar un servicio de frontend que se va a comunicar con el servicio de backend llamado learning-service.default.svc.cluster.local. Vamos a desplegarlo
1 2 3 4
> kubectl apply -f frontend.yaml namespace/frontend created deployment.apps/frontend created service/frontend-service created
Hay una curiosidad aquí. Si damos kubectl get pods no vamos a ver los pods del namespace frontend. En el yaml anterior tenemos una propiedad nueva
1 2 3
kind:Namespace metadata: name:frontend
Esto es una definición de namespace, por lo tanto, si damos el comando de get pods no va a estar en el contexto actual. Para cambiar el contexto, podemos hacerlo de la siguiente manera
1 2 3 4 5
> kubectl get pods -n frontend NAME READY STATUS RESTARTS AGE frontend-5d5d6f9c79-hg2fv 1/1 Running 0 2m37s frontend-5d5d6f9c79-jzj4c 1/1 Running 0 2m37s frontend-5d5d6f9c79-kc57n 1/1 Running 0 2m37s
Ya podemos ver las 3 replicas
1 2 3
> kubectl get svc -n frontend NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE frontend-service LoadBalancer 10.109.19.66 <pending> 80:30134/TCP 3m12s
Hasta el momento se ha instalado el minikube, se ha creado un clúster y se cambió el CNI de kindnet a Calico. Se han desplegado 3 microservicios, uno de tipo NodePort, otro de tipo ClusterIP y otro de tipo LoadBalancer. Se ha creado un namespace y se han desplegado 3 réplicas de un servicio en ese namespace.
Vamos a ver que significa eso de tener diferentes tipos de servicios para permitir que los pods se comuniquen entre sí.
K8s puede crear un servicio con una IP estática y un nombre. Y cuando un request llega a este servicio, el usa un balanceador de carga para redirigir el tráfico a los pods cuyas IPs están cambiando constantemente. Así que el servicio es un punto de entrada para los pods, uno no debe intentar conectarse a las IPs directas de los pods.
Este es el servicio que está usando el servicio de frontend. Este servicio es accesible solo dentro del clúster, esto siendo definido por el specs.type ClusterIP y no es accesible desde afuera del clúster, aunque se puede acceder a este servicio desde cualquier namespace. El spec.selector es el que define que pods van a ser asociados por este servicio.
La IP del servicio learning-resources-5d986c647d-flxz9 es 10.244.120.67. Ahora vamos a hacer un request a este servicio
1 2 3
/ # wget -O- 10.244.120.67 Connecting to 10.244.120.67 (10.244.120.67:80) wget: can't connect to remote host (10.244.120.67): Connection refused
Como se está intentando acceder a la IP del pod directamente, porque él está corriendo sobre un puerto en específico. La IP del pod está en el puerto 30000
1 2 3 4 5 6 7
/ # wget -O- 10.244.120.67:3000 Connecting to 10.244.120.67:3000 (10.244.120.67:3000) writing to stdout {"Intermediate Level Kubernetes Learning Resources":[{"id" ... 100% |**************************************************************************************| 8189 0:00:00 ETA written to stdout / #
¡Funciono! Aunque no deberíamos hacer eso porque las IPs de los pods varían, por lo cual se va a hacer este request al servicio.
Vamos a obtener la lista de los servicios actualmente creados.
1 2 3 4 5
> kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo-service NodePort 10.103.79.0 <none> 80:30076/TCP 5h13m kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5h56m learning-service ClusterIP 10.102.219.228 <none> 80/TCP 5h14m
Volvamos al pod de busybox e intentemos hacer el wget solamente especificando el nombre del servicio. No IP address.
1 2 3 4 5 6
/ # wget -O- learning-service Connecting to learning-service (10.102.219.228:80) writing to stdout {"Intermediate Level Kubernetes Learning Resources":[{"id": ... 100% |**************************************************************************************| 8189 0:00:00 ETA written to stdout
El DNS pudo resolver la dirección IP del servicio y redirigir el tráfico a los pods.
Hay otra forma de hacer esto, y es con el DNS completo.
1 2 3 4 5 6
/ # / # wget -O- http://learning-service.default.svc.cluster.local Connecting to learning-service.default.svc.cluster.local (10.102.219.228:80) writing to stdout {"Intermediate Level Kubernetes Learning Resources ... 100% |**************************************************************************************| 8189 0:00:00 ETA written to stdout
learning-service.default.svc.cluster.local se compone del
nombre del servicio,
seguido por el namespace default,
el tipo de k8s object svc
y el clúster domain. Esto es una forma de acceder a los servicios dentro del clúster.
Nodeport
Nodeport es un tiempo de servicio que ayuda a exponer un grupo de ports a internet.
Cualquier pod que tenga el label de spec.selector.app echo-service, va a recibir tráfico desde este servicio. En específico, este servicio usa las direcciones IP de los nodos de k8s, ósea que cualquiera que sepa las direcciones IPs de los nodos de k8s, puede hacer un request a estos servicios.
Este servicio tiene algunas implicaciones de seguridad, debe de ser usado con cuidado.
Ejemplo de uso de NodePort
Vamos a explorar el servicio de echo-server, para eso volvamos al busybox pod.
Pero antes de eso, vamos a ver la IP del pod echo-server
> kubectl exec -it busybox -- sh / # wget -O- 10.244.120.70 Connecting to 10.244.120.71 (10.244.120.71:80) writing to stdout {"host":{"hostname":"10.244.120.71","ip":"::ffff:10.244.120.75","ips":[]},"http":{"method":"GET","baseUrl":"","originalUrl":"/","protocol":"http"},"request":{"params":{"0":"/"},"query":{},"cookies":{},"body":{},"headers":{"host":"10.244.120.71","user-agent":"Wget","connection":"close"}},"environment":{"PATH":"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","HOSTNAME":"echo-server-6b4cb79dc5-gtjxj","PORT":"80","LEARNING_SERVICE_PORT":"tcp://10.102.219.228:80","ECHO_SERVICE_SERVICE_HOST":"10.103.79.0","ECHO_SERVICE_SERVICE_PORT_ECHO":"80","ECHO_SERVICE_PORT":"tcp://10.103.79.0:80","KUBERNETES_SERVICE_PORT_HTTPS":"443","KUBERNETES_PORT_443_TCP":"tcp://10.96.0.1:443","KUBERNETES_PORT_443_TCP_ADDR":"10.96.0.1","LEARNING_SERVICE_SERVICE_PORT":"80","LEARNING_SERVICE_PORT_80_TCP_PROTO":"tcp","LEARNING_SERVICE_PORT_80_TCP_ADDR":"10.102.219.228","ECHO_SERVICE_SERVICE_PORT":"80","ECHO_SERVICE_PORT_80_TCP_PORT":"80","KUBERNETES_PORT":"tcp://10.96.0.1:443","KUBERNETES_PORT_443_TCP_PROTO":"tcp","LEARNING_SERVICE_PORT_80_TCP":"tcp://10.102.219.228:80","ECHO_SERVICE_PORT_80_TCP":"tcp://10.103.79.0:80","KUBERNETES_SERVICE_PORT":"443","KUBERNETES_PORT_443_TCP_PORT":"443","LEARNING_SERVICE_SERVICE_HOST":"10.102.219.228","LEARNING_SERVICE_PORT_80_TCP_PORT":"80","ECHO_SERVICE_PORT_80_TCP_PROTO":"tcp","ECHO_SERVICE_PORT_80_TCP- 100% |**************************************************************************************| 1465 0:00:00 ETA written to stdout
El pod nos respondió bien, pero como sabemos, esto no es una buena práctica. Para eso vamos a hacer un request a la IP del servicio en sí. Pero para eso vamos a tener que buscar la dirección IP del node de k8s.
1 2 3
> kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME minikube Ready control-plane 6h57m v1.31.0 192.168.49.2 <none> Ubuntu 22.04.4 LTS 5.15.167.4-microsoft-standard-WSL2 docker://27.2.0
La IP del nodo es 192.168.49.2. Ahora vamos a hacer un request a la IP del nodo desde el busybox.
1 2 3
/ # wget -O- 192.168.49.2 Connecting to 192.168.49.2 (192.168.49.2:80) wget: can't connect to remote host (192.168.49.2): Connection refused
No podemos conectarnos, vamos a revisar el archivo yaml del servicio de echo-server
El servicio está corriendo en el puerto 80, pero el puerto que se está exponiendo es el 30076. Vamos a hacer un request a este puerto.
1 2 3 4 5
/ # wget -O- 192.168.49.2:30076 Connecting to 192.168.49.2:30076 (192.168.49.2:30076) writing to stdout {"host":{"hostname":"192.168.49.2","ip":"::ffff:192.168.49.2","ips":[]},"http":{"method":"GET","baseUrl":"","originalUrl":"/","protocol":"http"},"request":{"params":{"0":"/"},"query":{},"cookies":{},"body":{},"headers":{"host":"192.168.49.2:30076","user-agent":"Wget","connection":"close"}},"environment":{"PATH":"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","HOSTNAME":"echo-server-6b4cb79dc5-gtjxj","PORT":"80","LEARNING_SERVICE_PORT":"tcp://10.102.219.228:80","ECHO_SERVICE_SERVICE_HOST":"10.103.79.0","ECHO_SERVICE_SERVICE_PORT_ECHO":"80","ECHO_SERVICE_PORT":"tcp://10.103.79.0:80","KUBERNETES_SERVICE_PORT_HTTPS":"443","KUBERNETES_PORT_443_TCP":"tcp://10.96.0.1:443","KUBERNETES_PORT_443_TCP_ADDR":"10.96.0.1","LEARNING_SERVICE_SERVICE_PORT":"80","LEARNING_SERVICE_PORT_80_TCP_PROTO":"tcp","LEARNING_SERVICE_PORT_80_TCP_ADDR":"10.102.219.228","ECHO_SERVICE_SERVICE_PORT":"80","ECHO_SERVICE_PORT_80_TCP_PORT":"80","KUBERNETES_PORT":"tcp://10.96.0.1:443","KUBERNETES_PORT_443_TCP_PROTO":"tcp","LEARNING_SERVICE_PORT_80_TCP":"tcp://10.102.219.228:80","ECHO_SERVICE_PORT_80_TCP":"tcp://10.103.79.0:80","KUBERNETES_SERVICE_PORT":"443","KUBERNETES_PORT_443_TCP_PORT":"443","LEARNING_SERVICE_SERVICE_HOST":"10.102.219.228","LEARNING_SERVICE_PORT_80_TCP_PORT":"80","ECHO_SERVICE_PORT_80_TCP_PROTO":"tcp","ECHO_SERVICE_PORT_80_- 100% |**************************************************************************************| 1468 0:00:00 ETA written to stdout
Pudimos hacer el GET request al node de k8s y obtuvimos el response esperado del pod. Pero vamos a hacer al servicio en sí.
1 2 3 4 5
/ # wget -O- echo-service Connecting to echo-service (10.103.79.0:80) writing to stdout {"host":{"hostname":"echo-service","ip":"::ffff:10.244.120.75","ips":[]},"http":{"method":"GET","baseUrl":"","originalUrl":"/","protocol":"http"},"request":{"params":{"0":"/"},"query":{},"cookies":{},"body":{},"headers":{"host":"echo-service","user-agent":"Wget","connection":"close"}},"environment":{"PATH":"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","HOSTNAME":"echo-server-6b4cb79dc5-x67c8","PORT":"80","KUBERNETES_SERVICE_HOST":"10.96.0.1","KUBERNETES_PORT":"tcp://10.96.0.1:443","ECHO_SERVICE_SERVICE_PORT":"80","KUBERNETES_PORT_443_TCP":"tcp://10.96.0.1:443","LEARNING_SERVICE_SERVICE_PORT":"80","LEARNING_SERVICE_PORT_80_TCP_PORT":"80","ECHO_SERVICE_SERVICE_HOST":"10.103.79.0","ECHO_SERVICE_PORT_80_TCP_ADDR":"10.103.79.0","ECHO_SERVICE_PORT":"tcp://10.103.79.0:80","ECHO_SERVICE_PORT_80_TCP":"tcp://10.103.79.0:80","KUBERNETES_SERVICE_PORT":"443","KUBERNETES_PORT_443_TCP_ADDR":"10.96.0.1","LEARNING_SERVICE_PORT_80_TCP":"tcp://10.102.219.228:80","LEARNING_SERVICE_PORT_80_TCP_PROTO":"tcp","ECHO_SERVICE_SERVICE_PORT_ECHO":"80","LEARNING_SERVICE_PORT_80_TCP_ADDR":"10.102.219.228","ECHO_SERVICE_PORT_80_TCP_PROTO":"tcp","ECHO_SERVICE_PORT_80_TCP_PORT":"80","KUBERNETES_SERVICE_PORT_HTTPS":"443","KUBERNETES_PORT_443_TCP_PROTO":"tcp","KUBERNETES_PORT_443_TCP_PORT":"443","LEARNING_SERVICE_SERVICE_HOST":"10.102.21- 100% |**************************************************************************************| 1463 0:00:00 ETA written to stdout
Ahora usemos el DNS name. http://echo-service.default.svc.cluster.local
1 2 3 4
/ # wget -O- http://echo-service.default.svc.cluster.local Connecting to echo-service.default.svc.cluster.local (10.103.79.0:80) writing to stdout {"host":{"hostname":"echo-service.de...
Loadbalancer
Este servicio es accesible desde afuera del clúster. Este servicio crea un balanceador de carga en la nube y asigna una IP publica a este servicio.
En este yaml, se va a crear un nuevo namespace llamado frontend, y se va a desplegar un servicio de frontend llamado frontend-ui con 3 réplicas, y en las variables de env del contenedor frontend-container se ve la URL que se va a comunicar con el servicio de backend llamado learning-service.default.svc.cluster.local.
Finalmente, el servicio llamado frontend-service va a ser de tipo LoadBalancer. Vamos a desplegarlo.
> kubectl get svc -n frontend NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE frontend-service LoadBalancer 10.109.19.66 <pending> 80:30134/TCP 6h22m
Como podemos ver, este servicio está pendiente de asignar una IP pública. Si se está corriendo en un clúster en la nube, este servicio va a asignar una IP pública. Cuando el tráfico llegue por esa IP, eso se va a entrar al clúster, después a los servicios y finalmente a los pods. Este servicio es muy útil para exponer servicios a internet.
Vamos a usar una variante de busybox para hacer un request a este servicio.
> kubectl apply -f .\busybox-ui.yaml pod/busybox-ui created > kubectl -n frontend exec -it busybox-ui -- sh / # / # wget -O- frontend-service Connecting to frontend-service (10.109.19.66:80) writing to stdout <!DOCTYPE html> <html lang="en"> ... </body>
- 100% |**************************************************************************************| 12511 0:00:00 ETA written to stdout / # wget -O- http://frontend-service.frontend.svc.cluster.local Connecting to frontend-service.frontend.svc.cluster.local (10.109.19.66:80) writing to stdout <!DOCTYPE html> ... </body>
- 100% |**************************************************************************************| 12511 0:00:00 ETA written to stdout
Funciono, pudimos hacer un request al servicio de frontend desde el pod de busybox. Vamos a revisar de nuevo el servicio
1 2 3
kubectl get svc -n frontend NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE frontend-service LoadBalancer 10.109.19.66 <pending> 80:30134/TCP 6h30m
Si hubiéramos configurado un servicio apropiadamente en un clúster en la nube, este servicio hubiera asignado una IP pública. Pero hay una manera de hacerlo en minikube.
📌 NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ...
❗ Access to ports below 1024 may fail on Windows with OpenSSH clients older than v8.1. For more information, see: https://minikube.sigs.k8s.io/docs/handbook/accessing/#access-to-ports-1024-on-windows-requires-root-permission 🏃 Starting tunnel for service frontend-service.
Ahora vamos a revisar el servicio y ahora vemos que hay una external-ip asignada.
1 2 3
kubectl get svc -n frontend NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE frontend-service LoadBalancer 10.109.19.66 127.0.0.1 80:30134/TCP 6h33m
Actualmente, la página frontend cargada obtiene la información del servicio de backend.
Otra forma de verlo es con port-forwarding, vamos a obtener el nombre de los pods y vamos a hacer port-forwarding.
1 2 3 4 5 6 7 8 9 10 11
> kubectl get pods -n frontend NAME READY STATUS RESTARTS AGE busybox-ui 1/1 Running 0 11m frontend-5d5d6f9c79-hg2fv 1/1 Running 0 6h37m frontend-5d5d6f9c79-jzj4c 1/1 Running 0 6h37m frontend-5d5d6f9c79-kc57n 1/1 Running 0 6h37m > kubectl port-forward frontend-5d5d6f9c79-hg2fv 5478 4173 -n frontend Forwarding from 127.0.0.1:5478 -> 5478 Forwarding from [::1]:5478 -> 5478 Forwarding from 127.0.0.1:4173 -> 4173 Forwarding from [::1]:4173 -> 4173
Este servicio es un alias para un servicio externo. Este servicio no tiene un selector, pero tiene un campo externalName que es el nombre del servicio externo.
En vez de hacer load balancing del tráfico de los pods dentro del clúster, lo que hace este servicio es redirigir el tráfico a un nombre de DNS, que por lo general esta fuera del clúster.
En este caso hay un servicio llamado database-service, que vive en el namespace de prod, y cuando el tráfico es enviado a ese servicio se va a redirigir el tráfico a my.postgres.database.com.
Network Policies
Son una serie de reglas que te permiten controlar el flujo del tráfico a nivel de IP address o a nivel de puerto.
Ingress o Egress
Ingress: Controla el tráfico que entra a los pods
Egress: Controla el tráfico que sale de los pods
Revisemos un ejemplo de network policy. Esta politica va a denegar todo el tráfico de entrada y salida. Vamos a crear un archivo llamado deny-all.yaml
> kubectl apply -f .\deny-all.yaml networkpolicy.networking.k8s.io/deny-all created > kubectl get networkpolicy NAME POD-SELECTOR AGE deny-all <none> 10s
Esto se va a ejecutar a todos los pods porque no hay un selector asociado.
Ahora miremos un ejemplo de un network policy que va a permitir tráfico inbound de todos los pods en el mismo namespace.
> kubectl apply -f .\allow-ingress.yaml networkpolicy.networking.k8s.io/allow-from-learning-resources created > kubectl get networkpolicy NAME POD-SELECTOR AGE allow-from-learning-resources app=echo-server 3s deny-all <none> 4m22s
En la configuración anterior se está permitiendo el tráfico de entrada de los pods que tengan el label app: learning-resources al servicio de echo-server en el puerto 80.
Ahora vamos a crear un network policy que va a permitir el tráfico de egress desde la aplicación frontend-ui. Vamos a crear un archivo llamado allow-egress.yaml con el siguiente contenido
> kubectl apply -f .\allow-egress.yaml networkpolicy.networking.k8s.io/allow-egress created > kubectl get networkpolicy -n frontend NAME POD-SELECTOR AGE allow-egress app=frontend-ui 4m53s
Ahora vamos a reiniciar el clúster de minikube para poder hacer nuevas pruebas.
1
> minikube delete -p demo
Ingress
¿Como el tráfico llega el Clúster?
Por defecto, los pods solamente responden a solicitudes de tráfico que llegan de otros pods dentro del mismo clúster. El k8s ingress y egress controllers aceptan y enrutan el tráfico externo a los servicios del clúster.
Un objecto Ingress es parte de k8s y crea una dirección IP de acceso público. Así que cuando se envía una petición HTTP o HTTPs a esa dirección IP, el controlador de Ingress a enviar el tráfico al Ingress Controller, este va a revisar la lista de reglas del firewall configuradas y enrutara el tráfico al servicio correcto en funcion a esas reglas.
El objeto Ingress solamente define las reglas
El ingress controller es el que las aplica, siendo un proxy reverso y un balanceador de carga.
Cuando los Objetos ingress son parte del Core de k8s, los controladores de Ingress son implementaciones de terceros, similares a los CNIs. Por eso son plugins que se pueden instalar en el clúster.
En este ejemplo, el tipo sera determinado por kind: Ingress, y en annotations se definio que se usara el nginx.ingress. El objeto Ingress va a enrutar el tráfico que llega a lil-microservices.com al servicio frontend-ui en el puerto 8080.
En vez de obtener tráfico en el clúster usando NodePort o LoadBalancer, en frente de cada microservicio, K8s ingress te permite tener un punto de entrada para tu clúster. Esto te da más flexibilidad.
Service Mesh
Hay un punto en que implementar network policies se vuelve complicado. Por ejemplo, si se tiene un clúster con 1000 pods, y se quiere permitir que solo 10 de esos pods se comuniquen con un servicio en específico, se va a tener que escribir 1000 reglas de network policy. Esto se vuelve complicado.
Un Service Mesh es una capa de infraestructura que maneja la comunicacion entre los microservicios. Manejara todos los aspectos de Service Discovery. El proposito de un Service Mesh es:
Manejar la comunicacion entre los microservicios
Seguridad y control de trafico
Observabilidad y monitoreo
Hay varias implementaciones de Service Mesh
Istio
Linkerd
HashiCorp Consul
Algunas de paga como
AWS App Mesh
Google Anthos
Open Service Mesh (OSM) de Microsoft
El downside de un Service Mesh es que es una capa adicional de infraestructura que se tiene que manejar. Pero es una buena opcion si se tiene un clúster grande con muchos microservicios.