Часть 1. Настройка инфраструктуры с помощью Terraform

В первой части этого руководства, состоящего из двух частей, мы научимся создавать кластер Kubernetes, который развертывает модель Stable Diffusion на GCP. Стабильная диффузия (форма генеративного ИИ) — новый крутой парень в этом районе. Стабильная диффузия позволяет нам создавать реалистичные изображения из данной текстовой подсказки. Благодаря новизне и вычислительной нагрузке, создаваемой моделью стабильной диффузии, она предоставляет бесценные возможности для решения некоторых уникальных задач.

Примечание. Вы можете следовать этому руководству от начала до конца, даже если вы являетесь бесплатным пользователем (при условии, что у вас осталось немного средств на счете бесплатного уровня).

Гитхаб: https://github.com/thushv89/tf-serving-gke/tree/master/infrastrcture

Но для создания идеального шторма (или идеального продукта) доступ к последней версии весов моделей не поможет. Требуется приложить усилия, чтобы создать надежную производственную систему вокруг вашей модели, чтобы поддерживать запросы пользователей и обслуживать их надежно с разумной задержкой.

Для этого мы узнаем, как запустить модель стабильной диффузии в кластере GKE. Этот учебник, состоящий из 2 частей, будет состоять из 4 частей:

  • Настройка учетных записей и ролей (часть 1)
  • Настройка кластера (Часть 1)
  • Развертывание службы прогнозирования в подготовленном кластере (часть 2)
  • Создание новых образов с развернутой конечной точкой (часть 2)

Прежде чем начать, убедитесь, что вы создали проект GCP и вошли в свою учетную запись через gcloud auth login . Вы можете использовать gcloud config set project <project_id> и gcloud config set region <region>, чтобы убедиться, что вы находитесь в правильном проекте и регионе.

Примечание. Большая часть IAM (управление идентификацией и доступом), о которой я здесь говорю, основана на моем (ограниченном) личном опыте по этому вопросу. Если вы видите что-то, что можно улучшить, дайте мне знать!

terraform: стильное управление инфраструктурой

Если вы уже знакомы с terraform , перейдите к разделу «Определение учетных записей и ролей (IAM)».

Обзор

Для всей настройки инфраструктуры на GCP мы будем использовать terraform; инструмент IaaS (инфраструктура как услуга), позволяющий нам систематизировать все наши требования к инфраструктуре. Вы спросите, зачем управлять облачными ресурсами с помощью кода, а не кропотливых ручных операций, чреватых ошибками? Есть много (других) причин:

  • Код (написанный в удобочитаемой форме) облегчает понимание архитектуры, повышает возможность повторного использования и т. д.
  • terraform автоматически управляет зависимостями и выполняет операции в правильном порядке
  • Код с контролируемой версией предоставляет вам возможность получить моментальный снимок состояния вашей системы в заданный момент времени (для устранения неполадок).

terraform предоставляет комплексный готовый API для быстрого создания инфраструктуры для всех распространенных поставщиков, таких как GCP, AWS, Azure и т. д.

концепции терраформирования

Язык terraform организует код в конфигурации. Конфигурация terraform работает в рабочем каталоге, в котором будут файлы конфигурации, заканчивающиеся расширением .tf или .tf.json;

  • variables.tf — содержит все определения переменных, которые используются конфигурацией.
  • outputs.tf — любые выходные данные, которые необходимо записать
  • Помимо этого, вы можете включить любое количество .tf файлов, содержащих определения ресурсов, поставщиков и т. д. В нашем простом сценарии нам нужен только один файл, который мы назовем main.tf.

Далее давайте посмотрим, как terraform обеспечивает разделение кода.

terraform — это декларативный язык, то есть вы указываете terraform что делать (как в SQL), а не как это делать (как в Python). Задача terraform построить план (например, в виде графика) и выполнить его.

