Snowpark Container Services : utilisation des tâches

Snowpark Container Services vous permet de déployer, de gérer et d’adapter facilement des applications conteneurisées. Après avoir créé une application et chargé l’image de l’application dans un référentiel de votre compte Snowflake, vous pouvez exécuter vos conteneurs d’application en tant que service.

Un service représente l’exécution par Snowflake de votre application conteneurisée sur un pool de calcul, qui est une collection de nœuds de machine virtuelle (VM). Il existe deux types de services :

  • services de longue durée. Un service de longue durée est un service Web qui ne se termine pas automatiquement. Une fois que vous avez créé un service, Snowflake gère le service en cours d’exécution. Par exemple, si un conteneur de service s’arrête, pour quelque raison que ce soit, Snowflake redémarre ce conteneur afin que le service fonctionne sans interruption.

  • services de tâche. Un service de tâche se termine lorsque votre code se termine, de la même manière qu’une procédure stockée. Lorsque tous les conteneurs se terminent, le service de tâche est terminé.

Snowpark Container Services fournit un ensemble de commandes SQL que vous pouvez utiliser pour créer et gérer un service. Il s’agit notamment des éléments suivants :

Démarrage de services

Les informations minimales requises pour démarrer un service incluent :

  • Un nom : nom du service.

  • Une spécification de service : cette spécification fournit à Snowflake les informations nécessaires à l’exécution de votre service. La spécification est un fichier YAML.

  • Un pool de calcul : Snowflake exécute votre service dans le pool de calcul spécifié.

Créer un service de longue durée

Utilisez CREATE SERVICE pour créer un service de longue durée.

  • Créez un service à l’aide d’une spécification en ligne. Dans la plupart des cas, au cours du développement, vous pouvez choisir la spécification en ligne, comme indiqué :

    CREATE SERVICE echo_service
       IN COMPUTE POOL tutorial_compute_pool
       FROM SPECIFICATION $$
       spec:
         containers:
         - name: echo
           image: /tutorial_db/data_schema/tutorial_repository/my_echo_service_image:tutorial
           readinessProbe:
             port: 8000
             path: /healthcheck
         endpoints:
         - name: echoendpoint
           port: 8000
           public: true
       $$;
    
    Copy
  • Créez un service en utilisant les informations de la zone de préparation. Lorsque vous déployez le service dans un environnement de production, il est conseillé d’appliquer le principe de séparation des préoccupations et de charger la spécification dans une zone de préparation, de fournir la commande CREATE SERVICE sur les informations de zone de préparation, comme indiqué :

    CREATE SERVICE echo_service
      IN COMPUTE POOL tutorial_compute_pool
      FROM @tutorial_stage
      SPECIFICATION_FILE='echo_spec.yaml';
    
    Copy

Exécuter un service de tâche

Utilisez EXECUTE JOB SERVICE pour créer un service de tâche. Cette commande s’exécute de manière synchrone et renvoie la réponse après la sortie de tous les conteneurs du service de tâche.

  • Exécutez un service de tâche à l’aide d’une spécification en ligne :

    EXECUTE JOB SERVICE
       IN COMPUTE POOL tutorial_compute_pool
       NAME = example_job_service
       FROM SPECIFICATION $$
       spec:
         container:
         - name: main
           image: /tutorial_db/data_schema/tutorial_repository/my_job_image:latest
           env:
             SNOWFLAKE_WAREHOUSE: tutorial_warehouse
           args:
           - "--query=select current_time() as time,'hello'"
           - "--result_table=results"
       $$;
    
    Copy
  • Exécutez un service de tâche en utilisant les informations de la zone de préparation :

    EXECUTE JOB SERVICE
      IN COMPUTE POOL tutorial_compute_pool
      NAME = example_job_service
      FROM @tutorial_stage
      SPECIFICATION_FILE='my_job_spec.yaml';
    
    Copy

Création de plusieurs instances de service et activation de la mise à l’échelle automatique

Par défaut, Snowflake exécute une instance du service dans le pool de calcul spécifié. Pour gérer des charges de travail importantes, vous pouvez exécuter plusieurs instances de service en définissant les propriétés MIN_INSTANCES et MAX_INSTANCES, qui spécifient le nombre minimum d’instances du service au début et le nombre maximum d’instances que Snowflake peut ajouter en cas de besoin.

Exemple

CREATE SERVICE echo_service
   IN COMPUTE POOL tutorial_compute_pool
   FROM @tutorial_stage
   SPECIFICATION_FILE='echo_spec.yaml'
   MIN_INSTANCES=2
   MAX_INSTANCES=4;
Copy

Lorsque plusieurs instances de service sont en cours d’exécution, Snowflake fournit automatiquement un équilibreur de charge pour répartir les requêtes entrantes.

Note

Vous ne pouvez pas exécuter plus d’une instance d’un service de tâche.

Pour configurer Snowflake afin qu’il évalue automatiquement le nombre d’instances de service en cours d’exécution, procédez comme suit :

  1. Spécifiez les exigences en matière de mémoire et de CPU pour votre instance de service dans le fichier de spécification du service. Pour plus d’informations, voir le champ container.resources.

    Exemple

    resources:
      requests:
       memory: <memory-reserved>
       cpu: <cpu-units>
    
    Copy
  2. Lors de l’exécution de la commande CREATE SERVICE, définissez les paramètres MIN_INSTANCES et MAX_INSTANCES. Vous pouvez également utiliser ALTER SERVICE pour modifier ces valeurs. La mise à l’échelle automatique se produit lorsque MAX_INSTANCES est supérieur à MIN_INSTANCES.

