Tutoriel 3 : Créer et gérer les Snowpark Container Services

Introduction

Snowpark Container Services est une offre de conteneurs entièrement gérée, conçue pour faciliter le déploiement, la gestion et la mise à l’échelle des applications conteneurisées au sein de l’écosystème Snowflake. Grâce à cette fonctionnalité, vous pouvez exécuter des charges de travail conteneurisées directement dans Snowflake.

Dans ce tutoriel, vous apprendrez à utiliser Snowflake Python APIs pour gérer les composants dans Snowpark Container Services.

Important

Snowpark Container Services est généralement disponible pour les comptes Snowflake dans AWS. La prise en charge en avant-première est disponible pour les comptes dans Azure. Pour plus d’informations, voir Services de conteneurs Snowpark – Régions disponibles.

Conditions préalables

Avant de commencer ce tutoriel, vous devez suivre ces étapes :

  1. Installez Docker Desktop.

    Ce tutoriel fournit des instructions qui nécessitent Docker Desktop. Pour des instructions d’installation, voir https://docs.docker.com/get-docker/.

  2. Suivez les instructions de configuration commune, qui comprennent les étapes suivantes :

    • Configurez votre environnement de développement.

    • Installez le paquet Snowflake Python APIs.

    • Configurez votre connexion Snowflake.

    • Importez tous les modules nécessaires aux tutoriels d’API Python.

    • Créez un objet d’API Root.

    Note

    Si vous avez déjà terminé la configuration commune, vous pouvez ignorer cette étape et commencer le tutoriel.

Après avoir rempli ces conditions préalables, vous êtes prêt à commencer à utiliser l’API pour gérer Snowpark Container Services.

Configurez votre environnement de développement

Si vous utilisiez un notebook pour les précédents tutoriels Snowflake Python APIs, vous passez à un nouveau notebook dans ce tutoriel. Le notebook contiendra un exemple de code qui exécute un serveur Web NGINX utilisant Snowpark Container Services, qui s’exécutent tous dans Snowflake.

  1. Ouvrez un nouveau notebook à l’aide de votre éditeur de code préféré ou en exécutant la commande jupyter notebook.

  2. Dans la première cellule de votre notebook, exécutez le code suivant :

    from snowflake.core.database import Database
    from snowflake.core.schema import Schema
    
    database = root.databases.create(Database(name="spcs_python_api_db"), mode="orreplace")
    schema = database.schemas.create(Schema(name="public"), mode="orreplace")
    
    Copy

    En utilisant la connexion Snowflake et l’objet root que vous avez créé précédemment dans la configuration commune, vous créez une base de données nommée spcs_python_api_db et un schéma nommé public dans cette base de données. Vous enregistrez également les références qui représentent ces objets nouvellement créés. Vos composants Snowpark Container Services vivront dans cette base de données et ce schéma.

Aperçu des Snowpark Container Services

Avant de poursuivre le tutoriel, passez brièvement en revue les principaux composants de Snowpark Container Services. Pour exécuter des applications conteneurisées dans Snowpark Container Services, vous travaillez généralement avec les objets suivants :

  • Référentiel d’images : fournit une unité de stockage où vous pouvez télécharger les images de votre application dans votre compte Snowflake.

    Snowpark Container Services fournit un service de registre d’images conforme à OCIv2 qui permet aux clients OCI (tels que la CLI Docker et SnowSQL) d’accéder à un registre d’images dans votre compte Snowflake. Grâce à ces clients, vous pouvez charger les images de vos applications vers un référentiel.

    Pour plus d’informations, voir Utilisation d’un registre et d’un référentiel d’images.

  • Pool de calcul : représente un ensemble de ressources de calcul (nœuds de machine virtuelle).

    Ces ressources de calcul sont analogues, mais pas équivalentes, aux entrepôts virtuels Snowflake. Le service (dans ce cas, votre service NGINX) s’exécutera dans le pool de calcul. Les services à forte intensité de calcul nécessitent des pools de calcul très puissants avec de nombreux cœurs et de nombreux GPUs, tandis que les services moins intensifs peuvent s’exécuter dans des pools de calcul plus petits avec moins de cœurs.

    Pour plus d’informations, voir Utilisation de pools de calcul.

  • Service : fournit un moyen d’exécuter un conteneur d’application.

    Au minimum, les services nécessitent une spécification et un pool de calcul. Une spécification contient les informations nécessaires à l’exécution du conteneur d’application, telles que le chemin d’accès à une image de conteneur et les points de terminaison que les services exposeront. La spécification est écrite en YAML. Le pool de calcul est l’ensemble des ressources de calcul dans lesquelles le service s’exécutera.

    Pour plus d’informations, voir Utilisation des services.

Passez aux étapes suivantes pour créer et configurer ces objets.

Créer un référentiel d’images

Dans cette section, vous créez d’abord un référentiel d’images à l’aide de Snowflake Python APIs. Ensuite, vous allez chercher une image de l’application NGINX à partir de Docker Hub et télécharger l’image dans le référentiel d’images à l’aide de la CLI Docker.

Créer un référentiel et obtenir des informations sur le référentiel

  1. Dans la cellule suivante de votre notebook, exécutez le code suivant :

    from snowflake.core.image_repository import ImageRepository
    
    my_repo = ImageRepository("MyImageRepository")
    schema.image_repositories.create(my_repo)
    
    Copy

    Dans cet exemple de code, vous créez un référentiel d’images dans la base de données et le schéma que vous avez créés précédemment dans ce tutoriel.

  2. Pour confirmer que le référentiel a été créé avec succès en récupérant ses détails et en imprimant son nom, exécutez le code suivant :

    my_repo_res = schema.image_repositories["MyImageRepository"]
    my_repo = my_repo_res.fetch()
    print(my_repo.name)
    
    Copy
  3. Vous aurez besoin d’informations sur le référentiel (l’URL du référentiel et le nom d’hôte du registre) avant de pouvoir construire et charger l’image.

    Pour obtenir l’URL du référentiel, dans votre cellule suivante, exécutez le code suivant :

    repositories = schema.image_repositories
      for repo_obj in repositories.iter():
        print(repo_obj.repository_url)
    
    Copy
    • L’attribut repository_url dans la sortie fournit l’URL. Par exemple :

      <orgname>-<acctname>.registry.snowflakecomputing.com/spcs_python_api_db/public/myimagerepository
      
    • Le nom d’hôte dans l’URL du référentiel est le nom d’hôte du registre. Par exemple :

      <orgname>-<acctname>.registry.snowflakecomputing.com
      

Extraire l’image NGINX et la charger dans le référentiel

  1. Pour que Docker puisse charger une image en votre nom dans votre référentiel, vous devez d’abord authentifier Docker avec Snowflake.

    Pour authentifier Docker avec le registre Snowflake, ouvrez un terminal de ligne de commande et exécutez la commande docker login suivante en utilisant la CLI de Docker :

    docker login <registry_hostname> -u <username>
    
    Copy
    • registry_hostname : spécifiez le nom d’hôte dans repository_url à partir du résultat de l’étape précédente.

    • username : indiquez votre nom d’utilisateur Snowflake. Docker vous demandera votre mot de passe.

    Exemple

    docker login myorg-myacct.registry.snowflakecomputing.com -u admin
    
    Copy
  2. Récupérez la version intermédiaire AMD64 de l’image NGINXde Docker Hub:

    docker pull --platform linux/amd64 amd64/nginx
    
    Copy
  3. Étiquetez l’image amd64/nginx avec l’URL du référentiel d’images Snowflake :

    docker tag docker.io/amd64/nginx:latest <repository_url>/<image_name>
    
    Copy

    Exemple

    docker tag docker.io/amd64/nginx:latest myorg-myacct.registry.snowflakecomputing.com/spcs_python_api_db/public/myimagerepository/amd64/nginx:latest
    
    Copy

    Une balise est un identificateur personnalisé, lisible par l’homme, que vous pouvez éventuellement utiliser pour identifier une version ou une variante spécifique d’une image.

  4. Chargez l’image dans le référentiel de votre compte Snowflake :

    docker push <repository_url>/<image_name>
    
    Copy

    Exemple

    docker push myorg-myacct.registry.snowflakecomputing.com/spcs_python_api_db/public/myimagerepository/amd64/nginx:latest
    
    Copy

Créer un pool de calcul

Pour définir et créer un pool de calcul, dans la cellule suivante de votre notebook, exécutez le code suivant :

new_compute_pool_def = ComputePool(
    name="MyComputePool",
    instance_family="CPU_X64_XS",
    min_nodes=1,
    max_nodes=2,
)

new_compute_pool = root.compute_pools.create(new_compute_pool_def)
Copy

Dans cette cellule, vous définissez un pool de calcul à l’aide du constructeur ComputePool en fournissant des valeurs pour les attributs suivants :

  • instance_family : la famille d’instances identifie le type de machine à provisionner pour les nœuds du pool de calcul.

    Chaque type de machine fournit une quantité différente de ressources de calcul à ses pools de calcul. Dans cette cellule, vous utilisez le plus petit type de machine disponible, CPU_X64_XS. Pour plus d’informations, voir CREATE COMPUTE POOL.

  • min_nodes : le nombre minimum de nœuds pour démarrer un pool de calcul.

  • max_nodes : le nombre maximal de nœuds que le pool de calcul peut contenir.

    Lorsque vous créez un pool de calcul, Snowflake le lance avec le nombre minimum de nœuds spécifié. Snowflake gère ensuite automatiquement la mise à l’échelle et crée de nouveaux nœuds, jusqu’au nombre maximal spécifié, lorsque les nœuds en cours d’exécution ne peuvent pas supporter de charge de travail supplémentaire.

Ensuite, vous créez le pool de calcul en transmettant la définition du pool de calcul à compute_pools.create().

Créez un service

À l’aide du référentiel d’images et du pool de calcul que vous avez configurés, vous pouvez désormais définir et créer votre service. Un service fait référence à une collection de conteneurs exécutés dans un pool de calcul, qui sont tous orchestrés dans Snowflake.

  1. Pour récupérer le référentiel contenant votre image de conteneur, dans la cellule suivante de votre notebook, exécutez le code suivant :

    image_repository = schema.image_repositories["MyImageRepository"]
    
    Copy

    Ce référentiel se trouve dans votre compte Snowflake, répertorié comme une zone de préparation dans le schéma PUBLIC. Vous avez besoin de cette référence pour récupérer les informations de l’image du conteneur à l’étape suivante.

  2. Pour définir et créer votre service, dans votre cellule suivante, exécutez le code suivant :

    from textwrap import dedent
    from io import BytesIO
    from snowflake.core.service import Service, ServiceSpecInlineText
    
    specification = dedent(f"""\
        spec:
          containers:
          - name: web-server
            image: {image_repository.fetch().repository_url}/amd64/nginx:latest
          endpoints:
          - name: ui
            port: 80
            public: true
        """)
    
    service_def = Service(
        name="MyService",
        compute_pool="MyComputePool",
        spec=ServiceSpecInlineText(specification),
        min_instances=1,
        max_instances=1,
    )
    
    nginx_service = schema.services.create(service_def)
    
    Copy

    Cette cellule définit la spécification du service et le service, puis crée le service pour votre serveur Web NGINX. Les définitions de la spécification et du service ont les propriétés suivantes :

    • specification – Vous définissez la spécification à l’aide d’un littéral de chaîne formaté Python (f-string). La chaîne est formatée comme YAML.

      La spécification contient le nom du conteneur, un chemin vers l’image du conteneur et les points de terminaison que le service exposera pour l’accès public. Dans cet exemple, vous définissez la spécification en ligne, mais vous pouvez également définir une spécification en tant que référence à un fichier .yml dans une zone de préparation.

    • service_def – Vous définissez un service avec le constructeur Service , transmettant un nom pour le service, le pool de calcul dans lequel il s’exécutera, un chemin vers la spécification et le nombre total d’instances pour le service.

      Dans cette cellule, vous utilisez ServiceSpecInlineText pour définir la valeur de spec parce que vous définissez la spécification en ligne comme une chaîne f. Vous pouvez spécifier le service pour exécuter plusieurs instances, mais dans cet exemple, vous spécifiez une seule instance du service à exécuter en définissant min_instances et max_instances sur 1.

  3. Pour vérifier le statut du service, dans votre cellule suivante, exécutez le code suivant :

    from pprint import pprint
    
    pprint(nginx_service.get_service_status(timeout=5))
    
    Copy

    Le résultat devrait être similaire à ceci :

    {'auto_resume': True,
    'auto_suspend_secs': 3600,
    'instance_family': 'CPU_X64_XS',
    'max_nodes': 1,
    'min_nodes': 1,
    'name': 'MyService'}
    

Utilisez votre service

Après avoir créé le service, Snowpark Container Services prendra quelques minutes pour provisionner les points de terminaison nécessaires pour accéder au service.

  1. Pour vérifier le statut des points de terminaison, dans la cellule suivante de votre notebook, exécutez le code suivant :

    import json, time
    
    while True:
        public_endpoints = nginx_service.fetch().public_endpoints
        try:
            endpoints = json.loads(public_endpoints)
        except json.JSONDecodeError:
            print(public_endpoints)
            time.sleep(15)
        else:
            break
    
    Copy

    L’exemple de code n’est pas spécifique à Snowpark Container Services ou Snowflake Python APIs – cela fournit simplement un moyen pratique de vérifier si les points de terminaison sont prêts. Notez que vous récupérez les points de terminaison en appelant .fetch().public_endpoints sur votre objet de service.

    Le résultat devrait être similaire à ceci :

    Endpoints provisioning in progress... check back in a few minutes
    Endpoints provisioning in progress... check back in a few minutes
    Endpoints provisioning in progress... check back in a few minutes
    
  2. Une fois les points de terminaison provisionnés, vous pouvez ouvrir les points de terminaison publics dans votre navigateur.

    Dans votre cellule suivante, exécutez le code suivant :

    import webbrowser
    
    print(f"Visiting {endpoints['ui']} in your browser. You might need to log in there.")
    webbrowser.open(f"https://{endpoints['ui']}")
    
    Copy

    Le résultat devrait être similaire à ceci :

    Visiting myorg-myacct.snowflakecomputing.app in your browser. You might need to log in there.
    

    En cas de succès, vous verrez la page de réussite NGINX dans votre navigateur lors de la visite du point de terminaison :

    Capture d'écran de la page de réussite du serveur Web NGINX dans un navigateur
  3. Vous pouvez utiliser l’API Python pour gérer votre nouveau service.

    Par exemple, pour suspendre le service puis vérifier son statut, exécutez le code suivant :

    from time import sleep
    
    nginx_service.suspend()
    sleep(3)
    print(nginx_service.get_service_status(timeout=5))
    
    Copy
  4. Pour reprendre le service, exécutez le code suivant :

    nginx_service.resume()
    sleep(3)
    print(nginx_service.get_service_status(timeout=5))
    
    Copy

Avec seulement quelques lignes de Python, vous avez pu exécuter un serveur Web NGINX dans Snowflake utilisant Snowpark Container Services.

Nettoyage

Snowflake facture les nœuds de pool de calcul actifs sur votre compte. Pour éviter des frais indésirables, suspendez d’abord le service et le pool de calcul, puis supprimez les deux objets.

  1. Pour suspendre le pool de calcul et le service, dans la cellule suivante de votre notebook, exécutez le code suivant :

    new_compute_pool_def.suspend()
    nginx_service.suspend()
    
    Copy
  2. Pour supprimer le pool de calcul et le service, exécutez le code suivant :

    new_compute_pool_def.drop()
    nginx_service.drop()
    
    Copy

Quelle est la prochaine étape ?

Félicitations ! Dans ce tutoriel, vous avez appris les principes fondamentaux de la gestion des composants dans Snowpark Container Services en utilisant Snowflake Python APIs.

Résumé

En chemin, vous avez réalisé ces étapes :

  • Créer un référentiel d’images dans lequel vous téléchargez les images de votre application.

  • Créer un pool de calcul dans lequel votre service s’exécute.

  • Créer un service pour exécuter votre conteneur d’application.

  • Utiliser et gérer votre service.

  • Nettoyer vos objets de ressources Snowpark Container Services en les suspendant et en les supprimant.

Ressources supplémentaires

Pour plus d’exemples d’utilisation de l’API pour gérer d’autres types d’objets dans Snowflake, consultez les guides de développement suivants :

Guide

Description

Gestion des bases de données, schémas, tables et vues Snowflake avec Python

Utilisez l’API pour créer et gérer des bases de données, des schémas et des tables.

Gestion des utilisateurs, des rôles et des attributions Snowflake avec Python

Utilisez l’API pour créer et gérer les utilisateurs, les rôles et les autorisations.

Gestion des ressources de chargement et de déchargement de données avec Python

Utilisez l’API pour créer et gérer les ressources de chargement et de déchargement de données, y compris les volumes externes, les canaux et les zones de préparation.

Gestion des tâches et des graphiques de tâches Snowflake avec Python

Utilisez l’API pour créer, exécuter et gérer des tâches et des graphiques de tâches.