Referência de especificação de serviço¶
A especificação do Snowpark Container Services está em YAML (https://yaml.org/spec/). Fornece ao Snowflake as informações necessárias para configurar e executar seu serviço ou trabalho.
A sintaxe geral é:
spec:
containers: # container list
- name: <name>
image: <image-name>
command: # optional list of strings
- <cmd>
- <arg1>
args: # optional list of strings
- <arg2>
- <arg3>
- ...
env: # optional
<key>: <value>
<key>: <value>
...
readinessProbe: # optional
port: <TCP port-num>
path: <http-path>
volumeMounts: # optional list
- name: <volume-name>
mountPath: <mount-path>
- name: <volume-name>
...
resources: # optional
requests:
memory: <memory-reserved>
nvidia.com/gpu: <count>
cpu: <cpu-units>
limits:
memory: <memory-reserved>
nvidia.com/gpu: <count>
cpu: <cpu-units>
secrets: # optional list
- snowflakeSecret:
secretKeyRef:
envVarName: # specify this or directoryPath
directoryPath: # specify this or envVarName
endpoints: # optional endpoint list
- name: <name>
port: <TCP port-num>
public: <true / false>
protocol : < TCP / HTTP / HTTPS >
- name: <name>
...
volumes: # optional volume list
- name: <name>
source: local | @<stagename> | memory
size: <amount-of-memory> # specify if memory is the volume source
- name: <name>
source: local | @<stagename> | memory
size: <amount-of-memory> # specify if memory is the volume source
...
logExporters:
eventTableConfig:
logLevel: <INFO | ERROR | NONE>
Diretrizes gerais¶
Uma especificação de serviço/trabalho tem estes campos spec
de nível superior:
spec.containers
(obrigatório): uma lista de um ou mais contêineres de aplicativos. Seu aplicativo conteinerizado deve ter pelo menos um contêiner.spec.endpoints
(opcional): uma lista de pontos de extremidade que o serviço expõe. Você pode escolher um ponto de extremidade público, permitindo acesso de entrada de rede ao serviço.spec.volumes
(opcional): uma lista de volumes de armazenamento para uso pelos contêineres.spec.logExporters
(opcional): este campo gerencia o nível de logs de contêiner exportados para a tabela de eventos em sua conta.
As seguintes diretrizes de formato se aplicam aos campos name
(nomes de contêiner, ponto de extremidade e volume):
Pode ter até 63 caracteres
Pode conter uma sequência de caracteres alfanuméricos minúsculos ou “-”
Deve começar com um caractere alfabético
Deve terminar com um caractere alfanumérico
Atenção
Os clientes devem garantir que nenhum dado pessoal (exceto para um objeto do usuário), dados sensíveis, dados controlados por exportação ou outros dados regulamentados sejam inseridos como metadados no arquivo de especificação. Para obter mais informações, consulte Campos de metadados no Snowflake.
As seções a seguir explicam cada um dos campos spec
de nível superior.
Campo spec.containers
(obrigatório)¶
O campo containers
é uma lista de contêineres OCI no seu aplicativo. Para cada contêiner, apenas name
e image
são campos obrigatórios. O campo image
refere-se ao nome da imagem que você carregou em um repositório de imagens do Snowflake em sua conta Snowflake. Por exemplo:
spec:
containers:
- name: echo
image: /tutorial_db/data_schema/tutorial_repository/echo_service:dev
Quando você cria um serviço (ou trabalho), o Snowflake executa esses contêineres em um único nó no pool de computação especificado, compartilhando a mesma interface de rede. É possível executar diversas instâncias de serviço; nesse caso, cada conjunto desses contêineres em execução é conhecido como Instância de serviço.
Nota
Atualmente, o Snowpark Container Services requer imagens da plataforma Linux/AMD64.
As seções a seguir explicam os tipos de campos containers
.
Campos containers.command
e containers.args
¶
Use estes campos opcionais para substituir o ponto de entrada do contêiner (o comando que o contêiner executa junto com quaisquer parâmetros) definido em Dockerfile
(parte da imagem do seu aplicativo) sem precisar recriar a imagem do seu aplicativo:
containers.command
substitui oDockerfile
ENTRYPOINT
. Isso permite que você execute um executável diferente no contêiner.containers.args
substitui oDockerfile
CMD
. Isso permite fornecer diferentes argumentos ao comando (o executável).
Exemplo
Seu Dockerfile
inclui o seguinte código:
ENTRYPOINT ["python3", "main.py"]
CMD ["Bob"]
Essas entradas Dockerfile
executam o comando python3
e passam dois argumentos: main.py
e Bob
. Você pode substituir esses valores no arquivo de especificação da seguinte forma:
Para substituir ENTRYPOINT, adicione o campo
containers.command
no arquivo de especificação:spec: containers: - name: echo image: <image_name> command: - python3.9 - main.py
Para substituir o argumento “Bob”, adicione o campo
containers.args
no arquivo de especificação:spec: containers: - name: echo image: <image_name> args: - Alice
Campo containers.env
¶
Use o campo containers.env
para especificar variáveis de ambiente que são passadas para todos os processos no seu contêiner:
spec:
containers:
- name: <name>
image: <image_name>
env:
ENV_VARIABLE_1: <value1>
ENV_VARIABLE_2: <value2>
…
…
Exemplo
No Tutorial 1, o código do aplicativo (echo_service.py
) lê as variáveis de ambiente com valores padrão, se o valor não for definido explicitamente.
CHARACTER_NAME = os.getenv('CHARACTER_NAME', 'I')
SERVER_PORT = os.getenv('SERVER_PORT', 8080)
CHARACTER_NAME
: quando o serviço Echo recebe uma solicitação HTTP POST com uma cadeia de caracteres (por exemplo, «Olá»), o serviço retorna «Eu disse Olá». Você pode substituir esse valor padrão no arquivo de especificação. Por exemplo, defina o valor como «Bob»; o serviço Echo retorna uma resposta «Bob disse Olá».SERVER_PORT
: nesta configuração padrão, o serviço Echo escuta na porta 8080. Você pode substituir o valor padrão e especificar outra porta.
O arquivo de especificação a seguir substitui esses dois valores de variáveis de ambiente:
spec:
containers:
- name: echo
image: <image_name>
env:
CHARACTER_NAME: Bob
SERVER_PORT: 8085
endpoints:
- name: echo-endpoint
port: 8085
Observe que, como você alterou o número da porta em que seu serviço escuta, a especificação também atualizou o ponto de extremidade (valor do campo endpoints.port
).
Campo containers.readinessProbe
¶
Use o objeto containers.readinessProbe
para fornecer ao Snowflake uma análise de prontidão em seu aplicativo. Snowflake chama essa investigação para determinar quando seu aplicativo está pronto para atender solicitações.
Snowflake faz uma solicitação HTTP GET para a análise de prontidão especificada, na porta e no caminho especificados, e procura que seu serviço retorne um status HTTP 200 OK para garantir que apenas contêineres íntegros tenham tráfego.
Use os seguintes campos para fornecer as informações necessárias:
port
: a porta de rede na qual o serviço está atendendo às solicitações de análise de prontidão. Você não precisa declarar esta porta como um ponto de extremidade.path
: Snowflake faz solicitações HTTP GET ao serviço com este caminho.
Exemplo
No Tutorial 1, o código do aplicativo (echo_python.py
) implementa a seguinte análise de prontidão:
@app.get("/healthcheck")
def readiness_probe():
Assim, o arquivo de especificação inclui o campo containers.readinessProbe
:
spec:
containers:
- name: echo
image: <image_name>
env:
SERVER_PORT: 8088
CHARACTER_NAME: Bob
readinessProbe:
port: 8088
path: /healthcheck
endpoints:
- name: echo-endpoint
port: 8088
A porta especificada pela análise de prontidão não precisa ser um ponto de extremidade configurado. Seu serviço pode escutar em uma porta diferente apenas para fins de análise de prontidão.
Campo containers.volumeMounts
¶
Como os campos spec.volumes
e spec.containers.volumeMounts
funcionam juntos, eles são explicados juntos em uma seção. Para obter mais informações, consulte Campo spec.volumes (opcional).
Campo containers.resources
¶
Snowflake determina como usar os recursos do pool de computação disponíveis para executar seu aplicativo. É recomendável indicar explicitamente os requisitos de recursos para suas instâncias de serviço e definir limites apropriados na especificação. Observe que os recursos especificados são limitados pela família de instâncias dos nós no seu pool de computação. Para obter mais informações, consulte CREATE COMPUTE POOL.
Snowflake garante que os recursos especificados por containers.resources.requests
sejam fornecidos e também evita que o serviço utilize mais do que o containers.resources.limits
indicado. Você pode especificar solicitações e limites para os seguintes recursos:
memory
: esta é a memória necessária para o contêiner do seu aplicativo. Você pode usar unidades decimais ou binárias para expressar os valores. Por exemplo, 2G representa uma solicitação de 2.000.000.000 bytes. Para obter mais informações, consulte Sobre as unidades.cpu
: refere-se a unidades de núcleo virtual (vCPU). Por exemplo, a unidade 1 CPU é equivalente a 1 vCPU. São permitidas solicitações fracionárias, como 0,5, que também pode ser expressa como 500m. Para obter mais informações, consulte Sobre as unidades.nvidia.com/gpu
: se GPUs forem necessários, eles deverão ser solicitados e também deverá haver umlimit
especificado para a mesma quantidade. Se o seu contêiner não especificar solicitações e limites para a capacidade de GPU, ele não poderá acessar GPUs. O número de GPUs que você pode solicitar é limitado pelo máximo de GPUs suportado peloINSTANCE_TYPE
que você escolhe ao criar um pool de computação. Para obter mais informações, consulte CREATE COMPUTE POOL.
Se o Snowflake não puder alocar os recursos incluídos explicitamente no arquivo de especificação, você poderá criar os serviços (usando CREATE SERVICE), mas o status do serviço indicará que o serviço não pode ser agendado devido a recursos insuficientes.
Exemplo 1
Na especificação a seguir, o campo containers.resources
descreve os requisitos de recursos do contêiner:
spec:
containers:
- name: resource-test-gpu
image: ...
resources:
requests:
memory: 2G
cpu: 0.5
nvidia.com/gpu: 1
limits:
memory: 4G
nvidia.com/gpu: 1
Neste exemplo, o Snowflake é solicitado a alocar pelo menos 2 GB de memória, um GPU e meio núcleo CPU para o contêiner. Ao mesmo tempo, o contêiner não pode usar mais de 4 GB de memória e um GPU.
Exemplo 2
Você cria um pool de computação de dois nós; cada nó tem 16 GB de memória e um GPU:
CREATE COMPUTE POOL tutorial_compute_pool MIN_NODES = 2 MAX_NODES = 2 INSTANCE_FAMILY = gpu_nv_s
Você cria um serviço que pede ao Snowflake para executar duas instâncias do serviço:
CREATE SERVICE echo_service MIN_INSTANCES=2 MAX_INSTANCES=2 IN COMPUTE POOL tutorial_compute_pool FROM @<stage_path> SPEC=<spec-file-stage-path>;
Tanto
MIN_INSTANCES
quantoMAX_INSTANCES
estão definidos como 2. Portanto, o Snowflake executará duas instâncias do serviço.
Se você não incluir explicitamente os requisitos de recursos na especificação do aplicativo, o Snowflake decidirá se executará essas instâncias no mesmo nó ou em nós diferentes no pool de computação.
Você inclui requisitos de recursos e solicita 10 GB de memória para o contêiner:
- name: resource-test image: ... resources: requests: memory: 10G
Seu nó do pool de computação tem 16 GB de memória e o Snowflake não pode executar dois contêineres no mesmo nó. O Snowflake executará as duas instâncias de serviço em nós separados no pool de computação.
Solicite 1 GB de memória e um GPU para o contêiner:
spec: containers: - name: resource-test-gpu image: ... resources: requests: memory: 2G nvidia.com/gpu: 1 limits: nvidia.com/gpu: 1
Você está solicitando um GPU por contêiner e cada nó possui apenas um GPU. Nesse caso, embora a memória não seja um problema, o Snowflake não pode agendar ambos os serviços em um nó. Este requisito força o Snowflake a executar as duas instâncias de serviço em dois nós de pool de computação separados.
Campo containers.secrets
¶
secrets: # optional list
- snowflakeSecret:
secretKeyRef:
envVarName: # specify this or directoryPath
directoryPath: # specify this or envVarName
Use containers.secrets
para fornecer objetos de segredo ao Snowflake que o contêiner pode usar para autenticar quando um serviço ou trabalho se comunica com pontos de extremidade externos (fora do Snowflake). Para obter mais informações, consulte Como usar segredos do Snowflake para passar credenciais para um contêiner.
snowflakeSecret
(obrigatório): um nome de objeto do segredo do Snowflake.secretKeyRef
: o nome da chave no segredo. Quando este campo é fornecido, o Snowflake passa o valor associado a esta referência de chave para o contêiner. Necessário para segredos de autenticação básicos montados como variáveis de ambiente. Você especifica esse campo somente ao passar segredos para variáveis de ambiente em contêineres.envVarName
: o nome da variável de ambiente que contém o segredo. Este ou o campodirectoryPath
são obrigatórios.directoryPath
: o caminho do diretório no contêiner onde você deseja copiar os segredos. Snowflake preenche um arquivo para cada chave secreta neste diretório especificado. Ao especificardirectoryPath
, não especifiquesecretKeyRef
. Este ou o campoenvVarName
são obrigatórios.
Para obter mais informações, consulte Como passar segredos do Snowflake para um contêiner.
Campo spec.endpoints
(opcional)¶
Use o campo spec.endpoints
para especificar uma lista de nomes para as portas de rede TCP que seu aplicativo expõe. O Snowpark Container Services pode expor zero a muitos pontos de extremidade. Use os seguintes campos para descrever um ponto de extremidade:
name
: nome exclusivo do ponto de extremidade. Ao se referir ao ponto de extremidade em uma função de serviço, você especifica esse nome.port
: a porta de rede na qual seu aplicativo está escutando.protocol
: o protocolo suportado pelo ponto de extremidade. Os valores aceitos são TCP, HTTP e HTTPS. Por padrão, o protocolo é HTTP. O protocolo deve ser HTTP ou HTTPS quando esse ponto de extremidade for público ou o destino de uma função de serviço (consulte Como usar um serviço).public
: se você quiser que esse ponto de extremidade seja acessível pela internet, defina esse campo comotrue
.
Nota
O Snowflake realiza verificações de autenticação e autorização para acesso público que permite que apenas usuários do Snowflake tenham permissão para usar o serviço.
Exemplo
A seguir está a especificação do aplicativo usada no Tutorial 1:
spec:
container:
- name: echo
image: <image-name>
env:
SERVER_PORT: 8000
CHARACTER_NAME: Bob
readinessProbe:
port: 8000
path: /healthcheck
endpoint:
- name: echoendpoint
port: 8000
public: true
Este contêiner de aplicativo expõe um ponto de extremidade. Também inclui o campo opcional public
para permitir o acesso ao ponto de extremidade de fora do Snowflake (acesso à internet). Por padrão, public
é false
.
Campo spec.volumes
(opcional)¶
Esta seção explica os campos spec.volumes
e spec.containers.volumeMounts
. volumes
define um sistema de arquivos compartilhado. Um volumeMount
define onde um volume aparece em contêineres. Vários contêineres podem compartilhar o mesmo volume. Portanto, volumes
é um campo de nível spec
e volumeMount
faz parte de uma especificação de contêiner.
Use esses campos para descrever os volumes e montagens de volume
Use
spec.volumes
para especificar os volumes disponíveis para seus contêineres.volumes
é uma lista. Ou seja, pode haver vários volumes. Use os seguintes campos para descrever um volume:name
: nome exclusivo do volume. É referido porspec.containers.volumeMounts.name
.source
: pode serlocal
,memory
ou"@<nome do estágio>"
.uid
: para um volume de estágio Snowflake, esse é o uid do arquivo montado.gid
: para um volume de estágio Snowflake, este é o gid do arquivo montado.size
: para um volume de memória, esse é o tamanho do volume.
Use
spec.containers.volumeMounts
para indicar onde os volumes especificados estão montados no sistema de arquivos do contêiner.containers.volumeMounts
também é uma lista. Ou seja, cada contêiner pode ter múltiplas montagens de volume. Use os campos a seguir para descrever uma montagem de volume:name
: o nome do volume a ser montado. Um único contêiner pode fazer referência ao mesmo volume várias vezes.mountPath
: o caminho do arquivo onde o volume do contêiner deve ser montado.
Snowflake oferece suporte a estes tipos de volume para uso de contêineres de aplicativos: volumes locais, memória e estágio Snowflake.
Volume local: os contêineres em uma instância de serviço podem usar um disco local para compartilhar arquivos. Por exemplo, se seu aplicativo tiver dois contêineres—um contêiner de aplicativo e um analisador de logs—, o aplicativo poderá gravar logs no volume local e o analisador de logs poderá ler os logs.
Observe que, se você estiver executando diversas instâncias de um serviço, somente contêineres pertencentes a uma instância de serviço poderão compartilhar volumes. Os contêineres que pertencem a diferentes instâncias de serviço não compartilham volumes.
Memória: você pode usar um sistema de arquivos com suporte de RAM para uso em contêiner.
Estágio Snowflake: você pode criar um estágio Snowflake e fornecer aos contêineres acesso conveniente aos arquivos preparados. As seguintes condições se aplicam quando você monta um estágio Snowflake:
Estágios externos não são suportados. Somente estágios internos do Snowflake com criptografia SSE (consulte Parâmetros do estágio interno) são suportados. Use CREATE STAGE para criar esse estágio:
CREATE STAGE my_stage ENCRYPTION = (type = 'SNOWFLAKE_SSE');
Você pode montar um estágio ou subdiretório, por exemplo,
@my_stage
,@my_stage/folder
, em um estágio. Não é possível montar um arquivo, por exemplo,@my_stage/folder/file
, em um estágio.A função de serviço determina as permissões concedidas aos contêineres para acessar um estágio montado. A função de serviço é a função usada para criar o serviço/trabalho. É também a função que o serviço/trabalho usa para todas as interações do Snowflake.
Por exemplo, se a função de serviço não tiver o privilégio WRITE em um estágio, a montagem desse estágio será somente leitura. Ou seja, os containers só podem ler os arquivos do estágio. Se a função de serviço tiver o privilégio WRITE em um estágio, a montagem desse estágio oferecerá suporte para leitura e gravação. Snowflake carrega atualizações de arquivos de forma assíncrona.
Um contêiner que monta um estágio Snowflake normalmente é executado como um usuário root. No entanto, às vezes o seu contêiner pode ser executado como um usuário não root. Por exemplo:
Se o seu aplicativo usar uma biblioteca de terceiros, a biblioteca usará um usuário não root para executar o código do aplicativo dentro do contêiner.
Por outros motivos, como segurança, você pode executar seu aplicativo como um usuário não root dentro do contêiner.
Para evitar possíveis erros relacionados às permissões do usuário do arquivo, é importante definir o UID (ID do usuário) e o GID (ID do grupo) do contêiner como parte da especificação. Isto é especialmente relevante para contêineres que usam um usuário e grupo específico para iniciar ou executar o aplicativo dentro do contêiner. Ao definir UID e GID apropriados, você pode usar um contêiner em execução como usuário não root. Por exemplo:
spec: ... volumes: - name: stagemount source: "@test" uid: <UID-value> gid: <GID-value>
Snowflake usa essas informações para montar o estágio com as permissões apropriadas.
Para obter UID e GID do contêiner:
Execute o contêiner localmente usando
docker run
.Procure o ID do contêiner usando o comando
docker container list
. Amostra de saída parcial:CONTAINER ID IMAGE COMMAND —---------------------------------------------------------- a6a1f1fe204d tutorial-image "/usr/local/bin/entr…"
Execute o comando
docker id
dentro do contêiner para obter UID e GID:docker exec -it <container-id> id
Exemplo de saída:
uid=0(root) gid=0(root) groups=0(root)
Exemplo
Seu aplicativo de machine learning inclui os dois contêineres a seguir:
Um contêiner
app
para o aplicativo principalUm contêiner
logger-agent
que coleta logs e os carrega no Amazon S3
Esses contêineres usam os dois volumes a seguir:
Volume
local
: este aplicativo grava os logs que o agente de log lê.Estágio do Snowflake,
@model_stage
: o aplicativo principal lê arquivos deste estágio.
Na especificação de exemplo a seguir, o contêiner app
monta os volumes logs
e models
, e o contêiner logging-agent
monta apenas o volume logs
:
spec: containers: - name: app image: <image1-name> volumeMounts: - name: logs mountPath: /opt/app/logs - name: models mountPath: /opt/models - name: logging-agent image: <image2-name> volumeMounts: - name: logs mountPath: /opt/logs volumes: - name: logs source: local - name: models source: "@model_stage"
Se diversas instâncias do serviço estiverem em execução, os contêineres logging-agent
e app
em uma instância de serviço compartilharão o volume logs
. O volume logs
não é compartilhado entre instâncias de serviço.
Se, além desses volumes, seu contêiner app
também usar um volume de memória de 2 GB, revise a especificação para incluir o volume na lista volumes
e também adicione outra montagem de volume nos contêineres app
lista volumeMounts
:
spec: containers: - name: app image: <image1-name> volumeMounts: - name: logs mountPath: /opt/app/logs - name: models mountPath: /opt/models - name: my-mem-volume mountPath: /dev/shm - name: logging-agent image: <image2-name> volumeMounts: - name: logs mountPath: /opt/logs volumes: - name: logs source: local - name: models source: "@model_stage" - name: "my-mem-volume" source: memory size: 2G
Observe que, ao especificar memory
como o volume source
, você também deve especificar o campo volumes.size
para indicar o tamanho da memória. Para obter informações sobre as unidades de tamanho de memória que você pode especificar, consulte Sobre as unidades.
Campo spec.logExporters
(opcional)¶
Use spec.logExporters
para configurar como o Snowflake coleta os logs do seu aplicativo. Snowflake coleta a saída do seu código no contêiner do aplicativo para saída padrão ou erro padrão.
O Snowflake exporta esses registros para uma tabela de eventos na sua conta. Para obter mais informações, consulte Acesso a logs de contêiner locais. Use spec.logExporters.eventTableConfig
para indicar quais logs você deseja salvar na tabela de eventos:
logExporters:
eventTableConfig:
logLevel: < INFO | ERROR | NONE >
Os valores logLevel
aceitos são:
INFO
: exporte todos os logs do usuário.ERROR
: exporte apenas os logs de erros. Snowflake exporta apenas os logs do fluxo stderr.NONE
(padrão): não exporte logs para a tabela de eventos.
Sobre as unidades¶
Uma especificação de serviço assume valores numéricos em vários lugares. O Snowpark Container Services oferece suporte a diversas unidades para expressar esses valores. Para valores grandes e pequenos, você pode usar unidades binárias e decimais conforme mostrado. Na lista a seguir, “#” representa um valor inteiro.
Unidades binárias:
numberKi
significanumber*1024
. Por exemplo,memory: 4Ki
é equivalente amemory: 4096
.numberMi
significanumber*1024^2
.numberGi
significanumber*1024^3
.
Unidades decimais:
numberk
significanumber*10^3
. Por exemplo,memory: 4k
é equivalente amemory: 4000
.numberM
significanumber*10^6
.numberG
significanumber*10^9
.
Unidades fracionárias:
numberm
significanumber*0.001
. Por exemplo,cpu: 500m
é equivalente acpu: 0.5
.