Поделиться через


Развертывание контейнера распознавания языка в Службе Azure Kubernetes

Узнайте, как развертывать контейнер распознавания языка. В статье описано, как создавать локальные контейнеры Docker, отправлять их в закрытый реестр контейнеров и запускать в кластере Kubernetes, а также тестировать в веб-браузере.

Необходимые компоненты

Для выполнения этой процедуры необходимо установить и запустить несколько средств локально. Не используйте Azure Cloud Shell.

  • Используйте подписку Azure. Если у вас нет подписки Azure, создайте бесплатную учетную запись, прежде чем приступить к работе.
  • Git для вашей операционной системы, чтобы клонировать пример для этой процедуры.
  • Azure CLI.
  • Модуль Docker, для которого нужно проверить работоспособность Docker CLI в окне консоли.
  • kubectl.
  • Ресурс Azure с правильной ценовой категорией. Не все ценовые категории работают с этим контейнером:
    • Ресурс Язык с ценовой категорией F0 или "Стандартный".
    • Ресурс служб искусственного интеллекта Azure с ценовой категорией S0.

Выполнение примера

Эта процедура загружает и запускает пример контейнера служб ИИ Azure для обнаружения языка. В примере есть два контейнера, один для клиентского приложения и один для контейнера служб ИИ Azure. Мы отправим оба этих образа в Реестр контейнеров Azure. Разместив их в собственном реестре, создайте Службу Azure Kubernetes для доступа к образам и выполнения контейнеров. Когда контейнеры будут запущены, используйте интерфейс командной строки kubectl для контроля производительности контейнеров. Создайте HTTP-запрос к клиентскому приложению и проверьте результаты его выполнения.

Схема, показывающая концептуальную идею запуска контейнера в Kubernetes

Примеры контейнеров

Этот пример содержит два образа контейнеров, один из которых отвечает за интерфейсный веб-сайт. Второй образ — это контейнер распознавания языка, который возвращает сведения о языке (региональных параметрах), обнаруженном для текста. Когда вы завершите работу, оба эти контейнера будут доступны по внешнему IP-адресу.

Контейнер интерфейса для распознавания языка

Этот веб-сайт выполняет те же функции, что и клиентское приложение, то есть направляет запросы к конечной точки распознавания языка. Когда процедура будет завершена, вы сможете определить язык для строки символов, обращаясь к контейнеру веб-сайта через браузер по адресу http://<external-IP>/<text-to-analyze>. Пример URL-адреса: http://132.12.23.255/helloworld!. В браузере отображается результат English.

Контейнер распознавания языка

В нашем примере контейнер распознавания языка доступен для любых внешних запросов. Контейнер не был изменен каким-либо образом, поэтому доступен стандартный API обнаружения языков для служб искусственного интеллекта Azure.

Для этого используется запрос POST для распознавания языка. Как и во всех контейнерах ИИ Azure, вы можете узнать больше о контейнере из размещенных сведений Swagger. http://<external-IP>:5000/swagger/index.html

Порт 5000 — это порт по умолчанию, используемый с контейнерами ИИ Azure.

Создание службы Реестра контейнеров Azure

Чтобы развернуть контейнер в Службе Azure Kubernetes, должны быть доступны образы контейнеров. Создайте собственную службу Реестра контейнеров Azure для размещения образов.

  1. Вход в Azure CLI

    az login
    
  2. Создайте группу ресурсов с именем cogserv-container-rg, в которой будут размещены все созданные в этой процедуре ресурсы.

    az group create --name cogserv-container-rg --location westus
    
  3. Создайте Реестр контейнеров Azure, указав для него имя с постфиксом registry, например pattyregistry. Не используйте в имени символы дефиса или подчеркивания.

    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. Клонируйте этот репозиторий, чтобы получить локальную копию примера.

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

    Разместив репозиторий на локальном компьютере, найдите веб-сайт в каталоге \dotnet\Language\FrontendService. Этот веб-сайт выступает в качестве клиентского приложения, то есть вызывает API распознавания языка, размещенный в контейнере распознавания языка.

  2. Создайте образ Docker для этого веб-сайта. Убедитесь, что в консоли открыт каталог \FrontendService, в котором находится Dockerfile, и выполните следующую команду:

    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
    

    Сохраните из результата значение appId, которое вы присвоите параметру <appId> (уполномоченный объект) на шаге 3. Сохраните значение password, которое вы присвоите параметру <client-secret> (секрет клиента) в следующем разделе.

    {
      "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. Получите идентификатор реестра контейнеров.

    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. Все значения параметров, кроме имени взяты из предыдущих разделов. Выберите имя, которое описывает понять, кто и зачем его создал, например 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 для взаимодействия со Службой 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-frontend и language, а затем получите их внешний 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 имеет значение pending, выполните ту же команду еще один или несколько раз, пока не получите значение IP-адреса, прежде чем переходить к следующему шагу.

Тестирование контейнера распознавания языка

Откройте браузер и перейдите по внешнему IP-адресу контейнера language, который вы получили в предыдущем разделе: http://<external-ip>:5000/swagger/index.html. Для проверки конечной точки распознавания языка вы можете использовать функцию API Try it.

Снимок экрана: документация по swagger контейнера

Тестирование контейнера с клиентским приложением

В адресную строку браузера введите внешний IP-адрес контейнера language-frontend, используя следующий формат: http://<external-ip>/helloworld. Для текста helloworld распознается английский язык: English.

Очистка ресурсов

Когда вы закончите работу с кластером, удалите группу ресурсов Azure.

az group delete --name cogserv-container-rg

Следующие шаги

Контейнеры ИИ Azure