Proyecto Tye es una herramienta experimental que nos permitirá desarrollar, probar, y desplegar micro servicios y aplicaciones distribuidas de una forma simple. Si es que decidiste seguir ese diseño arquitectónico.
Este post esta basado en el artículo original de: https://devblogs.microsoft.com/aspnet/introducing-project-tye/ para que no tengan excusas con el ingles y con el plus de joedayz :P.
Es claro que al crear múltiples proyectos creamos un sitio web, su backend API y diferentes servicios que se comunicaran entre ellos. Lo que busca esta herramienta es hacer muchas de las tareas repetitivas simples e incluso publicar tu aplicación en una plataforma como Kubernetes.
Los objetivos del proyecto son:
1. Permitir el dearrollo de microservicios simple, ¿cómo?:
- Ejecutando varios servicios con un comando
- Usando dependencias en contenedores
- Descubrir la dirección de otros servicios usando convenciones simples
2. Automatizar el despliegue de aplicaciones .NET a Kubernetes, ¿cómo?:
- Automaticamente se contenerizan las aplicaciones .NET
- Generar manifiestos de Kubernetes con poco conocimiento del mismo o configuración
- Usar un simple archivo de configuración.
Microsoft ha demostrado el uso de Tye en dos sesiones del Microsoft Build, los cuales son: Cloud Native Apps with .NET and AKS y Journey to one .NET.
Instalación
El pre-requisito es tener instalado .NET Core 3.1 en nuestra computadora.
Luego instalar Tye como una herramienta global usando este comando:
dotnet tool update -g Microsoft.Tye --version "0.3.0-alpha.20319.3"
NOTA: Verifica si hay una versión más reciente en https://github.com/dotnet/tye/blob/master/docs/getting_started.md
Ejecutando un simple servicio
1. Crear un directorio llamado microservicios e ingresar en el:
mkdir microservicios
cd microservicios
2. Luego crea un proyecto frontend:
dotnet new razor -n frontend
3. Ahora ejecutemos el programa usando tye run:
tye run frontend
Tye como puede ver, ha construido, esta ejecutando y monitoreando la aplicación frontend.
Tye viene con un dashboard para ver el estado de tu aplicación. Vamos a http://localhost:8000 para ver este.
El fin del dashboard es mostrar todos nuestros servicios. La columna Bindings tiene los links URLs del servicio. La columna Logs nos permite ver los logs del servicio.
Los servicios escritos con ASP.NET Core usan puertos asignados de forma aleatoria, si es que estos no son configurados de forma explicita. Esto es por defecto y útil para evitar conflictos de puertos.
Ejecutando múltiples servicios
Ahora imaginemos el escenario de una multi-aplicación donde nuestro frontend se comunica con un proyecto backend. Para continuar para el tye run con Ctrl + C.
1. Crea un backend API que el frontend llamará internamente en el directorio microservicios.
dotnet new webapi -n backend
2. Crea un archivo solución y agrega estos dos proyectos:
dotnet new sln
dotnet sln add frontend backend
Tendremos una solución llamada microservicios.sln que hace referencia a los dos proyectos.
3. Ahora ejecutamos tye run para correr la solución.
tye run
Ahora el dashboard mostrará los servicios frontend y el backend.
Si vamos al servicio backend este retornará un error HTTP 404 para su URL root.
Comunicando el frontend con el backend
Para lograr que ambas aplicaciones se comuniquen, tye usa service discovery. Tye usa variables de entorno para especificar los strings de conexión y URIs de servicios.
Para usar el service discovery de Tye, se usa Microsoft.Extensions.Configuration que esta disponible en ASP.NET Core o en el proyecto .NET Core Worker. Pero, tambien se dispone de Microsoft.Tye.Extensions.Configuration y algunas extensiones específicas de Tye. Más información de como Tye implementa service discovery lo puede ver este link.
1. Primero, asegurate de parar el comando tye run con Ctrl + C. Y abramos la solución en un editor de texto.
2. Agrega el archivo WeatherForecast.cs en el proyecto frontend.
using System;
namespace frontend
{
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
}
Este archivo corresponde con el backend WeatherForecast.cs que se crea por defecto en un webapi template.
3. Agregamos un WeatherClient.cs al proyecto frontend con el siguiente contenido:
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
namespace frontend
{
public class WeatherClient
{
private readonly JsonSerializerOptions options = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
private readonly HttpClient client;
public WeatherClient(HttpClient client)
{
this.client = client;
}
public async Task<WeatherForecast[]> GetWeatherAsync()
{
var responseMessage = await this.client.GetAsync("/weatherforecast");
var stream = await responseMessage.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync<WeatherForecast[]>(stream, options);
}
}
}
4. Agregamos el package Microsoft.Tye.Extensions.Configuration al proyecto frontend.
dotnet add frontend/frontend.csproj package Microsoft.Tye.Extensions.Configuration --version "0.2.0-*"
5. Ahora registremos este cliente en el frontend agregando lo siguiente al método ConfigureServices presente en el archivo Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
/** Add the following to wire the client to the backend **/
services.AddHttpClient<WeatherClient>(client =>
{
client.BaseAddress = Configuration.GetServiceUri("backend");
});
/** End added code **/
}
Esto conectará el WeatherClient para usar la URL correcta para el servicio de back-end.
6. Agrega una propiedad Forecasts en la página Index ubicada en Pages\Index.cshtml.cs en el proyecto frontend.
public WeatherForecast[] Forecasts { get; set; }
7. Cambiar el método OnGet para usar el WeatherClient y llamar al servicio backend y guardar el resultado en la propiedad Forecasts:
public async Task OnGet([FromServices]WeatherClient client)
{
Forecasts = await client.GetWeatherAsync();
}
8. Cambiaremos la vista Index.cshtml para renderizar la propiedad Forecasts en la página razor:
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
Weather Forecast:
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in @Model.Forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
9. Ejecutar el proyecto con tye run y por fin, el servicio frontend podra llamar al servicio backend.
Esquema de Configuración de Tye
Tye tiene un archivo de configuración denominado tye.yaml para permitir configuración personalizada.
Este archivo contiene todos tus proyectos y dependencias externas. Si se tiene una solución existente, Tye automaticamente populará este con todos sus proyectos actuales.
Para inicializar este archivo, se necesita ejecutar este comando en el directorio microservicios para generar un archivo tye.yaml:
tye init
El contenido del archivo tye.yaml luce así:
El alcance a nivel global (como el nombre de nodo) es donde la configuración global es aplicada.
Tye.yaml lista todos los servicios de la aplicación bajo el nodo services. Este es el lugar para configuración por servicio.
Para aprender, a cerca de, la especificación yaml y esquema, tu puedes encontrar más información en este link.
Agregando dependencias externas (Redis)
Tye hace simple el agregar dependencias externas a nuestras aplicaciones. Veremos ahora como agregar redis a el frontend y backend para guardar datos.
Tye puede usar Docker para ejecutar imagenes que que son parte de nuestra aplicación. Hay que asegurarnos de que Docker esta instalado en nuestra máquina.
1. Hay que cambiar el método WeatherForecastController.Get() en el proyecto backend para poner en cache la información del clima en redis usando un IDistributedCache.
2. Agregar los siguientes usings en el archivo:
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;
3. Modificar el método Get():
[HttpGet]
public async Task<string> Get([FromServices]IDistributedCache cache)
{
var weather = await cache.GetStringAsync("weather");
if (weather == null)
{
var rng = new Random();
var forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
weather = JsonSerializer.Serialize(forecasts);
await cache.SetStringAsync("weather", weather, new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(5)
});
}
return weather;
}
Esto guardará la data de clima en Redis con un tiempo de expiración de 5 segundos.
4. Agregar la referencia Microsoft.Extensions.Caching.StackExchangeRedis en el proyecto backend:
cd backend/
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
cd ..
5. Modificamos el Startup.ConfigureServices en el proyecto backend para agregar la implementación IDistributedCache de redis.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddStackExchangeRedisCache(o =>
{
o.Configuration = Configuration.GetConnectionString("redis");
});
}
Esto configura redis en la configuración string para el servicio redis inyectado por el tye host.
6. Modifica el tye.yaml para incluir redis como dependencia.
name: microservice
services:
- name: backend
project: backend\backend.csproj
- name: frontend
project: frontend\frontend.csproj
- name: redis
image: redis
bindings:
- port: 6379
connectionString: "${host}:${port}"
- name: redis-cli
image: redis
args: "redis-cli -h redis MONITOR"
Se ha agregado 2 servicios a el archivo tye.yaml. El servicio redis y el servicio redis-cli que usaremos para ver los datos enviados y recuperados desde redis.
NOTA: El formato "${host}:${port}" en la propiedad connectionString substituíra los valores del host y port para producir un connection string que pueden ser usados con el StackExchange.Redis.
7. Ubicate en el directorio microservicios y ejecuta tye run.
Ve a la aplicación frontend y verifica que los datos retornados son los mismos despues de refrescar la página varias veces. Nuevo contenido será cargado cada 5 segundos, de modo que si esperas un buen tiempo y refrescas, veras nuevos datos. También puedes ver los logs del redis-cli usando el dashboard y ver la data que esta siendo cacheada en redis.
Desplegando a Kubernetes
Tye hace que el proceso de desplegar tu aplicación a Kubernetes sea muy simple con conocimiento mínimo o configuración requerida.
NOTA: Tye usa tus credenciales actuales para pushear tus imagenes Docker y acceder a clusters de Kubernetes. Si tu ya has configurado kubectl apuntando a un contexto, esto es lo que tye deploy va a usar.
NOTA: Aquí puedes ver a que contextos de kubernetes te has conectado anteriormente y si ves un check, ahí estarás apuntando actualmente.
Antes de Desplegar tu aplicación, asegurate de tener lo siguiente:
1. Docker instalado.
2. Un container registry. Docker por defecto crea un container registry en Dockerhub. También podemos usar Azure Container Registry (ACR) u otro container registry de tu elección.
3. Un cluster de Kubernetes. Hay diferentes opciones aquí, cómo:
- Kubernetes en Docker Desktop
- Azure Kubernetes Service
- Minikube
- K3s - un kubernetes ligero distribuido por Rancher.
- Otro proveedor de Kubernetes de tu elección.
NOTA: Para un container registry provisto por otro cloud provider (diferente a Dockerhub), tendrás que seguir las instrucciones provistas por dicho proveedor.
Creando Grupo de Recursos, Container Registry y AKS Cluster
Partimos de que no tenemos grupo de recursos, container registry, ni cluster AKS. Así que definimos primero las variables de entorno respectivas:
jose@Azure:~$ REGION_NAME=eastus
jose@Azure:~$ RESOURCE_GROUP=tyeworkshop
jose@Azure:~$ ACR_NAME=acr$RANDOM
jose@Azure:~$ AKS_CLUSTER_NAME=akstyecluster
Lo creamos con el siguiente comando:
# Creamos el grupo de recursos
az group create \
--name $RESOURCE_GROUP \
--location $REGION_NAME
# Creamos el ACR
az acr create \
--resource-group $RESOURCE_GROUP \
--location $REGION_NAME \
--name $ACR_NAME \
--sku basic
acr28602.azurecr.io
# Creamos el AKS cluster con ACR integration
az aks create -n $AKS_CLUSTER_NAME -g $RESOURCE_GROUP --generate-ssh-keys --attach-acr $ACR_NAME
Asociando mi Kubectl a mi AKS
Según lo expuesto anteriormente me conecto a mi AKS con el siguiente comando:
az aks get-credentials --resource-group $RESOURCE_GROUP --name $AKS_CLUSTER_NAME
Y me conecto a mi ACR:
az acr login -n acr28602
Desplegando Redis
tye deploy no desplegará la configuración de redis, así que se necesitará desplegar esto primero, ejecutando:
kubectl apply -f https://raw.githubusercontent.com/dotnet/tye/master/docs/tutorials/hello-tye/redis.yaml
Esto creará un deployment y un service para redis.
kubectl get all
Tye deploy
Podemos desplegar tu aplicación ejecutando el siguiente comando:
tye deploy --interactive
Se te consultará para que ingreses tu container registry. Esto es necesario para taggear imagenes, y pushear ellas a una ubicación accesible por Kubernetes. Ese dato ya lo tenemos.
Se nos consultará también por la conexión string para redis: el valor correcto es redis:6379
tye deploy creará un Kubernetes secret para guardar el connection string.
Tye usa Kubernetes secrets para guardar información de conexión de dependencias como redis, ya que estas pueden vivir fuera del cluster. Tye automaticamente generará mappings entre nombres de servicios, nombres de binding y nombres de secretos.
tye deploy realiza varios pasos para desplegar una aplicación en Kubenetes. Este hará lo siguiente:
- Creará una imagen docker para cada proyecto en tu aplicación.
- Pusheara la imagen docker en tu container registry
- Generará un Kubernetes deployment y service para cada proyecto
- Aplicará el Deployment y Service generado en tu actual contexto de Kubernetes
Cuando ya tenemos este resultado, deberíamos tener 3 pods ejecutandose despues del despliegue.
Podemos visitar la aplicación frontend, para eso se necesita port-forward para acceder al frontend desde fuera del cluster.
kubectl port-forward svc/frontend 5000:80
Ahora ve a http://localhost:5000 para ver la aplicación frontend trabajando en kubernetes.
La comunicación es sobre HTTP no HTTPS. Habilitar TLS es una opción por defecto en el futuro.
Agregar un registry en tye.yaml
Si deseas usar tye deploy como parte de un sistema CI/CD, se espera que ya tengas tu archivo tye.yaml inicializado. Tu necesitas agregar un container registry a tye.yaml. Entonces agregaremos al tye.yaml:
registry: acr28602.azurecr.io
Ahora es posible usar tye deploy sin --interactive puesto que ya el registry esta como parte de la configuración. Mas información sobre tye deploy en este link.
Desinstalando tu aplicación
Después de desplegar y jugar un rato con la aplicación, ya estamos listos para eliminar todos los recursos asociados con el cluster de Kubernetes. Para lograr eso ejecutamos:
tye undeploy
Esto eliminará todos los recursos desplegados. Si deseas ver que recursos serán eliminados, puedes ejecutar:
tye undeploy --what-if
Continúa tu aprendizaje
Si deseas experimentar mas con Tye, se tiene una gran variedad de ejemplos y tutoriales que puedes verificar en:
Roadmap de Tye
A continuación algunas integraciones que han sido liberadas recientemente. Existe también información provista de coo comenzar con cada uno de ellos:
Tye seguirá en fase experimental y con .NET 5 cuando se lance, se evaluará que se tiene en ese momento para ver que hacer con él en el futuro.
El objetivo del team es sacar cada mes nuevas capacidades como:
- Más destinos de despliegue
- Soporte a Sidecar
- Desarrollo conectado
- Migraciones de base de datos
Conclusión
Tye hace el desarrollo de aplicaciones distribuidas sencillo. Pruebalo, da tu feedback, crea issues y participa en Github.
Post Original de: Amiee Lo (Program Manager, ASP .NET)
Traducción y pruebas en AKS: Joe
Vídeo para practicarlo en casa:
Enjoy!!
Joe