你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将语言检测容器部署到 Azure Kubernetes 服务

了解如何部署语言检测容器。 此过程说明如何创建本地 Docker 容器,将容器推送到自己的专用容器注册表,在 Kubernetes 群集中运行容器,以及在 Web 浏览器中对其进行测试。

先决条件

此过程要求必须在本地安装和运行多个工具。 请勿使用 Azure Cloud Shell。

  • 使用 Azure 订阅。 如果没有 Azure 订阅,请在开始之前创建一个免费帐户
  • 适用于操作系统的 Git,以便克隆此过程中使用的示例
  • Azure CLI
  • Docker 引擎并验证 Docker CLI 是否可在控制台窗口中工作。
  • kubectl
  • 具有适当定价层的 Azure 资源。 并非所有定价层都适用于此容器:
    • 仅具有 F0 或标准定价层的语言资源。
    • 具有 S0 定价层的 Azure AI 服务资源

运行示例

此过程加载并运行 Azure AI 服务容器示例以进行语言检测。 该示例有两个容器,一个用于客户端应用程序,另一个用于 Azure AI 服务容器。 我们会将这两个映像都推送到 Azure 容器注册表。 这些映像推送到自己的注册表后,请创建 Azure Kubernetes 服务来访问这些映像和运行容器。 容器在运行时,请使用 kubectl CLI,监视容器性能。 使用 HTTP 请求访问客户端应用程序,并查看结果。

显示在 Kubernetes 上运行容器的概念的关系图

示例容器

该示例有两个容器映像,一个用于前端网站。 第二个映像是可返回检测到的文本语言(区域性)的语言检测容器。 完成后,这两个容器都可以从外部 IP 进行访问。

语言前端容器

此网站相当于自己的进行语言检测终结点的请求的客户端应用程序。 完成此过程后,使用 http://<external-IP>/<text-to-analyze> 在浏览器中访问网站容器,即可获得检测到的字符串语言。 此 URL 的一个示例为 http://132.12.23.255/helloworld!。 浏览器中的结果为 English

语言容器

在此特定过程中,任何外部访问请求都可以访问语言检测容器。 容器未以任何方式更改,因此标准的特定于的 Azure AI 服务容器的语言检测 API 可供使用。

