Implementa una app de ASP.NET Core en Google Kubernetes Engine con Istio (parte 1)

1. Descripción general

ASP.NET Core es un marco de trabajo de código abierto y multiplataforma que sirve para compilar aplicaciones modernas basadas en la nube y conectadas a Internet a través del lenguaje de programación C#.

Kubernetes es un sistema de código abierto para automatizar la implementación, el escalamiento y la administración de aplicaciones alojadas en contenedores. Istio es un framework abierto para conectar, proteger, administrar y supervisar servicios.

En esta primera parte del lab, implementarás una app simple de ASP.NET Core en Kubernetes, que se ejecuta en Google Kubernetes Engine (GKE), y la configurarás para que Istio la administre.

En la segunda parte del lab, explorarás más funciones de Istio, como métricas, seguimiento, administración dinámica del tráfico, inserción de fallas y mucho más.

Qué aprenderás

  • Cómo crear y empaquetar una aplicación simple de ASP.NET Core en un contenedor de Docker
  • Cómo crear un clúster de Kubernetes con Google Kubernetes Engine (GKE)
  • Cómo instalar Istio en un clúster de Kubernetes en GKE
  • Cómo implementar tu app de ASP.NET Core y configurar su tráfico para que lo administre Istio

Requisitos

¿Cómo usarás este instructivo?

Leer Leer y completar los ejercicios

¿Cómo calificarías tu experiencia con Google Cloud Platform?

Principiante Intermedio Avanzado

2. Configuración y requisitos

Configuración del entorno de autoaprendizaje

  1. Accede a la consola de Cloud y crea un proyecto nuevo o reutiliza uno existente. Si aún no tienes una cuenta de Gmail o de Google Workspace, debes crear una.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Recuerde el ID de proyecto, un nombre único en todos los proyectos de Google Cloud (el nombre anterior ya se encuentra en uso y no lo podrá usar). Se mencionará más adelante en este codelab como PROJECT_ID.

  1. A continuación, deberás habilitar la facturación en la consola de Cloud para usar los recursos de Google Cloud recursos.

Ejecutar este codelab no debería costar mucho, tal vez nada. Asegúrate de seguir las instrucciones de la sección “Realiza una limpieza”, en la que se aconseja cómo cerrar recursos para que no se te facture más allá de este instructivo. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de USD 300.

Inicia Cloud Shell

Si bien Google Cloud se puede operar de manera remota desde tu laptop, en este codelab usarás Google Cloud Shell, un entorno de línea de comandos que se ejecuta en Google Cloud.

Activar Cloud Shell

  1. En la consola de Cloud, haz clic en Activar Cloud Shell4292cbf4971c9786.png.

bce75f34b2c53987.png

Si nunca has iniciado Cloud Shell, aparecerá una pantalla intermedia (mitad inferior de la página) en la que se describirá qué es. Si ese es el caso, haz clic en Continuar (y no volverás a verla). Así es como se ve la pantalla única:

70f315d7b402b476.png

El aprovisionamiento y la conexión a Cloud Shell solo tomará unos minutos.

fbe3a0674c982259.png

Esta máquina virtual está cargada con todas las herramientas de desarrollo que necesitas. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Gran parte de tu trabajo en este codelab, si no todo, se puede hacer simplemente con un navegador o tu Chromebook.

Una vez conectado a Cloud Shell, debería ver que ya se autenticó y que el proyecto ya se configuró con tu ID del proyecto.

  1. En Cloud Shell, ejecuta el siguiente comando para confirmar que está autenticado:
gcloud auth list

Resultado del comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. En Cloud Shell, ejecuta el siguiente comando para confirmar que el comando gcloud conoce tu proyecto:
gcloud config list project

Resultado del comando

[core]
project = <PROJECT_ID>

De lo contrario, puedes configurarlo con el siguiente comando:

gcloud config set project <PROJECT_ID>

Resultado del comando

Updated property [core/project].

3. Cree una aplicación de ASP.NET Core en Cloud Shell

En el símbolo del sistema de Cloud Shell, puedes verificar que la herramienta de línea de comandos de dotnet ya esté instalada. Para ello, verifica su versión. Esto debería imprimir la versión de la herramienta de línea de comandos de dotnet instalada:

dotnet --version

A continuación, crea una nueva aplicación web de ASP.NET Core de base.

dotnet new mvc -o HelloWorldAspNetCore

Esto creará un proyecto y restablecerá sus dependencias. Deberías ver un mensaje similar al que se muestra a continuación.

