使用 Azure Kubernetes 服务 (AKS) 上的 KEDA 外接程序和工作负载标识,安全地扩展应用程序

本文介绍如何使用 Azure Kubernetes 服务 (AKS) 上的 Kubernetes 事件驱动的自动缩放 (KEDA) 加载项和工作负载标识安全地缩放应用程序。

重要

你的群集的 Kubernetes 版本决定了将在 AKS 群集上安装的 KEDA 版本。 若要查看哪些 KEDA 版本映射到每个 AKS 版本,请参阅 Kubernetes 组件版本表的“AKS 托管附加产品”列。

对于 GA Kubernetes 版本,AKS 提供对表中相应 KEDA 次要版本的完全支持。 客户支持部门会尽力为 Kubernetes 预览版和最新的 KEDA 修补程序提供部分支持。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:

开始之前

创建资源组

  • 使用 az group create 命令创建资源组。 请务必将占位符值替换为你自己的值。

    LOCATION=<azure-region>
    RG_NAME=<resource-group-name>
    
    az group create --name $RG_NAME --location $LOCATION
    

创建 AKS 群集

  1. 使用带有 az aks create--enable-workload-identity--enable-keda 标志的 --enable-oidc-issuer 命令创建启用了 KEDA 加载项、工作负载标识和 OIDC 颁发者的 AKS 群集。 请务必将占位符的值替换为你自己的值。

    AKS_NAME=<cluster-name>
    
    az aks create \
        --name $AKS_NAME \
        --resource-group $RG_NAME \
        --enable-workload-identity \
        --enable-oidc-issuer \
        --enable-keda \
        --generate-ssh-keys 
    
  2. 验证部署是否成功,并使用 az aks show 命令将 --query 标志设置为 "[workloadAutoScalerProfile, securityProfile, oidcIssuerProfile]",以确保群集已启用 KEDA、工作负载标识和 OIDC 颁发者。

    az aks show \
        --name $AKS_NAME \
        --resource-group $RG_NAME \
        --query "[workloadAutoScalerProfile, securityProfile, oidcIssuerProfile]"
    
  3. 使用 az aks get-credentials 命令连接到群集。

    az aks get-credentials \
        --name $AKS_NAME \
        --resource-group $RG_NAME \
        --overwrite-existing
    

创建 Azure 服务总线

  1. 使用 az servicebus namespace create 命令创建 Azure 服务总线命名空间。 请务必将占位符的值替换为您自己的值。

    SB_NAME=<service-bus-name>
    SB_HOSTNAME="${SB_NAME}.servicebus.chinacloudapi.cn"
    
    az servicebus namespace create \
        --name $SB_NAME \
        --resource-group $RG_NAME \
        --disable-local-auth
    
  2. 使用 az servicebus queue create 命令创建 Azure 服务总线队列。 请务必将占位符的值替换为您自己的值。

    SB_QUEUE_NAME=<service-bus-queue-name>
    
    az servicebus queue create \
        --name $SB_QUEUE_NAME \
        --namespace $SB_NAME \
        --resource-group $RG_NAME
    

创建托管标识

  1. 使用 az identity create 命令创建托管标识。 请务必将占位符的值替换为您自己的值。

    MI_NAME=<managed-identity-name>
    
    MI_CLIENT_ID=$(az identity create \
        --name $MI_NAME \
        --resource-group $RG_NAME \
        --query "clientId" \
        --output tsv)
    
  2. 使用 az aks show 命令并将 --query 标志设置为 oidcIssuerProfile.issuerUrl 获取 OIDC 颁发者 URL。

    AKS_OIDC_ISSUER=$(az aks show \
        --name $AKS_NAME \
        --resource-group $RG_NAME \
        --query oidcIssuerProfile.issuerUrl \
        --output tsv)
    
  3. 使用 az identity federated-credential create 命令在托管标识与工作负载使用的命名空间和服务帐户之间创建联合凭据。 请务必将占位符值替换为你自己的值。

    FED_WORKLOAD=<federated-credential-workload-name>
    
    az identity federated-credential create \
        --name $FED_WORKLOAD \
        --identity-name $MI_NAME \
        --resource-group $RG_NAME \
        --issuer $AKS_OIDC_ISSUER \
        --subject system:serviceaccount:default:$MI_NAME \
        --audience api://AzureADTokenExchange
    
  4. 使用 az identity federated-credential create 命令在托管标识与 keda-operator 使用的命名空间和服务帐户之间创建第二个联合凭据。 请务必将占位符值替换为你自己的值。

    FED_KEDA=<federated-credential-keda-name>
    
    az identity federated-credential create \
        --name $FED_KEDA \
        --identity-name $MI_NAME \
        --resource-group $RG_NAME \
        --issuer $AKS_OIDC_ISSUER \
        --subject system:serviceaccount:kube-system:keda-operator \
        --audience api://AzureADTokenExchange
    

