Verwalten von Snowpark Container Services (einschließlich Dienstfunktionen) mit Python

Sie können Python verwenden, um Snowpark Container Services zu verwalten, einen vollständig verwalteten Containerdienst, über den Sie containerisierte Anwendungen bereitstellen, verwalten und skalieren können. Eine Übersicht zu Snowpark Container Services finden Sie unter Allgemeine Informationen zu Snowpark Container Services.

Mit dem Snowflake Python APIs können Sie Computepools, Image-Repositorys und Dienste verwalten.

Voraussetzungen

Die Beispiele in diesem Thema gehen davon aus, dass Sie Code hinzugefügt haben, um eine Verbindung zu Snowflake herzustellen und ein Root-Objekt zu erstellen, von dem aus Sie die Snowflake Python APIs verwenden können.

Beispielsweise verwendet der folgende Code Verbindungsparameter, die in einer Konfigurationsdatei definiert sind, um eine Verbindung zu Snowflake zu erstellen:

from snowflake.core import Root
from snowflake.snowpark import Session

session = Session.builder.config("connection_name", "myconnection").create()
root = Root(session)
Copy

Unter Verwendung des resultierenden Session-Objekts erstellt der Code ein Root-Objekt, das die Typen und Methoden der API verwendet. Weitere Informationen dazu finden Sie unter Verbinden mit Snowflake mit dem Snowflake Python APIs.

Verwalten von Computepools

Sie können Computepools verwalten, bei denen es sich um Sammlungen von VM-Knoten (virtuelle Maschinen) handelt, auf denen Snowflake Ihre Snowpark Container Services-Jobs und -Dienste ausführt.

Die Snowflake Python APIs stellt Computepools mit zwei verschiedenen Typen dar:

  • ComputePool: Zeigt die Eigenschaften eines Computepools an, z. B. sein Warehouse, die maximale und minimale Anzahl von Knoten sowie die Einstellungen für das automatische Anhalten und Fortsetzen.

  • ComputePoolResource: Stellt Methoden für das Ausführen von Aktionen auf Computepools zur Verfügung, wie z. B. das Abrufen eines entsprechenden ComputePool-Objekts und das Anhalten, Fortsetzen und Beenden von Pools.

Weitere Informationen zu Computepools finden Sie unter Snowpark Container Services: Verwenden von Computepools.

Erstellen von Computepools

Sie können einen Computepool erstellen, indem Sie die Methode ComputePoolCollection.create aufrufen und ein ComputePool-Objekt übergeben, das den zu erstellenden Computepool repräsentiert.

Um einen Computepool zu erstellen, erstellen Sie zunächst ein ComputePool-Objekt, das Pool-Eigenschaften wie die folgenden angibt:

  • Name des Computepools

  • Maximale und minimale Anzahl von Knoten, die der Pool enthalten soll

  • Name der Instanz-Familie, die den Maschinentyp angibt, der für die Knoten im Pool bereitgestellt werden soll

  • Ob der Pool automatisch fortgesetzt werden soll, wenn ein Dienst oder Job an ihn übermittelt wird

Der Code im folgenden Beispiel erstellt ein ComputePool-Objekt, das einen Pool namens my_compute_pool repräsentiert:

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)
Copy

Der Code erstellt dann den Computepool, indem das ComputePool-Objekt an die Methode ComputePoolCollection.create übergeben wird.

Abrufen von Details zum Computepool

Sie können Informationen zu einem Computepool erhalten, indem Sie die Methode ComputePoolResource.fetch aufrufen, die ein ComputePool-Objekt zurückgibt.

Der Code im folgenden Beispiel ruft Informationen über einen Pool namens my_compute_pool ab:

compute_pool = root.compute_pools["my_compute_pool"].fetch()
print(compute_pool.to_dict())
Copy

Auflisten von Computepools

Zum Auflisten der Computepools können Sie die Methode iter verwenden, die einen PagedIter-Iterator zurückgibt.

Der Code im folgenden Beispiel listet Computepools auf, deren Name mit my beginnt:

compute_pools = root.compute_pools.iter(like="my%")
for compute_pool in compute_pools:
  print(compute_pool.name)
Copy

Ausführen von Computepool-Operationen

Mit einem ComputePoolResource-Objekt, das Sie mit der ComputePool.fetch-Methode abrufen, können Sie allgemeine Computepool-Operationen wie das Anhalten, Fortsetzen und Beenden von Pools ausführen.

Der Code im folgenden Beispiel hält den Computepool my_compute_pool an, setzt ihn fort und beendet ihn:

compute_pool_res = root.compute_pools["my_compute_pool"]
compute_pool_res.suspend()
compute_pool_res.resume()
compute_pool_res.stop_all_services()
Copy