Затем мы можем составить нашу terraform конфигурацию с помощью модулей. Модульность необязательна, однако она разбивает сложную инфраструктуру на логические компоненты/подсистемы и значительно повышает возможность повторного использования. В нашем случае мы будем определять три модуля;

  1. Управляет учетными записями и ролями (modules/iam)
  2. Управляет кластером GKE (modules/gke_cluster)
  3. Управляет хранилищем — настройка корзины GCS (modules/storage)

Когда вы перейдете к этим модулям в коде, вы увидите следующие основные строительные блоки, гармонично используемые для достижения желаемого состояния инфраструктуры, в которой мы нуждаемся (конкретные примеры см. в Приложении).

  • Блоки ресурсов — описывает объекты инфраструктуры (например, виртуальные машины, кластер, VPC).
  • Источник данных/блок данных — представляет источник данных (например, файл) и связанные с ним данные.
  • Плагин провайдера — предоставляет доступ к типам ресурсов и источникам данных, связанным с определенным провайдером.
  • Входные и выходные переменные модулей

Как только вы определите свою конфигурацию, вы можете запустить terraform plan , чтобы увидеть, что будет выполняться terraform. Далее можно использовать terraform apply для применения этих изменений. После применения terraform запишет внесенные изменения в файл terraform.tfstate. Поэтому, если вы хотите внести изменения (или уничтожить), terraform знает о текущем состоянии вашей инфраструктуры, поэтому может составить план необходимых изменений.

Если вам нужно дальнейшее закрепление концепций terraform, вы можете прочитать документацию здесь или пройти этот учебник по GCP. Теперь, когда мы поняли основы terraform, давайте перейдем к пониманию логики.

Определение учетных записей и ролей (IAM)

Для наших операций, связанных с настройкой кластера GKE, мы создадим учетную запись службы. Как следует из названия, учетная запись службы обычно используется приложениями и рабочими нагрузками, а не реальным человеком. Например, узлы GKE могут использовать учетную запись службы для выполнения приложения от имени. Учетной записи службы могут быть назначены разрешения и роли (т. е. совокупность разрешений, сопоставленных осмысленным образом), как и у учетной записи пользователя. Несколько преимуществ сервисных аккаунтов:

  • Мы можем быстро привязать/удалить привязку пользователя к сервисной учетной записи, что позволяет нам предоставлять необходимые разрешения пользователю с повторным назначением ролей/разрешений отдельным пользователям.
  • Сервисные учетные записи могут быть настроены с краткосрочными учетными данными, что делает их более безопасными.

Мы настроим две служебные учетные записи со следующими идентификаторами:

  • gke-admin — имеет необходимые права для создания кластера GKE и предоставления узлов.
  • gke-node — имеет необходимое разрешение для успешного выполнения рабочей нагрузки (например, чтение из корзины GCS).

Хотя учетная запись службы не используется человеком напрямую и не привязана к нему, можно выдать себя за учетную запись службы, позволяя пользователю выполнять команды так же, как это является учетной записью службы. Это метод, который мы будем использовать для настройки кластера.

Вот этот процесс будет описан в нашем коде terraform,

  • Создайте сервисные аккаунты: gke-admin и gke-node
  • Назначьте необходимые роли для созданных учетных записей
    gke-admin: container.admin (например, создать кластер), compute.viewer (например, создать пул узлов), iam.serviceAccountUser
    gke-node: container.nodeServiceAccount (разрешение для типичной рабочей нагрузки Kubernetes)
    — Вы можете посмотреть в Консоль GCP → IAM → Роли, чтобы узнать, какие разрешения предоставляются каждой ролью.
  • Назначьте необходимые роли учетной записи пользователя, чтобы создать недолговечный токен доступа (iam.serviceAccountTokenCreator)
  • Создайте привязку учетной записи пользователя к учетной записи службы, чтобы пользователь мог олицетворять учетную запись службы.

Наконец, мы объявим имена двух учетных записей служб, которые мы создали, как выходные данные (в outputs.tf), чтобы на них можно было ссылаться в конфигурации и других дочерних модулях.