创建角色分配

  1. 使用 az identity show 命令并将 --query 标志设为 "principalId",获取托管标识的对象 ID。

    MI_OBJECT_ID=$(az identity show \
        --name $MI_NAME \
        --resource-group $RG_NAME \
        --query "principalId" \
        --output tsv)
    
  2. 使用 az servicebus namespace show 命令并将 --query 标志设置为 "id" 获取服务总线命名空间资源 ID。

    SB_ID=$(az servicebus namespace show \
        --name $SB_NAME \
        --resource-group $RG_NAME \
        --query "id" \
        --output tsv)
    
  3. 使用 az role assignment create 命令将 Azure 服务总线 数据所有者角色分配给托管标识。

    az role assignment create \
        --role "Azure Service Bus Data Owner" \
        --assignee-object-id $MI_OBJECT_ID \
        --assignee-principal-type ServicePrincipal \
        --scope $SB_ID
    

在 KEDA 运算符上启用工作负载标识

  1. keda-operator ServiceAccount 创建联合凭据后,使用托管标识的客户端 ID 为 ServiceAccount 添加批注。 这会告知工作负载身份 Webhook 应将哪个身份绑定到 keda-operator Pod。

    kubectl annotate serviceaccount keda-operator \
        azure.workload.identity/client-id=$MI_CLIENT_ID \
        -n kube-system
    
  2. 重启keda-operator pod,确保将工作负载身份环境变量注入到 pod 中。

    kubectl rollout restart deploy keda-operator -n kube-system
    
  3. 确认 keda-operator Pods 已重启

    kubectl get pod -n kube-system -lapp=keda-operator -w
    
  4. 确认 keda-operator Pod 已完成滚动后,按 Ctrl+c 中断上一个监视命令,然后确认已注入工作负载标识环境变量。

    KEDA_POD_ID=$(kubectl get po -n kube-system -l app.kubernetes.io/name=keda-operator -ojsonpath='{.items[0].metadata.name}')
    kubectl describe po $KEDA_POD_ID -n kube-system
    
  5. 你应该会在“环境”下看到与以下内容类似的输出。

    ---
    AZURE_CLIENT_ID:               xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx
    AZURE_TENANT_ID:               xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx
    AZURE_FEDERATED_TOKEN_FILE:    /var/run/secrets/azure/tokens/azure-identity-token
    AZURE_AUTHORITY_HOST:          https://login.partner.microsoftonline.cn/
    ---
    
  6. 部署包含用户分配托管标识的客户端 ID 的 KEDA TriggerAuthentication 资源。

    kubectl apply -f - <<EOF
    apiVersion: keda.sh/v1alpha1
    kind: TriggerAuthentication
    metadata:
      name: azure-servicebus-auth
      namespace: default  # this must be same namespace as the ScaledObject/ScaledJob that will use it
    spec:
      podIdentity:
        provider:  azure-workload
        identityId: $MI_CLIENT_ID
    EOF
    

    注意

    有了 TriggerAuthentication 后,KEDA 将能够通过工作负载标识进行身份验证。 评估缩放触发器时,keda-operator Pod 使用 identityId 对 Azure 资源进行身份验证。

将消息发布到 Azure 服务总线

