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. Você fornece a especificação no momento da criação de um serviço.

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: <amount-of-memory>
          nvidia.com/gpu: <count>
          cpu: <cpu-units>
        limits:
          memory: <amount-of-memory>
          nvidia.com/gpu: <count>
          cpu: <cpu-units>
    secrets:                                # optional list
      - snowflakeSecret:
          objectName: <object-name>         # specify this or objectReference
          objectReference: <reference-name> # specify this or objectName
        directoryPath: <path>               # specify this or envVarName
        envVarName: <name>                  # specify this or directoryPath
        secretKeyRef: username | password | secret_string # specify only with envVarName
  endpoints:                             # optional endpoint list
    - name: <name>
      port: <TCP port-num>                     # specify this or portRange
      portRange: <TCP port-num>-<TCP port-num> # specify this or port
      public: <true / false>
      protocol : < TCP / HTTP / HTTPS >
    - name: <name>
      ...
  volumes:                               # optional volume list
    - name: <name>
      source: local | @<stagename> | memory | block
      size: <bytes-of-storage>           # specify if memory or block is the volume source
      blockConfig:                       # optional
        initialContents:
          fromSnapshot: <snapshot-name>
        iops: <number-of-operations>
        throughput: <MiB per second>
      uid: <UID-value>                   # optional, only for stage volumes
      gid: <GID-value>                   # optional, only for stage volumes
    - name: <name>
      source: local | @<stagename> | memory | block
      size: <bytes-of-storage>           # specify if memory or block is the volume source
      ...
  logExporters:
    eventTableConfig:
      logLevel: <INFO | ERROR | NONE>
  platformMonitor:                      # optional, platform metrics to log to the event table
    metricConfig:
      groups:
      - <group-1>
      - <group-2>
      ...
serviceRoles:                   # Optional list of service roles
- name: <service-role-name>
  endpoints:
  - <endpoint_name1>
  - <endpoint_name2>
  - ...
- ...
Copy

Observe que spec e serviceRoles são os campos de nível superior na especificação.

  • spec: Use este campo para fornecer detalhes de especificação. Inclui estes campos de nível superior:

    • spec.containers (obrigatório): Uma lista de um ou mais contêineres de aplicativo. 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 tornar 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 os contêineres usarem.

    • spec.logExporters (opcional): Este campo gerencia o nível de logs de contêiner exportados para a tabela de evento em sua conta.

  • serviceRoles: Use este campo para definir uma ou mais funções de serviço. A função de serviço é o mecanismo que você usa para gerenciar privilégios para pontos de extremidade que o serviço expõe.

Diretrizes gerais

  • 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 caracteres -.

    • Deve começar com um caractere alfabético.

    • Deve terminar com um caractere alfanumérico.

  • Os clientes devem garantir que nenhum dado pessoal, 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)

Use o campo spec.containers para descrever cada um dos contêineres de OCI em seu aplicativo.

Observe o seguinte:

  • Quando você cria um serviço, o Snowflake executa esses contêineres em um único nó no pool de computação especificado, compartilhando a mesma interface de rede.

  • É possível optar por executar várias instâncias de serviço para balancear a carga das solicitações recebidas. O Snowflake pode optar por executar essas instâncias de serviço no mesmo nó ou em nós diferentes no pool de computação especificado. Todos os contêineres de uma determinada instância sempre são executados em um nó.

  • Atualmente, o Snowpark Container Services requer imagens da plataforma Linux/AMD64.

As seções a seguir explicam os tipos de campos de contêineres.

Campos containers.name e containers.image

Para cada contêiner, apenas os campos nome e imagem são obrigatórios.

  • name é o nome da imagem. Este nome pode ser usado para identificar um contêiner específico para fins de observabilidade (por exemplo, logs, metrics).

  • image é o 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
Copy

Campos containers.command e containers.args

