Python을 사용하여 Snowpark 컨테이너 서비스(서비스 함수 포함) 관리하기

Python을 사용하여 컨테이너화된 애플리케이션을 배포, 관리, 확장할 수 있는 완전 관리형 컨테이너 서비스인 Snowpark Container Services를 관리할 수 있습니다. Snowpark Container Services의 개요는 Snowpark Container Services 정보 섹션을 참조하십시오.

Snowflake Python APIs 을 사용하면 컴퓨팅 풀, 이미지 리포지토리, 서비스를 관리할 수 있습니다.

전제 조건

이 항목의 예제에서는 Snowflake와 연결하고 Snowflake Python APIs 을 사용할 수 있는 Root 오브젝트를 생성하는 코드를 추가했다고 가정합니다.

예를 들어, 다음 코드는 구성 파일에 정의된 연결 매개 변수를 사용하여 Snowflake에 대한 연결을 생성합니다.

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

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

해당 코드에서는 결과 Session 오브젝트를 사용하여 API의 유형과 메서드를 사용하기 위해 Root 오브젝트를 생성합니다. 자세한 내용은 Snowflake Python APIs 을 사용하여 Snowflake에 연결 섹션을 참조하십시오.

컴퓨팅 풀 관리하기

Snowflake가 Snowpark Container Services 작업과 서비스를 실행하는 가상 머신(VM) 노드 모음인 컴퓨팅 풀을 관리할 수 있습니다.

Snowflake Python APIs 은 다음 두 가지 유형이 있는 컴퓨팅 풀을 나타냅니다.

  • ComputePool: 웨어하우스, 최대 및 최소 노드, 자동 재개 및 자동 일시 중단 설정과 같은 컴퓨팅 풀의 속성을 노출합니다.

  • ComputePoolResource: 해당 ComputePool 오브젝트 가져오기와 풀 일시 중단, 재개, 중지와 같은 작업을 컴퓨팅 풀에서 수행하기 위한 메서드를 노출합니다.

컴퓨팅 풀에 대한 자세한 내용은 Snowpark Container Services: 컴퓨팅 풀 작업하기 섹션을 참조하십시오.

컴퓨팅 풀 만들기

ComputePoolCollection.create 메서드를 호출하고 생성하려는 컴퓨팅 풀을 나타내는 ComputePool 오브젝트를 전달하여 컴퓨팅 풀을 생성할 수 있습니다.

컴퓨팅 풀을 생성하려면 먼저 다음과 같은 풀 속성을 지정하는 ComputePool 오브젝트를 생성합니다.

  • 컴퓨팅 풀 이름

  • 풀에 포함될 노드의 최대 및 최소 개수

  • 풀의 노드에 대해 프로비저닝할 컴퓨터 유형을 식별하는 인스턴스 패밀리의 이름

  • 서비스나 작업이 풀에 제출될 때 풀이 자동으로 재개해야 하는지 여부

다음 예제의 코드는 my_compute_pool 이라는 풀을 나타내는 ComputePool 오브젝트를 생성합니다.

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

그런 다음 ComputePool 오브젝트를 ComputePoolCollection.create 메서드에 전달하여 컴퓨팅 풀을 생성합니다.

컴퓨팅 풀 세부 정보 가져오기

ComputePool 오브젝트를 반환하는 ComputePoolResource.fetch 메서드를 호출하여 컴퓨팅 풀에 대한 정보를 얻을 수 있습니다.

다음 예제의 코드로 my_compute_pool 풀에 대한 정보를 가져옵니다.

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

컴퓨팅 풀 나열하기

PagedIter 반복기를 반환하는 iter 메서드를 사용하여 컴퓨팅 풀을 나열할 수 있습니다.

다음 예제의 코드로 이름이 my 로 시작하는 컴퓨팅 풀을 나열합니다.

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

컴퓨팅 풀 작업 수행하기

