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 marco de trabajo 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 ejecute 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 las métricas, el seguimiento, la administración dinámica del tráfico, la inyecció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 Istio lo administre

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 no incurrir en facturación más allá de este instructivo. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de$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 iniciaste Cloud Shell, aparecerá una pantalla intermedia (mitad inferior de la página) que describe en qué consiste. Si ese es el caso, haz clic en Continuar (y no volverás a verlo). 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. Ejecuta el siguiente comando en Cloud Shell para confirmar que el comando de 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 comprobar que la herramienta de línea de comandos dotnet ya esté instalada revisando su versión. Esto debería imprimir la versión de la herramienta de línea de comandos 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 nuestra aplicación. 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 la app se esté ejecutando, haz clic en el botón Vista previa en la Web, que se encuentra en la parte superior derecha, 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 hayas verificado que la aplicación se está ejecutando, presiona Ctrl + C para cerrarla.

5. Empaquetar la aplicación de ASP.NET Core en un contenedor de Docker

A continuación, prepara la app para que se ejecute como 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 ello, se debe configurar la variable de entorno ASPNETCORE_URLS, que las aplicaciones de ASP.NET Core usan para determinar qué puerto escuchar.

Guarda este Dockerfile. Ahora, compilemos la imagen:

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

Una vez que se complete este proceso (la descarga y extracción tardará un poco en completarse), podrás ver que la imagen se compiló y se guardó de forma local:

docker images

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

Prueba la imagen localmente con el siguiente comando, que ejecutará un contenedor de Docker localmente en el puerto 8080 desde la imagen de contenedor recién creada:

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

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

Captura de pantalla del 3-11-2015 17:20:22.png

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

f579a9baedc108a9.png

Una vez que hayas verificado que la app se ejecuta correctamente de manera local en un contenedor de Docker, puedes detener el contenedor en ejecución antes del 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 va bien después de un tiempo, deberías poder ver la imagen de contenedor en la sección Container Registry. En este punto, ya tienes disponible una imagen de Docker para todo el proyecto a la que Kubernetes puede acceder y organizar, como verás en unos minutos.

73558f3a54ce1c0c.png

Si desea conocer más, puede navegar por las imágenes de contenedores almacenadas en Google Cloud Storage en este vínculo: https://console.cloud.google.com/storage/browser/ (el vínculo completo debe tener el siguiente 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 tener habilitada la API de Kubernetes Engine:

gcloud services enable container.googleapis.com

Crearás un clúster de Kubernetes. Puedes cambiar la región a un lugar cercano a ti, como se indica a continuación:

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. Podrás verlo 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. Hay otras opciones de instalación, como el complemento de Istio para GKE y Anthos Service Mesh. Los pasos de la aplicación posteriores funcionarán en cualquier instalación de Istio.

Primero, descarguemos el cliente y las muestras de Istio. La página de actualizaciones de Istio ofrece descargas de artefactos para varios SO. En este caso, podemos usar un comando conveniente para descargar y extraer la última versión de 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 objeto binario de cliente istioctl. Cambia a ese directorio:

cd istio-1.8.1

Copia y pega el comando proporcionado para agregar el directorio bin a 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 dice 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 ahora 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.

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

kubectl label namespace default istio-injection=enabled

Para verificar que la etiqueta se aplicó 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”), llamados 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 es de tipo LoadBalancer, por lo que se puede acceder a ella desde Internet. las 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:

kubectl get pods -n istio-system

Cuando todos los Pods se estén ejecutando, puedes 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. Controla la configuración y la programación de los sidecars del proxy, el descubrimiento de servicios, la distribución de certificados y la inserción de sidecars
  • ingress gateway: Controla las solicitudes entrantes que provienen del exterior del 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 aplicación de ASP.NET Core.

Implementación y servicio

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 consta de implementaciones y servicios estándar para implementar la aplicación y no incluye 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 Gateway y un VirtualService.

Una puerta de enlace configura un balanceador de cargas para el tráfico HTTP/TCP, que por lo general opera en el perímetro de la malla para habilitar el tráfico de entrada a 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

Luego, ejecuta el siguiente comando para implementar 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

Finalmente 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 y el puerto externos 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}/

Como alternativa, puedes abrir el navegador y navegar a http://<gatewayurl> para ver la app:

f579a9baedc108a9.png

10. ¡Felicitaciones!

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

Quizás te preguntes cuál es el beneficio de Istio. Excelente pregunta. Hasta ahora, no existe la ventaja de que Istio administre esta app. En la segunda parte del lab, exploraremos más a fondo las funciones de Istio, como las métricas, el seguimiento, la administración dinámica del tráfico, la visualización de servicios y la inyección de errores.

Próximos pasos

Licencia

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

11. Limpieza

Si no continúas con la segunda parte del lab, puedes borrar la app y desinstalar Istio, o simplemente borrar el clúster de Kubernetes.

Cómo borrar 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á disponible, sigue estos pasos:

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 desapareció, ejecuta el siguiente comando:

kubectl get pods -n istio-system

Borra el clúster de Kubernetes

gcloud container clusters delete hello-istio