Use esses campos opcionais para controlar qual executável é iniciado em seu contêiner e os argumentos que são passados para esse executável. É possível configurar padrões para eles no momento da criação da imagem, normalmente em um Dockerfile. Usar esses campos de especificação de serviço permite que você altere esses padrões (e, assim, altere o comportamento do contêiner) sem precisar reconstruir sua imagem de contêiner:

  • containers.command substitui o Dockerfile ENTRYPOINT. Isso permite que você execute um executável diferente no contêiner.

  • containers.args substitui o Dockerfile 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"]
Copy

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
    
    Copy
  • Para substituir o argumento “Bob”, adicione o campo containers.args no arquivo de especificação:

    spec:
      containers:
      - name: echo
        image: <image_name>
        args:
          - Alice
    
    Copy

Campo containers.env

Use o campo containers.env para definir variáveis de ambiente do contêiner. Todos os processos no contêiner têm acesso a estas variáveis de ambiente:

spec:
  containers:
  - name: <name>
    image: <image_name>
    env:
      ENV_VARIABLE_1: <value1>
      ENV_VARIABLE_2: <value2>
      
      
Copy

Exemplo

No Tutorial 1, o código do aplicativo (echo_service.py) lê as variáveis de ambiente conforme mostrado:

CHARACTER_NAME = os.getenv('CHARACTER_NAME', 'I')
SERVER_PORT = os.getenv('SERVER_PORT', 8080)
Copy

Observe que o exemplo passa valores padrão das variáveis para a função getenv. Se as variáveis de ambiente não forem definidas, esses padrões serão usados.

  • 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.

A especificação de serviço a seguir substitui esses dois valores de variável de ambiente:

spec:
  containers:
  - name: echo
    image: <image_name>
    env:
      CHARACTER_NAME: Bob
      SERVER_PORT: 8085
  endpoints:
  - name: echo-endpoint
    port: 8085
Copy

Observe que, como você alterou o número da porta em que seu serviço escuta, a especificação também deve atualizar o ponto de extremidade (valor endpoints.port field), conforme mostrado.

Campo containers.readinessProbe

Use o campo containers.readinessProbe para identificar uma sonda 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():
Copy

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
Copy

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

Um pool de computação define um conjunto de recursos disponíveis (CPU, memória e armazenamento) e o Snowflake determina onde no pool de computação seus serviços serão executados.

É recomendável indicar explicitamente os requisitos de recurso para o contêiner específico 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.

Use o campo containers.resources para especificar requisitos de recurso explícitos para o contêiner de aplicativo específico:

  • containers.resources.requests: As solicitações que você especificar devem ser o uso médio de recurso que você prevê para seu serviço. O Snowflake usa essas informações para determinar o posicionamento da instância de serviço no pool de computação. O Snowflake garante que a soma das solicitações de recurso colocadas em um determinado nó se ajuste aos recursos disponíveis no nó.

  • containers.resources.limits: Os limites especificados determinam que o Snowflake não aloque recursos maiores que os limites especificados. Assim, você pode evitar custos excedentes.

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. É possível usar unidades decimais ou binárias para expressar os valores. Por exemplo, 2G representa uma solicitação de 2.000.000.000 bytes e 2Gi representa uma solicitação de 2 × 1.024 × 1.024 × 1.024 bytes.

    Ao especificar memória, é necessária uma unidade. Por exemplo, 100M ou 5Gi. As unidades suportadas são: M, Mi, G, Gi.

  • 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.

  • nvidia.com/gpu: se GPUs forem necessários, eles deverão ser solicitados e também deverá haver um limit 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 é possível solicitar é limitado pelo máximo de GPUs compatível com o INSTANCE_TYPE que você escolhe ao criar um pool de computação.

resource.requests e resource.limits são relativos à capacidade do nó (vCPU e memória) da família de instâncias do pool de computação associado.

  • Se uma solicitação de recurso (CPU, memória ou ambos) não for fornecida, o Snowflake deriva uma para você:

    • Para cpu, o valor derivado é 0,5 ou o limite de cpu fornecido, o que for menor.

    • Para memory, o valor derivado é 0,5 GiB ou o limite de memory fornecido, o que for menor.

  • Se um limite de recurso (CPU, memória ou ambos) não for fornecido, o Snowflake definirá os limites como padrão para a capacidade do nó para a família de instância do pool de computação associado.

  • Se você fornecer resource.limits e eles excederem a capacidade do nó, o Snowflake limitará a capacidade do nó.

  • O Snowflake avalia esses requisitos de recurso de forma independente para cpu e memory.

