Introducción a Dapr .NET SDK (8/N): Kubernetes (AKS) mode


Siguiendo con nuestra ruta, es el turno de desplegar nuestra aplicación de ejemplo “AllTogetherApp” (según vimos en el post anterior), pero ahora, en Kubernetes y, concretamente en Azure Kubernetes Services (AKS).

Recordemos que este articulo forma parte de un listado (aún por cerrar) y que seguirá creciendo:

  1. Introducción a Dapr .NET SDK (1/N) y “Service-to-service invocation”
  2. Introducción a Dapr .NET SDK (2/N): State management
  3. Introducción a Dapr .NET SDK (3/N): Secrets
  4. Introducción a Dapr .NET SDK (4/N): Pub/Sub
  5. Introducción a Dapr .NET SDK (5/N): Bindings y Triggers
  6. Introducción a Dapr .NET SDK (6/N): Debugging (VSCode y VS) + Sidekick
  7. Introducción a Dapr .NET SDK (7/N): Docker Compose and HTTPS
  8. [ -> ] Introducción a Dapr .NET SDK (8/N): Kubernetes mode

Dapr en Kubernetes

Partimos de la base de que los prerrequisitos como kubectl se encuentran instalados y, disponemos de un cluster: minikube, kind, k3s, AKS, GCK o AKS. En este link podemos encontrar más detalle al respecto.

En primer lugar seleccionamos el cluster sobre el que trabajar. Para ello, usamos los siguientes comandos. El primero de ellos para mostrar el listado de contextos de AKS y, el segundo para serleccionarlo y trabajar con y sobre el a partir de dicho instante:

kubectl config get-contexts
kubectl config use-context <CONTEXT>

Instalación predeterminada

Una vez seleccionado el cluster con el que vamos a trabajar, la instalación predeterminada, en un namespace también predeterminado, “dapr-system” es seniclla:

dapr init -k

Si por el contrario, queremos indicar un namesapace concreto, entonces usamos el parámetro “-n”:

dapr init -k -n mynamespace

Y por ultimo, y de la misma manera, para indicar que queremos alta disponiblidad (usando 3 replicas):

dapr init -k --enable-ha=true

Instalación con Helm3

Aunque en el apartado anterior acabamos de ver como realizar la instalación de Dapr en Kubernetes, la recomendación para entornos de producción y en mecanismos de DevOps (CI/CD), es usar Helm y en concreto, la versión 3 o superior. La versión 2, ha dejado de estar soportada por las ultimas versiones de Dapr. Ejecutaremos los siguientes comandos:

helm repo add dapr https://dapr.github.io/helm-charts/
helm repo update
helm upgrade --install dapr dapr/dapr --namespace dapr-system --create-namespace --wait

Al igual que para la instalación predeterminada, vía Helm también tenemos la opción de usar parámetros para la creación de un nuevo namespace, habilitar alta disponibilidad, etc.

Al usar helm para la instalación, necesitamos también crear nuestro componente de Redis, por lo que ejecutamos los siguientes comandos:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install redis bitnami/redis

Y, también creamos opcionalmente el componente zipkin como sigue. ¡Recuerda que es el componente para observabilidad, que se incluye con la instalación predeterminda !:

kubectl create deployment zipkin --image openzipkin/zipkin
kubectl expose deployment zipkin --type ClusterIP --port 9411

Preparando y configurando la aplicación

Ahora que ya tenemos instado Dapr y sus componentes, continuamos con los siguientes comandos que nos van a permitir, construir y publicar las imagenes docker de nuestra aplicación de ejemplo en Azure Container Registry (ACR):

# Creación de imágenes Docker localmente
docker build -t alltogether.counterservice .\CounterService
docker build -t alltogether.weatherservice .\WeatherService
docker build -t alltogether.website .\Website

# Creación de nuevas imágenes para su posterior publicación en ACR.
docker tag alltogether.counterservice <ACR-NAME>/alltogether.counterservice
docker tag alltogether.weatherservice <ACR-NAME>/alltogether.weatherservice
docker tag alltogether.website <ACR-NAME>/alltogether.website

# Login en ACR y publicación de imágenes
az acr login -n <ACR-NAME>
docker push <ACR-NAME>/alltogether.counterservice

Necesitamos también que el AKS tenga visibilidad con el ACR. Aunque podemos optar por crear un secret vamos a optar por ejecutar este otro comando para otorgar esta integración/visibilidad entre AKS y ACR.

az aks update -n <AKS-NAME> -g <RESOURCE-GROPU> --attach-acr <ACR-NAME>

A continuación y como vamos a usar helm para desplegar nuestros contenedores en AKS, tenemos que construir nuestros Charts (website, counterservice y weatherservice) incluyendo para cada uno de ellos los ficheros; values.yaml, deployment.yaml y service.yaml, tal y como vemos a continuación:

# values.yaml

replicaCount: 1

