1. Introdução
O Kubeflow é um kit de ferramentas de machine learning para Kubernetes. O objetivo do projeto é fazer com que as implantações de fluxos de trabalho de machine learning (ML) no Kubernetes sejam simples, portáteis e escalonáveis. O objetivo é oferecer uma maneira simples de implantar os melhores sistemas de código aberto para ML em diversas infraestruturas. | |
Um fluxo de trabalho de machine learning pode envolver muitas etapas que dependem umas das outras, desde a preparação e análise de dados até o treinamento, a avaliação, a implantação e muito mais. É difícil compor e rastrear esses processos de maneira ad-hoc, por exemplo, em um conjunto de notebooks ou scripts, e coisas como auditoria e reprodutibilidade se tornam cada vez mais problemáticas.O Kubeflow Pipelines (KFP) ajuda a resolver esses problemas fornecendo uma maneira de implantar pipelines de machine learning robustos e repetíveis com monitoramento, auditoria, rastreamento de versões e reprodutibilidade. O Cloud AI Pipelines facilita a configuração de uma instalação de KFP. |
O que você vai criar
Neste codelab, você criará um app da Web que resume problemas do GitHub usando o Kubeflow Pipelines (em inglês) para treinar e exibir um modelo. Ele é baseado em um exemplo no repositório de exemplos do Kubeflow (em inglês). Ao final do processo, a infraestrutura terá:
- Um cluster do Google Kubernetes Engine (GKE) com o Kubeflow Pipelines instalado (usando o Cloud AI Pipelines)
- Um pipeline que treina um modelo do Tensor2Tensor em GPUs
- Um contêiner de exibição que fornece previsões do modelo treinado
- Uma interface que interpreta as previsões para fornecer resumos de problemas do GitHub.
- Um notebook que cria um pipeline do zero usando o SDK do Kubeflow Pipelines (KFP)
O que você vai aprender
O pipeline que você criará treina um modelo do Tensor2Tensor nos dados de problemas do GitHub para aprender a prever títulos de problemas com base nos corpos. Em seguida, ele exporta o modelo treinado e o implanta usando o Tensorflow Serving. A etapa final do pipeline inicia um app da Web, que interage com a instância do TF- Serving para receber as previsões do modelo.
- Como instalar o Kubeflow Pipelines em um cluster do GKE
- Como criar e executar fluxos de trabalho de ML usando o Kubeflow Pipelines
- Como definir e executar pipelines em um notebook do AI Platform
O que é necessário
- Ter noções básicas do Kubernetes é útil, mas não é necessário
- Um projeto do GCP ativo em que você tem permissões de proprietário.
- (Opcional) Uma conta do GitHub
- Acesso ao Google Cloud Shell, disponível no Console do Google Cloud Platform (GCP)
2. Configuração
Cloud Shell
Acesse o Console do GCP no navegador e faça login com as credenciais do projeto:
Clique em "Selecionar um projeto" se necessário, para que você esteja trabalhando com seu projeto do codelab.
Depois clique em "Ativar o Cloud Shell" no canto superior direito do console para iniciar o Cloud Shell.
Quando você iniciar o Cloud Shell, ele informará o nome do projeto que está configurado para ser usado. Verifique se essa configuração está correta.
Para encontrar o ID do projeto, acesse o painel inicial do Console do GCP. Se a tela estiver vazia, clique em "Sim". no comando para criar um painel.
Em seguida, no terminal do Cloud Shell, execute estes comandos, se necessário, para configurar o gcloud
e usar o projeto correto:
export PROJECT_ID=<your_project_id> gcloud config set project ${PROJECT_ID}
Crie um bucket de armazenamento
Criar um bucket do Cloud Storage para armazenar arquivos de pipeline. Você vai precisar usar um ID globalmente exclusivo. Assim, é conveniente definir um nome de bucket que inclua o ID do projeto. Crie o bucket usando o comando gsutil mb
(criar bucket):
export PROJECT_ID=<your_project_id> export BUCKET_NAME=kubeflow-${PROJECT_ID} gsutil mb gs://${BUCKET_NAME}
Também é possível criar um bucket por meio do Console do GCP.
Opcional**: crie um token do GitHub**
Este codelab chama a API GitHub para recuperar dados disponíveis publicamente. Para evitar a limitação de taxa, especialmente em eventos em que um grande número de solicitações anônimas é enviado às APIs do GitHub, configure um token de acesso sem permissões. Isso serve somente para autorizar você como indivíduo em vez de usuário anônimo.
- Acesse https://github.com/settings/tokens e gere um novo token sem escopos.
- Salve-o em um lugar seguro. Em caso de perda, será necessário excluir e criar uma nova.
Se você pular esta etapa, o laboratório continuará funcionando. Você terá um pouco mais de limitação nas opções de geração de dados de entrada para testar o modelo.
Opcional: fixar painéis úteis
No console do GCP, fixe os painéis do Kubernetes Engine e do Armazenamento para facilitar o acesso.
Criar uma instalação do AI Platform Pipelines (pipelines hospedados do Kubeflow)
Siga as instruções na seção "Antes de começar" e "Configurar sua instância" seções aqui para configurar uma instância do GKE com o KFP instalado. Marque a caixa Permitir acesso às seguintes APIs do Cloud, como indicado na documentação. Caso contrário, o pipeline de exemplo não será executado com êxito. Deixe o namespace de instalação como default
.
Você precisará escolher uma zona compatível com Nvidia K80s. Você pode usar us-central1-a ou us-central1-c como padrões.
Anote o nome do cluster e a zona do GKE listados para sua instalação no painel do AI Pipelines depois que a instalação for concluída. Para facilitar, defina as variáveis de ambiente com esses valores.
export ZONE=<your zone> export CLUSTER_NAME=<your cluster name>
Configure o kubectl para usar as credenciais do seu novo cluster do GKE
Depois que o cluster do GKE for criado, configure kubectl
para usar as credenciais do novo cluster executando o seguinte comando no Cloud Shell:
gcloud container clusters get-credentials ${CLUSTER_NAME} \
--project ${PROJECT_ID} \
--zone ${ZONE}
Como alternativa, clique no nome do cluster no painel do AI Pipelines para acessar a página do GKE e clique em "Conectar" na parte superior da página. No pop-up, cole o comando no Cloud Shell.
Isso configura seu contexto kubectl
para que você possa interagir com o cluster. Para verificar a configuração, execute o seguinte comando:
kubectl get nodes -o wide
Você vai ver os nós listados com o status "Ready
" e outras informações sobre idade, versão, endereço IP externo, imagem do SO, versão do kernel e ambiente de execução do contêiner.
Configure o cluster para instalar o driver da Nvidia em pools de nós com GPU ativada
Em seguida, aplicaremos um daemonset ao cluster, que instalará o driver da Nvidia em todos os nós do cluster ativados para GPU:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/cos/daemonset-preloaded.yaml
Em seguida, execute o seguinte comando, que dá aos componentes do KFP permissão para criar novos recursos do Kubernetes:
kubectl create clusterrolebinding sa-admin --clusterrole=cluster-admin --serviceaccount=kubeflow:pipeline-runner
Criar um pool de nós de GPU
Em seguida, vamos configurar um pool de nós de GPU com tamanho 1:
gcloud container node-pools create gpu-pool \ --cluster=${CLUSTER_NAME} \ --zone ${ZONE} \ --num-nodes=1 \ --machine-type n1-highmem-8 \ --scopes cloud-platform --verbosity error \ --accelerator=type=nvidia-tesla-k80,count=1
3. Executar um pipeline no painel "Pipelines"
Abrir o painel de pipelines
No Console do Cloud, acesse o painel "Pipelines", caso ainda não tenha feito isso. Depois clique em ABRIR PAINEL DE PIPELINES. para sua instalação e clique em Pipelines na barra de menus à esquerda. Se você receber um erro de carregamento, atualize a guia. Você verá uma nova página como esta:
Descrição do pipeline
O pipeline que você vai executar tem várias etapas. Consulte mais detalhes no Apêndice deste codelab:
- Um checkpoint do modelo atual é copiado para o bucket.
- Um modelo do Tensor2Tensor é treinado usando dados pré-processados.
- O treinamento começa no checkpoint do modelo copiado na primeira etapa e depois treina por mais algumas centenas de etapas. O treinamento dela levaria muito tempo durante o codelab.
- Quando o treinamento termina, a etapa do pipeline exporta o modelo em um formato adequado para veiculação pelo TensorFlow Serving.
- Uma instância do TensorFlow Serving é implantada usando esse modelo.
- Um app da Web é iniciado para interagir com o modelo disponibilizado e recuperar previsões.
Fazer o download e compilar o pipeline
Nesta seção, veremos como compilar uma definição de pipeline. A primeira coisa que precisamos fazer é instalar o SDK do KFP. Execute o seguinte comando no Cloud Shell:
pip3 install -U kfp
Para fazer o download do arquivo de definição do pipeline, execute este comando no Cloud Shell:
curl -O https://raw.githubusercontent.com/amygdala/kubeflow-examples/ghsumm/github_issue_summarization/pipelines/example_pipelines/gh_summ_hosted_kfp.py
Em seguida, compile o arquivo de definição do pipeline executando-o desta forma:
python3 gh_summ_hosted_kfp.py
Você verá o arquivo gh_summ_hosted_kfp.py.tar.gz
como resultado.
Fazer upload do pipeline compilado
Na IU da Web do Kubeflow Pipelines, clique em Fazer upload do pipeline e selecione Importar por URL. Copie e cole o URL a seguir, que aponta para o mesmo pipeline que você acabou de compilar. Temos algumas etapas extras para fazer upload de um arquivo do Cloud Shell, então vamos usar um atalho.
Dê um nome ao pipeline (por exemplo, gh_summ
).
Executar o pipeline
Clique no pipeline enviado na lista para visualizar o gráfico estático dele. Em seguida, clique em Criar experimento para criar um novo Experimento usando o pipeline. Um experimento é uma maneira de agrupar execuções semanticamente relacionadas.
Dê um nome ao experimento (por exemplo, o mesmo nome do pipeline, gh_summ
) e clique em Próxima para criá-lo.
Isso abrirá uma página em que você pode inserir os parâmetros para uma execução e iniciá-la.
Execute os comandos a seguir no Cloud Shell para preencher os parâmetros.
gcloud config get-value project echo "gs://${BUCKET_NAME}/codelab"
O nome da execução vai ser preenchido automaticamente, mas é possível mudar o nome.
Em seguida, preencha três campos de parâmetro:
project
- (opcional)
github-token
working-dir
Para o work-dir, insira algum caminho no bucket do GCS que você criou. Incluir o "gs://
" . No campo github-token
, insira o token que você gerou anteriormente ou deixe a string do marcador como está se não tiver gerado um token.
Depois de preencher os campos, clique em Start e na execução listada para ver os detalhes. Enquanto uma determinada etapa do pipeline está em execução, é possível clicar nela para ver mais informações sobre ela, inclusive os registros do pod. Também é possível visualizar os registros de uma etapa do pipeline pelo link para os registros do Cloud Logging (Stackdriver), mesmo que o nó do cluster tenha sido removido.
Veja a definição do pipeline
Enquanto o pipeline está em execução, analise como ele é montado e o que está fazendo. Há mais detalhes na seção Apêndice do codelab.
Veja informações de treinamento de modelo no TensorBoard
Quando a etapa de treinamento terminar, selecione a guia Visualizações e clique no botão azul Iniciar o TensorBoard. Quando estiver tudo pronto, clique em Abrir o TensorBoard.
Explore o painel de Artefatos e Execuções
O Kubeflow Pipelines registra automaticamente metadados sobre as etapas do pipeline conforme um pipeline é executado. As informações de Artifact e Execution são registradas. Clique nessas entradas na barra de navegação esquerda do painel para explorar mais.
Em Artefatos, é possível ter um painel de visão geral e um painel do Lineage Explorer.
Abra o app da Web criado pelo pipeline e faça algumas previsões
A última etapa do pipeline implanta um app da Web, que fornece uma IU para consultar o modelo treinado, disponibilizado pelo TF Serving, para fazer previsões.
Após a conclusão do pipeline, conecte-se ao app da Web encaminhando portas ao serviço dele. Estamos encaminhando portas porque, neste codelab, o serviço do app da Web não está configurado para ter um endpoint externo.
Execute este comando no Cloud Shell para encontrar o nome do serviço:
kubectl get services
Procure um nome de serviço como este: ghsumm-*-webappsvc
na lista.
No Cloud Shell, faça o encaminhamento de portas para esse serviço da seguinte maneira, alterando o comando a seguir para usar o nome do webappsvc:
kubectl port-forward svc/ghsumm-xxxxx-webappsvc 8080:80
Quando o encaminhamento de portas estiver em execução, clique em "preview" acima do painel do Cloud Shell e, no menu suspenso, clique em "Visualizar na porta 8080".
Uma página como esta vai aparecer em uma nova guia:
Clique no botão Validate Random Issue para recuperar um bloco de texto. Clique em Generate TItle para chamar o modelo treinado e exibir uma previsão.
Se os parâmetros do pipeline incluírem um token GitHub válido, insira um URL do GitHub no segundo campo e clique em "Gerar título". Se você não tiver configurado um token do GitHub válido, use apenas a opção "Preencher Random Issue" .
4. executar um pipeline de um notebook do AI Platform
Também é possível definir e executar o Kubeflow Pipelines de forma interativa em um notebook do Jupyter usando o SDK do KFP. O AI Platform Notebooks, que usaremos neste codelab, simplifica bastante o processo.
Criar uma instância de notebook
Vamos criar uma instância de notebook no Cloud Shell usando sua API. Também é possível criar um notebook por meio do console do Cloud. Para mais informações, consulte a documentação.
Defina as variáveis de ambiente a seguir no Cloud Shell:
export INSTANCE_NAME="kfp-ghsumm" export VM_IMAGE_PROJECT="deeplearning-platform-release" export VM_IMAGE_FAMILY="tf2-2-3-cpu" export MACHINE_TYPE="n1-standard-4" export LOCATION="us-central1-c"
Em seguida, no Cloud Shell, execute o comando para criar a instância do notebook:
gcloud beta notebooks instances create $INSTANCE_NAME \ --vm-image-project=$VM_IMAGE_PROJECT \ --vm-image-family=$VM_IMAGE_FAMILY \ --machine-type=$MACHINE_TYPE --location=$LOCATION
Ao executar esse comando pela primeira vez, talvez seja necessário ativar a API notebooks
para o projeto. Responda "y
" se for o caso.
Após alguns minutos, o servidor de notebook estará ativo e em execução. Confira suas instâncias de notebook listadas no console do Cloud.
Fazer upload do notebook do codelab
Depois que a instância do notebook for criada, clique neste link para fazer upload do notebook do Jupyter do codelab. Selecione a instância de notebook a ser usada. O notebook será aberto automaticamente.
Executar o notebook
Siga as instruções do notebook durante o laboratório. No menu "Configuração", do notebook, você precisará preencher seus próprios valores antes de executar o restante do notebook.
Se estiver usando seu próprio projeto, não se esqueça de retornar e fazer a seção "Limpar" deste laboratório.
5. Limpar
Não é necessário fazer isso se você estiver usando uma conta temporária do codelab, mas é recomendável encerrar a instalação do Pipelines e o Notebook se estiver usando seu próprio projeto.
Remover o cluster do GKE de pipelines
É possível excluir o cluster de pipelines do Console do Cloud. Você tem a opção de excluir a instalação do Pipelines se quiser reutilizar o cluster do GKE.
Exclua a instância do notebook de IA
Se você executou o "Notebook" como EXCLUIR ou INTERROMPER a instância do notebook no console do Cloud.
Opcional: remover o token do GitHub
Navegue até https://github.com/settings/tokens e remova o token gerado.
6. Anexos
Uma olhada no código
Como definir o pipeline
O pipeline usado neste codelab está definido aqui.
Vamos dar uma olhada em como ele é definido e como seus componentes (etapas) são definidos. Vamos abordar alguns destaques, mas consulte a documentação para saber mais.
As etapas do Kubeflow Pipelines são baseadas em contêineres. Ao criar um pipeline, é possível usar componentes pré-criados, com imagens de contêiner já criadas, ou criar seus próprios componentes. Neste codelab, criamos o nosso próprio.
Quatro das etapas do pipeline são definidas a partir de componentes reutilizáveis, acessados por meio dos respectivos arquivos de definição de componentes. Neste primeiro snippet de código, estamos acessando esses arquivos de definição de componente por meio de seu URL e usando essas definições para criar "ops" que usaremos para criar uma etapa do pipeline.
import kfp.dsl as dsl
import kfp.gcp as gcp
import kfp.components as comp
...
copydata_op = comp.load_component_from_url(
'https://raw.githubusercontent.com/kubeflow/examples/master/github_issue_summarization/pipelines/components/t2t/datacopy_component.yaml'
)
train_op = comp.load_component_from_url(
'https://raw.githubusercontent.com/kubeflow/examples/master/github_issue_summarization/pipelines/components/t2t/train_component.yaml'
)
Confira abaixo uma das definições de componente para a operação de treinamento no formato yaml. Observe que as entradas, saídas, a imagem do contêiner e os args de ponto de entrada do contêiner estão definidos.
name: Train T2T model
description: |
A Kubeflow Pipeline component to train a Tensor2Tensor
model
metadata:
labels:
add-pod-env: 'true'
inputs:
- name: train_steps
description: '...'
type: Integer
default: 2019300
- name: data_dir
description: '...'
type: GCSPath
- name: model_dir
description: '...'
type: GCSPath
- name: action
description: '...'
type: String
- name: deploy_webapp
description: '...'
type: String
outputs:
- name: launch_server
description: '...'
type: String
- name: train_output_path
description: '...'
type: GCSPath
- name: MLPipeline UI metadata
type: UI metadata
implementation:
container:
image: gcr.io/google-samples/ml-pipeline-t2ttrain:v3ap
args: [
--data-dir, {inputValue: data_dir},
--action, {inputValue: action},
--model-dir, {inputValue: model_dir},
--train-steps, {inputValue: train_steps},
--deploy-webapp, {inputValue: deploy_webapp},
--train-output-path, {outputPath: train_output_path}
]
env:
KFP_POD_NAME: "{{pod.name}}"
fileOutputs:
launch_server: /tmp/output
MLPipeline UI metadata: /mlpipeline-ui-metadata.json
Também é possível definir uma etapa do pipeline usando o construtor dsl.ContainerOp
, como veremos abaixo.
Veja abaixo a maior parte da definição do pipeline. Vamos definir as entradas do pipeline (e os valores padrão delas). Em seguida, definimos as etapas do pipeline. Para a maioria, usamos o botão "ops" definido acima, mas também definimos um etapa inline usando ContainerOp
, especificando a imagem do contêiner e os argumentos de ponto de entrada diretamente.
Observe que as etapas train
, log_model
e serve
estão acessando as saídas das etapas anteriores como entradas. Leia mais sobre como isso é especificado aqui.
@dsl.pipeline(
name='Github issue summarization',
description='Demonstrate Tensor2Tensor-based training and TF-Serving'
)
def gh_summ( #pylint: disable=unused-argument
train_steps: 'Integer' = 2019300,
project: str = 'YOUR_PROJECT_HERE',
github_token: str = 'YOUR_GITHUB_TOKEN_HERE',
working_dir: 'GCSPath' = 'gs://YOUR_GCS_DIR_HERE',
checkpoint_dir: 'GCSPath' = 'gs://aju-dev-demos-codelabs/kubecon/model_output_tbase.bak2019000/',
deploy_webapp: str = 'true',
data_dir: 'GCSPath' = 'gs://aju-dev-demos-codelabs/kubecon/t2t_data_gh_all/'
):
copydata = copydata_op(
data_dir=data_dir,
checkpoint_dir=checkpoint_dir,
model_dir='%s/%s/model_output' % (working_dir, dsl.RUN_ID_PLACEHOLDER),
action=COPY_ACTION,
)
train = train_op(
data_dir=data_dir,
model_dir=copydata.outputs['copy_output_path'],
action=TRAIN_ACTION, train_steps=train_steps,
deploy_webapp=deploy_webapp
)
serve = dsl.ContainerOp(
name='serve',
image='gcr.io/google-samples/ml-pipeline-kubeflow-tfserve:v6',
arguments=["--model_name", 'ghsumm-%s' % (dsl.RUN_ID_PLACEHOLDER,),
"--model_path", train.outputs['train_output_path']
]
)
train.set_gpu_limit(1)
Observe que estamos exigindo a função "train" a ser executada em um nó do cluster que tenha pelo menos uma GPU disponível.
train.set_gpu_limit(1)
A etapa final no pipeline, também definida in-line, é condicional. Ela será executada após "serve
" etapa for concluída, somente se a saída da etapa de treinamento launch_server
for a string "true". Ele inicia o "app da Web de previsão", que usamos para solicitar resumos de problemas do modelo T2T treinado.
with dsl.Condition(train.outputs['launch_server'] == 'true'):
webapp = dsl.ContainerOp(
name='webapp',
image='gcr.io/google-samples/ml-pipeline-webapp-launcher:v1',
arguments=["--model_name", 'ghsumm-%s' % (dsl.RUN_ID_PLACEHOLDER,),
"--github_token", github_token]
)
webapp.after(serve)
As definições da imagem do contêiner do componente
A documentação do Kubeflow Pipelines descreve algumas práticas recomendadas para criar seus próprios componentes. Como parte desse processo, você precisará definir e criar uma imagem de contêiner. Confira as etapas do componente para o pipeline deste codelab aqui. As definições do Dockerfile estão nos subdiretórios containers
, por exemplo: aqui.
Usar VMs preemptivas com GPUs para treinamento
VMs preemptivas são instâncias de VM do Compute Engine que duram no máximo 24 horas e não oferecem garantias de disponibilidade. O preço das VMs preemptivas é menor do que o das VMs padrão do Compute Engine.
Com o Google Kubernetes Engine (GKE), é fácil configurar um cluster ou pool de nós que usa VMs preemptivas. É possível configurar esse pool de nós com GPUs anexadas às instâncias preemptivas. Eles funcionam da mesma forma que os nós normais ativados para GPU, mas as GPUs persistem apenas durante a vida útil da instância.
Para configurar um pool de nós preemptivo e ativado para GPU no cluster, execute um comando semelhante ao seguinte, edite o comando a seguir com o nome e a zona do cluster e ajuste o tipo e a contagem do acelerador de acordo com os requisitos. Também é possível definir o pool de nós para escalonamento automático com base nas cargas de trabalho atuais.
gcloud container node-pools create preemptible-gpu-pool \
--cluster=<your-cluster-name> \
--zone <your-cluster-zone> \
--enable-autoscaling --max-nodes=4 --min-nodes=0 \
--machine-type n1-highmem-8 \
--preemptible \
--node-taints=preemptible=true:NoSchedule \
--scopes cloud-platform --verbosity error \
--accelerator=type=nvidia-tesla-k80,count=4
Também é possível configurar um pool de nós usando o Console do Cloud.
Como definir um pipeline do Kubeflow que usa os nós preemptivos do GKE
Se você estiver executando o Kubeflow no GKE, agora será fácil definir e executar o Kubeflow Pipelines, em que uma ou mais etapas (componentes) do pipeline são executadas em nós preemptivos, reduzindo o custo de execução de um job. Para que as VMs preemptivas forneçam resultados corretos, as etapas identificadas como preemptivas precisam ser idempotentes (ou seja, se você executar uma etapa várias vezes, ela terá o mesmo resultado), ou o checkpoint, será necessário que o checkpoint funcione para que a etapa possa continuar de onde parou se for interrompida.
Ao definir um pipeline do Kubeflow, é possível indicar que uma determinada etapa precisa ser executada em um nó preemptivo modificando a operação da seguinte maneira:
your_pipelines_op.apply(gcp.use_preemptible_nodepool())
Confira mais detalhes na documentação.
Provavelmente, também será necessário repetir a etapa algumas vezes se o nó passar por uma interrupção forçada. Você pode fazer isso da seguinte maneira. Aqui, estamos especificando cinco novas tentativas.
your_pipelines_op.set_gpu_limit(1).apply(gcp.use_preemptible_nodepool()).set_retry(5)
Edite o pipeline do Kubeflow que usamos neste codelab para executar a etapa de treinamento em uma VM preemptiva.
Altere a linha a seguir na especificação do pipeline para usar adicionalmente um pool de nós preemptivo (verifique se você criou um conforme indicado acima) acima e tente novamente cinco vezes:
train.set_gpu_limit(1)
Em seguida, recompile o pipeline, faça upload da nova versão (atribua um novo nome) e execute a nova versão.