Для предоставления инфраструктуры мы будем использовать две формы аутентификации:

  • Типичная аутентификация, которую вы получаете, запустив gcloud auth login, которая будет использоваться для создания учетных записей служб и привязок.
  • После этого мы будем использовать олицетворение учетной записи службы для настройки кластера.

Примечание 1. У меня есть роль owner (т. е. владелец проекта), прикрепленная к моей учетной записи пользователя. В противном случае вам потребуется разрешение, необходимое для создания служебной учетной записи и т. д.

Примечание 2. Создание и привязка всех этих сервисных учетных записей может показаться излишним, когда у вас есть роль владельца, однако при работе над проектом, где вы сотрудничаете с командой (или в организация), вам нужно будет подумать и настроить разрешение с мышлением пользователя с наименьшими привилегиями, чтобы избежать эксплуатации системы безопасности.

Мы пока не будем запускать terraform apply, так как будем создавать сервисные аккаунты и кластер GKE одновременно.

Определение кластера GKE

Мы создадим кластер GKE, который сможет настроить даже пользователь бесплатного уровня. Кластер состоит из плоскости управления и одного или нескольких рабочих узлов. Плоскость управления предоставляет доступ к кластеру, так что вы можете проверять узлы, модули, службы и т. д. Каждый узел может запускать один или несколько модулей (с определенными требованиями к ресурсам — например, ЦП/памяти). Модуль (который может запускать один или несколько контейнеров) будет выполнять указанную рабочую нагрузку (например, изображение tensorlfow-serving для обслуживания модели). Вы можете обратиться здесь, чтобы узнать об архитектуре GKE.

Мы создадим кластер в стандартном режиме с:

  • machine_type: n2-стандарт-4
  • max_node_count(максимальное количество узлов для предоставления): 2
  • preemptible : true (Вы также можете использовать экземпляры spot, которые дешевле, чем экземпляры preemptible. Узнайте о различиях здесь.)

Обратите внимание, что мы не используем графические процессоры, так как у вас, как бесплатного пользователя, может не быть права на получение квоты графических процессоров. Но если вы это сделаете, не стесняйтесь следовать процессу здесь для настройки пула узлов с графическими процессорами.

Примечание 1. Если вы являетесь пользователем бесплатного уровня, вы будете ограничены двумя важными квотами:

all_regions_cpus: по умолчанию 12

all_n2_cpus: по умолчанию 8

all_regions_gpus: по умолчанию 0

Поскольку мы используем экземпляры типа N2, каждый из которых имеет 4 виртуальных ЦП, мы можем развернуть только 2 таких экземпляра в пределах квоты. Вы можете поэкспериментировать с другими экземплярами, такими как n2-standard-2 или n1, если хотите иметь больше узлов в кластере.

Примечание 2. Это глобальные квоты. Это означает, что если у вас, например, есть блокнот Vertext AI с другим запущенным экземпляром типа n2, он также будет учитываться в этой квоте.

Если вы не будете соблюдать их, вы столкнетесь с ошибками типа Quota exceeded, когда будете применять эту инфраструктуру на terraform.

Полную конфигурацию вы можете прочитать в здесь. Я не буду вдаваться в подробности здесь, так как это просто. Тем не менее, я хотел бы упомянуть об одном понятии региональных и зональных кластеров. Игнорирование этого различия может привести к несколько загадочным ошибкам, таким как этот вопрос Stackoverflow.

Создание инфраструктуры и ресурсов на GCP

Прежде чем применить обсуждаемые изменения terraform, нам нужно выполнить некоторые служебные действия. Первый забег

./setup.sh -u <user name> -p <project id> -r <region>

Это создаст файл конфигурации с определенными аргументами, чтобы их можно было импортировать в код terraform. Дальше беги,

terraform init 

Это установит плагин предоставления, а также локальные модули, которые мы определили. После этого мы можем запустить следующую команду, чтобы узнать, что будет делать terraform.

terraform plan [-var="include_module_storage=<true or false>"]

План будет выглядеть так.

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create
 <= read (data resources)