appName: "AllTogetherApp"

image:  
  repository: k8sappsregistry.azurecr.io/alltogether.counterservice # <- local docker  
  pullPolicy: Always #<- IfNotPresent | Always | Never
  tag: "latest"


nameOverride: ""
fullnameOverride: ""

podAnnotations: {
  dapr.io/enabled: "true",
  dapr.io/app-id: "counterservice", 
  dapr.io/config: "tracing",
  dapr.io/app-port: "80"

}

service:
  type: LoadBalancer # <- ClusterIP | LoadBalancer | ...
  port: 80
  targetPort: 80
  containerPort: 80 # <- port must be expose in Dockerfile
  strategy: Recreate # <- Recreate | RollingUpdate | ...
  # rollingUpdateEnabled: true
  restartPolicy: Always # <- Always | OnFailure | Never
# deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:  
  name: {{ .Chart.Name }}
  labels:        
    app: {{ .Values.appName }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  strategy:
    type: {{ .Values.service.strategy }}
    {{- if .Values.service.rollingUpdateEnabled }}
    rollingUpdate:
      maxSurge: 3 # <- avoid issue: nodes are available: 1 node(s) didn't have free ports for the requested pod ports
      maxUnavailable: 0
    {{- end }}
  selector:
    matchLabels:    
      app: {{ .Values.appName }}
      service: {{ .Chart.Name }}
  template:
    metadata:
      {{- with .Values.podAnnotations }}
      annotations:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      labels:
        app: {{ .Values.appName }}
        service: {{ .Chart.Name }}
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          args: ["1"]
          ports:
            - name: http
              containerPort: {{ .Values.service.containerPort }}
              protocol: TCP
          env:
            - name: ASPNETCORE_URLS
              value: "http://+:{{ .Values.service.port }}"
          livenessProbe:
            httpGet:
              path: /
              port: http
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
      restartPolicy: {{ .Values.service.restartPolicy }}
# service.yaml

kind: Service
apiVersion: v1
metadata:
  name: {{ .Chart.Name }}
  labels:
    app: {{ .Values.appName }}
    service: {{ .Chart.Name }}
spec:
  type: {{ .Values.service.type }}
  selector:
    service: {{ .Chart.Name }}
  ports:
  - name: http
    protocol: TCP
    port: {{ .Values.service.port }}
    targetPort: {{ .Values.service.targetPort }}

Una vez que ya tenemos las imágenes en ACR, y los Charts de helm listos el siguiente paso es desplegar la web y los dos servicios que conforman la aplicación completa. La primera vez usamos la opción install para que helm cree la “release” y las sucesivas, es decir, cada vez que hagamos cambios en los Charts o bien en el código, o algún fichero de configuración, “upgrade“.

helm <install|upgrade> website .\k8s\helm\website
helm <install|upgrade> counterservice .\k8s\helm\counterservice
helm <install|upgrade> weatherservice .\k8s\helm\weatherservice

Finalmente, desplegamos los componentes Dapr:

kubectl apply -f .\dapr\components\k8s\pubsub.yaml
kubectl apply -f .\dapr\components\k8s\statestore.yaml
kubectl apply -f .\dapr\components\k8s\config.yaml

Nota: Para el despligue en kubernetes han sufrido una pequeña modificación en lo que respecta a los nombres de los servidores, que marco en negrita.

# config.yaml

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: tracing
  namespace: default
spec:
  tracing:
    samplingRate: "1"
    zipkin:      
      endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"
# pubsub.yaml y statestore.yml

apiVersion: dapr.io/v1alpha1
kind: Component

  ...

  version: v1
  metadata:
    - name: redisHost      
      value: redis-master.default.svc.cluster.local:6379      
  ...

Verificando el entorno

Tenemos todo desplegado y configurado, por lo que es el momento de verificar que todo funciona correctaente. En primer lugar que Dapr se ha instalado correctamente:

kubectl get pods --namespace dapr-system

En segundo lugar que nuestros componentes y servicios se encuentran también correctamente instalados:

kubectl get pods

Podemos usar también LENS, que como ya comenté en este post, se tratar de un Interfaz de Usuario muy potente e intuitiva para gestión de nuestro cluster de Kubernetenes.

Ejecutando la aplicación

Y, como último paso, probamos la aplicación, ejecutanto para ello estos tres comando en tres pestañas diferentes de Windows Terminal, o bien en tres consolas diferentes.

kubectl port-forward service/website 5000:80
kubectl port-forward service/zipkin 9412:9411
kubectl port-forward service/dapr-dashboard 8081:8080 -n dapr-system

Navegamos a http://localhost:5000, http://localhost:9412 y http://localhost:8081 y comprobaremos que todo funciona correctamente.

Happy #Dapr coding !!!

Referencias

8 comentarios sobre “Introducción a Dapr .NET SDK (8/N): Kubernetes (AKS) mode

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios .