En el último artículo compartí contigo cómo desplegar un ejemplo con Dapr, bastante completo, en Kubernetes, usando Kind. Hoy quiero mostrarte cómo desplegar el control plane de Dapr en AKS, gracias a la extensión que tenemos disponible para ello y desplegar el mismo ejemplo.
Prepara tu suscripción
Antes de nada, es necesario preparar tu suscripción para que la extensión de Dapr para AKS esté disponible. Para ello es necesario lanzar los siguientes comandos:
# In order to use the AKS Dapr extension, you must first enable the AKS-ExtensionManager and AKS-Dapr feature flags on your Azure subscription.
az feature register --namespace "Microsoft.ContainerService" --name "AKS-ExtensionManager"
az feature register --namespace "Microsoft.ContainerService" --name "AKS-Dapr"
# Confirm the registration status
az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/AKS-ExtensionManager')].{Name:name,State:properties.state}"
az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/AKS-Dapr')].{Name:name,State:properties.state}"
# Refresh the registration of the Microsoft.KubernetesConfiguration and Microsoft.ContainerService
az provider register --namespace Microsoft.KubernetesConfiguration
az provider register --namespace Microsoft.ContainerService
El proceso puede tardar unos minutos, sobre todo el registro de AKS-Dapr.
Instalar k8s-extension
Para poder usar la extensión de Dapr a través de Azure CLI, necesitas instalar la extension llamada k8s-extension:
# Enable the Azure CLI extension for cluster extensions
az extension add --name k8s-extension
# or update it
az extension update --name k8s-extension
Con estos pasos previos ya puedes provisionar tu clúster e instalar Dapr en él.
Crear clúster de AKS
Ahora que ya tienes todo listo, el siguiente paso es crear tu clúster como lo harías siempre:
# Variables
RESOURCE_GROUP="aks-for-dapr"
LOCATION="northeurope"
AKS_NAME="dapr-demo"
# Create resource group
az group create -n $RESOURCE_GROUP -l $LOCATION
# Create cluster
az aks create --resource-group $RESOURCE_GROUP \
--name $AKS_NAME \
--node-count 2 \
--node-vm-size Standard_B4ms \
--generate-ssh-keys
# Get credentials
az aks get-credentials -n $AKS_NAME -g $RESOURCE_GROUP
Instalar la extensión de Dapr
Por último, utiliza k8s-extension para desplegar el control plane de Dapr:
# Create the extension and install Dapr on your AKS cluster
az k8s-extension create --cluster-type managedClusters \
--cluster-name $AKS_NAME \
--resource-group $RESOURCE_GROUP \
--name daprExtension \
--extension-type Microsoft.Dapr \
--auto-upgrade-minor-version true
Este comando te preguntará si Dapr está ya instalado en tu clúster (le decimos que no) y el proceso comenzará. Para confirmar que todo se ha instalado correctamente puedes ver los pods bajo dapr-system:
# Check Dapr control plane
kubectl get pods -n dapr-system
El resultado debería ser parecido al siguiente:
Desplegar la aplicación de ejemplo
Si quieres desplegar mi ejemplo de Tour of Heroes, que te muestra diferentes aspectos de Dapr, puedes utilizar los manifiestos del directorio dapr-k8s-manifests, pero antes debemos modificar los servicios de las API, cambiando el tipo NodePort a LoadBalancer:
backend/tour-of-heroes-api.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: tour-of-heroes-api
name: tour-of-heroes-api
spec:
# type: NodePort
type: LoadBalancer
ports:
- name: web
# port: 5222
port: 80
targetPort: 5222
# nodePort: 30080
selector:
app: tour-of-heroes-api
---
backend/tour-of-villains-api.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: tour-of-villains-api
name: tour-of-villains-api
spec:
# type: NodePort
type: LoadBalancer
ports:
- name: web
port: 80
targetPort: 5111
# nodePort: 30090
selector:
app: tour-of-villains-api
---
Y para Zipkin lo dejaría como ClusterIP y accedería a él a través de port forwarding.
services/zipkin.yaml
apiVersion: v1
kind: Service
metadata:
labels:
name: zipkin
name: zipkin
spec:
# type: NodePort
type: ClusterIP
ports:
- port: 9411
targetPort: 9411
# nodePort: 30070
selector:
app: zipkin
---
Una vez hechos los cambios puedes desplegar todos los manifiestos con este comando:
# Deploy demo
NAMESPACE="tour-of-heroes"
kubectl create ns $NAMESPACE
kubectl apply -f dapr-k8s-manifests --recursive -n $NAMESPACE
En este artículo he desplegado mi aplicación en un namespace diferente de default para que veas lo siguiente:
Si compruebas el estado de los pods:
# Check pods
watch kubectl get pods -n $NAMESPACE
Verás que tour-of-heroes-api no ha arrancado correctamente. Si revisas los logs te encontrarás con lo siguiente:

Esto es así porque la instalación de Dapr solo da permisos de lectura sobre el namespace default, tal y como se cuenta aquí. Para arreglarlo entonces debemos lanzar lo siguiente:
# If your Dapr enabled apps are using components that fetch secrets from non-default namespaces, apply the following resources to that namespace:
kubectl create -f - <<EOF
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
namespace: $NAMESPACE
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: dapr-secret-reader
namespace: $NAMESPACE
subjects:
- kind: ServiceAccount
name: default
roleRef:
kind: Role
name: secret-reader
apiGroup: rbac.authorization.k8s.io
EOF
Si quieres probar el ejemplo, como en el artículo anterior, puedes usar los siguientes comandos:
# Get public IPs
TOUR_OF_HEROES_PUBLIC_IP=$(kubectl get svc tour-of-heroes-api -n $NAMESPACE -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
TOUR_OF_VILLAIN_PUBLIC_IP=$(kubectl get svc tour-of-villains-api -n $NAMESPACE -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
# Variables for cURL commands
HERO_API_URL=http://$TOUR_OF_HEROES_PUBLIC_IP/api/hero
VILLAIN_API_URL=http://$TOUR_OF_VILLAIN_PUBLIC_IP/villain
# Check if hero api is working
curl $HERO_API_URL | jq
curl --header "Content-Type: application/json" \
--request POST \
--data '{
"name": "Batman",
"description": "Un multimillonario magnate empresarial y filántropo dueño de Empresas Wayne en Gotham City. Después de presenciar el asesinato de sus padres, el Dr. Thomas Wayne y Martha Wayne en un violento y fallido asalto cuando era niño, juró venganza contra los criminales, un juramento moderado por el sentido de la justicia.",
"alterEgo": "Bruce Wayne"
}' \
$HERO_API_URL | jq
# Get heroes again
curl $HERO_API_URL | jq
# Check if villain api is working
curl --header "Content-Type: application/json" \
--request POST \
--data '{
"name": "Octopus",
"hero":{
"name": "Spiderman",
"description": "un joven huérfano neoyorquino que adquiere superpoderes después de ser mordido por una araña radiactiva, y cuya ideología como héroe se ve reflejada primordialmente en la expresión «un gran poder conlleva una gran responsabilidad».2021 Suele ser asociado con una personalidad bromista, amable, inventiva y optimista, lo que le ha llevado a ser catalogado como el «vecino amigable» de cualquiera lo cual, aunado a sus vivencias caracterizadas por los problemas cotidianos.",
"alterEgo": "Peter Parker"
},
"description": "Es un científico loco muy inteligente y algo fornido que tiene cuatro apéndices fuertes que se asemejan a los tentáculos de un pulpo, que se extienden desde la parte posterior de su cuerpo y pueden usarse para varios propósitos."
}' \
$VILLAIN_API_URL | jq
# Check if pub sub is working viewing logs
kubectl logs -l app=tour-of-heroes-api -c tour-of-heroes-api -n $NAMESPACE
# Check if service to service invocation is working
curl $HERO_API_URL/villain/spiderman | jq
# Forward a port to Dapr dashboard
dapr dashboard -k -p 9999
# Access to zipkin to see traces
kubectl port-forward deployment/zipkin -n $NAMESPACE 9411:9411
http://localhost:9411
Todos estos pasos los tienes en mi GitHub.
¡Saludos!