对于此容器,该 API 是进行语言检测的 POST 请求。 与所有 Azure AI 容器一样,你可以从该容器的托管 Swagger 信息 (http://<external-IP>:5000/swagger/index.html) 了解有关该容器的详细信息。

端口 5000 是用于 Azure AI 容器的默认端口。

创建 Azure 容器注册表服务

若要将容器部署到 Azure Kubernetes 服务,需要能够访问容器映像。 创建自己的 Azure 容器注册表服务以托管映像。

  1. 登录 Azure CLI

    az login
    
  2. 创建名为 cogserv-container-rg 的资源组来保存此过程中创建的每一个资源。

    az group create --name cogserv-container-rg --location westus
    
  3. 使用名字后加 registry 这一格式(如 pattyregistry)创建自己的 Azure 容器注册表。 请勿在名称中使用短划线或下划线字符。

    az acr create --resource-group cogserv-container-rg --name pattyregistry --sku Basic
    

    保存结果,以获取 loginServer 属性。 这将是托管容器地址的一部分,稍后将在 language.yml 文件中使用。

    az acr create --resource-group cogserv-container-rg --name pattyregistry --sku Basic
    
    {
        "adminUserEnabled": false,
        "creationDate": "2019-01-02T23:49:53.783549+00:00",
        "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/cogserv-container-rg/providers/Microsoft.ContainerRegistry/registries/pattyregistry",
        "location": "westus",
        "loginServer": "pattyregistry.azurecr.io",
        "name": "pattyregistry",
        "provisioningState": "Succeeded",
        "resourceGroup": "cogserv-container-rg",
        "sku": {
            "name": "Basic",
            "tier": "Basic"
        },
        "status": null,
        "storageAccount": null,
        "tags": {},
        "type": "Microsoft.ContainerRegistry/registries"
    }
    
  4. 登录容器注册表。 需登录后才能将映像推送到注册表。

    az acr login --name pattyregistry
    

获取网站 Docker 映像

  1. 此过程中使用的示例代码位于 Azure AI 容器示例存储库中。 克隆存储库以生成示例的本地副本。

    git clone https://github.com/Azure-Samples/cognitive-services-containers-samples
    

    如果存储库已在本地计算机上,请在 \dotnet\Language\FrontendService 目录中查找网站。 该网站用作客户端应用程序,可调用语言检测容器中托管的语言检测 API。

  2. 为网站生成 Docker 映像。 运行以下命令时,确保控制台位于 Dockerfile 所在的\FrontendService 目录中:

    docker build -t language-frontend -t pattiyregistry.azurecr.io/language-frontend:v1 .
    

    若要在容器注册表上跟踪版本,请添加具有版本格式的标记,如 v1

  3. 将映像推送到容器注册表。 这可能需要几分钟的时间。

    docker push pattyregistry.azurecr.io/language-frontend:v1
    

    如果收到 unauthorized: authentication required 错误,请使用 az acr login --name <your-container-registry-name> 命令登录。

    该过程完成后,结果应类似于以下内容:

    The push refers to repository [pattyregistry.azurecr.io/language-frontend]
    82ff52ee6c73: Pushed
    07599c047227: Pushed
    816caf41a9a1: Pushed
    2924be3aed17: Pushed
    45b83a23806f: Pushed
    ef68f6734aa4: Pushed
    v1: digest: sha256:31930445deee181605c0cde53dab5a104528dc1ff57e5b3b34324f0d8a0eb286 size: 1580
    

获取语言检测 Docker 映像

  1. 将 Docker 映像的最新版本拉取到本地计算机上。 这可能需要几分钟的时间。 如果有此容器的较新版本,请将值从 1.1.006770001-amd64-preview 更改到较新版本。

    docker pull mcr.microsoft.com/azure-cognitive-services/language:1.1.006770001-amd64-preview
    
  2. 使用容器注册表标记图像。 查找最新版本,如果有更新的版本,请替换版本 1.1.006770001-amd64-preview

    docker tag mcr.microsoft.com/azure-cognitive-services/language pattiyregistry.azurecr.io/language:1.1.006770001-amd64-preview
    
  3. 将映像推送到容器注册表。 这可能需要几分钟的时间。

    docker push pattyregistry.azurecr.io/language:1.1.006770001-amd64-preview
    

获取容器注册表凭据

需要执行以下步骤来获取所需信息,以便将容器注册表与稍后此过程中要创建的 Azure Kubernetes 服务进行连接。

  1. 创建服务主体。

    az ad sp create-for-rbac
    

    为步骤 3 中代理人参数 <appId> 的保存结果 appId 值。 为下一节中 client-secret 参数 <client-secret> 保存 password

    {
      "appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "displayName": "azure-cli-2018-12-31-18-39-32",
      "name": "http://azure-cli-2018-12-31-18-39-32",
      "password": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    }
    
  2. 获取容器注册表 ID。

    az acr show --resource-group cogserv-container-rg --name pattyregistry --query "id" --output table
    

    为下一步中范围参数值 <acrId> 保存输出。 输出如下所示:

    /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/cogserv-container-rg/providers/Microsoft.ContainerRegistry/registries/pattyregistry
    

    为本节中步骤 3 保存完整值。

  3. 若要授予 AKS 群集使用容器注册表中存储的映像的适当访问权限,请创建角色分配。 将 <appId><acrId> 替换为在前两个步骤中收集的值。

    az role assignment create --assignee <appId> --scope <acrId> --role Reader
    

创建 Azure Kubernetes 服务

  1. 创建 Kubernetes 群集。 所有参数值都来自前一部分,name 参数除外。 选择一个名称,指明其创建者及其用途,例如 patty-kube

    az aks create --resource-group cogserv-container-rg --name patty-kube --node-count 2  --service-principal <appId>  --client-secret <client-secret>  --generate-ssh-keys
    

    这个步骤可能需要几分钟的时间。 结果为:

    {
      "aadProfile": null,
      "addonProfiles": null,
      "agentPoolProfiles": [
        {
          "count": 2,
          "dnsPrefix": null,
          "fqdn": null,
          "maxPods": 110,
          "name": "nodepool1",
          "osDiskSizeGb": 30,
          "osType": "Linux",
          "ports": null,
          "storageProfile": "ManagedDisks",
          "vmSize": "Standard_DS1_v2",
          "vnetSubnetId": null
        }
      ],
      "dnsPrefix": "patty-kube--65a101",
      "enableRbac": true,
      "fqdn": "patty-kube--65a101-341f1f54.hcp.westus.azmk8s.io",
      "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/cogserv-container-rg/providers/Microsoft.ContainerService/managedClusters/patty-kube",
      "kubernetesVersion": "1.9.11",
      "linuxProfile": {
        "adminUsername": "azureuser",
        "ssh": {
          "publicKeys": [
            {
              "keyData": "ssh-rsa AAAAB3NzaC...ohR2d81mFC
            }
          ]
        }
      },
      "location": "westus",
      "name": "patty-kube",
      "networkProfile": {
        "dnsServiceIp": "10.0.0.10",
        "dockerBridgeCidr": "172.17.0.1/16",
        "networkPlugin": "kubenet",
        "networkPolicy": null,
        "podCidr": "10.244.0.0/16",
        "serviceCidr": "10.0.0.0/16"
      },
      "nodeResourceGroup": "MC_patty_westus",
      "provisioningState": "Succeeded",
      "resourceGroup": "cogserv-container-rg",
      "servicePrincipalProfile": {
        "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "keyVaultSecretRef": null,
        "secret": null
      },
      "tags": null,
      "type": "Microsoft.ContainerService/ManagedClusters"
    }
    

    服务已创建,但还没有网站容器或语言检测容器。

  2. 获取 Kubernetes 群集的凭据。

    az aks get-credentials --resource-group cogserv-container-rg --name patty-kube
    

将业务流程定义加载到 Kubernetes 服务中

本部分使用 kubectl CLI 与 Azure Kubernetes 服务通信

  1. 在加载业务流程定义之前,请检查 kubectl 是否有权访问节点

    kubectl get nodes
    

    响应如下所示:

    NAME                       STATUS    ROLES     AGE       VERSION
    aks-nodepool1-13756812-0   Ready     agent     6m        v1.9.11
    aks-nodepool1-13756812-1   Ready     agent     6m        v1.9.11
    
  2. 复制以下文件并将其命名为 language.yml。 该文件含有一个 service 部分和一个 deployment 部分,各自用于两种容器类型,即 language-frontend 网站容器和 language 检测容器。

    # A service which exposes the .net frontend app container through a dependable hostname: http://language-frontend:5000
    apiVersion: v1
    kind: Service
    metadata:
      name: language-frontend
      labels:
        run: language-frontend
    spec:
      selector:
        app: language-frontend
      type: LoadBalancer
      ports:
      - name: front
        port: 80
        targetPort: 80
        protocol: TCP
    ---
    # A deployment declaratively indicating how many instances of the .net frontend app container we want up
    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
      name: language-frontend
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            app: language-frontend
        spec:
          containers:
          - name: language-frontend
            image: # < URI of the Frontend App image >
            ports:
            - name: public-port
              containerPort: 80
            livenessProbe:
              httpGet:
                path: /status
                port: public-port
              initialDelaySeconds: 30
              timeoutSeconds: 1
              periodSeconds: 10
          imagePullSecrets:
            - name: # < Name of the registry secret providing access to the frontend image >
          automountServiceAccountToken: false
    ---
    # A service which exposes the cognitive-service containers through a dependable hostname: http://language:5000
    apiVersion: v1
    kind: Service
    metadata:
      name: language
      labels:
        run: language
    spec:
      selector:
        app: language
      type: LoadBalancer
      ports:
      - name: language
        port: 5000
        targetPort: 5000
        protocol: TCP
    ---
    # A deployment declaratively indicating how many instances of the cognitive-service container we want up
    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
      name: language
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            app: language
        spec:
          containers:
          - name: language
            image: # < URI of the Language Image >
            ports:
            - name: public-port
              containerPort: 5000
            livenessProbe:
              httpGet:
                path: /status
                port: public-port
              initialDelaySeconds: 30
              timeoutSeconds: 1
              periodSeconds: 10
            args:
                - "eula=accept"
                - "apikey=" # < API Key for the Language Service >
                - "billing=" # < Language billing endpoint URI >
    
          imagePullSecrets:
            - name: # < Name of the registry secret providing access to the Language image >
    
          automountServiceAccountToken: false
    
  3. 根据下表更改 language.yml 的语言前端部署行,以添加自己的容器注册表映像名称、客户端密码和语言服务设置。

    语言前端部署设置 用途
    第 32 行
    image 属性
    容器注册表中的前端映像的映像位置
    <container-registry-name>.azurecr.io/language-frontend:v1
    第 44 行
    name 属性
    映像的容器注册表机密,在上一节中称为 <client-secret>
  4. 根据下表更改 language.yml 的语言部署行,以添加自己的容器注册表映像名、客户端密码和语言服务设置。

    语言部署设置 用途
    第 78 行
    image 属性
    容器注册表中语言映像的映像位置
    <container-registry-name>.azurecr.io/language:1.1.006770001-amd64-preview
    第 95 行
    name 属性
    映像的容器注册表机密,在上一节中称为 <client-secret>
    第 91 行
    apiKey 属性
    语言服务资源密钥
    第 92 行
    billing 属性
    语言服务资源的计费终结点。
    https://westus.api.cognitive.microsoft.com/text/analytics/v2.1

    由于 apiKey 和账单终结点已设置为 Kubernetes 业务流程定义的一部分,因此网站容器无需了解这些内容或将其作为请求的一部分传递。 网站容器按其业务流程协调程序名称 language 引用语言检测容器。

  5. 从创建和保存 language.yml 的文件夹中加载此示例的业务流程定义文件。

    kubectl apply -f language.yml
    

    响应为:

    service "language-frontend" created
    deployment.apps "language-frontend" created
    service "language" created
    deployment.apps "language" created
    

获取容器的外部 IP

对于这两个容器,请验证 language-frontendlanguage 服务是否正在运行,并获取外部 IP 地址。

kubectl get all
NAME                                     READY     STATUS    RESTARTS   AGE
pod/language-586849d8dc-7zvz5            1/1       Running   0          13h
pod/language-frontend-68b9969969-bz9bg   1/1       Running   1          13h

NAME                        TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)          AGE
service/kubernetes          ClusterIP      10.0.0.1      <none>          443/TCP          14h
service/language            LoadBalancer   10.0.39.169   104.42.172.68   5000:30161/TCP   13h
service/language-frontend   LoadBalancer   10.0.42.136   104.42.37.219   80:30943/TCP     13h