Terraform will perform the following actions:

  # data.google_service_account_access_token.default will be read during apply
  # (config refers to values not yet known)
 <= data "google_service_account_access_token" "default" {
      + access_token           = (sensitive value)
      + id                     = (known after apply)
      + scopes                 = [
          + "cloud-platform",
          + "userinfo-email",
        ]
      + target_service_account = (known after apply)
    }

  ...

  # module.iam.google_service_account_iam_binding.admin_account_iam will be created
  + resource "google_service_account_iam_binding" "admin_account_iam" {
      + etag               = (known after apply)
      + id                 = (known after apply)
      + members            = [
          + "user:[email protected]",
        ]
      + role               = "roles/iam.serviceAccountTokenCreator"
      + service_account_id = (known after apply)
    }

Plan: 9 to add, 0 to change, 0 to destroy.

Если мы довольны планом, мы можем запустить команду ниже, чтобы применить изменения.

terraform apply [-var="include_module_storage=<true or false>"]

Если все сделано успешно, вы должны увидеть файл terraform.tfstate, появившийся в вашем рабочем каталоге, с описанием всех примененных изменений. Посетите README здесь для получения подробных инструкций. Вы можете перейти в консоль GCP → IAM → Учетные записи служб и убедиться, что учетные записи служб созданы правильно.

Вы также увидите кластер с именем sd-cluster в консоли GCP → Kubernetes Engine → Кластеры.

Отлично, теперь у нас есть все необходимое для развертывания нашей модели машинного обучения как сервиса. Мы рассмотрим, как мы можем это сделать, в следующей части руководства.

До сих пор вы,

  • Узнали, что такое terraform и как с его помощью упростить управление инфраструктурой.
  • Создал удостоверения (сервисные учетные записи) и настроил их с правильными ролями.
  • Поняли, что такое кластер GKE, и создали его, выдав себя за требуемую учетную запись службы.

Устранение неполадок и предостережения

  • Ошибка: Unable to connect to the server: x509: certificate has expired or is not yet valid
  • Решение 1. Это может быть связано с истечением срока действия сеанса gcloud. Просто запустите gcloud auth login и завершите процесс входа в систему.
  • Решение 2. Существует ошибка в WSL, из-за которой часы в WSL не синхронизируются с часами Windows. Вы можете запустить sudo hwclock -s, чтобы запустить синхронизацию

Предупреждение: если вы используете bash в Powershell (на базе WSL), вы не сможете экспортировать переменные среды (для использования terraform). Поэтому я бы рекомендовал не использовать переменные окружения, если вы полагаетесь на это.

Приложение

Блоки ресурсов

Описывает один или несколько объектов инфраструктуры (например, виртуальные машины, кластер, VPC). Каждый ресурс идентифицируется по типу ресурса и уникальному имени.

resource "google_service_account" "sa_gke_admin" {
  account_id   = "gke-admin"
  display_name = "GKE Service Account (Admin)"
}

Источник данных/блок данных

Представляет источник данных и связанные с ним данные.

data "google_service_account_access_token" "default" {
 provider                = google.impersonation_helper
 target_service_account  = module.iam.service_account_gke_admin
 scopes                  = ["userinfo-email", "cloud-platform"]
 depends_on = [module.iam]
}

Плагин провайдера

Предоставляет доступ к типам ресурсов и источникам данных, связанным с определенным поставщиком.

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "3.5.0"
    }
  }
}

Входные и выходные переменные

Выступают в качестве аргументов и возвращаемых типов для модулей.

variable "gcp_user" {
  type = string
  description = "Your username for GCP"
}
output "service_account_gke_node" {
  description = "GKE node service account"
  value       = google_service_account.sa_gke_node.email
}
variable "gcp_user" {
  type = string
  description = "Your username for GCP"
}
output "service_account_gke_node" {
  description = "GKE node service account"
  value       = google_service_account.sa_gke_node.email
}

Подтверждение

Я хотел бы отметить Программы для разработчиков ML и команду за кредиты GCP, предоставленные для успеха этого руководства.