Snowflake commence par créer le nombre minimum d’instances de service sur le pool de calcul spécifié. Snowflake utilise un seuil de 80 % (pour le CPU et la mémoire) afin d’augmenter ou de réduire le nombre d’instances de service. Snowflake surveille en permanence l’utilisation des ressources (mémoire ou CPU) dans le pool de calcul, en agrégeant les données d’utilisation de toutes les instances de service en cours d’exécution.

Lorsque l’utilisation agrégée des ressources (pour toutes les instances de service) dépasse 80 %, Snowflake déploie une instance de service supplémentaire dans le pool de calcul. Si l’utilisation des ressources agrégées tombe en dessous de 80 %, Snowflake procède à une diminution en supprimant une instance de service en cours d’exécution. Snowflake utilise une fenêtre de stabilisation de cinq minutes pour éviter les mises à l’échelle fréquentes.

Notez les comportements de mise à l’échelle suivants :

  • La mise à l’échelle des instances de service est limitée par les paramètres MIN_INSTANCES et MAX_INSTANCES configurés pour le service.

  • Si une mise à l’échelle est nécessaire et que les nœuds du pool de calcul n’ont pas la capacité de ressources nécessaire pour démarrer une autre instance de service, la mise à l’échelle automatique du pool de calcul peut être déclenchée. Pour plus d’informations, voir Mise à l’échelle automatique des nœuds d’un pool de calcul.

  • Si vous spécifiez les paramètres MAX_INSTANCES et MIN_INSTANCES lors de la création d’un service, mais que vous ne spécifiez pas les exigences en matière de mémoire et de CPU pour votre instance de service dans le fichier de spécification du service, aucune mise à l’échelle automatique ne se produit ; Snowflake démarre avec le nombre d’instances spécifié par le paramètre MIN_INSTANCES et ne fera pas de mise à l’échelle automatique.

Utilisation de modèles de spécifications

Il peut arriver que vous souhaitiez créer plusieurs services en utilisant la même spécification, mais avec des configurations différentes. Par exemple, vous supposez que vous définissez une variable d’environnement dans une spécification de service et vous souhaitez créer plusieurs services en utilisant la même spécification mais des valeurs différentes pour la variable d’environnement.

La spécification de modèles vous permet de définir des variables pour des valeurs de champ dans la spécification. Lorsque vous créez un service, vous fournissez des valeurs pour ces variables.

L’utilisation des modèles de spécification se fait en deux étapes :

  1. Créez une spécification en utilisant des variables comme valeurs pour les différents champs de la spécification. Utilisez la syntaxe {{ variable_name }} pour spécifier ces variables. Par exemple, la spécification suivante utilise une variable nommée « tag_name » pour le nom de la balise d’image, afin que vous spécifiiez une balise d’image différente pour chaque service.

    spec:
      containers:
      - name: echo
        image: myorg-myacct.registry.snowflakecomputing.com/tutorial_db/data_schema/tutorial_repository/my_echo_service_image:{{ tag_name }}
        ...
      endpoints:
      
    
    Copy
  2. Créez un service en fournissant le modèle de spécification dans une commande CREATE SERVICE. Vous utilisez SPECIFICATION_TEMPLATE ou SPECIFICATION_TEMPLATE_FILE pour spécifier le modèle. Utilisez le paramètre USING pour spécifier la valeur de la variable. Par exemple, l’instruction suivante utilise un modèle de spécification d’une zone de préparation Snowflake. Le paramètre USING définit la variable tag_name sur la valeur 'latest'.

    CREATE SERVICE echo_service
       IN COMPUTE POOL tutorial_compute_pool
       FROM @STAGE SPECIFICATION_TEMPLATE_FILE='echo.yaml'
       USING (tag_name=>'latest');
    
    Copy

Lignes directrices pour la définition des variables dans une spécification

  • Utilisez la syntaxe {{ variable_name }} pour définir des variables en tant que valeurs de champ dans la spécification.

  • Ces variables peuvent avoir des valeurs par défaut. Pour spécifier la valeur par défaut, utilisez la fonction default dans la déclaration de la variable. Par exemple, la spécification suivante définit deux variables (character_name et endpoint_name) avec des valeurs par défaut.

    spec:
      containers:
      - name: echo
        image: <image_name>
        env:
          CHARACTER_NAME: {{ character_name | default('Bob') }}
          SERVER_PORT: 8085
      endpoints:
      - name: {{ endpoint_name | default('echo-endpoint') }}
        port: 8085
    
    Copy

    De plus, vous pouvez spécifier un paramètre booléen facultatif à la fonction default pour indiquer si vous souhaitez que la valeur par défaut soit utilisée lorsqu’une valeur vide est transmise pour la variable. Considérez cette spécification :

    spec:
      containers:
      - name: echo
        image: <image_name>
        env:
          CHARACTER_NAME: {{ character_name | default('Bob', false) }}
          SERVER_PORT: 8085
      endpoints:
      - name: {{ endpoint_name | default('echo-endpoint', true) }}
        port: 8085
    
    Copy

    Dans la spécification :

    • Pour la variable character_name, le paramètre booléen est fixé à false. Par conséquent, si la variable est définie sur une valeur de chaîne vide (“”) pour ce paramètre, la valeur reste vide ; la valeur par défaut (« Bob ») n’est pas utilisée.

    • Pour la variable echo_endpoint, le paramètre booléen est fixé à true. Par conséquent, si vous donnez une valeur vide à ce paramètre, la valeur par défaut (« point de terminaison ») est utilisée.

    Par défaut, le paramètre booléen de la fonction default est false.

Lignes directrices pour la transmission de valeurs pour les variables de spécification

Spécifiez le paramètre USING dans la commande CREATE SERVICE pour fournir des valeurs aux variables. La syntaxe générale de USING est la suivante :

USING( var_name=>var_value, [var_name=>var_value, ... ] );
Copy