Der Code verwendet die Methode Root.compute_pools, um ein Objekt ComputePool zu erstellen, das den Computepool repräsentiert. Über das ComputePool-Objekt wird ein ComputePoolResource-Objekt abgerufen, mit dem Computepool-Operationen ausgeführt werden können.

Verwalten von Image-Repositorys

Sie können Image-Repositorys verwalten, in denen Images für Anwendungen gespeichert werden, die Sie in Containerdiensten ausführen.

Ein Image-Repository ist ein Objekt auf Schemaebene. Wenn Sie eine Tabelle erstellen oder auf diese verweisen, tun Sie dies im Kontext des zugehörigen Schemas.

Die Snowflake Python APIs stellt Image-Repositorys mit zwei verschiedenen Typen dar:

  • ImageRepository: Zeigt die Eigenschaften eines Image-Repository wie Datenbank- und Schemanamen, Repository-URL und Eigentümer an.

  • ImageRepositoryResource: Stellt Methoden zur Verfügung, mit denen Sie ein entsprechendes ImageRepository-Objekt abrufen und die Ressource des Image-Repositorys ablegen können.

Weitere Informationen zu Image-Repositorys finden Sie unter Snowpark Container Services: Verwenden von Image-Registry und Image-Repository.

Erstellen von Image-Repositorys

Um ein Image-Repository zu erstellen, erstellen Sie zunächst ein ImageRepository-Objekt, das den Repository-Namen angibt.

Der Code im folgenden Beispiel erstellt ein ImageRepository-Objekt, das ein Repository namens my_repo repräsentiert:

from snowflake.core.image_repository import ImageRepository

my_repo = ImageRepository("my_repo")
root.databases["my_db"].schemas["my_schema"].image_repositories.create(my_repo)
Copy

Der Code erstellt dann das Image-Repository, indem das ImageRepository-Objekt an die Methode ImageRepositoryCollection.create übergeben und so das Image-Repository in der Datenbank my_db und dem Schema my_schema erstellt wird.

Abrufen von Details zu Image-Repositorys

Sie können Informationen zu einem Image-Repository abrufen, indem Sie die Methode ImageRepositoryResource.fetch aufrufen, die ein ImageRepository-Objekt zurückgibt.

Der Code im folgenden Beispiel ruft ein ImageRepository-Objekt ab, das das Image-Repository my_repo repräsentiert, und gibt dann den Namen des Eigentümers des Repositorys aus.

my_repo_res = root.databases["my_db"].schemas["my_schema"].image_repositories["my_repo"]
my_repo = my_repo_res.fetch()
print(my_repo.owner)
Copy

Auflisten von Image-Repositorys

Sie können die Image-Repositorys in einem bestimmten Schema mit der Methode iter auflisten, die einen Iterator PagedIter für ImageRepository-Objekte zurückgibt.

Der Code im folgenden Beispiel listet Repository-Namen in der Datenbank my_db und dem Schema my_schema auf:

repo_list = root.databases["my_db"].schemas["my_schema"].image_repositories.iter()
for repo_obj in repo_list:
  print(repo_obj.name)
Copy

Löschen eines Image-Repositorys

Sie können ein Image-Repository mit der Methode ImageRepositoryResource.drop löschen.

Der Code im folgenden Beispiel löscht das Repository my_repo:

my_repo_res = root.databases["my_db"].schemas["my_schema"].image_repositories["my_repo"]
my_repo_res.drop()
Copy

Management von Services und Dienstfunktionen

Sie können Dienste verwalten, die Anwendungscontainer ausführen, bis Sie sie stoppen. Snowflake startet einen Dienst automatisch neu, wenn der Dienstcontainer stoppt. Auf diese Weise wird der Dienst praktisch ohne Unterbrechung ausgeführt.

Ein Dienst ist ein Objekt auf Schemaebene. Wenn Sie einen Dienst erstellen oder auf ihn verweisen, tun Sie dies im Kontext des zugehörigen Schemas.

Die Snowflake Python APIs stellt Dienste mit zwei verschiedenen Typen dar:

  • Service: Zeigt die Eigenschaften eines Dienstes an, wie z. B. seine Spezifikation, die minimale und maximale Anzahl an Instanzen sowie die Namen von Datenbank und Schema.

  • ServiceResource: Stellt Methoden zur Verfügung, mit denen Sie ein entsprechendes Service-Objekt abrufen, den Dienst anhalten und fortsetzen sowie seinen Status abrufen können.

Weitere Informationen zu Diensten finden Sie unter Snowpark Container Services: Verwenden von Diensten.

Erstellen von Diensten

Um einen Dienst zu erstellen, führen Sie die Methode services.create aus und übergeben ein Service-Objekt, das den zu erstellenden Dienst repräsentiert.

