Référence Spécification de service

La spécification Snowpark Container Services se trouve dans YAML (https://yaml.org/spec/). Cela donne à Snowflake les informations nécessaires pour configurer et exécuter votre service. Vous fournissez les spécifications au moment de la création d’un service.

La syntaxe générale est la suivante :

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

Notez que spec et serviceRoles sont les champs de niveau supérieur dans la spécification.

  • spec : utilisez ce champ pour fournir des détails de spécification. Il comprend ces champs de premier niveau :

    • spec.containers (obligatoire) : une liste d’un ou plusieurs conteneurs d’application. Votre application conteneurisée doit avoir au moins un conteneur.

    • spec.endpoints (facultatif) : une liste de points de terminaison que le service expose. Vous pouvez choisir un point de terminaison public, permettant l’accès au service par le réseau.

    • spec.volumes (facultatif) : une liste de volumes de stockage à utiliser par les conteneurs.

    • spec.logExporters (facultatif) : ce champ permet de gérer le niveau des journaux de conteneurs exportés vers la table d’événements de votre compte.

  • serviceRoles : utilisez ce champ pour définir un ou plusieurs rôles de service. Le rôle de service est le mécanisme que vous utilisez pour gérer les privilèges sur les points de terminaison exposés par le service.

Lignes directrices générales

  • Les règles de format suivantes s’appliquent aux champs name (noms de conteneurs, de points de terminaison et de volumes) :

    • Peut contenir jusqu’à 63 caractères.

    • Peut contenir une séquence de caractères alphanumériques minuscules ou -.

    • Doit commencer par un caractère alphabétique.

    • Doit se terminer par un caractère alphanumérique.

  • Les clients doivent s’assurer qu’aucune donnée personnelle, donnée sensible, donnée à exportation contrôlée ou autre donnée réglementée n’est saisie comme métadonnée dans le fichier de spécification. Pour plus d’informations, voir Champs de métadonnées dans Snowflake.

Les sections suivantes expliquent chacun des champs spec de premier niveau.

Champ spec.containers (obligatoire)

Utilisez le champ spec.containers pour décrire chacun des conteneurs OCI dans votre application.

Remarques :

  • Lorsque vous créez un service, Snowflake exécute ces conteneurs sur un seul nœud dans le pool de calcul spécifié, en partageant la même interface réseau.

  • Vous pouvez choisir d’exécuter plusieurs instances de service pour équilibrer la charge des demandes entrantes. Snowflake peut choisir d’exécuter ces instances de service sur le même nœud ou sur des nœuds différents dans le pool de calcul spécifié. Tous les conteneurs d’une instance donnée s’exécutent toujours sur un seul nœud.

  • Actuellement, Snowpark Container Services nécessite des images de plateforme linux/amd64.

Les sections suivantes expliquent les types de champs de conteneurs.

Champs containers.name et containers.image.

Pour chaque conteneur, seuls le nom et l’image sont des champs obligatoires.

  • name est le nom de l’image. Ce nom peut être utilisé pour identifier un conteneur spécifique à des fins d’observabilité (par exemple, journaux, métriques).

  • image est le nom de l’image que vous avez chargée dans un référentiel d’images Snowflake dans votre compte Snowflake.

Par exemple :

spec:
  containers:
    - name: echo
      image: /tutorial_db/data_schema/tutorial_repository/echo_service:dev
Copy

Champs containers.command et containers.args.

Utilisez ces champs facultatifs pour contrôler quel exécutable est démarré dans votre conteneur et les arguments qui sont transmis à cet exécutable. Vous pouvez configurer les valeurs par défaut au moment de la création de l’image, généralement dans un Dockerfile. L’utilisation de ces champs de spécification de service vous permet de modifier ces valeurs par défaut (et donc de modifier le comportement du conteneur) sans avoir à reconstruire votre image de conteneur :

  • containers.command remplace le ENTRYPOINT Dockerfile. Cela vous permet d’exécuter un exécutable différent dans le conteneur.

  • containers.args remplace le CMD Dockerfile. Cela vous permet de fournir différents arguments à la commande (l’exécutable).

Exemple

Votre Dockerfile comprend le code suivant :

ENTRYPOINT ["python3", "main.py"]
CMD ["Bob"]
Copy

Ces entrées Dockerfile exécutent la commande python3 et transmettent deux arguments : main.py et Bob. Vous pouvez remplacer ces valeurs dans le fichier de spécification de la manière suivante :

  • Pour remplacer le ENTRYPOINT, ajoutez le champ containers.command dans le fichier de spécification :

    spec:
      containers:
      - name: echo
        image: <image_name>
        command:
        - python3.9
        - main.py
    
    Copy
  • Pour remplacer l’argument « Bob », ajoutez le champ containers.args dans le fichier de spécification :

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

champ containers.env

Utilisez le champ containers.env pour définir les variables d’environnement du conteneur. Tous les processus du conteneur ont accès à ces variables d’environnement :

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

Exemple

Dans le Tutoriel 1, le code de l’application (echo_service.py) lit les variables d’environnement comme indiqué :

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

Notez que l’exemple transmet les valeurs par défaut des variables à la fonction getenv. Si les variables d’environnement ne sont pas définies, ces valeurs par défaut sont utilisées.

  • CHARACTER_NAME : lorsque le service echo reçoit une requête HTTP POST avec une chaîne (par exemple, « Hello »), le service renvoie « I said Hello ». Vous pouvez remplacer cette valeur par défaut dans le fichier de spécification. Par exemple, définissez la valeur « Bob » ; le service echo renvoie une réponse « Bob said Hello ».

  • SERVER_PORT : dans cette configuration par défaut, le service echo écoute sur le port 8080. Vous pouvez remplacer la valeur par défaut et spécifier un autre port.

La spécification de service suivante remplace ces deux valeurs de variables d’environnement :

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

Notez que, parce que vous avez modifié le numéro de port sur lequel votre service écoute, la spécification doit également mettre à jour le point de terminaison (valeur endpoints.port field) comme indiqué.

champ containers.readinessProbe

Utilisez le champ containers.readinessProbe pour identifier une sonde de préparation dans votre application. Snowflake appelle cette sonde pour déterminer quand votre application est prête à servir des requêtes.

Snowflake envoie une requête HTTP GET à la probe readiness spécifiée, au port et au chemin spécifiés, et attend que votre service renvoie un statut HTTP 200 OK pour s’assurer que seuls les conteneurs sains servent le trafic.

Utilisez les champs suivants pour fournir les informations requises :

  • port : le port réseau sur lequel le service écoute les probe readiness de disponibilité. Il n’est pas nécessaire de déclarer ce port comme point de terminaison.

  • path : Snowflake envoie des requêtes HTTP GET au service avec ce chemin.

Exemple

Dans le tutoriel 1, le code d’application (echo_python.py) met en œuvre la probe readiness :

@app.get("/healthcheck")
def readiness_probe():
Copy

En conséquence, le fichier de spécification comprend le champ 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

Le port spécifié par la probe readiness ne doit pas nécessairement être un point de terminaison configuré. Votre service pourrait écouter sur un port différent uniquement pour la probe readiness.

champ containers.volumeMounts

Les champs spec.volumes et spec.containers.volumeMounts fonctionnant ensemble, ils sont expliqués dans une même section. Pour plus d’informations, voir Champ spec.volumes (facultatif).

champ containers.resources

Un pool de calcul définit un ensemble de ressources disponibles (CPU, mémoire et stockage) et Snowflake détermine où dans le pool de calcul exécuter vos services.

Il est recommandé d’indiquer explicitement les besoins en ressources du conteneur spécifique et de définir les limites appropriées dans la spécification. Notez que les ressources que vous spécifiez sont limitées par la famille d’instances des nœuds de votre pool de calcul. Pour plus d’informations, voir CREATE COMPUTE POOL.

Utilisez le champ containers.resources permettant de spécifier les besoins explicites en ressources pour le conteneur d’application spécifique :

  • containers.resources.requests : les demandes que vous spécifiez doivent correspondre à l’utilisation moyenne des ressources que vous prévoyez par votre service. Snowflake utilise ces informations pour déterminer le placement de l’instance de service dans le pool de calcul. Snowflake garantit que la somme des demandes de ressources placées sur un nœud donné correspond aux ressources disponibles sur le nœud.

  • containers.resources.limits : les limites que vous spécifiez indiquent à Snowflake de ne pas allouer de ressources supérieures aux limites spécifiées. Vous pouvez ainsi éviter les dépassements de coûts.

Vous pouvez spécifier des requêtes et des limites pour les ressources suivantes :

  • memory : il s’agit de la mémoire requise pour votre conteneur d’application. Vous pouvez utiliser des unités décimales ou binaires pour exprimer les valeurs. Par exemple, 2G représente une demande de 2 000 000 000 octets et 2Gi représente une demande de 2 x 1024 x 1024 x 1024 octets.

    Lors de la spécification de la mémoire, une unité est requise. Par exemple, 100M ou 5Gi Les unités prises en charge sont : M, Mi, G, Gi.

  • cpu : il s’agit d’unités de noyaux virtuels (vCPU). Par exemple, l’unité CPU 1 est équivalente à 1 vCPU. Les requêtes fractionnaires sont autorisées, telles que 0,5, qui peut également être exprimé sous la forme 500m.

  • nvidia.com/gpu : si des GPUs sont nécessaires, ils doivent être demandés, et il doit également y avoir une limit spécifiée pour la même quantité. Si votre conteneur ne spécifie pas de requêtes et de limites pour la capacité GPU, il ne peut accéder à aucun GPUs. Le nombre de GPUs que vous pouvez demander est limité par le nombre maximum de GPUs pris en charge par le INSTANCE_TYPE que vous choisissez lors de la création d’un pool de calcul.

resource.requests et resource.limits sont relatifs à la capacité du nœud (vCPU et mémoire) de la famille d’instances du pool de calcul associé.

  • Si une demande de ressource (CPU, mémoire ou les deux) n’est pas fournie, Snowflake en dérive une pour vous :

    • Pour cpu, la valeur dérivée est soit 0,5 soit la limite cpu que vous avez fournie, selon la plus petite des deux.

    • Pour memory, la valeur dérivée est soit 0,5 GiB ou la limite memory que vous avez fournie, selon la plus petite des deux.

  • Si aucune limite de ressources (processeur, mémoire ou les deux) n’est fournie, Snowflake définit par défaut les limites de la capacité du nœud pour la famille d’instances du pool de calcul associé.

  • Si vous fournissez resource.limits et qu’elles dépassent la capacité du nœud, Snowflake plafonnera la limite de la capacité du nœud.

  • Snowflake évalue ces besoins en ressources de manière indépendante pour cpu et memory.

Notez que s’il est théoriquement impossible pour Snowflake de planifier le service sur le pool de calcul donné, CREATE SERVICE échouera. Théoriquement impossible, on suppose que le pool de calcul dispose du nombre maximal de nœuds autorisés et qu’aucun autre service n’est en cours d’exécution sur le pool de calcul. Autrement dit, Snowflake ne peut en aucun cas allouer les ressources demandées dans les limites du pool de calcul. Si c’est théoriquement possible, mais que les ressources nécessaires sont utilisées, alors CREATE SERVICE réussira. Certaines instances de service signaleront un statut indiquant que le service ne peut pas être planifié en raison de ressources insuffisantes jusqu’à ce que des ressources soient disponibles.

Exemple 1

Dans la spécification suivante, le champ containers.resources décrit les exigences en matière de ressources pour le conteneur :

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

Dans cet exemple, il est demandé à Snowflake d’allouer au moins 2 GB de mémoire, un GPU et un demi-cœur de CPU pour le conteneur. En même temps, le conteneur n’est pas autorisé à utiliser plus de 4 GB de mémoire et un GPU.

Exemple 2

Supposons :

  • Vous créez un pool de calcul composé de deux nœuds ; chaque nœud dispose de 27 GB de mémoire et d’un GPU :

    CREATE COMPUTE POOL tutorial_compute_pool
      MIN_NODES = 2
      MAX_NODES = 2
      INSTANCE_FAMILY = gpu_nv_s
    
    Copy
  • Vous créez un service qui demande à Snowflake d’exécuter deux instances du service :

    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

    MIN_INSTANCES et MAX_INSTANCES sont tous deux définis sur 2. Par conséquent, Snowflake exécutera deux instances du service.

Maintenant, envisagez ces scénarios :

  • Si votre service n’inclut pas explicitement les besoins en ressources dans la spécification de votre application, Snowflake décide d’exécuter ces instances sur le même nœud ou sur différents nœuds du pool de calcul.

  • Vous incluez les besoins en ressources dans la spécification de service et demandez 10 GB de mémoire pour le conteneur :

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

    Votre nœud de pool de calcul a 27 GB de mémoire, et Snowflake ne peut pas exécuter deux conteneurs sur le même nœud. Snowflake exécutera les deux instances de service sur des nœuds distincts dans le pool de calcul.

  • Vous incluez les besoins en ressources dans la spécification de service et demandez 1 GB de mémoire et un GPU pour le conteneur :

    spec:
      containers:
      - name: resource-test-gpu
        image: ...
        resources:
          requests:
            memory: 2G
            nvidia.com/gpu: 1
          limits:
            nvidia.com/gpu: 1
    
    Copy

    Vous demandez un GPU par conteneur, et chaque nœud n’a qu’un GPU. Dans ce cas, bien que la mémoire ne soit pas un problème, Snowflake ne peut pas planifier les deux instances de services sur un seul nœud. Cette exigence oblige Snowflake à exécuter les deux instances de service sur deux nœuds de pool de calcul distincts.

champ 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

Utilisez le champ containers.secrets dans votre spécification de service pour fournir des identifiants de connexion gérés par Snowflake à vos conteneurs d’application. Commencez par stocker les identifiants de connexion dans des objets de secrets Snowflake. Ensuite, dans la spécification du service, référencez l’objet secret et spécifiez où placer les identifiants de connexion à l’intérieur du conteneur.

Ce qui suit est un résumé de la façon d’utiliser les champs containers.secrets :

  • Spécifiez le secret Snowflake : utilisez le champ snowflakeSecret pour spécifier soit un nom d’objet secret Snowflake, soit une référence d’objet. Les références d’objet sont applicables lors de l’utilisation de Snowpark Container Services pour créer une Native App (une application avec des conteneurs).

    • Utilisez secretKeyRef pour fournir le nom de la clé dans le secret Snowflake.

  • Spécifiez le placement du secret dans le conteneur d’application : utilisez le champ envVarName pour transmettre le secret en tant que variables d’environnement ou directoryPath pour écrire les secrets dans les fichiers de conteneurs locaux.

Pour plus d’informations, voir Transmission d’identifiants de connexion à un conteneur à l’aide de secrets Snowflake.

Notez que le rôle qui crée le service (rôle propriétaire) aura besoin du privilège READ sur les secrets référencés.

Champ spec.endpoints (facultatif)

Utilisez le champ spec.endpoints pour spécifier une liste des ports réseau TCP que votre application expose. Un service peut exposer zéro à plusieurs points de terminaison. Utilisez les champs suivants pour décrire un point de terminaison :

  • name : nom unique du point de terminaison. Le nom est utilisé pour identifier le point de terminaison dans la spécification de la fonction de service et du rôle de service.

  • port : le port réseau sur lequel votre service écoute. Vous devez spécifier ce champ ou le champ portRange.

  • portRange : la plage de ports réseau sur laquelle votre application écoute. Vous devez spécifier ce champ ou le champ port.

    Notez que vous ne pouvez spécifier que le champ portRange si le champ protocol est défini sur TCP et que le champ public est faux.

  • public : si vous souhaitez que ce point de terminaison soit accessible depuis Internet, définissez ce champ sur true. Les points de terminaison publics ne sont pas pris en charge par le protocole TCP.

  • protocol : protocole pris en charge par le point de terminaison. Les valeurs prises en charge sont TCP, HTTP et HTTPS. Par défaut, le protocole est HTTP. Lors de la spécification du protocol, les dispositions suivantes s’appliquent :

    • Quand ce point de terminaison est public ou la cible d’une fonction de service (voir Utilisation d’un service), le protocole doit être HTTP ou HTTPS.

    • Les services de tâches exigent que tous les points de terminaison spécifiés utilisent le protocole TCP ; les protocoles HTTP/HTTPS ne sont pas pris en charge.

Note

Snowflake effectue des contrôles d’authentification et d’autorisation pour l’accès public qui permettent uniquement aux utilisateurs de Snowflake qui ont la permission d’utiliser le service. L’accès public à un point de terminaison nécessite l’authentification Snowflake. L’utilisateur authentifié doit également disposer d’une autorisation sur ce point de terminaison de service (l’utilisateur dispose de l’autorisation d’utilisation d’un rôle qui a accès au point de terminaison).

Exemple

Voici la spécification de l’application utilisée dans le tutoriel 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

Ce conteneur d’application expose un point de terminaison. Il comprend également le champ facultatif public pour permettre l’accès au point de terminaison depuis l’extérieur de Snowflake (accès Internet). Par défaut, public est false.

Champ spec.volumes (facultatif)

Cette section explique les champs de spécification spec.volumes et spec.containers.volumeMounts car ils sont étroitement liés.

  • spec.volumes définit un système de fichiers partagé. Ces volumes peuvent être mis à disposition dans vos conteneurs.

  • spec.containers.volumeMount définit l’emplacement d’un volume dans des conteneurs spécifiques.

Remarque : le champ volumes est spécifié au niveau spec, mais comme plusieurs conteneurs peuvent partager le même volume, volumeMounts devient un champ de niveau spec.containers.

Utilisez ces champs pour décrire les volumes et les montages de volumes.

  • spec.volumes : il peut y avoir zéro ou plusieurs volumes. Utilisez les champs suivants pour décrire un volume :

    • Champs obligatoires pour tous les types de volumes :

      • name : nom unique du volume. Il est désigné par spec.containers.volumeMounts.name.

      • source : il peut s’agir de local, memory, block, ou "@<stagename>". La section suivante explique ces types de volumes.

      • size (obligatoire uniquement pour les types de volumes memory et block) : pour des volumes de mémoire et de bloc, il s’agit de la taille du volume en octets. Pour le stockage en bloc, la valeur doit toujours être un nombre entier, spécifié à l’aide du suffixe de l’unité Gi. Par exemple, 5Gi signifie 5*1024*1024*1024 octets.

    • Pour le type de volume block, vous pouvez spécifier les champs facultatifs suivants. Pour plus d’informations, voir Spécification du stockage en bloc dans la spécification du service.

      • blockConfig.initialContents.fromSnapshot : spécifiez un instantané précédemment pris d’un autre volume pour initialiser le volume de bloc. L’instantané doit être dans l’état CREATED avant de pouvoir être utilisé pour créer un volume, sinon la création du service échouera. Utilisez la commande DESCRIBE SNAPSHOT pour obtenir le statut de l’instantané.

      • blockConfig.iops : spécifiez le nombre d’opérations d’entrée/sortie de pointe prises en charge par seconde. La plage prise en charge est de 3000 à 16000 dans AWS et 3000-80000 dans Azure, avec une valeur par défaut de 3000. Notez que la taille des données par opération est limitée à 256 KiB pour les volumes de blocs.

      • blockConfig.throughput : spécifiez le débit maximal, en MiB/seconde, pour provisionner le volume. La plage prise en charge est de 125 à 1 000 dans AWS et 125-1200 dans Azure, avec une valeur par défaut de 125.

  • spec.containers.volumeMounts : chaque conteneur peut avoir zéro ou plusieurs montages de volume. containers.volumeMounts est aussi une liste. En d’autres termes, chaque conteneur peut avoir plusieurs montages de volumes. Utilisez les champs suivants pour décrire un montage de volume :

    • name : nom du volume à monter. Un même conteneur peut faire plusieurs fois référence au même volume.

    • mountPath : le chemin d’accès au fichier où le volume du conteneur doit être monté.

À propos des types de volumes pris en charge

Snowflake prend en charge les types de volumes suivants pour les conteneurs d’application : volumes locaux, mémoire, blocs et zone de préparation Snowflake.

  • Volume local : les conteneurs d’une instance de service peuvent utiliser un disque local pour partager des fichiers. Par exemple, si votre application comporte deux conteneurs, un conteneur d’application et un analyseur de journaux, l’application peut écrire des journaux sur le volume local et l’analyseur de journaux peut lire les journaux.

    Notez que, si vous exécutez plusieurs instances d’un service, seuls les conteneurs appartenant à une instance de service peuvent partager des volumes. Les conteneurs qui appartiennent à des instances de service différentes ne partagent pas de volumes.

  • Mémoire : vous pouvez utiliser un système de fichiers RAM pour les conteneurs.

  • Bloc : les conteneurs peuvent également utiliser des volumes de stockage en bloc. Pour plus d’informations, voir Utilisation de volumes de stockage en bloc avec des services.

  • Zone de préparation Snowflake : vous pouvez également donner aux conteneurs un accès pratique aux fichiers sur une zone de préparation Snowflake de votre compte. Pour plus d’informations, voir Utilisation des volumes de zones de préparation Snowflake avec des services.

Exemple

Votre application de machine learning comprend les deux conteneurs suivants :

  • Un conteneur app pour l’application principale

  • Un conteneur logger-agent qui collecte les journaux et les charge sur Amazon S3

Ces conteneurs utilisent les deux volumes suivants :

  • Volume local : cette application écrit les journaux que l’agent de journalisation lit.

  • Zone de préparation Snowflake, @model_stage : l’application principale lit les fichiers de cette zone de préparation.

Dans l’exemple de spécification suivant, le conteneur app monte les volumes logs et models, et le conteneur logging-agent ne monte que le 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

Si plusieurs instances du service sont en cours d’exécution, les conteneurs logging-agent et app d’une instance de service partagent le volume logs. Le volume logs n’est pas partagé entre les instances de service.

Si, en plus de ces volumes, votre conteneur app utilise également un volume de mémoire à 2 GB, vérifiez la spécification pour inclure le volume dans la liste volumes et ajoutez également un autre montage de volume dans la liste volumeMounts des conteneurs app :

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

Notez que lorsque vous spécifiez memory comme étant la source du volume, vous devez également spécifier le champ volumes.size pour indiquer la taille de la mémoire. Pour plus d’informations sur les unités de taille de mémoire que vous pouvez spécifier, voir À propos des unités.

À propos des autorisations de fichiers sur les volumes montés

Un conteneur qui monte une zone de préparation ou un volume de stockage en bloc Snowflake s’exécute généralement en tant qu’utilisateur root. Cependant, il peut arriver que votre conteneur s’exécute en tant qu’utilisateur non root. Par exemple :

  • Si votre application utilise une bibliothèque tierce, celle-ci utilise un utilisateur non root pour exécuter le code de l’application à l’intérieur du conteneur.

  • Pour d’autres raisons, telles que la sécurité, vous pouvez exécuter votre application en tant qu’utilisateur non root à l’intérieur du conteneur.

Pour éviter les erreurs potentielles liées aux autorisations des utilisateurs de fichiers, il est important de définir les UID (ID utilisateur) et GID (ID groupe) du conteneur dans le cadre de la spécification. Ceci est particulièrement important pour les conteneurs qui utilisent un utilisateur et un groupe spécifiques pour lancer ou exécuter l’application dans le conteneur. En définissant les paramètres UID et GID appropriés, vous pouvez utiliser un conteneur fonctionnant en tant qu’utilisateur non root. Par exemple :

spec:
  ...

  volumes:
  - name: stagemount
    source: "@test"
    uid: <UID-value>
    gid: <GID-value>
Copy

Snowflake utilise ces informations pour monter la zone de préparation avec les permissions appropriées.

Pour obtenir l’UID et le GID du conteneur, procédez comme suit :

  1. Exécutez le conteneur localement en utilisant docker run.

  2. Recherchez l’ID du conteneur à l’aide de la commande docker container list. Exemple de sortie partielle :

    CONTAINER ID   IMAGE                       COMMAND
    —----------------------------------------------------------
    a6a1f1fe204d  tutorial-image         "/usr/local/bin/entr…"
    
  3. Exécutez la commande docker id à l’intérieur du conteneur pour obtenir les UID et GID :

    docker exec -it <container-id> id
    
    Copy

    Exemple de sortie :

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

Champ spec.logExporters (facultatif)

Snowflake collecte tout ce que vos applications envoient à la sortie standard ou aux erreurs standard. Pour plus d’informations, voir Accès aux journaux des conteneurs locaux. Utilisez spec.logExporters pour configurer laquelle de ces sorties Snowflake exporte vers votre table des événements.

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

Les valeurs logLevel prises en charge sont les suivantes :

  • INFO (par défaut) : exporter tous les journaux des utilisateurs.

  • ERROR : exporter uniquement les journaux d’erreurs. Snowflake n’exporte que les journaux du flux stderr.

  • NONE : ne pas exporter les journaux dans la table d’événements.

Champ spec.platformMonitor (facultatif)

Les services individuels publient des métriques. Ces métriques fournies par Snowflake sont également appelées métriques de la plateforme. Vous ajoutez le champ spec.platformMonitor dans la spécification pour demander à Snowflake d’envoyer des métriques du service à la table d’événements configurée pour votre compte. Le cas d’utilisation cible pour cela est d’observer l’utilisation des ressources d’un service spécifique.

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

group_N fait référence à un groupes de métriques prédéfinis qui vous intéresse. Pendant que le service est en cours d’exécution, Snowflake enregistre les métriques des groupes spécifiés dans la table des événements. Vous pouvez ensuite interroger les métriques de la table des événements. Pour plus d’informations, consultez Surveillance des services.

À propos des unités

Une spécification de service prend des valeurs numériques à plusieurs endroits. Une variété d’unités sont prises en charge pour exprimer ces valeurs. Pour les grandes et les petites valeurs, vous pouvez utiliser les unités binaires et décimales comme indiqué. Dans la liste suivante, « # » représente une valeur entière.

  • Unités binaires :

    • numberKi signifie number*1024. Par exemple, 4Ki équivaut à 4096.

    • numberMi signifie number*1024*1024.

    • numberGi signifie number*1024*1024*1024.

  • Unités décimales :

    • numberk signifie number*1000. Par exemple, 4k équivaut à 4000.

    • numberM signifie number*1000*1000.

    • numberG signifie number*1000*1000*1000

  • Unités fractionnaires :

    • numberm signifie number*0.001. Par exemple, cpu: 500m est équivalent à cpu: 0.5.

Champ serviceRoles (facultatif)

Utilisez le champ de niveau supérieur serviceRoles dans la spécification pour définir un ou plusieurs rôles de service. Pour chaque rôle de service, indiquez un nom et une liste d’un ou plusieurs points de terminaison (définis dans spec.endpoints) pour lesquels vous souhaitez que le rôle de service accorde le privilège USAGE.

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

Remarques :

  • name et endpoints sont tous deux nécessaires.

  • Le nom du rôle du service doit respecter le format suivant :

    • Doit contenir des caractères alphanumériques ou _.

    • Doit commencer par un caractère alphabétique.

    • Doit se terminer par un caractère alphanumérique.

Pour plus d’informations, voir Gestion de l’accès aux points de terminaison de service.