Este guia fornece um exemplo de como implantar e disponibilizar um modelo de Stable Diffusion no Google Kubernetes Engine (GKE) usando Ray Serve e o complemento Ray Operator como um exemplo de implementação.
Sobre o Ray e o Ray Serve
O Ray é um framework de computação escalonável e de código aberto para aplicativos de IA/ML. O Ray Serve é uma biblioteca de disponibilização de modelos para Ray usado para dimensionar e exibir modelos em um ambiente distribuído. Para mais informações, consulte Ray Serve na documetação do Ray.
Use um recurso do RayCluster ou do RayService para implantar seu aplicativos do Ray Serve. Use um recurso do RayService na produção pelos seguintes motivos:
- Atualizações no local para aplicativos do RayService
- Upgrade sem inatividade para recursos do RayCluster
- Aplicativos do Ray Serve altamente disponíveis
Objetivos
Este guia é destinado a clientes de IA generativa, usuários novos ou atuais do GKE, engenheiros de ML, engenheiros de MLOps (DevOps) ou administradores de plataformas interessados em usar os recursos de orquestração de contêineres do Kubernetes para disponibilizar modelos usando o Ray.
- Criar um cluster do GKE com um pool de nós de GPU
- Crie um cluster do Ray usando o recurso personalizado do RayCluster.
- Execute um aplicativo do Ray Serve.
- Implantar um recurso personalizado do RayService.
Custos
Neste documento, você vai usar os seguintes componentes faturáveis do Google Cloud:
Para gerar uma estimativa de custo baseada na sua projeção de uso, utilize a calculadora de preços.
Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Para mais informações, consulte Limpeza.
Antes de começar
O Cloud Shell vem pré-instalado com o software
necessário para este tutorial, incluindo kubectl e
a gcloud CLI. Se você não usa o Cloud Shell,
é necessário instalar a gcloud CLI.
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
Install the Google Cloud CLI.
-
Ao usar um provedor de identidade (IdP) externo, primeiro faça login na gcloud CLI com sua identidade federada.
-
Para inicializar a gcloud CLI, execute o seguinte comando:
gcloud init -
Create or select a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_IDwith a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_IDwith your Google Cloud project name.
-
Verify that billing is enabled for your Google Cloud project.
-
Enable the GKE API:
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.gcloud services enable container.googleapis.com
-
Install the Google Cloud CLI.
-
Ao usar um provedor de identidade (IdP) externo, primeiro faça login na gcloud CLI com sua identidade federada.
-
Para inicializar a gcloud CLI, execute o seguinte comando:
gcloud init -
Create or select a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_IDwith a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_IDwith your Google Cloud project name.
-
Verify that billing is enabled for your Google Cloud project.
-
Enable the GKE API:
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.gcloud services enable container.googleapis.com
-
Grant roles to your user account. Run the following command once for each of the following IAM roles:
roles/container.clusterAdmin, roles/container.admingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Replace the following:
PROJECT_ID: Your project ID.USER_IDENTIFIER: The identifier for your user account. For example,myemail@example.com.ROLE: The IAM role that you grant to your user account.
Inicie uma sessão do Cloud Shell no console do Google Cloud clicando em
Ativar o Cloud Shell no console doGoogle Cloud . Isso inicia uma sessão no painel inferior do console Google Cloud .
Defina as variáveis de ambiente:
export PROJECT_ID=PROJECT_ID export CLUSTER_NAME=rayserve-cluster export COMPUTE_REGION=us-central1 export COMPUTE_ZONE=us-central1-c export CLUSTER_VERSION=CLUSTER_VERSION export TUTORIAL_HOME=`pwd`Substitua:
PROJECT_ID: o Google Cloud ID do projeto.CLUSTER_VERSION: a versão do GKE a ser usada. Precisa ser1.30.1ou mais recente.
Clone o repositório do GitHub:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samplesMude para o diretório de trabalho:
cd kubernetes-engine-samples/ai-ml/gke-ray/rayserve/stable-diffusionCrie um ambiente virtual em Python:
venv
python -m venv myenv && \ source myenv/bin/activateConda
Execute os comandos a seguir:
conda create -c conda-forge python=3.9.19 -n myenv && \ conda activate myenv
Ao implantar um aplicativo do Serve com
serve run, o Ray espera que a versão do Python do cliente local corresponda à versão usada no cluster do Ray. A imagemrayproject/ray:2.37.0usa o Python 3.9. Se você estiver executando uma versão diferente do cliente, selecione a imagem do Ray apropriada.Instale as dependências necessárias para executar o aplicativo de serviço:
pip install ray[serve]==2.37.0 pip install torch pip install requestsCriar um cluster padrão
gcloud container clusters create ${CLUSTER_NAME} \ --addons=RayOperator \ --cluster-version=${CLUSTER_VERSION} \ --machine-type=c3d-standard-8 \ --location=${COMPUTE_ZONE} \ --num-nodes=1Crie um pool de nós de GPU:
gcloud container node-pools create gpu-pool \ --cluster=${CLUSTER_NAME} \ --machine-type=g2-standard-8 \ --location=${COMPUTE_ZONE} \ --num-nodes=1 \ --accelerator type=nvidia-l4,count=1,gpu-driver-version=latestAnalise o seguinte manifesto:
Esse manifesto descreve um recurso do RayCluster.
Aplique o manifesto ao cluster:
kubectl apply -f ray-cluster.yamlVerifique se o recurso do RayCluster está pronto:
kubectl get rayclusterO resultado será assim:
NAME DESIRED WORKERS AVAILABLE WORKERS CPUS MEMORY GPUS STATUS AGE stable-diffusion-cluster 2 2 6 20Gi 0 ready 33sNesta saída,
readyna colunaSTATUSindica que o recurso do RayCluster está pronto.Verifique se o GKE criou o serviço RayCluster:
kubectl get svc stable-diffusion-cluster-head-svcO resultado será assim:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE pytorch-mnist-cluster-head-svc ClusterIP 34.118.238.247 <none> 10001/TCP,8265/TCP,6379/TCP,8080/TCP 109sEstabeleça sessões de encaminhamento de portas para o head do Ray:
kubectl port-forward svc/stable-diffusion-cluster-head-svc 8265:8265 2>&1 >/dev/null & kubectl port-forward svc/stable-diffusion-cluster-head-svc 10001:10001 2>&1 >/dev/null &Verifique se o cliente Ray pode se conectar ao cluster usando localhost:
ray list nodes --address http://localhost:8265O resultado será assim:
======== List: 2024-06-19 15:15:15.707336 ======== Stats: ------------------------------ Total: 3 Table: ------------------------------ NODE_ID NODE_IP IS_HEAD_NODE STATE NODE_NAME RESOURCES_TOTAL LABELS 0 1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2 10.28.1.21 False ALIVE 10.28.1.21 CPU: 2.0 ray.io/node_id: 1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2 # Several lines of output omittedExecute o aplicativo Stable Diffusion do Ray Serve:
serve run stable_diffusion:entrypoint --working-dir=. --runtime-env-json='{"pip": ["torch", "torchvision", "diffusers==0.12.1", "huggingface_hub==0.25.2", "transformers", "fastapi==0.113.0"], "excludes": ["myenv"]}' --address ray://localhost:10001O resultado será assim:
2024-06-19 18:20:58,444 INFO scripts.py:499 -- Running import path: 'stable_diffusion:entrypoint'. 2024-06-19 18:20:59,730 INFO packaging.py:530 -- Creating a file package for local directory '.'. 2024-06-19 18:21:04,833 INFO handle.py:126 -- Created DeploymentHandle 'hyil6u9f' for Deployment(name='StableDiffusionV2', app='default'). 2024-06-19 18:21:04,834 INFO handle.py:126 -- Created DeploymentHandle 'xo25rl4k' for Deployment(name='StableDiffusionV2', app='default'). 2024-06-19 18:21:04,836 INFO handle.py:126 -- Created DeploymentHandle '57x9u4fp' for Deployment(name='APIIngress', app='default'). 2024-06-19 18:21:04,836 INFO handle.py:126 -- Created DeploymentHandle 'xr6kt85t' for Deployment(name='StableDiffusionV2', app='default'). 2024-06-19 18:21:04,836 INFO handle.py:126 -- Created DeploymentHandle 'g54qagbz' for Deployment(name='APIIngress', app='default'). 2024-06-19 18:21:19,139 INFO handle.py:126 -- Created DeploymentHandle 'iwuz00mv' for Deployment(name='APIIngress', app='default'). 2024-06-19 18:21:19,139 INFO api.py:583 -- Deployed app 'default' successfully.Estabeleça uma sessão de encaminhamento de portas para a porta do Ray Serve (8000):
kubectl port-forward svc/stable-diffusion-cluster-head-svc 8000:8000 2>&1 >/dev/null &Execute o script Python:
python generate_image.pyO script gera uma imagem para um arquivo chamado
output.png. O resultado será assim:
Analise o seguinte manifesto:
Este manifesto descreve um recurso personalizado do RayService.
Aplique o manifesto ao cluster:
kubectl apply -f ray-service.yamlVerifique se o serviço está pronto:
kubectl get svc stable-diffusion-serve-svcO resultado será assim:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE stable-diffusion-serve-svc ClusterIP 34.118.236.0 <none> 8000/TCP 31mConfigure o encaminhamento de portas para o serviço Ray Serve:
kubectl port-forward svc/stable-diffusion-serve-svc 8000:8000 2>&1 >/dev/null &Execute o script Python da seção anterior:
python generate_image.pyO script gera uma imagem semelhante à imagem gerada na seção anterior.
- Confira arquiteturas de referência, diagramas, tutoriais e práticas recomendadas do Google Cloud. Confira o Centro de arquitetura do Cloud.
Preparar o ambiente
Para configurar o ambiente, siga estas etapas:
Criar um cluster com um pool de nós de GPU
Crie um cluster do GKE Autopilot ou Standard com um pool de nós de GPU:
Piloto automático
Criar um cluster do Autopilot:
gcloud container clusters create-auto ${CLUSTER_NAME} \
--enable-ray-operator \
--cluster-version=${CLUSTER_VERSION} \
--location=${COMPUTE_REGION}
Padrão
Implantar um recurso do RayCluster
Para implantar um recurso do RayCluster:
Conectar-se ao recurso do RayCluster
Para se conectar ao recurso do RayCluster:
Executar um aplicativo do Ray Serve
Para executar um aplicativo do Ray Serve:
Implantar um RayService
O recurso personalizado do RayService gerencia o ciclo de vida de um recurso do RayCluster e do aplicativo do Ray Serve.
Para mais informações sobre o RayService, consulte Implantar aplicativos do Ray Serve e Guia de produção na documentação do Ray.
Para implantar um recurso do RayService, siga estas etapas:
Observar suas cargas de trabalho do Ray
Para conferir detalhes dos RayJobs, acesse a seção Kubernetes Engine > IA/ML > Jobs em Google Cloud console.
Limpar
Excluir o projeto
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
Excluir recursos individuais
Para excluir o cluster, digite:
gcloud container clusters delete ${CLUSTER_NAME}