ComputePool.fetch 메서드를 사용하여 가져올 수 있는 ComputePoolResource 오브젝트를 사용하여 풀 일시 중단, 재개, 중지와 같은 일반적인 컴퓨팅 풀 작업을 수행할 수 있습니다.

다음 예제의 코드는 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()
Copy

이 코드는 Root.compute_pools 메서드를 사용하여 컴퓨팅 풀을 나타내는 ComputePool 오브젝트를 생성합니다. ComputePool 오브젝트에서 컴퓨팅 풀 작업을 수행하는 데 사용할 ComputePoolResource 오브젝트를 가져옵니다.

이미지 리포지토리 관리하기

컨테이너 서비스에서 실행하는 애플리케이션의 이미지를 저장하는 이미지 리포지토리를 관리할 수 있습니다.

이미지 리포지토리는 스키마 수준 오브젝트입니다. 해당 스키마의 컨텍스트에서 리포지토리를 생성하거나 참조합니다.

Snowflake Python APIs 은 두 가지 별개 유형의 이미지 리포지토리를 나타냅니다.

  • ImageRepository: 데이터베이스 및 스키마 이름, 리포지토리 URL, 소유자 등 이미지 리포지토리의 속성을 노출합니다.

  • ImageRepositoryResource: 해당 ImageRepository 오브젝트를 가져오고 이미지 리포지토리 리소스를 삭제하는 데 사용할 수 있는 메서드를 노출합니다.

이미지 리포지토리에 대한 자세한 내용은 Snowpark Container Services: 이미지 레지스트리 및 리포지토리 작업하기 섹션을 참조하십시오.

이미지 리포지토리 만들기

이미지 리포지토리를 생성하려면 리포지토리 이름을 지정하는 ImageRepository 오브젝트를 먼저 생성하십시오.

다음 예제의 코드는 이름이 my_repo 인 리포지토리를 나타내는 ImageRepository 오브젝트를 생성합니다.

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

그런 다음 코드는 ImageRepository 오브젝트를 ImageRepositoryCollection.create 메서드에 전달하고 my_db 데이터베이스와 my_schema 스키마에 이미지 리포지토리를 생성하는 방법으로 이미지 리포지토리를 생성합니다.

이미지 리포지토리 세부 정보 가져오기

ImageRepository 오브젝트를 반환하는 ImageRepositoryResource.fetch 메서드를 호출하여 이미지 리포지토리에 대한 정보를 얻을 수 있습니다.

다음 예제의 코드는 my_repo 이미지 리포지토리를 나타내는 ImageRepository 오브젝트를 가져온 다음 리포지토리 소유자의 이름을 인쇄합니다.

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

이미지 리포지토리 나열하기

ImageRepository 오브젝트의 PagedIter 반복기를 반환하는 iter 메서드를 사용하여 지정된 스키마의 이미지 리포지토리를 나열할 수 있습니다.

다음 예제의 코드는 my_db 데이터베이스 및 my_schema 스키마의 저장소 이름을 나열합니다.

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

이미지 리포지토리 삭제하기

ImageRepositoryResource.drop 메서드를 사용하여 이미지 리포지토리를 삭제할 수 있습니다.

다음 예제의 코드는 my_repo 리포지토리를 삭제합니다.

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

서비스 및 서비스 함수 관리

중지할 때까지 애플리케이션 컨테이너를 실행하는 서비스를 관리할 수 있습니다. Snowflake는 서비스 컨테이너가 중지되면 자동으로 서비스를 다시 시작합니다. 이러한 방식으로 서비스는 중단 없이 효과적으로 실행됩니다.

서비스는 스키마 수준 오브젝트입니다. 해당 스키마의 컨텍스트에서 서비스를 생성하거나 참조합니다.

Snowflake Python APIs 은 다음 두 가지 별개 유형의 서비스를 나타냅니다.

  • Service: 사양, 최소 및 최대 인스턴스 수, 데이터베이스 및 스키마 이름 등 서비스 속성을 노출합니다.

  • ServiceResource: 해당 Service 오브젝트를 가져오고, 서비스를 일시 중단 및 재개하고, 서비스의 상태를 가져오는 데 사용할 수 있는 메서드를 노출합니다.