où :

  • var_name est sensible à la casse et doit être un identificateur Snowflake valide (voir Exigences relatives à l’identificateur).

  • var_value peut être une valeur alphanumérique ou une valeur JSON valide.

    Exemples :

    -- Alphanumeric string and literal values
    USING(some_alphanumeric_var=>'blah123',
          some_int_var=>111,
          some_bool_var=>true,
          some_float_var=>-1.2)
    
    -- JSON string
    USING(some_json_var=>' "/path/file.txt" ')
    
    -- JSON map
    USING(env_values=>'{"SERVER_PORT": 8000, "CHARACTER_NAME": "Bob"}' );
    
    -- JSON list
    USING (ARGS='["-n", 2]' );
    
    Copy
  • Le paramètre USING dans CREATE SERVICE doit fournir des valeurs pour les variables de la spécification (à l’exception des variables pour lesquelles la spécification fournit des valeurs par défaut). Sinon, une erreur est renvoyée.

Exemples

Ces exemples illustrent la création de services à l’aide de modèles de spécification. Les commandes CREATE SERVICE présentées dans ces exemples utilisent la spécification en ligne.

Exemple 1 : fournir des valeurs simples

Dans le tutoriel 1, vous créez un service en fournissant une spécification en ligne. L’exemple suivant est une version modifiée du même exemple où la spécification définit deux variables : image_url et SERVER_PORT. Notez que la variable SERVER_PORT est répétée à trois endroits. C’est l’un des avantages ajoutés de l’utilisation de variables, qui garantit que tous les champs censés avoir la même valeur ont bien la même valeur.

CREATE SERVICE echo_service
   IN COMPUTE POOL tutorial_compute_pool
   MIN_INSTANCES=1
   MAX_INSTANCES=1
   FROM SPECIFICATION_TEMPLATE $$
      spec:
         containers:
         - name: echo
           image: {{ image_url }}
           env:
             SERVER_PORT: {{SERVER_PORT}}
             CHARACTER_NAME: Bob
           readinessProbe:
             port: {{SERVER_PORT}}
             path: /healthcheck
         endpoints:
         - name: echoendpoint
           port: {{SERVER_PORT}}
           public: true
         $$
      USING (image_url=>' "/tutorial_db/data_schema/tutorial_repository/my_echo_service_image:latest" ', SERVER_PORT=>8000 );
Copy

Dans cette commande CREATE SERVICE, le paramètre USING fournit des valeurs pour les deux variables de spécification. La valeur image_url comprend des barres obliques et un signe deux-points. Il ne s’agit pas de caractères alphanumériques. Par conséquent, l’exemple met la valeur entre guillemets pour en faire une valeur de chaîne JSON valide. La spécification du modèle étend la spécification suivante :

spec:
  containers:
  - name: echo
    image: /tutorial_db/data_schema/tutorial_repository/my_echo_service_image:latest
    env:
      SERVER_PORT: 8000
      CHARACTER_NAME: Bob
    readinessProbe:
      port: 8000
      path: /healthcheck
    endpoints:
    - name: echoendpoint
      port: 8000
      public: true
Copy

Exemple 2 : fournir une valeur JSON

Dans le tutoriel 1, la spécification définit deux variables d’environnement (SERVER_PORT et CHARACTER_NAME) comme indiqué :

spec:
 containers:
 - name: echo
   image: /tutorial_db/data_schema/tutorial_repository/my_echo_service_image:latest
   env:
     SERVER_PORT: 8000
     CHARACTER_NAME: Bob
   
Copy

Vous pouvez modéliser cette spécification en utilisant une variable pour le champ env. Cela vous permet de créer plusieurs services avec des valeurs différentes pour les variables d’environnement. La commande CREATE SERVICE suivante utilise une variable (env_values) pour le champ env.

CREATE SERVICE echo_service
  IN COMPUTE POOL tutorial_compute_pool
  MIN_INSTANCES=1
  MAX_INSTANCES=1
  FROM SPECIFICATION_TEMPLATE $$
     spec:
       containers:
       - name: echo
         image: /tutorial_db/data_schema/tutorial_repository/my_echo_service_image:latest
         env: {{env_values}}
         readinessProbe:
           port: {{SERVER_PORT}}    #this and next tell SF to connect to port 8000
           path: /healthcheck
       endpoints:
       - name: echoendpoint
         port: {{SERVER_PORT}}
         public: true
        $$
     USING (env_values=>'{"SERVER_PORT": 8000, "CHARACTER_NAME": "Bob"}' );
Copy

Le paramètre USING dans CREATE SERVICE fournit une valeur à la variable env_values. La valeur est un mappage JSON qui fournit les valeurs des deux variables d’environnement.

Exemple 3 : fournir une liste comme valeur de la variable

Dans le tutoriel 2, la spécification comprend le champ args qui inclut deux arguments.

spec:
  container:
  - name: main
    image: /tutorial_db/data_schema/tutorial_repository/my_job_image:latest
    env:
      SNOWFLAKE_WAREHOUSE: tutorial_warehouse
    args:
    - "--query=select current_time() as time,'hello'"
    - "--result_table=results"
Copy

Dans une version de modèle de la spécification, vous pouvez fournir ces arguments sous la forme d’une liste JSON, comme indiqué :

spec:
  container:
  - name: main
    image: /tutorial_db/data_schema/tutorial_repository/my_job_image:latest
    env:
      SNOWFLAKE_WAREHOUSE: tutorial_warehouse
    args: {{ARGS}}
  $$
  USING (ARGS=$$["--query=select current_time() as time,'hello'", "--result_table=results"]$$ );
Copy

Modifier et supprimer des services

