Gestion de Snowpark Container Services (y compris les fonctions de service) avec Python¶
Vous pouvez utiliser Python pour gérer Snowpark Container Services, un service de conteneurs entièrement géré par lequel vous pouvez déployer, gérer et mettre à l’échelle des applications conteneurisées. Pour une vue d’ensemble de Snowpark Container Services, voir À propos de Snowpark Container Services.
Avec les Snowflake Python APIs, vous pouvez gérer des pools de calcul, des référentiels d’images et des services.
Conditions préalables¶
Les exemples de cette rubrique supposent que vous ayez ajouté le code nécessaire pour vous connecter à Snowflake et créer un objet Root
à partir duquel utiliser les Snowflake Python APIs.
Par exemple, le code suivant utilise les paramètres de connexion définis dans un fichier de configuration pour créer une connexion à Snowflake.
from snowflake.core import Root
from snowflake.snowpark import Session
session = Session.builder.config("connection_name", "myconnection").create()
root = Root(session)
En utilisant l’objet Session
obtenu, le code crée un objet Root
pour utiliser les types et les méthodes de l’API. Pour plus d’informations, voir Connexion à Snowflake avec Snowflake Python APIs.
Gestion des pools de calcul¶
Vous pouvez gérer des pools de calcul, qui sont des collections de nœuds de machines virtuelles (VM) sur lesquels Snowflake exécute vos tâches et services Snowpark Container Services.
Les Snowflake Python APIs représentent des pools de calcul de deux types distincts :
ComputePool
: affiche les propriétés d’un pool de calcul, telles que son entrepôt, le nombre de nœuds maximum et minimum, ainsi que les paramètres de reprise et de suspension automatiques.ComputePoolResource
: expose des méthodes permettant d’effectuer des actions sur les pools de calcul, telles que la récupération d’un objetComputePool
correspondant, ainsi que la suspension, la reprise et l’arrêt des pools.
Pour plus d’informations sur les pools de calcul, voir Snowpark Container Services : utilisation des pools de calcul.
Création d’un pool de calcul¶
Vous pouvez créer une base de données en appelant la méthode ComputePoolCollection.create
et en lui transmettant un objet ComputePool
représentant le pool de calcul que vous souhaitez créer.
Pour créer un pool de calcul, créez d’abord un objet ComputePool
qui spécifie les propriétés du pool comme suit :
Nom du pool de calcul
Nombre maximum et minimum de nœuds que le pool contiendra
Nom de la famille d’instances identifiant le type de machine à provisionner pour les nœuds du pool
Si le pool doit reprendre automatiquement lorsqu’un service ou une tâche lui est soumis
Le code de l’exemple suivant crée un objet ComputePool
représentant un pool nommé my_compute_pool
:
from snowflake.core.compute_pool import ComputePool
compute_pool = ComputePool(name="my_compute_pool", min_nodes=1, max_nodes=2, instance_family="CPU_X64_XS", auto_resume=False)
root.compute_pools.create(compute_pool)
Le code crée ensuite le pool de calcul en transmettant l’objet ComputePool
à la méthode ComputePoolCollection.create
.
Obtention des détails d’un pool de calcul¶
Vous pouvez obtenir des informations sur un pool de calcul en appelant la méthode ComputePoolResource.fetch
qui renvoie un objet ComputePool
.
Le code de l’exemple suivant permet d’obtenir des informations sur un pool de calcul nommé my_compute_pool
:
compute_pool = root.compute_pools["my_compute_pool"].fetch()
print(compute_pool.to_dict())
Répertorier les pools de calcul¶
Vous pouvez répertorier les pools de calcul en utilisant la méthode iter
, qui renvoie un itérateur PagedIter
.
Le code de l’exemple suivant répertorie les pools de calcul dont le nom commence par my
:
compute_pools = root.compute_pools.iter(like="my%")
for compute_pool in compute_pools:
print(compute_pool.name)
Effectuer des opérations sur le pool de calcul¶
Vous pouvez effectuer des opérations courantes sur les pools de calcul, telles que la suspension, la reprise et l’arrêt des pools, à l’aide d’un objet ComputePoolResource
qui vous pouvez obtenir en utilisation la méthode ComputePool.fetch
.
Le code de l’exemple suivant suspend, reprend et arrête le pool de calcul my_compute_pool
:
compute_pool_res = root.compute_pools["my_compute_pool"]
compute_pool_res.suspend()
compute_pool_res.resume()
compute_pool_res.stop_all_services()
Le code utilise la méthode Root.compute_pools
pour créer un objet ComputePool
représentant le pool de calcul. À partir de l’objet ComputePool
, il récupère un objet ComputePoolResource
avec lequel il effectue des opérations de pool de calcul.
Gestion des référentiels d’images¶
Vous pouvez gérer des référentiels d’images, qui stockent des images pour les applications que vous exécutez sur des services de conteneurs.
Un référentiel d’images est un objet de niveau schéma. Lorsque vous créez ou faites référence à un référentiel, vous le faites dans le contexte de son schéma.
Les Snowflake Python APIs représentent des référentiels d’images de deux types distincts :
ImageRepository
: expose les propriétés d’un référentiel d’images telles que les noms de sa base de données et de son schéma, l’URL du référentiel et le propriétaire.ImageRepositoryResource
: expose des méthodes que vous pouvez utiliser pour extraire un objetImageRepository
correspondant et pour supprimer la ressource de référentiel d’images.
Pour plus d’informations sur les référentiels d’images, voir Snowpark Container Services : utilisation d’un registre et d’un référentiel d’images.
Création d’un référentiel d’images¶
Pour créer un référentiel d’images, il faut d’abord créer un objet ImageRepository
qui spécifie le nom du référentiel.
Le code de l’exemple suivant crée un objet ImageRepository
représentant un référentiel nommé my_repo
:
from snowflake.core.image_repository import ImageRepository
my_repo = ImageRepository("my_repo")
root.databases["my_db"].schemas["my_schema"].image_repositories.create(my_repo)
Le code crée ensuite le référentiel d’images en transmettant l’objet ImageRepository
à la méthode ImageRepositoryCollection.create
, créant ainsi le référentiel d’images dans la base de données my_db
et le schéma my_schema
.
Obtention des détails du référentiel d’images¶
Vous pouvez obtenir des informations sur un référentiel d’images en appelant la méthode ImageRepositoryResource.fetch
, qui renvoie un objet ImageRepository
.
Le code de l’exemple suivant récupère un objet ImageRepository
représentant le référentiel d’images my_repo
et affiche le nom du propriétaire du référentiel :
my_repo_res = root.databases["my_db"].schemas["my_schema"].image_repositories["my_repo"]
my_repo = my_repo_res.fetch()
print(my_repo.owner)
Répertorier des référentiels d’images¶
Vous pouvez répertorier les référentiels d’images d’un schéma spécifié via la méthode iter
, qui renvoie un itérateur PagedIter
d’objets ImageRepository
.
Le code de l’exemple suivant répertorie les noms des référentiels dans la base de données my_db
et le schéma my_schema
:
repo_list = root.databases["my_db"].schemas["my_schema"].image_repositories.iter()
for repo_obj in repo_list:
print(repo_obj.name)
Suppression d’un référentiel d’images¶
Vous pouvez supprimer un référentiel d’images en utilisant la méthode ImageRepositoryResource.drop
.
Le code dans l’exemple suivant supprime le référentiel my_repo
:
my_repo_res = root.databases["my_db"].schemas["my_schema"].image_repositories["my_repo"]
my_repo_res.drop()
Gestion des services et des fonctions de service¶
Vous pouvez gérer les services, qui exécutent les conteneurs d’application jusqu’à ce que vous les arrêtiez. Snowflake redémarre automatiquement un service si le conteneur de service s’arrête. De cette manière, le service fonctionne effectivement sans interruption.
Un service est un objet de niveau schéma. Lorsque vous créez ou faites référence à un service, vous le faites dans le contexte de son schéma.
Les Snowflake Python APIs représentent des services avec deux types distincts :
Service
: expose les propriétés d’un service telles que sa spécification, le nombre d’instances minimum et maximum, le nom de la base de données et du schéma.ServiceResource
: expose des méthodes que vous pouvez utiliser pour récupérer un objetService
correspondant, suspendre et reprendre le service et obtenir son statut.
Pour plus d’informations sur les services, voir Snowpark Container Services : utilisation des tâches.
Création d’un service¶
Pour créer un service, vous exécutez la méthode services.create
, en transmettant un objet Service
représentant le service que vous souhaitez créer.
Vous créez un service à partir d’un fichier de spécification de service .yaml
qui a été chargé dans une zone de préparation. Pour plus d’informations sur la création d’une spécification de service, voir Référence Spécification de service.
Chargement de la spécification¶
Si vous créez un service à partir d’une spécification qui n’a pas encore été chargée dans une zone de préparation, vous pouvez charger la spécification à l’aide d’un objet Snowpark FileOperation.
Le code de l’exemple suivant utilise la méthode FileOperation.put
pour charger une spécification sous forme de fichier :
session.file.put("/local_location/my_service_spec.yaml", "@my_stage")
Le code de l’exemple suivant utilise la méthode FileOperation.put_stream
pour charger une spécification sous forme de chaîne :
service_spec_string = """
// Specification as a string.
"""
session.file.put_stream(StringIO(sepc_in_string), "@my_stage/my_service_spec.yaml")
Création du service¶
Pour créer un service à partir d’une spécification en zone de préparation, créez d’abord un objet Service
qui spécifie les propriétés du service comme suit :
Nom du service
Nombre maximum et minimum d’instances de service que Snowflake peut créer
Pool de calcul auquel le service doit être ajouté
Emplacement de la zone de préparation et nom de la spécification
Le code de l’exemple suivant crée un objet Service
représentant un service nommé my_service
à partir d’une spécification dans @my_stage/my_service_spec.yaml
:
from snowflake.core.service import Service, ServiceSpec
my_service = Service(name="my_service", min_instances=1, max_instances=2, compute_pool="my_compute_pool", spec=ServiceSpec("@my_stage/my_service_spec.yaml"))
root.databases["my_db"].schemas["my_schema"].services.create(my_service)
Le code crée ensuite le service en transmettant l’objet Service
à la méthode ServiceCollection.create
, créant ainsi le service dans la base de données my_db
et le schéma my_schema
.
Vous pouvez également créer un service à partir d’une spécification que vous fournissez sous forme de texte en ligne, comme le montre l’exemple suivant. La fonction ServiceSpec
prend un seul argument de chaîne spec
. Si la chaîne commence par @
, la fonction l’interprète et la valide comme un chemin de fichier de zone de préparation. Sinon, la chaîne est transmise en tant que texte en ligne.
from textwrap import dedent
from snowflake.core.service import Service, ServiceSpec
spec_text = dedent(f"""\
spec:
containers:
- name: hello-world
image: repo/hello-world:latest
endpoints:
- name: hello-world-endpoint
port: 8080
public: true
""")
my_service = Service(name="my_service", min_instances=1, max_instances=2, compute_pool="my_compute_pool", spec=ServiceSpec(spec_text))
root.databases["my_db"].schemas["my_schema"].services.create(my_service)
Création d’une fonction de service¶
Une fois le service opérationnel, vous pouvez créer une fonction de service qui communique avec le point de terminaison de service. Une fonction de service est une fonction définie par l’utilisateur (UDF) que vous créez et associez à un service dans Snowpark Container Services. Pour plus d’informations, voir Fonctions de service : utilisation d’un service à partir d’une requête SQL.
Le code de l’exemple suivant crée une UDF nommée my-udf
qui spécifie le service hello-world
et le point de terminaison hello-world-endpoint
que vous avez précédemment défini :
from snowflake.core import CreateMode
from snowflake.core.function import FunctionArgument, ServiceFunction
root.databases["my_db"].schemas["my_schema"].functions.create(
ServiceFunction(
name="my-udf",
arguments=[
FunctionArgument(name="input", datatype="TEXT")
],
returns="TEXT",
service="hello-world",
endpoint="'hello-world-endpoint'",
path="/hello-world-path",
max_batch_rows=5,
),
mode = CreateMode.or_replace
)
Appel d’une fonction de service¶
Une fois la fonction de service créée, vous pouvez alors appeler la fonction pour la tester.
Le code de l’exemple suivant appelle la fonction de service my-udf
que vous avez créée précédemment :
result = root.databases["my_db"].schemas["my_schema"].functions["my-udf(TEXT)"].execute_function(["test"])
print(result)
Obtention d’informations sur les services¶
Vous pouvez obtenir des informations sur un service Snowflake en appelant la méthode ServiceResource.fetch
, qui renvoie un objet Service
.
Le code de l’exemple suivant permet d’obtenir des informations sur un service nommé my_service
:
my_service = root.databases["my_db"].schemas["my_schema"].services["my_service"].fetch()
Répertorier des services¶
Vous pouvez répertorier les services d’un schéma spécifié en utilisant la méthode iter
qui renvoie un itérateur PagedIter
d’objets Service
.
Le code de l’exemple suivant répertorie les services dont le nom commence par my
:
services = root.databases["my_db"].schemas["my_schema"].services.iter(like="my%")
for service_obj in services:
print(service_obj.name)
Effectuer des opérations de service¶
Vous pouvez effectuer des opérations de service courantes, telles que la suspension, la reprise et l’obtention du statut du service, à l’aide d’un objet ServiceResource
.
Le code de l’exemple suivant suspend et reprend le service my_service
puis récupère le statut du service :
my_service_res = root.databases["my_db"].schemas["my_schema"].services["my_service"]
my_service_res.suspend()
my_service_res.resume()
status = my_service_res.get_service_status(10)