Observe que, se for teoricamente impossível para o Snowflake agendar o serviço no pool de computação fornecido, CREATE SERVICE falhará. Teoricamente impossível pressupõe que o pool de computação tenha o número máximo de nós permitidos e não haja outros serviços em execução no pool de computação. Ou seja, não há como o Snowflake alocar os recursos solicitados dentro dos limites do pool de computação. Se for teoricamente possível, mas os recursos necessários estiverem em uso, então CREATE SERVICE será bem-sucedido. Algumas instâncias de serviço relatarão o status indicando que o serviço não pode ser agendado devido a recursos insuficientes até que os recursos estejam disponíveis.

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
Copy

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

Suponha o seguinte:

  • Você cria um pool de computação de dois nós; cada nó tem 27 GB de memória e uma GPU:

    CREATE COMPUTE POOL tutorial_compute_pool
      MIN_NODES = 2
      MAX_NODES = 2
      INSTANCE_FAMILY = gpu_nv_s
    
    Copy
  • 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>;
    
    Copy

    Tanto MIN_INSTANCES quanto MAX_INSTANCES estão definidos como 2. Portanto, o Snowflake executará duas instâncias do serviço.

Agora, considere estes cenários:

  • Se o seu serviço não incluir explicitamente os requisitos de recurso 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 recurso na especificação do serviço e solicita 10 GB de memória para o contêiner:

    - name: resource-test
      image: ...
      resources:
        requests:
          memory: 15G
    
    Copy

    O nó do pool de computação tem 27 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.

  • Você inclui requisitos de recurso na especificação do serviço e solicita 1 GB de memória e uma 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
    
    Copy

    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 ambas as instâncias de serviço 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:
      objectName: <object-name>         # specify this or objectReference
      objectReference: <reference-name> # specify this or objectName
    directoryPath: <path>               # specify this or envVarName
    envVarName: <name>                  # specify this or directoryPath
    secretKeyRef: username | password | secret_string # specify only with envVarName
  - snowflakeSecret: <object-name>      # equivalent to snowflakeSecret.objectName
    ...
Copy

Use o campo containers.secrets em sua especificação de serviço para fornecer credenciais gerenciadas pelo Snowflake aos seus contêineres de aplicativo. Comece armazenando as credenciais em objetos secretos do Snowflake. Em seguida, na especificação do serviço, faça referência ao objeto secreto e especifique onde colocar as credenciais dentro do contêiner.

A seguir está um resumo de como usar os campos containers.secrets:

  • Especificar segredo do Snowflake: Use campo snowflakeSecret para especificar um nome de objeto ou uma referência de objeto do segredo do Snowflake. Referências de objeto são aplicáveis ao usar o Snowpark Container Services para criar um Native App (um aplicativo com contêineres).

    • Use secretKeyRef para fornecer o nome da chave no segredo do Snowflake.

  • Especifique o posicionamento do segredo no contêiner do aplicativo: Use o campo envVarName para passar o segredo como variáveis de ambiente ou directoryPath para gravar os segredos em arquivos do contêiner locais.

Para obter mais informações, consulte Como passar credenciais para um contêiner usando segredos do Snowflake.

Observe que a função que está criando o serviço (função do proprietário) precisará do privilégio READ sobre os segredos referenciados.

Campo spec.endpoints (opcional)