Après avoir créé un service :

  • Utilisez la commande DROP SERVICE pour supprimer un service d’un schéma (Snowflake met fin à tous les conteneurs de services).

  • Utilisez la commande ALTER SERVICE pour modifier le service (par exemple, suspendez ou reprenez le service, modifiez le nombre d’instances en cours d’exécution et demandez à Snowflake de redéployer votre service à l’aide d’une nouvelle spécification de service).

    Note

    • Vous ne pouvez pas modifier un service de tâche.

Résiliation du service

Lorsque vous suspendez un service (ALTER SERVICE … SUSPEND) ou supprimez un service (DROP SERVICE), Snowflake met fin à toutes les instances de service. De même, lorsque vous mettez à niveau le code de service (ALTER SERVICE … <fromSpecification>), Snowflake applique des mises à niveau progressives en mettant fin et en redéployant une instance de service à la fois.

Lors de la fin d’une instance de service, Snowflake envoie d’abord un signal SIGTERM à chaque conteneur de service. Le conteneur a la possibilité de traiter le signal et de s’arrêter correctement avec une fenêtre de 30 secondes. Sinon, après la période de grâce, Snowflake termine tous les processus du conteneur.

Mise à jour du code de service de redéploiement du service

Une fois qu’un service est créé, utilisez la commande ALTER SERVICE … <fromSpecification> pour mettre à jour le code du service et redéployer le service.

Vous chargez d’abord le code d’application modifié dans votre référentiel d’images, puis vous appelez ALTER SERVICE en fournissant la spécification du service, soit en ligne, soit en spécifiant le chemin d’accès à un fichier de spécification dans la zone de préparation Snowflake. Par exemple :

ALTER SERVICE echo_service
FROM SPECIFICATION $$
spec:
  
  
$$;
Copy

Dès réception de la requête, Snowflake redéploie le service en utilisant le nouveau code.

Lorsque vous exécutez la commande CREATE SERVICE … <from-Specification>, Snowflake enregistre la version spécifique de l’image fournie. Snowflake déploie cette même version d’image dans les scénarios suivants, même si l’image dans le référentiel a été mise à jour :

  • Lorsqu’un service suspendu est repris (en utilisant ALTER SERVICE … RESUME).

  • Lorsque la mise à l’échelle automatique ajoute davantage d’instances de service.

  • Lorsque les instances de service sont redémarrées pendant la maintenance du cluster.

Mais si vous appelez ALTER SERVICE … <fromSpecification>, cela incite Snowflake à utiliser la dernière version du référentiel pour cette image.

Si vous êtes le propriétaire du service, la sortie de la commande DESCRIBE SERVICE inclut la spécification du service, qui inclut le condensé d’image (la valeur du champ sha256 dans la spécification), comme indiqué ci-dessous :

spec:
containers:
- name: "echo"
    image: "/tutorial_db/data_schema/tutorial_repository/my_echo_service_image:latest"
    sha256: "@sha256:8d912284f935ecf6c4753f42016777e09e3893eed61218b2960f782ef2b367af"
    env:
      SERVER_PORT: "8000"
      CHARACTER_NAME: "Bob"
    readinessProbe:
      port: 8000
      path: "/healthcheck"
endpoints:
- name: "echoendpoint"
    port: 8000
    public: true
Copy

ALTER SERVICE peut avoir un impact sur les communications (voir Utilisation d’un service) avec le service.

  • Si ALTER SERVICE … <fromSpecification> supprime un point de terminaison ou supprime les autorisations pertinentes requises pour utiliser un point de terminaison (voir serviceRoles dans la référence de spécification), l’accès au service échouera. Pour plus d’informations, voir Utilisation d’un service.

  • Pendant que la mise à niveau est en cours, de nouvelles connexions peuvent être acheminées vers la nouvelle version. Si la nouvelle version du service n’est pas rétrocompatible, elle perturbera toute utilisation active du service. Par exemple, les requêtes en cours utilisant une fonction de service peuvent échouer.

Note

Lors de la mise à jour du code de service qui fait partie d’une application native avec des conteneurs, vous pouvez utiliser la fonction système SYSTEM$WAIT_FOR_SERVICES permettant de mettre en pause le script d’installation de l’application native pour permettre la mise à niveau complète des services. Pour plus d’informations, voir Mettre à niveau une application avec des conteneurs.

Surveillance des mises à niveau progressives

Lorsque plusieurs instances de service sont en cours d’exécution, Snowflake effectue une mise à niveau progressive par ordre décroissant en fonction de l’ID des instances de service. Utilisez les commandes suivantes pour surveiller les mises à niveau du service :

  • DESCRIBE SERVICE et SHOW SERVICES :

    • La colonne is_upgrading dans la sortie indique TRUE si le service est en cours de mise à niveau.

    • La colonne spec_digest dans la sortie représente le condensé de spécifications de la spécification de service actuelle. Vous pouvez exécuter cette commande périodiquement ; un changement dans la valeur spec_digest indique qu’une mise à niveau du service a été déclenchée. Utilisez la commande SHOW SERVICE INSTANCES IN SERVICE pour vérifier si toutes les instances ont été mises à niveau vers la dernière version comme expliqué ci-dessous.

  • SHOW SERVICE INSTANCES IN SERVICE :

    • La colonne status dans la sortie fournit le statut de chaque instance de service individuelle pendant que la mise à niveau progressive est en cours. Pendant la mise à niveau, vous observerez le statut de transition de chaque instance de service, tel que TERMINATING à PENDING, et PENDING à READY.

    • Pendant la mise à niveau du service, les commandes SHOW SERVICE INSTANCES IN SERVICE peuvent renvoyer des valeurs différentes dans la colonne de sortie spec_digest depuis SHOW SERVICES, qui renvoie toujours le dernier condensé de spécifications. Cela indique simplement que la mise à niveau du service est en cours et que les instances de service exécutent toujours l’ancienne version du service.

Obtenir des informations sur les services

Vous pouvez utiliser ces commandes :

  • Utilisez la commande DESCRIBE SERVICE permettant de récupérer les propriétés et le statut d’un service.

  • Utilisez la commande SHOW SERVICES pour lister les services actuels (y compris les services de tâche), pour lesquels vous disposez d’autorisations. Pour chaque service, la sortie fournit les propriétés et le statut du service. Par défaut, la sortie répertorie les services de la base de données et du schéma actuels. Vous pouvez également spécifier l’une des portées suivantes. Par exemple :

    • Répertoriez les services du compte, d’une base de données spécifique ou d’un schéma spécifique : Par exemple, utilisez le filtre IN ACCOUNT pour répertorier les services de votre compte Snowflake, quelle que soit la base de données ou le schéma auquel appartiennent les services. Ceci est utile si vous avez des services Snowflake créés dans plusieurs bases de données et schémas dans votre compte. Comme toutes les autres commandes, SHOW SERVICES IN ACCOUNTS est limitée par les privilèges et ne renvoie que les services pour lesquels le rôle que vous utilisez dispose d’autorisations de visualisation.

      Vous pouvez également spécifier IN DATABASE ou IN SCHEMA pour établir la liste des services de la base de données ou du schéma actuel (ou spécifié).

    • Répertoriez les services exécutés dans un pool de calcul : Par exemple, utilisez le filtre IN COMPUTE POOL pour répertorier les services exécutés dans un pool de calcul.

    • Répertoriez les services qui commencent par un préfixe ou qui correspondent à un modèle : Vous pouvez appliquer les filtres LIKE et STARTS WITH pour filtrer les services par nom.

    • Répertoriez les services de travail ou excluez les services de travail de la liste : Vous pouvez utiliser SHOW JOB SERVICES ou SHOW SERVICES EXCLUDE JOBS pour répertorier uniquement les services de travail ou exclure certains services de travail.

    Vous pouvez également combiner ces options pour personnaliser la sortie de SHOW SERVICES.

  • Utilisez la commande SHOW SERVICE INSTANCES IN SERVICE pour récupérer les propriétés des instances de service.

  • Utilisez la commande SHOW SERVICE CONTAINERS IN SERVICE pour récupérer les propriétés et le statut des instances de service.

Surveillance des services

Snowpark Container Services propose des outils pour surveiller les pools de calcul de votre compte et les services exécutés sur ceux-ci. Pour plus d’informations, voir Snowpark Container Services : services de surveillance.

Gestion de l’accès aux points de terminaison de service

Le rôle propriétaire du service (le rôle que vous utilisez pour créer le service) a un accès complet au service et aux points de terminaison auxquels le service est exposé. Les autres rôles devront disposer du privilège USAGE sur les points de terminaison pour communiquer avec le service. Par exemple,

  • Le rôle propriétaire du client a besoin du privilège USAGE sur le point de terminaison. Client fait référence à une fonction de service ou à un service adressant des requêtes aux points de terminaison d’un autre service.

    • Pour créer une fonction de service faisant référence à un point de terminaison, l’utilisateur doit avoir accès au point de terminaison. En d’autres termes, le rôle de propriétaire de la fonction de service doit disposer du privilège USAGE sur le point de terminaison référencé dans CREATE FUNCTION.

    • Dans les communications de service à service, le rôle de propriétaire du service client (qui appelle le point de terminaison de l’autre service) a besoin du privilège USAGE sur le point de terminaison.

  • Un utilisateur effectuant des requêtes d’entrée depuis l’extérieur de Snowflake vers un point de terminaison public a besoin du privilège USAGE sur le point de terminaison.

Un rôle de service est un mécanisme permettant d’accorder des privilèges sur les points de terminaison de service à d’autres rôles. Vous avez ces options :

  • Utilisez le rôle de service par défaut : Snowflake définit un rôle de service par défaut (ALL_ENDPOINTS_USAGE) qui accorde le privilège USAGE sur tous les points de terminaison auxquels le service est exposé et accorde ce rôle de service par défaut au rôle propriétaire du service. Ainsi, le rôle de propriétaire peut accéder à tous les points de terminaison auxquels le service est exposé. Vous pouvez accorder ce rôle de service par défaut à d’autres rôles.

  • Créer un rôle de service : au lieu d’accorder des privilèges sur tous les points de terminaison à l’aide du rôle de service par défaut, vous pouvez définir un ou plusieurs rôles de service dans le Spécification de service. Dans la définition, indiquez les points de terminaison spécifiques pour lesquels le rôle obtient le privilège USAGE. Vous pouvez accorder (ou révoquer) le rôle de service à d’autres rôles à l’aide des commandes GRANT SERVICE ROLE et REVOKE SERVICE ROLE. Vous pouvez également utiliser ces commandes SHOW ROLES IN SERVICE, SHOW GRANTS pour afficher des informations sur les autorisations.

    Snowflake crée les rôles de service lorsque vous créez un service et les supprime lorsque vous supprimez le service.

    La création de rôles de service personnalisés vous permet d’accorder différentes autorisations d’accès pour différents scénarios. Par exemple, vous pouvez accorder une autorisation de rôle de service à un point de terminaison pour l’utiliser avec une fonction de service. Vous pouvez créer un autre rôle de service avec autorisation sur un point de terminaison public utilisé avec une UI Web.

Remarques :

  • Si vous utilisez le même rôle pour créer plusieurs services, comme le rôle propriétaire a accès à tous les points de terminaison, ces services peuvent communiquer entre eux de manière transparente, sans changement de configuration supplémentaire.

  • Si un service possède plusieurs conteneurs, ceux-ci peuvent communiquer entre eux via localhost, et ces communications sont locales au sein de chaque instance de service et ne font pas l’objet d’un contrôle d’accès basé sur les rôles.

Les sections suivantes fournissent des détails. Vous pouvez également consulter un tutoriel (Configurer et tester les privilèges des points de terminaison de service) qui fournit des instructions étape par étape pour explorer cette fonction.

Accorder le privilège USAGE sur tous les points de terminaison utilisant le rôle de service par défaut

Lorsque vous créez un service (y compris un service de tâche), Snowflake crée également un rôle par défaut, nommé ALL_ENDPOINTS_USAGE. Ce rôle dispose du privilège USAGE sur tous les points de terminaison auxquels le service est exposé. Vous pouvez attribuer à d’autres rôles ce rôle par défaut à l’aide de la commande GRANT SERVICE ROLE :

GRANT SERVICE ROLE my_echo_service_image!ALL_ENDPOINTS_USAGE TO ROLE some_other_role;
Copy

Les utilisateurs qui utilisent some_other_role ont le privilège USAGE sur tous les points de terminaison de service.

Lorsque vous supprimez un service, Snowflake supprime tous les rôles de service (rôle par défaut et rôles de service définis dans la spécification de service) associés au service et annule toutes les autorisations de rôle de service.

Accorder le privilège USAGE sur des points de terminaison spécifiques à l’aide des rôles de service définis dans la spécification

Utilisez les rôles de service pour gérer l’accès affiné aux points de terminaison de service. Vous définissez les rôles de service, ainsi que la liste des points de terminaison auxquels ils accordent le privilège USAGE, dans la spécification de service.

L’octroi de privilèges sur des points de terminaison spécifiques d’un service se fait en deux étapes :

  1. Définir un rôle de service : utilisez une spécification de service pour définir un rôle de service en fournissant un nom de rôle et une liste d’un ou plusieurs points de terminaison pour lesquels vous souhaitez accorder le privilège USAGE. Par exemple, dans le fragment de spécification suivant, le champ de premier niveau serviceRoles définit deux rôles de service, chacun ayant le privilège USAGE sur des points de terminaison spécifiques.

    spec:
    ...
    serviceRoles:                 # Optional list of service roles
    - name: <svc_role_name1>
      endpoints:                  # endpoints that role can access
      - <endpoint_name1>
      - <endpoint_name2>
    - name: <svc_role_name2>
      endpoints:
      - <endpoint_name3>
      - <endpoint_name4>
    
    Copy
  2. Accordez le rôle de service à d’autres rôles. La commande GRANT SERVICE ROLE vous permet d’attribuer le rôle de service à d’autres rôles (rôles de compte, d’application ou de base de données). Par exemple :

    GRANT SERVICE ROLE <service-name>!<svc_role_name1> TO ROLE <another-role>
    
    Copy

Utilisation d’un service

Après avoir créé un service, les utilisateurs du même compte (qui a créé le service) peuvent utiliser l’une des trois méthodes prises en charge suivantes pour l’utiliser. L’utilisateur devra accéder aux rôles disposant des privilèges nécessaires.

  • Utilisez le service à partir d’une requête SQL (Fonction de service) : vous créez une fonction de service, une fonction définie par l’utilisateur (UDF) associée à un service et l’utilisez dans une requête SQL pour communiquer avec le service. Pour un exemple, voir le tutoriel 1.

  • Utilisez le service depuis l’extérieur de Snowflake (Entrée) : vous pouvez déclarer un ou plusieurs points de terminaison de service comme publics pour autoriser l’accès réseau au service. Pour un exemple, voir le tutoriel 1.

  • Utilisez le service d’un autre service (Communications de service à service) : les services peuvent communiquer entre eux à l’aide du nom de DNS de service attribué par Snowflake pour la communication de service à service. Pour un exemple, voir Tutoriel 3.

Note

  • Un service de tâche s’exécute comme une tâche et se termine lorsqu’il est terminé. L’utilisation de la fonction de service ou de l’entrée pour communiquer avec un service de travail n’est pas prise en charge.

    • Vous ne pouvez pas associer une fonction de service à un point de terminaison d’un service de travail.

    • Vous ne pouvez pas créer un service de travail avec une spécification qui définit un point de terminaison public.

  • Les communications de service à service avec les services de travail sont prises en charge. Autrement dit, les services et les services de travail peuvent communiquer entre eux.

Les sections suivantes fournissent des détails.

Fonctions de service : utilisation d’un service à partir d’une requête SQL

Une fonction de service est une fonction définie par l’utilisateur (UDF) que vous créez à l’aide de CREATE FUNCTION (Snowpark Container Services). Cependant, au lieu d’écrire directement le code de l’UDF, vous associez l’UDF à votre point de terminaison de service. Notez que vous ne pouvez associer une fonction de service qu’à un point de terminaison de service prenant en charge le protocole HTTP ou HTTPS.

Par exemple, dans le tutoriel 1, vous créez un service nommé echo_service qui expose un point de terminaison (echoendoint) tel que défini dans la spécification du service :

spec:

  endpoints:
  - name: echoendpoint
    port: 8080
Copy

echoendpoint est un nom de point de terminaison convivial qui représente le port correspondant (8080). Pour communiquer avec ce point de terminaison de service, vous créez une fonction de service en fournissant les paramètres SERVICE et ENDPOINT comme indiqué :

CREATE FUNCTION my_echo_udf (text varchar)
   RETURNS varchar
   SERVICE=echo_service
   ENDPOINT=echoendpoint
   AS '/echo';
Copy

Le paramètre AS fournit le chemin HTTP vers le code de service. Vous obtenez cette valeur de chemin à partir du code du service. Par exemple, les lignes de code suivantes proviennent de service.py dans Tutoriel 1.

@app.post("/echo")
def echo():
...
Copy

Lorsque vous invoquez la fonction de service, Snowflake dirige la requête vers le point de terminaison et le chemin du service associé.

Note

Une fonction de service est utilisée pour communiquer avec un service, et non avec une tâche. En d’autres termes, vous ne pouvez associer qu’un service (et non une tâche) à une fonction de service.

Spécification de la taille du lot lors de l’envoi de données à un service pour augmenter la concurrence

Lorsque vous exécutez plusieurs instances de votre service, vous pouvez créer une fonction de service en spécifiant le paramètre facultatif MAX_BATCH_ROWS pour limiter la taille du lot, c’est-à-dire le nombre maximum de lignes que Snowflake envoie par lot au service. Par exemple, supposons que MAX_BATCH_ROWS soit 10 et que vous appeliez la fonction de service my_echo_udf avec 100 lignes d’entrée. Snowflake divise les lignes d’entrée en lots, chaque lot ayant au plus 10 lignes, et envoie une série de requêtes au service avec le lot de lignes dans le corps de la requête. La configuration de la taille des lots peut être utile lorsque le traitement prend un temps non négligeable, de même que la répartition des lignes sur tous les serveurs disponibles.

Vous pouvez utiliser ALTER FUNCTION pour modifier une fonction de service. La commande ALTER FUNCTION suivante modifie le point de terminaison de service auquel elle s’associe et la taille du lot :

ALTER FUNCTION my_echo_udf(VARCHAR)
   SET SERVICE=other_service
   ENDPOINT=otherendpoint
   MAX_BATCH_ROWS=100
Copy

Format d’échange de données

Pour l’échange de données entre une fonction de service et un conteneur d’application, Snowflake suit le même format que celui utilisé par les fonctions externes (voir Formats de données). Par exemple, supposons que vous ayez des lignes de données stockées dans une table (input_table) :

"Alex", "2014-01-01 16:00:00"
"Steve", "2015-01-01 16:00:00"

Pour envoyer ces données à votre service, vous invoquez la fonction de service en lui transmettant ces lignes en tant que paramètres :

SELECT service_func(col1, col2) FROM input_table;
Copy

Snowflake envoie une série de requêtes au conteneur, avec des lots de lignes de données dans le corps de la requête dans ce format :

{
   "data":[
      [
         0,
         "Alex",
         "2014-01-01 16:00:00"
      ],
      [
         1,
         "Steve",
         "2015-01-01 16:00:00"
      ],
      …
      [
         <row_index>,
         "<column1>",
         "<column2>"
      ],
   ]
}
Copy

Le conteneur renvoie ensuite la sortie dans le format suivant :

{
   "data":[
      [0, "a"],
      [1, "b"],
      …
      [ row_index,  output_column1]
   ]
}
Copy

L’exemple de sortie présenté suppose que le résultat est une table à une colonne avec des lignes (« a », « b »…).

Lorsque plusieurs instances de service sont en cours d’exécution, vous pouvez créer une fonction de service à l’aide du paramètre MAX_BATCH_ROWS afin de répartir les lignes d’entrée à traiter sur tous les serveurs disponibles. Pour plus d’informations, voir Spécification de la taille du lot lors de l’envoi de données à un service pour augmenter la concurrence.

Privilèges requis pour créer et gérer des fonctions de service

Pour créer et gérer des fonctions de service, un rôle doit disposer des privilèges suivants :

  • Pour créer une fonction de service : le rôle actuel doit avoir le privilège USAGE sur le service auquel il est fait référence.

  • Pour modifier une fonction de service : vous pouvez modifier une fonction de service et l’associer à un autre service. Le rôle actuel doit avoir le privilège USAGE sur le nouveau service.

  • Pour utiliser une fonction de service : le rôle actuel doit avoir le privilège USAGE sur la fonction de service, et le rôle de propriétaire de la fonction de service doit avoir le privilège USAGE sur le service associé.

L’exemple de script suivant montre comment vous pouvez accorder l’autorisation d’utiliser une fonction de service :

USE ROLE service_owner;
GRANT USAGE ON service service_db.my_schema.my_service TO ROLE func_owner;

USE ROLE func_owner;
CREATE OR REPLACE test_udf(v VARCHAR)
  RETURNS VARCHAR
  SERVICE=service_db.my_schema.my_service
  ENDPOINT=endpointname1
  AS '/run';

SELECT test_udf(col1) FROM some_table;

ALTER FUNCTION test_udf(VARCHAR) SET
  SERVICE = service_db.other_schema.other_service
  ENDPOINT=anotherendpoint;

GRANT USAGE ON FUNCTION test_udf(varchar) TO ROLE func_user;
USE ROLE func_user;
SELECT my_test_udf('abcd');
Copy

Entrée : utilisation d’un service en dehors de Snowflake

Un service peut exposer un ou plusieurs points de terminaison comme étant publics pour permettre aux utilisateurs d’utiliser le service à partir du Web public. Dans ce cas, Snowflake gère le contrôle d’accès. Remarque : l’entrée n’est autorisée qu’avec les points de terminaison HTTP ou HTTPS.

Marquez le point de terminaison comme public dans votre fichier de spécification de service :

spec
  ...
  endpoints
  - name: <endpoint name>
    port: <port number>
    public: true
Copy

Accès aux points de terminaison publics depuis l’extérieur de Snowflake et authentification

Tout le monde ne peut pas accéder aux points de terminaison publics exposés par un service. Seuls les utilisateurs du même compte Snowflake que le service et ayant le privilège USAGE sur le point de terminaison public peut accéder au point de terminaison public. Vous pouvez utiliser le rôle de service pour accorder ce privilège.

Vous pouvez accéder au point de terminaison public à l’aide d’un navigateur ou de manière programmatique. Snowflake utilise OAuth pour authentifier ces requêtes :

  • Accès à un point de terminaison public en utilisant un navigateur : Lorsqu’un navigateur est utilisé pour accéder à un point de terminaison public, Snowflake fournit une redirection automatique pour l’authentification de l’utilisateur. L’utilisateur est tenu de se connecter et, dans les coulisses, la connexion de l’utilisateur génère un jeton OAuth de Snowflake. Le jeton OAuth est ensuite utilisé pour envoyer une demande au point de terminaison de service.

  • Accès à un point de terminaison public par programmation : votre application peut utiliser l’authentification par paire de clés pour authentifier les requêtes adressées au point de terminaison public. Dans votre code, vous générez un jeton Web JSON (JWT) à partir de la paire de clés, échangez le jeton JWT avec Snowflake pour un jeton OAuth, puis utilisez le jeton OAuthpermettant d’authentifier les requêtes adressées au point de terminaison public d’un service.

Le tutoriel 1 fournit des instructions étape par étape pour vous permettre de tester l’accès aux points de terminaison publics.

L’authentification par paire de clés, comme indiqué dans le tutoriel 1, est la méthode recommandée pour authentifier les requêtes lors de l’accès aux points de terminaison publics. Le code suivant peut être utilisé pour l’authentification comme alternative à l’utilisation d’une paire de clés ; cependant, rien ne garantit que le code fonctionnera avec les futures versions de Connecteur Snowflake pour Python. Ce code Python utilise le connecteur Python pour générer d’abord un jeton de session qui représente votre identité. Le code utilise ensuite le jeton de session pour se connecter au point de terminaison public.

import snowflake.connector
import requests

ctx = snowflake.connector.connect(
   user="<username>",# username
   password="<password>", # insert password here
   account="<orgname>-<acct-name>",
   session_parameters={
      'PYTHON_CONNECTOR_QUERY_RESULT_FORMAT': 'json'
   })

# Obtain a session token.
token_data = ctx._rest._token_request('ISSUE')
token_extract = token_data['data']['sessionToken']

# Create a request to the ingress endpoint with authz.
token = f'\"{token_extract}\"'
headers = {'Authorization': f'Snowflake Token={token}'}
# Set this to the ingress endpoint URL for your service
url = 'http://<ingress_url>'

# Validate the connection.
response = requests.get(f'{url}', headers=headers)
print(response.text)

# Insert your code to interact with the application here
Copy

Dans le code :

  • Si vous ne connaissez pas les informations de votre compte (<orgname>-<acctname>), consultez le tutoriel Configuration commune.

  • Vous pouvez obtenir le ingress_url du point de terminaison public exposé par le service en utilisant SHOW ENDPOINTS.

En-têtes spécifiques à l’utilisateur dans les demandes d’entrée

Lorsqu’une requête pour un point de terminaison arrive, Snowflake transmet automatiquement l’en-tête suivant avec la requête HTTP au conteneur.

Sf-Context-Current-User: <user_name>
Copy

Le code de votre conteneur peut éventuellement lire cet en-tête, savoir qui est l’appelant et appliquer une personnalisation spécifique au contexte pour différents utilisateurs. En outre, Snowflake peut éventuellement inclure l’en-tête Sf-Context-Current-User-Email. Pour inclure cet en-tête, contactez le support Snowflake.

Communications de service à service

Les services peuvent communiquer entre eux en utilisant le nom DNS que Snowflake attribue automatiquement à chaque service. Pour un exemple, voir le tutoriel 3. Notez que si un point de terminaison de service est créé uniquement pour autoriser les communications de service à service, le protocole TCP doit être utilisé.

Le format du nom DNS est le suivant :

<service-name>.<schema-name>.<db-name>.snowflakecomputing.internal

Utilisez SHOW SERVICES (ou DESCRIBE SERVICE) pour obtenir le nom DNS d’un service. Le nom DNS qui précède est un nom complet. Les services créés dans le même schéma peuvent communiquer en utilisant uniquement <service-name>. Les services qui se trouvent dans la même base de données, mais dans des schémas différents doivent fournir le nom du schéma, par exemple <service-name>.<schema-name>.

Snowflake autorise les communications réseau entre les services créés par le même rôle et bloque les communications réseau entre les services créés par des rôles différents. Si vous souhaitez empêcher vos services de communiquer entre eux (pour des raisons de sécurité, par exemple), utilisez différents rôles Snowflake pour créer ces services.

Les noms DNS présentent les limitations suivantes :

  • Les noms de votre base de données, de votre schéma ou de votre service doivent être des étiquettes DNS valides. (Voir aussi https://www.ietf.org/rfc/rfc1035.html#section-2.3.1). Sinon, la création d’un service échouera.

  • Snowflake remplace le trait de soulignement (_) dans les noms (base de données, schéma et nom de service) par un tiret (-) dans le nom DNS.

  • Après avoir créé un service, ne modifiez pas le nom de la base de données ou du schéma, car Snowflake ne mettra pas à jour le nom DNS du service.

  • Un nom DNS est uniquement destiné aux communications internes au sein de Snowflake entre les services fonctionnant dans le même compte. Il n’est pas accessible depuis Internet.

Privilèges

Privilège

Utilisation

Remarques

USAGE

Pour communiquer avec un service, vous devez disposer du privilège USAGE sur le point de terminaison de service. Nécessaire pour créer une fonction de service, utiliser des points de terminaison publics et se connecter à partir d’un autre service.

MONITOR

Surveiller un service et obtenir son statut d’exécution.

OPERATE

Suspendre ou reprendre un service.

OWNERSHIP

Avoir le contrôle total du service. Un seul rôle peut détenir ce privilège sur un objet spécifique à la fois.

ALL [ PRIVILEGES ]

Accorder tous les privilèges, sauf OWNERSHIP, sur le service.