서비스에 대한 자세한 내용은 Snowpark Container Services: 서비스 사용하기 섹션을 참조하십시오.

서비스 만들기

서비스를 생성하려면 services.create 메서드를 실행하여 생성하려는 서비스를 나타내는 Service 오브젝트를 전달합니다.

스테이지에 업로드된 서비스 사양 .yaml 파일에서 서비스를 생성합니다. 서비스 사양 생성에 대한 자세한 내용은 서비스 사양 참조 섹션을 참조하십시오.

사양 업로드하기

아직 스테이지에 업로드되지 않은 사양에서 서비스를 생성하는 경우 Snowpark FileOperation 오브젝트를 사용하여 사양을 업로드할 수 있습니다.

다음 예제의 코드는 FileOperation.put 메서드를 사용하여 사양을 파일로 업로드합니다.

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

다음 예제의 코드는 FileOperation.put_stream 메서드를 사용하여 사양을 문자열로 업로드합니다.

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

서비스 만들기

스테이징된 사양에서 서비스를 생성하려면 먼저 다음과 같은 서비스 속성을 지정하는 Service 오브젝트를 생성합니다.

  • 서비스 이름

  • Snowflake가 생성할 수 있는 최대 및 최소 서비스 인스턴스 수

  • 서비스를 추가해야 하는 컴퓨팅 풀

  • 사양의 스테이지 위치 및 이름

다음 예제의 코드는 @my_stage/my_service_spec.yaml 의 사양에서 my_service 서비스를 나타내는 Service 오브젝트를 생성합니다.

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

그런 다음 코드는 Service 오브젝트를 ServiceCollection.create 메서드에 전달하고 my_db 데이터베이스와 my_schema 스키마에 서비스를 생성하는 방법으로 서비스를 생성합니다.

다음 예제에서와 같이, 인라인 텍스트로 제공하는 사양에서 서비스를 만들 수도 있습니다. ServiceSpec 함수는 단일 문자열 인자 spec 을 받습니다. 문자열이 @ 로 시작하면 이 함수는 이를 스테이지 파일 경로로 해석하고 유효성을 검사합니다. 그렇지 않으면 문자열은 인라인 텍스트로 전달됩니다.

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

서비스 함수 생성

서비스가 실행된 후 서비스 엔드포인트와 통신하는 서비스 함수를 생성할 수 있습니다. 서비스 함수는 사용자가 생성하여 Snowpark Container Services 의 서비스와 연결하는 사용자 정의 함수(UDF)입니다. 자세한 내용은 서비스 함수: SQL 쿼리에서 서비스 사용하기 섹션을 참조하십시오.

다음 예제의 코드는 이전에 정의한 hello-world 서비스 및 hello-world-endpoint 엔드포인트를 지정하는 my-udf 라는 이름의 UDF를 생성합니다.

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

서비스 함수 호출

서비스 함수가 생성된 후에는 해당 함수를 호출하여 테스트할 수 있습니다.

다음 예제의 코드는 이전에 생성한 my-udf 서비스 함수를 호출합니다.

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

서비스 세부 정보 가져오기

Service 오브젝트를 반환하는 ServiceResource.fetch 메서드를 호출하여 Snowflake 서비스에 대한 정보를 얻을 수 있습니다.

다음 예제의 코드는 my_service 서비스에 대한 정보를 가져옵니다.

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

서비스 나열하기

Service 오브젝트의 PagedIter 반복기를 반환하는 iter 메서드를 사용하여 지정된 스키마의 서비스를 나열할 수 있습니다.

다음 예제의 코드는 이름이 my 로 시작하는 서비스를 나열합니다.

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

서비스 작업 수행하기

ServiceResource 오브젝트를 사용하여 서비스의 일시 중단, 재개, 상태 가져오기 등 일반적인 서비스 작업을 수행할 수 있습니다.

다음 예제의 코드는 my_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)
Copy