Use o campo spec.endpoints para especificar uma lista de portas de rede TCP que seu aplicativo expõe. Um serviço pode expor de zero a vários pontos de extremidade. Use os seguintes campos para descrever um ponto de extremidade:

  • name: nome exclusivo do ponto de extremidade. O nome é usado para identificar o ponto de extremidade na especificação da função de serviço e da função de serviço.

  • port: A porta de rede na qual seu serviço está escutando. É necessário especificar este campo ou o campo portRange.

  • portRange: O intervalo de porta de rede em que seu aplicativo está escutando. É necessário especificar este campo ou o campo port.

    Observe que só é possível especificar o campo portRange se campo protocol estiver definido como TCP e o campo public for falso.

  • public: se você quiser que esse ponto de extremidade seja acessível pela internet, defina esse campo como true. Os pontos de extremidade públicos não são suportados com o protocolo TCP.

  • protocol: o protocolo suportado pelo ponto de extremidade. Os valores aceitos são TCP, HTTP e HTTPS. Por padrão, o protocolo é HTTP. Ao especificar o protocol, o seguinte é aplicado:

    • Quando este ponto de extremidade for público ou o destino de uma função de serviço (consulte Como usar um serviço), o protocolo deve ser HTTP ou HTTPS.

    • Os serviços de trabalho exigem que todos os pontos de extremidade especificados usem o protocolo TCP; protocolos HTTP/HTTPS não são suportados.

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. O acesso público a um ponto de extremidade requer autenticação Snowflake. O usuário autenticado também deve ter autorização para este ponto de extremidade do servidor (o usuário tem permissão de uso de uma função que tem acesso ao ponto de extremidade).

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
Copy

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 de especificação spec.volumes e spec.containers.volumeMounts porque eles estão intimamente relacionados.

  • spec.volumes define um sistema de arquivo compartilhado. Esses volumes podem ser disponibilizados em seus contêineres.

  • spec.containers.volumeMount define onde um volume aparece em contêineres específicos.

Observe que o campo volumes é especificado no nível spec, mas como vários contêineres podem compartilhar o mesmo volume, volumeMounts se torna um campo de nível spec.containers.

Use esses campos para descrever os volumes e montagens de volume

  • spec.volumes: Pode haver zero ou mais volumes. Use os seguintes campos para descrever um volume:

    • Campos obrigatórios para todos os tipos de volume:

      • name: nome exclusivo do volume. É referido por spec.containers.volumeMounts.name.

      • source: isso pode ser local, memory, block ou "@<nome do estágio>". A próxima seção explica esses tipos de volume.

      • size (obrigatório apenas para os tipos de volume memory e block): Para volumes de memória e bloco, este é o tamanho do volume em bytes. Para armazenamento em bloco, o valor deve ser sempre um inteiro, especificado usando o sufixo da unidade Gi. Por exemplo, 5Gi significa 5*1024*1024*1024 bytes.

    • Para o tipo de volume block, é possível especificar os seguintes campos opcionais. Para obter mais informações, consulte Especificação do armazenamento em bloco na especificação de serviço.

      • blockConfig.initialContents.fromSnapshot: Especifique um instantâneo tirado anteriormente de outro volume para inicializar o volume do bloco. O instantâneo deve estar no estado CREATED antes de poder ser usado para criar um volume, caso contrário, a criação do serviço falhará. Use o comando DESCRIBE SNAPSHOT para obter o status do instantâneo.

      • blockConfig.iops: Especifique o número de operações de entrada/saída de pico compatíveis por segundo. O intervalo compatível é de 3.000 a 16.000 no AWS e de 3.000 a 80.000 no Azure, com um padrão de 3.000. Observe que o tamanho dos dados por operação é limitado a 256 KiB para volumes de bloco.

      • blockConfig.throughput: Especifique o pico de taxa de transferência, em MiB/segundo, para provisionar o volume. O intervalo compatível é de 125 a 1.000 no AWS e de 125 a 1.200 no Azure, com um padrão de 125.

  • spec.containers.volumeMounts: Cada contêiner pode ter zero ou mais montagens de volume. 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.

Sobre os tipos de volume suportados

O Snowflake oferece suporte a estes tipos de volume para uso pelos contêineres de aplicativos: local, memória, bloco e estágio do 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.

  • Bloco: os contêineres também podem usar volumes de armazenamento em bloco. Para obter mais informações, consulte Uso de volumes de armazenamento em bloco com serviços.

  • Estágio Snowflake: Também é possível dar aos contêineres acesso conveniente aos arquivos em um estágio Snowflake em sua conta. Para obter mais informações, consulte Usando volumes de estágio Snowflake com serviços.