Restore completed in 11.44 sec for HelloWorldAspNetCore.csproj.

Restore succeeded.

4. Ejecute la aplicación de ASP.NET Core

Ya está casi todo listo para ejecutar la app. Navega a la carpeta de la app.

cd HelloWorldAspNetCore

Por último, ejecuta la app.

dotnet run --urls=http://localhost:8080

La aplicación inicia la escucha en el puerto 8080.

Hosting environment: Production
Content root path: /home/atameldev/HelloWorldAspNetCore
Now listening on: http://[::]:8080
Application started. Press Ctrl+C to shut down.

Para verificar que se esté ejecutando la app, haz clic en el botón Vista previa en la Web, que se encuentra en la parte superior derecha de la pantalla, y selecciona “Vista previa en el puerto 8080”.

Capture.PNG

Verás la página web predeterminada de ASP.NET Core:

f579a9baedc108a9.png

Una vez que verifiques que la app se está ejecutando, presiona Ctrl + C para detenerla.

5. Empaqueta la app de ASP.NET Core en un contenedor de Docker

A continuación, prepara tu app para que se ejecute como un contenedor. El primer paso es definir el contenedor y su contenido.

En el directorio base de la app, crea un Dockerfile para definir la imagen de Docker.

touch Dockerfile

Agrega lo siguiente a Dockerfile con tu editor favorito (vim, nano,emacs o el editor de código de Cloud Shell).

# Use Microsoft's official build .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-sdk/
FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build
WORKDIR /app

# Install production dependencies.
# Copy csproj and restore as distinct layers.
COPY *.csproj ./
RUN dotnet restore

# Copy local code to the container image.
COPY . ./
WORKDIR /app

# Build a release artifact.
RUN dotnet publish -c Release -o out

# Use Microsoft's official runtime .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-aspnet/
FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine AS runtime
WORKDIR /app
COPY --from=build /app/out ./

# Make sure the app binds to port 8080
ENV ASPNETCORE_URLS http://*:8080

# Run the web service on container startup.
ENTRYPOINT ["dotnet", "HelloWorldAspNetCore.dll"]

Una configuración importante incluida en su Dockerfile es el puerto que utiliza la aplicación para escuchar el tráfico entrante (8080). Para cumplir con ese requisito, se debe configurar la variable de entorno ASPNETCORE_URLS, que utilizan las aplicaciones de ASP.NET Core a fin de determinar el puerto que se debe escuchar.

Guarda este Dockerfile. Ahora, compilaremos la imagen:

docker build -t gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1 .

Una vez que se complete este proceso (tardará un tiempo en descargar y extraer todo), podrás ver que la imagen se compiló y guardó de forma local:

docker images

REPOSITORY                             TAG   
gcr.io/yourproject-XXXX/hello-dotnet   v1            

Prueba la imagen de forma local con el siguiente comando, que ejecutará un contenedor de Docker de forma local en el puerto 8080 desde la imagen de contenedor que creaste recientemente:

docker run -p 8080:8080 gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1

Nuevamente, aprovecha la función de vista previa en la Web de Cloud Shell :

Screenshot from 2015-11-03 17:20:22.png

Deberías ver la página web predeterminada de ASP.NET Core en una pestaña nueva.

f579a9baedc108a9.png

Después de verificar que la app se ejecuta correctamente de forma local en un contenedor de Docker, puedes detener el contenedor en ejecución con Ctrl-> C.

Ahora que la imagen funciona como debe, puede enviarla a Google Container Registry, un repositorio privado para sus imágenes de Docker al que puede acceder desde cada proyecto de Google Cloud y también desde fuera de Google Cloud Platform:

docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1

Si todo sale bien, después de un tiempo, deberías poder ver la imagen de contenedor en la sección Container Registry. Ahora tienes una imagen de Docker disponible para todo el proyecto, a la que Kubernetes puede acceder y que puede organizar, como verás en unos minutos.

73558f3a54ce1c0c.png

Si deseas conocer más, puedes explorar las imágenes de contenedor almacenadas en Google Cloud Storage a través del siguiente vínculo: https://console.cloud.google.com/storage/browser/ (el vínculo final completo debe tener este formato: https://console.cloud.google.com/project/PROJECT_ID/storage/browser/).

6. Crea un clúster de Kubernetes/GKE con Istio

Primero, asegúrate de que la API de Kubernetes Engine esté habilitada:

gcloud services enable container.googleapis.com

Crearás un clúster de Kubernetes. Si lo deseas, puedes cambiar la región a un lugar cercano a ti:

