服务规范参考¶
要查看 Snowpark Container Services 规范,请参阅 YAML (` https://yaml.org/spec/ (https://yaml.org/spec/) <https://yaml.org/spec/ (https://yaml.org/spec/)>`_)。它为 Snowflake 提供了配置和运行服务所需的信息。
一般语法为:
spec:
containers: # container list
- name: <name>
image: <image-name>
command: # optional list of strings
- <cmd>
- <arg1>
args: # optional list of strings
- <arg2>
- <arg3>
- ...
env: # optional
<key>: <value>
<key>: <value>
...
readinessProbe: # optional
port: <TCP port-num>
path: <http-path>
volumeMounts: # optional list
- name: <volume-name>
mountPath: <mount-path>
- name: <volume-name>
...
resources: # optional
requests:
memory: <amount-of-memory>
nvidia.com/gpu: <count>
cpu: <cpu-units>
limits:
memory: <amount-of-memory>
nvidia.com/gpu: <count>
cpu: <cpu-units>
secrets: # optional list
- snowflakeSecret:
secretKeyRef:
envVarName: # specify this or directoryPath
directoryPath: # specify this or envVarName
endpoints: # optional endpoint list
- name: <name>
port: <TCP port-num>
public: <true / false>
protocol : < TCP / HTTP / HTTPS >
- name: <name>
...
volumes: # optional volume list
- name: <name>
source: local | @<stagename> | memory | block
size: <bytes-of-storage> # specify if memory or block is the volume source
blockConfig: # optional
initialContents:
fromSnapshot: <snapshot-name>
uid: <UID-value> # optional, only for stage volumes
gid: <GID-value> # optional, only for stage volumes
- name: <name>
source: local | @<stagename> | memory | block
size: <bytes-of-storage> # specify if memory or block is the volume source
...
logExporters:
eventTableConfig:
logLevel: <INFO | ERROR | NONE>
serviceRoles: # Optional list of service roles
- name: <service-role-name>
endpoints:
- <endpoint_name1>
- <endpoint_name2>
- ...
- ...
一般准则¶
服务规范具有以下这些顶级 spec
字段:
spec.containers
(必填):一个或多个应用程序容器的列表。容器化应用程序必须至少有一个容器。spec.endpoints
(可选):服务显示的端点列表。您可选择将端点设为公开,以允许网络入口访问该服务。spec.volumes
(可选):供容器使用的存储卷列表。spec.logExporters
(可选):此字段管理导出到您账户中的事件表的容器日志级别。
以下格式准则适用于 name
字段(容器、端点和卷名称):
最多可包含 63 个字符
可包含一串小写字母数字或“-”字符
必须以字母字符开头
必须以字母数字字符结尾
注意
客户应确保没有个人数据、敏感数据、出口控制数据或其他受监管数据作为元数据输入规范文件。有关更多信息,请参阅 Snowflake 中的元数据字段。
以下各节介绍了每个顶级 spec
字段。
spec.containers
字段(必填)¶
containers
字段是您应用程序中 ` OCI <https://opencontainers.org/ (https://opencontainers.org/)> _ 容器的列表。对于每个容器,仅 :code:`name 和 image
为必填字段。image
字段是指您上传到 Snowflake 账户中的 Snowflake 镜像仓库中镜像的名称。例如:
spec:
containers:
- name: echo
image: /tutorial_db/data_schema/tutorial_repository/echo_service:dev
当您创建服务(包括作业服务)时,Snowflake 会在指定计算池中的单个节点上运行这些容器,共享相同的网络接口。您可运行多个服务实例;在这种情况下,正在运行的这些容器中的每一组都称为一个服务实例。
备注
目前,Snowpark Container Services 需要 linux/amd64 平台镜像。
以下各节介绍了 containers
字段的类型。
containers.command
和 containers.args
字段¶
使用这些可选字段来替换在 Dockerfile
(应用程序镜像的一部分)中定义的容器的入口点(容器与任何参数一起运行的命令),而无需重新创建应用程序镜像:
containers.command
可替换Dockerfile
ENTRYPOINT
。这允许您在容器中运行不同的可执行文件。containers.args
可替换Dockerfile
CMD
。这允许您为命令(可执行文件)提供不同的实参。
示例
Dockerfile
包括以下代码:
ENTRYPOINT ["python3", "main.py"]
CMD ["Bob"]
这些 Dockerfile
条目执行 python3
命令并传递两个实参:main.py
和 Bob
。您可按如下方式替换规范文件中的这些值:
要替换 ENTRYPOINT,请在规范文件中添加
containers.command
字段:spec: containers: - name: echo image: <image_name> command: - python3.9 - main.py
要替换实参“Bob”,请在规范文件中添加
containers.args
字段:spec: containers: - name: echo image: <image_name> args: - Alice
containers.env
字段¶
使用 containers.env
字段来指定传递给容器中所有进程的环境变量:
spec:
containers:
- name: <name>
image: <image_name>
env:
ENV_VARIABLE_1: <value1>
ENV_VARIABLE_2: <value2>
…
…
示例
在 教程 1 中,如未显式设置环境变量的值,则应用程序代码 (echo_service.py
) 将读取其默认值。
CHARACTER_NAME = os.getenv('CHARACTER_NAME', 'I')
SERVER_PORT = os.getenv('SERVER_PORT', 8080)
CHARACTER_NAME
:当 Echo 服务收到带字符串(例如,“Hello”)的 HTTP POST 请求时,服务默认返回“I said Hello”。 您可在规范文件中覆盖此默认值。例如,将值设置为“Bob”,则 Echo 服务会返回“Bob said Hello”的响应。SERVER_PORT
:在此默认配置中,Echo 服务监听端口 8080。您可以替换该默认值并指定另一端口。
以下规范文件将替换这两个环境变量值:
spec:
containers:
- name: echo
image: <image_name>
env:
CHARACTER_NAME: Bob
SERVER_PORT: 8085
endpoints:
- name: echo-endpoint
port: 8085
请注意,由于您更改了服务监听的端口号,因此在规范中也更新了端点(endpoints.port
字段值)。
containers.readinessProbe
字段¶
在您的应用程序中使用 containers.readinessProbe
对象为 Snowflake 提供就绪情况探测。Snowflake 调用此探测以确定应用程序何时准备好处理请求。
Snowflake 在指定的端口和路径上向指定的就绪情况探测发出 HTTP GET 请求,并查找您的服务以返回 HTTP 200 OK 状态,以确保只有正常运行的容器才能提供流量。
使用以下字段提供所需信息:
port
:服务正在监听就绪情况探测请求的网络端口。您无需将此端口声明为端点。path
:Snowflake 使用此路径向服务发出 HTTP GET 请求。
示例
在教程 1 中,应用程序代码 (echo_python.py
) 实现以下就绪情况探测:
@app.get("/healthcheck")
def readiness_probe():
因此,规范文件包括 containers.readinessProbe
字段:
spec:
containers:
- name: echo
image: <image_name>
env:
SERVER_PORT: 8088
CHARACTER_NAME: Bob
readinessProbe:
port: 8088
path: /healthcheck
endpoints:
- name: echo-endpoint
port: 8088
就绪情况探测指定的端口可以不是已配置的端点。服务可以仅出于就绪情况探测的目的来监听不同的端口。
containers.volumeMounts
字段¶
因为 spec.volumes
和 spec.containers.volumeMounts
字段是一起使用的,所以将在一个小节中一起介绍它们。有关更多信息,请参阅 spec.volumes 字段(可选)。
containers.resources
字段¶
Snowflake 确定如何使用可用的计算池资源来运行应用程序。建议您在规范中明确指出服务实例的资源需求,并设置适当的限制。请注意,您指定的资源受到计算池中节点的实例系列的约束。有关更多信息,请参阅 CREATE COMPUTE POOL。
Snowflake 确保提供 containers.resources.requests
指定的资源,并防止服务使用超过指定数目的 containers.resources.limits
。您可以为以下资源指定请求和限制:
memory
:这是应用程序容器所需的内存。您可以使用小数或二进制单位来表示值。例如,2G 表示 2,000,000,000 字节的请求。指定内存时,单位是必填项。例如,100M
或5Gi
。支持的单位有:M、Mi、G、Gi。有关更多信息,请参阅 关于单位。cpu
:这是指虚拟核心 (vCPU) 单位。例如,1 个 CPU 单位相当于 1 个 vCPU。允许小数请求,例如 0.5,也可表示为 500m。有关更多信息,请参阅 关于单位。nvidia.com/gpu
:如果需要 GPUs,则必须请求它们,并且对于相同的数量也必须指定limit
。如果容器未指定 GPU 容量的请求和限制,则它无法访问任何 GPUs。您可请求的 GPUs 的数量受您在创建计算池时所选择的INSTANCE_TYPE
所支持的最大 GPUs 数量的限制。有关更多信息,请参阅 CREATE COMPUTE POOL。
如果 Snowflake 无法分配规范文件中明确包含的资源,您可创建服务(使用 CREATE SERVICE),但服务状态会显示:由于资源不足,无法安排服务。
示例 1
在以下规范中,containers.resources
字段描述容器的资源需求:
spec:
containers:
- name: resource-test-gpu
image: ...
resources:
requests:
memory: 2G
cpu: 0.5
nvidia.com/gpu: 1
limits:
memory: 4G
nvidia.com/gpu: 1
在此示例中,要求 Snowflake 为容器至少分配 2 个 GB 内存,1 个 GPU 和 0.5 个 CPU 核心。同时,不允许容器使用超过 4 个 GB 内存和 1 个 GPU。
示例 2
创建包含两个节点的计算池;每个节点有 16 个 GB 内存和 1 个 GPU:
CREATE COMPUTE POOL tutorial_compute_pool MIN_NODES = 2 MAX_NODES = 2 INSTANCE_FAMILY = gpu_nv_s
您创建一个服务,该服务要求 Snowflake 运行该服务的两个实例:
CREATE SERVICE echo_service MIN_INSTANCES=2 MAX_INSTANCES=2 IN COMPUTE POOL tutorial_compute_pool FROM @<stage_path> SPEC=<spec-file-stage-path>;
将
MIN_INSTANCES
和MAX_INSTANCES
均设置为 2。因此,Snowflake 将运行该服务的两个实例。
如果未在应用程序规范中明确包含资源需求,那么 Snowflake 将决定是在计算池中的同一节点还是不同节点上运行这些实例。
您确实需要包括资源需求,并为容器请求 10 个 GB 内存:
- name: resource-test image: ... resources: requests: memory: 10G
计算池节点有 16 个 GB 内存,并且 Snowflake 无法在同一节点上运行两个容器。Snowflake 将在计算池中的不同节点上运行这两个服务实例。
为容器请求 1 个 GB 内存和 1 个 GPU:
spec: containers: - name: resource-test-gpu image: ... resources: requests: memory: 2G nvidia.com/gpu: 1 limits: nvidia.com/gpu: 1
您正在为每个容器请求 1 个 GPU,并且每个节点只有 1 个 GPU。在这种情况下,尽管内存不是问题,但 Snowflake 无法在一个节点上安排这两项服务。此需求迫使 Snowflake 在两个单独的计算池节点上运行两个服务实例。
containers.secrets
字段¶
secrets: # optional list
- snowflakeSecret:
secretKeyRef:
envVarName: # specify this or directoryPath
directoryPath: # specify this or envVarName
使用 containers.secrets
将 密钥 对象提供给Snowflake,当服务与外部端点(在Snowflake 之外)通信时,容器可使用这些对象进行身份验证。有关更多信息,请参阅 使用 Snowflake 密钥将凭据传递到容器。
snowflakeSecret
(必填):Snowflake :doc:` 密钥 </sql-reference/sql/create-secret>` 对象名称。secretKeyRef
:密钥中密钥的名称。提供此字段后,Snowflake 会将与此键引用关联的值传递给容器。这对于作为环境变量挂载的基本身份验证密钥是必填项。仅当将密钥传递给容器中的环境变量时,才指定此字段。envVarName
:保存密钥的环境变量的名称。此字段或directoryPath
字段为必填项。directoryPath
:容器中要复制密钥的目录路径。Snowflake 为此指定目录中的每个密钥填充一个文件。当您指定directoryPath
时,请勿指定secretKeyRef
。此字段或envVarName
字段为必填项。
有关更多信息,请参阅 将 Snowflake 密钥传递到容器中。
spec.endpoints
字段(可选)¶
使用 spec.endpoints
字段指定应用程序显示的 TCP 网络端口的名称列表。Snowpark Container Services 可能会向多个端点显示为零。使用以下字段描述端点:
name
:端点的唯一名称。在服务函数中引用端点时,请指定其名称。port
:应用程序正在监听的网络端口。protocol
:端点支持的协议。支持的值为:TCP、HTTP 和 HTTPS。默认情况下,该协议为 HTTP。当此端点是公共的或某一服务功能的目标时,该协议必须为 HTTP 或 HTTPS(请参阅 使用服务)。作业服务要求所有指定的端点使用 TCP 协议;不支持 HTTP/HTTPS 协议。public
:如果您希望可以从 Internet 访问此端点,请将此字段设置为true
。TCP 协议不支持公共端点。
备注
Snowflake 对公共访问执行身份验证和授权检查,只允许有权限的 Snowflake 用户使用该服务。
示例
以下是 教程 1 中使用的应用程序规范:
spec:
container:
- name: echo
image: <image-name>
env:
SERVER_PORT: 8000
CHARACTER_NAME: Bob
readinessProbe:
port: 8000
path: /healthcheck
endpoint:
- name: echoendpoint
port: 8000
public: true
此应用程序容器显示一个端点。它还包括一个可选的 public
字段,允许从 Snowflake 外部访问端点(互联网访问)。默认情况下,public
是 false
。
spec.volumes
字段(可选)¶
本节将介绍 spec.volumes
和 spec.containers.volumeMounts
规范字段,因为它们密切相关。
spec.volumes
定义共享文件系统,即容器可用的卷。spec.containers.volumeMount
定义卷在特定容器中显示的位置。
在规范中,volumes
字段在 spec
级别指定,但由于多个容器可共享相同的卷,所以 volumeMounts
成为 spec.containers
级别的字段。
使用这些字段来描述卷和卷挂载。
使用
spec.volumes
指定可用于容器的卷。volumes
是一个列表。也就是说,可以存在多个卷。使用以下字段描述卷:name
:卷的唯一名称。该名称请参考spec.containers.volumeMounts.name
。source
:这可以是local
、memory
、block
或"@<stagename>"
。下一节将介绍这些卷类型。size
:对于内存卷和块卷,这是以字节为单位的卷的大小。对于块存储,该值必须始终是一个整型,使用 Gi 单位后缀指定。例如,5Gi
表示5*1024*1024*1024
个字节。blockConfig
:对于block
类型的卷,如果您希望使用先前获取的另一个卷的快照初始化块卷,请指定此可选字段。有关更多信息,请参阅 在服务规范中指定块存储。
使用
spec.containers.volumeMounts
指示指定卷在容器文件系统中的挂载位置。containers.volumeMounts
也是一个列表。也就是说,每个容器可以有多个卷挂载。使用以下字段来描述卷装载:name
:要挂载的卷的名称。单个容器可以多次引用同一卷。mountPath
:容器中应挂载的卷的文件路径。
关于支持的卷类型¶
Snowflake 支持应用程序容器使用以下这些卷类型:本地、内存、块和 Snowflake 暂存区。
本地卷: 服务实例中的容器可使用本地磁盘来共享文件。例如,如果应用程序有两个容器 – 一个应用程序容器和一个日志分析器,则应用程序可将日志写入本地卷,而日志分析器可读取日志。
请注意,如果您正在运行一个服务的多个实例,则只有属于一个服务实例的容器才能共享卷。属于不同服务实例的容器不共享卷。
内存: 您可以使用 RAM 支持的文件系统供容器使用。
块: 容器也可以使用块存储卷。大小值可以介于
1Gi
到16384Gi
之间。有关更多信息,请参阅 将块存储卷与服务一起使用。Snowflake 暂存区: 您可以创建一个 Snowflake 暂存区,并让容器可以很方便地访问暂存文件。挂载 Snowflake 暂存区时,以下条件适用:
不支持外部暂存区。只支持使用 SSE 加密的 Snowflake 内部暂存区(请参阅 内部暂存区参数)。要使用 CREATE STAGE 创建这样的暂存区,请执行以下操作:
CREATE STAGE my_stage ENCRYPTION = (type = 'SNOWFLAKE_SSE');
您可以在一个暂存区内挂载一个暂存区或一个子目录,例如
@my_stage
和@my_stage/folder
。您无法在暂存区内挂载一个文件,例如@my_stage/folder/file
。服务角色确定授予容器访问已挂载暂存区的权限。服务角色是用于创建服务的角色。它也是服务用于所有 Snowflake 交互的角色。
例如,如果服务角色在某个暂存区没有 WRITE 权限,则该暂存区的挂载将为只读。也就是说,容器只能从暂存区读取文件。如果服务角色在某个暂存区确实具有 WRITE 权限,则该暂存区的挂载将同时支持读取和写入。Snowflake 异步上传文件更新。
挂载 Snowflake 暂存区的容器通常以根用户身份运行。但是,有时您的容器可能会以非根用户身份运行。例如:
如果应用程序使用第三方库,则该库将使用非根用户在容器内运行应用程序代码。
出于安全性等其他原因,您可以在容器内以非根用户身份运行应用程序。
为避免与文件用户权限相关的潜在错误,将容器的 UID(用户 ID)和 GID(组 ID)设置为规范的一部分非常重要。这对于使用特定用户和组在容器内启动或运行应用程序的容器来说,这一点尤为重要。通过设置适当的 UID 和 GID,您可以使用以非根用户身份运行的容器。例如:
spec: ... volumes: - name: stagemount source: "@test" uid: <UID-value> gid: <GID-value>
Snowflake 使用此信息以适当的权限挂载暂存区。
要获取容器的 UID 和 GID,请执行以下操作:
使用
docker run
在本地运行容器。使用
docker container list
命令查找容器 ID。部分样本输出:CONTAINER ID IMAGE COMMAND —---------------------------------------------------------- a6a1f1fe204d tutorial-image "/usr/local/bin/entr…"
在容器内运行
docker id
命令来获取 UID 和 GID:docker exec -it <container-id> id
示例输出:
uid=0(root) gid=0(root) groups=0(root)
示例
机器学习应用程序包括以下两个容器:
一个适用于主应用程序的
app
容器一个收集日志并将其上传到 Amazon S3 的
logger-agent
容器
这些容器使用以下两个卷:
local
卷:此应用程序写入日志代理读取的日志。Snowflake 暂存区 –
@model_stage
:主应用程序从此暂存区中读取文件。
在以下示例规范中,app
容器挂载 logs
和 models
两个卷,而 logging-agent
容器仅挂载 logs
卷:
spec: containers: - name: app image: <image1-name> volumeMounts: - name: logs mountPath: /opt/app/logs - name: models mountPath: /opt/models - name: logging-agent image: <image2-name> volumeMounts: - name: logs mountPath: /opt/logs volumes: - name: logs source: local - name: models source: "@model_stage"
如果服务的多个实例正在运行,则一个服务实例中的 logging-agent
和 app
容器共享 logs
卷。logs
卷不在服务实例之间共享。
如果除这些卷之外,您的 app
容器还使用一个 2-GB 内存的卷,请修改规范,以将该卷包含在 volumes
列表中,并在 app
容器 volumeMounts
列表中添加另一个卷挂载:
spec: containers: - name: app image: <image1-name> volumeMounts: - name: logs mountPath: /opt/app/logs - name: models mountPath: /opt/models - name: my-mem-volume mountPath: /dev/shm - name: logging-agent image: <image2-name> volumeMounts: - name: logs mountPath: /opt/logs volumes: - name: logs source: local - name: models source: "@model_stage" - name: "my-mem-volume" source: memory size: 2G
请注意,当您指定 memory
作为卷 source
时,您还必须指定 volumes.size
字段来表示内存大小。有关您可以指定的内存大小单位的信息,请参阅 关于单位。
spec.logExporters
字段(可选)¶
使用 spec.logExporters
配置 Snowflake 收集应用程序日志的方式。 Snowflake 将应用程序容器中代码的输出收集为标准输出或标准错误。
Snowflake 将这些日志导出到您账户中的 事件表 中。有关更多信息,请参阅 访问本地容器日志。要使用 spec.logExporters.eventTableConfig
来指示您想要保存到事件表中的日志,请执行以下操作:
logExporters:
eventTableConfig:
logLevel: < INFO | ERROR | NONE >
支持的 logLevel
值为:
:code:`INFO`(默认):导出所有用户日志。
ERROR
:仅导出错误日志。Snowflake 仅导出标准错误 (stderr) 流中的日志。NONE
:不将日志导出到事件表中。
关于单位¶
服务规范在多个地方采用数值。Snowpark Container Services 支持各种单元来表示这些值。对于大值和小值,您可使用二进制和十进制单位,如下所示。在以下列表中,“#”表示整数值。
二进制单位:
numberKi
表示number*1024
。 例如,4Ki 等于 4096。numberMi
表示number*1024^2
。numberGi
表示number*1024^3
。
十进制单位:
numberk
表示number*10^3
。例如,4k 等于 4000。numberM
表示number*10^6
。numberG
表示number*10^9
。
小数单位:
numberm
表示number*0.001
。例如,cpu: 500m
相当于cpu: 0.5
。
serviceRoles
字段(可选)¶
使用规范中的 serviceRoles
顶级字段来定义一个或多个服务角色。对于每个服务角色,提供您希望服务角色授予 USAGE 权限的一个或多个端点的名称和列表(在 spec.endpoints
中定义)。
serviceRoles: # Optional list of service roles
- name: <name>
endpoints:
- <endpoint-name>
- <endpoint-name>
- ...
- ...
请注意以下事项:
name
和endpoints
都是必填项。服务角色名称须遵循以下格式:
必须包含字母数字或 _ 字符。
必须以字母字符开头。
必须以字母数字字符结尾。
有关更多信息,请参阅 管理对服务端点的访问。