
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:
- Introducción a Dapr .NET SDK (1/N) y “Service-to-service invocation”
- Introducción a Dapr .NET SDK (2/N): State management
- Introducción a Dapr .NET SDK (3/N): Secrets
- Introducción a Dapr .NET SDK (4/N): Pub/Sub
- Introducción a Dapr .NET SDK (5/N): Bindings y Triggers
- Introducción a Dapr .NET SDK (6/N): Debugging (VSCode y VS) + Sidekick
- Introducción a Dapr .NET SDK (7/N): Docker Compose and HTTPS
- [ -> ] Introducción a Dapr .NET SDK (8/N): Kubernetes mode
- Introducción a Dapr .NET SDK (9/N): Azure Container Apps 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 .\deploy\k8s\helm\website
helm <install|upgrade> counterservice .\deploy\k8s\helm\counterservice
helm <install|upgrade> weatherservice .\deploy\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 !!!
Reblogueó esto en El Bruno.
Me gustaMe gusta