Sie erstellen einen Dienst aus einer Dienstspezifikationsdatei .yaml, die in einen Stagingbereich hochgeladen wurde. Weitere Informationen zum Erstellen einer Dienstspezifikation finden Sie unter Referenz der Dienstspezifikation.

Hochladen der Spezifikation

Wenn Sie einen Dienst aus einer Spezifikation erstellen, die noch nicht in einen Stagingbereich hochgeladen wurde, können Sie die Spezifikation mit einem Snowpark-FileOperation-Objekt hochladen.

Der Code im folgenden Beispiel verwendet die Methode FileOperation.put, um eine Spezifikation als Datei hochzuladen:

session.file.put("/local_location/my_service_spec.yaml", "@my_stage")
Copy

Der Code im folgenden Beispiel verwendet die Methode FileOperation.put_stream, um eine Spezifikation als Zeichenfolge (String) hochzuladen:

service_spec_string = """
// Specification as a string.
"""
session.file.put_stream(StringIO(sepc_in_string), "@my_stage/my_service_spec.yaml")
Copy

Erstellen des Dienstes

Um einen Dienst aus einer in einem Stagingbereich gespeicherten Spezifikationsdatei zu erstellen, erstellen Sie zunächst ein Service-Objekt, das Diensteigenschaften wie die folgenden angibt:

  • Name des Dienstes

  • Maximale und minimale Anzahl von Dienstinstanzen, die Snowflake erstellen kann

  • Computepool, zu dem der Dienst hinzugefügt werden soll

  • Speicherort des Stagingbereichs und Name der Spezifikation

Der Code im folgenden Beispiel erstellt ein Service-Objekt, das einen Dienst namens my_service aus einer Spezifikation in @my_stage/my_service_spec.yaml repräsentiert:

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)
Copy

Der Code erstellt dann den Dienst, indem das Service-Objekt an die Methode ServiceCollection.create übergeben und so der Dienst in der Datenbank my_db und dem Schema my_schema erstellt wird.

Sie können einen Dienst auch anhand einer Spezifikation erstellen, die Sie als Inline-Text bereitstellen, wie im folgenden Beispiel gezeigt. Die Funktion ServiceSpec nimmt ein einzelnes Zeichenfolgenargument spec entgegen. Wenn die Zeichenfolge mit @ beginnt, interpretiert und validiert die Funktion sie als Pfad zu einer Stagingdatei. Andernfalls wird die Zeichenfolge als Inline-Text weitergegeben.

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)
Copy

Erstellen einer Dienstfunktion

Nachdem der Service eingerichtet ist und läuft, können Sie eine Funktion erstellen, die mit dem Dienstendpunkt kommuniziert. Eine Dienstfunktion ist eine benutzerdefinierte Funktion (UDF), die Sie erstellen und mit einem Service in Snowpark Container Services verknüpfen. Weitere Informationen dazu finden Sie unter Dienstfunktionen: Verwenden eines Dienstes aus einer SQL-Abfrage.

Der Code im folgenden Beispiel erstellt eine UDF mit dem Namen my-udf, die den Dienst hello-world und den Endpunkt hello-world-endpoint angibt, die Sie zuvor definiert haben:

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
)
Copy

Aufrufen einer Dienstfunktion

Nachdem die Dienstfunktion erstellt wurde, können Sie die Funktion aufrufen, um sie zu testen.

Der Code im folgenden Beispiel ruft die my-udf-Dienstfunktion auf, die Sie zuvor erstellt haben:

result = root.databases["my_db"].schemas["my_schema"].functions["my-udf(TEXT)"].execute_function(["test"])
print(result)
Copy

Abrufen von Details zum Dienst

Sie können Informationen zu einem Snowflake-Dienst erhalten, indem Sie die Methode ServiceResource.fetch aufrufen, die ein Service-Objekt zurückgibt.

Der Code im folgenden Beispiel ruft Informationen über einen Dienst namens my_service ab:

my_service = root.databases["my_db"].schemas["my_schema"].services["my_service"].fetch()
Copy

Auflisten von Diensten

Sie können die Dienste in einem bestimmten Schema mit der Methode iter auflisten, die einen Iterator PagedIter für Service-Objekte zurückgibt.

Der Code im folgenden Beispiel listet Dienste auf, deren Name mit my beginnt:

services = root.databases["my_db"].schemas["my_schema"].services.iter(like="my%")
for service_obj in services:
  print(service_obj.name)
Copy

Ausführen von Dienstoperationen

Mit einem ServiceResource-Objekt können Sie allgemeine Dienstoperationen wie Anhalten, Fortsetzen und Abrufen des Dienststatus ausführen.

Der Code im folgenden Beispiel hält den Dienst my_service an und setzt ihn dann fort und ruft außerdem den Status des Dienstes ab:

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)
Copy