Exemplo

Seu aplicativo de machine learning inclui os dois contêineres a seguir:

  • Um contêiner app para o aplicativo principal

  • Um 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"
Copy

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
Copy

Observe que ao especificar memory como o volume source, também é necessário 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.

Sobre permissões de arquivo em volumes montados

Um contêiner que monta um estágio Snowflake ou um volume de armazenamento em bloco normalmente é executado como um usuário raiz. 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 ID do usuário (UID) e o ID de grupo (GID) 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>
Copy

Snowflake usa essas informações para montar o estágio com as permissões apropriadas.

Para obter o UID e GID do contêiner, faça o seguinte:

  1. Execute o contêiner localmente usando docker run.

  2. 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…"
    
  3. Execute o comando docker id dentro do contêiner para obter UID e GID:

    docker exec -it <container-id> id
    
    Copy

    Exemplo de saída:

    uid=0(root) gid=0(root) groups=0(root)
    

Campo spec.logExporters (opcional)

O Snowflake coleta a saída de seus aplicativos para saída padrão ou erro padrão. Para obter mais informações, consulte Acessando logs de contêiner locais. Use spec.logExporters para configurar quais dessas saídas o Snowflake exporta para sua tabela de evento.

logExporters:
  eventTableConfig:
    logLevel: < INFO | ERROR | NONE >
Copy

Os valores logLevel aceitos são:

  • INFO (padrão): exporte todos os logs do usuário.

  • ERROR: exporte apenas os logs de erros. Snowflake exporta apenas os logs do fluxo stderr.

  • NONE: não exporte logs para a tabela de eventos.

Campo spec.platformMonitor (opcional)

Serviços individuais publicam métricas. Essas métricas fornecidas pelo Snowflake também são chamadas de métricas da plataforma. Adicione o campo spec.platformMonitor na especificação para direcionar o Snowflake a enviar métricas do serviço para a tabela de evento configurada para sua conta. O caso de uso destino para isso é observar a utilização de recurso de um serviço específico.

platformMonitor:
  metricConfig:
    groups:
    - <group_1>
    - <group_2>
    ...
Copy

group_N refere-se a grupos de métricas predefinidos nos quais você está interessado. Enquanto o serviço está em execução, o Snowflake registra métricas a partir de grupos especificados na tabela de evento. É possível então consultar as métricas da tabela de evento. Para obter mais informações, consulte Serviços de monitoramento.

Sobre as unidades

Uma especificação de serviço assume valores numéricos em vários lugares. Uma variedade de unidades é compatível 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 significa number*1024. Por exemplo, 4Ki é equivalente a 4096.

    • numberMi significa number*1024*1024.

    • numberGi significa number*1024*1024*1024.

  • Unidades decimais:

    • numberk significa number*1000. Por exemplo, 4k é equivalente a 4000.

    • numberM significa number*1000*1000.

    • numberG significa number*1000*1000*1000.

  • Unidades fracionárias:

    • numberm significa number*0.001. Por exemplo, cpu: 500m é equivalente a cpu: 0.5.

Campo serviceRoles (opcional)

Use o campo de nível superior serviceRoles na especificação para definir uma ou mais funções de serviço. Para cada função de serviço, forneça um nome e uma lista de um ou mais pontos de extremidade (definidos na seção spec.endpoints) aos quais você deseja que a função de serviço conceda privilégio USAGE.

serviceRoles:                   # Optional list of service roles
- name: <name>
  endpoints:
  - <endpoint-name>
  - <endpoint-name>
  - ...
- ...
Copy

Observe o seguinte:

  • Ambos name e endpoints são obrigatórios.

  • O nome da função de serviço deve seguir o seguinte formato:

    • Deve conter caracteres alfanuméricos ou _.

    • Deve começar com um caractere alfabético.

    • Deve terminar com um caractere alfanumérico.

Para obter mais informações, consulte Gerenciamento do acesso aos pontos de extremidade do servidor.