gcloud container clusters create hello-istio \
  --cluster-version=latest \
  --machine-type=n1-standard-2 \
  --num-nodes=4 \
  --region europe-west1

Espere unos minutos mientras su clúster se configura. Se mostrará en la sección Kubernetes Engine de la consola de Google Cloud Platform.

e46fd9c6ee82bcc4.png

Para este codelab, descargaremos e instalaremos Istio desde istio.io. Existen otras opciones de instalación, como el complemento de Istio para GKE y Anthos Service Mesh. Los pasos de la aplicación posteriores a este funcionarán en cualquier instalación de Istio.

Primero, descarguemos el cliente y los ejemplos de Istio. La página de versiones de Istio ofrece artefactos de descarga para varios SO. En nuestro caso, podemos usar un comando conveniente para descargar y extraer la versión más reciente para nuestra plataforma actual:

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

La secuencia de comandos te indicará la versión de Istio que se descargó:

Istio has been successfully downloaded into the istio-1.8.1 folder on your system.

El directorio de instalación contiene aplicaciones de ejemplo y el archivo binario del cliente istioctl. Cambia a ese directorio:

cd istio-1.8.1

Copia y pega el comando proporcionado para agregar el directorio bin a tu PATH, de modo que puedas usar istioctl:

export PATH="$PATH:/home/<YOURHOMEID>/istio-1.8.1/bin"

Verifica que istioctl esté disponible. Para ello, comprueba que tu clúster esté listo para Istio:

istioctl x precheck

Deberías ver un mensaje que diga Install Pre-Check passed! The cluster is ready for Istio installation..

Instala Istio con el perfil de demostración:

istioctl install --set profile=demo

Istio ya está instalado en tu clúster.

Inserción automática de sidecar

Para comenzar a usar Istio, no es necesario que realices ningún cambio en la aplicación. Cuando configuras y ejecutas los servicios, los sidecars de Envoy se insertan automáticamente en cada pod del servicio.

Para que eso funcione, debes habilitar la inserción de sidecar para el espacio de nombres (“predeterminado”) que usas para tus microservicios. Para ello, aplica una etiqueta:

kubectl label namespace default istio-injection=enabled

Para verificar que la etiqueta se haya aplicado correctamente, ejecuta el siguiente comando:

kubectl get namespace -L istio-injection

El resultado confirma que la inserción de sidecar está habilitada para el espacio de nombres predeterminado:

NAME              STATUS   AGE    ISTIO-INJECTION
default           Active   3m     enabled
istio-system      Active   63s    disabled
...

7. Verifique la instalación

Istio incluye tres servicios: el plano de control istiod y las puertas de enlace de entrada y salida (que puedes considerar como "proxies de sidecar para el resto de Internet"), denominados istio-ingressgateway y istio-egressgateway, respectivamente.

kubectl get svc -n istio-system

El resultado debería ser similar al siguiente:

NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP                                                                     AGE
istio-egressgateway    ClusterIP      10.55.252.182   <none>
istio-ingressgateway   LoadBalancer   10.55.250.185   35.233.118.42
istiod                 ClusterIP      10.55.253.217   <none>

La puerta de enlace de entrada tiene un tipo de LoadBalancer, por lo que se puede acceder a ella desde Internet. Los demás solo deben ser accesibles desde el clúster.

A continuación, asegúrate de que los pods de Kubernetes correspondientes estén implementados y de que todos los contenedores estén en funcionamiento. Para ello, ejecuta el siguiente comando:

kubectl get pods -n istio-system

Cuando todos los Pods estén en ejecución, podrás continuar.

NAME                                    READY   STATUS
istio-egressgateway-674988f895-m6tk4    1/1     Running
istio-ingressgateway-6996f7dcc8-7lvm2   1/1     Running
istiod-6bf5fc8b64-j79hj                 1/1     Running
  • istiod: Es el plano de control de Istio. Se encarga de la configuración y la programación de los sidecars del proxy, la detección de servicios, la distribución de certificados y la inserción de sidecars.
  • ingress gateway: Controla las solicitudes entrantes que provienen del exterior de tu clúster.
  • egress gateway: Controla las solicitudes salientes a los extremos fuera de tu clúster.

8. Implemente la aplicación

Ahora que verificaste que Istio está instalado y en ejecución, puedes implementar la app de ASP.NET Core.

Deployment y Service

Primero, crea un archivo aspnetcore.yaml con tu editor favorito (vim, nano,emacs o el editor de código de Cloud Shell) y define la implementación y el servicio de Kubernetes para la app:

apiVersion: v1
kind: Service
metadata:
  name: aspnetcore-service
  labels:
    app: aspnetcore
spec:
  ports:
  - port: 8080
    name: http
  selector:
    app: aspnetcore
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aspnetcore-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aspnetcore
      version: v1
  template:
    metadata:
      labels:
        app: aspnetcore
        version: v1
    spec:
      containers:
      - name: aspnetcore
        image: gcr.io/YOUR-PROJECT-ID/hello-dotnet:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

El contenido del archivo son objetos Deployments y Services estándar para implementar la aplicación y no contienen nada específico de Istio.

Implementa los servicios en el espacio de nombres predeterminado con kubectl:

kubectl apply -f aspnetcore.yaml
service "aspnetcore-service" created
deployment.extensions "aspnetcore-v1" created

Verifica que los pods se estén ejecutando:

kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
aspnetcore-v1-6cf64748-mddb   2/2       Running   0          34s

Gateway y VirtualService

Para permitir que el tráfico de entrada llegue a la malla, debes crear una puerta de enlace y un VirtualService.

Un objeto Gateway configura un balanceador de cargas para el tráfico HTTP/TCP, que suele operar en el perímetro de la malla para habilitar el tráfico de entrada de una aplicación. Un VirtualService define las reglas que controlan cómo se enrutan las solicitudes de un servicio dentro de una malla de servicios de Istio.

Crea un archivo aspnetcore-gateway.yaml para definir la puerta de enlace:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: aspnetcore-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"

Crea un archivo aspnetcore-virtualservice.yaml para definir el VirtualService:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - route:
    - destination:
        host: aspnetcore-service

Ejecuta el comando de kubectl para implementar la puerta de enlace con el siguiente comando:

kubectl apply -f aspnetcore-gateway.yaml

El comando produce el siguiente resultado:

gateway.networking.istio.io "aspnetcore-gateway" created

A continuación, ejecuta el siguiente comando para implementar el VirtualService:

kubectl apply -f aspnetcore-virtualservice.yaml

El comando produce el siguiente resultado:

virtualservice.networking.istio.io "aspnetcore-virtualservice" created

Verifica que todo se esté ejecutando:

kubectl get gateway
NAME                      AGE
aspnetcore-gateway   28s
kubectl get virtualservice
NAME                             AGE
aspnetcore-virtualservice   33s

¡Felicitaciones! Acabas de implementar una aplicación habilitada para Istio. A continuación, verás la aplicación en uso.

9. Prueba la aplicación

Por último, puedes ver la aplicación en acción. Debes obtener la IP externa y el puerto de la puerta de enlace. Aparece en EXTERNAL-IP:

kubectl get svc istio-ingressgateway -n istio-system

Exporta la IP externa y el puerto a una variable GATEWAY_URL:

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')

export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

Usa curl para probar la app. El servicio debería responder con un código de respuesta 200:

curl -o /dev/null -s -w "%{http_code}\n" http://${GATEWAY_URL}/

También puedes abrir el navegador y navegar a http://<gatewayurl> para ver la app:

f579a9baedc108a9.png

10. ¡Felicitaciones!

Acabas de implementar una app simple de ASP.NET Core en Kubernetes, que se ejecuta en Google Kubernetes Engine (GKE), y la configuraste para que Istio la administre.

Quizás te preguntes: "¿Cuáles son los beneficios de Istio?". Es una excelente pregunta. Hasta ahora, no hay ninguna ventaja en que Istio administre esta app. En la segunda parte del lab, exploraremos más funciones de Istio, como métricas, seguimiento, administración dinámica del tráfico, visualización de servicios y la inserción de fallas.

Próximos pasos

Licencia

Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.

11. Limpieza

Si no continuarás con la segunda parte del lab, puedes borrar la app y desinstalar Istio, o bien borrar el clúster de Kubernetes.

Borra la app

Para borrar la app, sigue estos pasos:

kubectl delete -f aspnetcore-gateway.yaml
Kubectl delete -f aspnetcore-virtualservice.yaml
kubectl delete -f aspnetcore.yaml

Para confirmar que la app ya no está, haz lo siguiente:

kubectl get gateway 
kubectl get virtualservices 
kubectl get pods

Desinstala Istio

Para borrar Istio, haz lo siguiente:

kubectl delete -f install/kubernetes/istio-demo-auth.yaml

Para confirmar que Istio ya no está, haz lo siguiente:

kubectl get pods -n istio-system

Borra el clúster de Kubernetes

gcloud container clusters delete hello-istio