此时,一切都已配置好,可以使用 KEDA 和 Microsoft Entra 工作负载标识进行缩放。 我们将通过部署生成者和使用者工作负载来测试这一点。

  1. 为工作负载创建新的 ServiceAccount。

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        azure.workload.identity/client-id: $MI_CLIENT_ID
      name: $MI_NAME
    EOF
    
  2. 部署一个作业以发布 100 条消息。

    kubectl apply -f - <<EOF
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: myproducer
    spec:
      template:
        metadata:
          labels:
            azure.workload.identity/use: "true"
        spec:
          serviceAccountName: $MI_NAME
          containers:
          - image: ghcr.io/azure-samples/aks-app-samples/servicebusdemo:latest
            name: myproducer
            resources: {}
            env:
            - name: OPERATION_MODE
              value: "producer"
            - name: MESSAGE_COUNT
              value: "100"
            - name: AZURE_SERVICEBUS_QUEUE_NAME
              value: $SB_QUEUE_NAME
            - name: AZURE_SERVICEBUS_HOSTNAME
              value: $SB_HOSTNAME
          restartPolicy: Never
    EOF
    

从 Azure 服务总线接收消息

现在,我们已经将消息发送到 Azure 服务总线 队列,接下来将部署 ScaledJob 来处理这些消息。 此 ScaledJob 资源将使用 KEDA TriggerAuthentication 资源,借助工作负载标识向 Azure 服务总线 队列进行身份验证,并按每 10 条消息扩容一次。

  1. 部署一个 ScaledJob 资源以使用消息。 缩放触发器将被配置为每 10 条消息扩容一次。 KEDA 缩放器将创建 10 个作业以使用 100 条消息。

    kubectl apply -f - <<EOF
    apiVersion: keda.sh/v1alpha1
    kind: ScaledJob
    metadata:
      name: myconsumer-scaledjob
    spec:
      jobTargetRef:
        template:
          metadata:
            labels:
              azure.workload.identity/use: "true"
          spec:
            serviceAccountName: $MI_NAME
            containers:
            - image: ghcr.io/azure-samples/aks-app-samples/servicebusdemo:latest
              name: myconsumer
              env:
              - name: OPERATION_MODE
                value: "consumer"
              - name: MESSAGE_COUNT
                value: "10"
              - name: AZURE_SERVICEBUS_QUEUE_NAME
                value: $SB_QUEUE_NAME
              - name: AZURE_SERVICEBUS_HOSTNAME
                value: $SB_HOSTNAME
            restartPolicy: Never
      triggers:
      - type: azure-servicebus
        metadata:
          queueName: $SB_QUEUE_NAME
          namespace: $SB_NAME
          messageCount: "10"
        authenticationRef:
          name: azure-servicebus-auth
    EOF
    

    注意

    ScaledJob 会在发生缩放事件时创建 Kubernetes 作业资源,因此在创建资源时需要传入作业模板。 随着新 Job 的创建,Pod 将使用工作负载身份凭据进行部署,以消费消息。

  2. 验证 KEDA 缩放器是否按预期工作。

    kubectl describe scaledjob myconsumer-scaledjob
    
  3. 您应该会看到如下所示的事件。

    Events:
    Type     Reason              Age   From           Message
    ----     ------              ----  ----           -------
    Normal   KEDAScalersStarted  10m   scale-handler  Started scalers watch
    Normal   ScaledJobReady      10m   keda-operator  ScaledJob is ready for scaling
    Warning  KEDAScalerFailed    10m   scale-handler  context canceled
    Normal   KEDAJobsCreated     10m   scale-handler  Created 10 jobs
    

清理资源

验证部署成功后,可以清理资源以避免产生 Azure 成本。

  1. 使用 [az group delete][az-group-delete] 命令删除 Azure 资源组及其中所有资源。

    az group delete --name $RG_NAME --yes --no-wait
    

后续步骤

本文向你展示了如何在 AKS 中使用 KEDA 加载项和工作负载标识,以安全的方式扩展应用程序。

有关 KEDA 故障排除的详细信息,请参阅 排查 Kubernetes 事件驱动自动缩放 (KEDA) 加载项

若要了解有关 KEDA 的详细信息,请参阅上游 KEDA 文档