NAME                                      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/language            1         1         1            1           13h
deployment.extensions/language-frontend   1         1         1            1           13h

NAME                                                 DESIRED   CURRENT   READY     AGE
replicaset.extensions/language-586849d8dc            1         1         1         13h
replicaset.extensions/language-frontend-68b9969969   1         1         1         13h

NAME                                DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/language            1         1         1            1           13h
deployment.apps/language-frontend   1         1         1            1           13h

NAME                                           DESIRED   CURRENT   READY     AGE
replicaset.apps/language-586849d8dc            1         1         1         13h
replicaset.apps/language-frontend-68b9969969   1         1         1         13h

如果服务的 EXTERNAL-IP 显示为挂起,请重新运行该命令,直到显示 IP 地址,然后再转到下一步。

测试语言检测容器

打开浏览器并导航到上一节中 language 容器的外部 IP:http://<external-ip>:5000/swagger/index.html。 可以使用 API 的 Try it 功能来测试语言检测终结点。

显示容器的 swagger 文档的屏幕截图

测试客户端应用程序容器

使用以下格式将浏览器中的 URL 更改为 language-frontend 容器的外部 IP:http://<external-ip>/helloworldhelloworld 的英文区域性文本预测为 English

清理资源

群集操作完成后,请删除 Azure 资源组。

az group delete --name cogserv-container-rg

后续步骤

Azure AI 容器