部署 SkyPilot API 服务器#
SkyPilot API 服务器被打包为一个 Helm chart,用于部署 Kubernetes Ingress 控制器和 API 服务器。
提示
本指南面向管理员,用于部署 API 服务器。如果您是希望连接到 API 服务器的用户,请参阅 连接到 API 服务器。
先决条件#
提示
如果您没有 Kubernetes 集群,请参阅 Kubernetes 部署指南 进行设置。
您也可以使用现有的 SkyPilot 安装在云虚拟机上部署 API 服务器。请参阅 备选方案:在云虚拟机上部署。
步骤 1:部署 API 服务器 Helm chart#
使用以下命令安装 SkyPilot Helm chart
# Ensure the helm repository is added and up to date
helm repo add skypilot https://helm.skypilot.co
helm repo update
# The following variables will be used throughout the guide
# NAMESPACE is the namespace to deploy the API server in
NAMESPACE=skypilot
# RELEASE_NAME is the name of the helm release, must be unique within the namespace
RELEASE_NAME=skypilot
# Replace with your username and password to configure the basic auth credentials for the API server
WEB_USERNAME=skypilot
WEB_PASSWORD=yourpassword
AUTH_STRING=$(htpasswd -nb $WEB_USERNAME $WEB_PASSWORD)
# Deploy the API server
helm upgrade --install $RELEASE_NAME skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
--create-namespace \
--set ingress.authCredentials=$AUTH_STRING
标志解释
以下是上面命令中使用的标志的详细说明
upgrade --install
:如果 API 服务器已存在,则升级;如果不存在,则安装。--devel
:使用 SkyPilot helm chart 的最新开发版本。要使用特定版本,请向helm upgrade
命令传递--version
标志(例如,--version 0.1.0
)。--namespace $NAMESPACE
:指定部署 API 服务器的命名空间。--create-namespace
:如果命名空间不存在,则创建。–set ingress.authCredentials=$AUTH_STRING:设置 API 服务器的基本认证凭据。
有关可用配置选项的更多详细信息,请参阅 SkyPilot API 服务器 Helm Chart 值。
提示
默认情况下,部署的 API 服务器将被配置为使用托管 Kubernetes 集群来启动任务。请参阅 可选:配置云账户 以配置更多云和 Kubernetes 集群的凭据。
API 服务器部署后,您可以使用以下命令检查 API 服务器 Pod 的状态
kubectl get pods --namespace $NAMESPACE -l app=${RELEASE_NAME}-api --watch
您应该会看到 Pod 正在初始化并最终变为运行和就绪状态。如果不是,请参阅 Helm 部署故障排除 来诊断问题。
步骤 2:获取 API 服务器 URL#
API 服务器部署后,我们可以获取 API 服务器 URL。我们使用 nginx ingress 来暴露 API 服务器。
我们默认使用 NodePort 服务是暴露 API 服务器的推荐方式,因为某些云负载均衡器(例如 GKE)不支持 websocket 连接,而 SkyPilot 的 Kubernetes SSH 隧道需要 websocket 连接。
获取 ingress 控制器 URL
$ HOST=$(kubectl get svc ${RELEASE_NAME}-ingress-nginx-controller --namespace $NAMESPACE -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ ENDPOINT=http://${WEB_USERNAME}:${WEB_PASSWORD}@${HOST}
$ echo $ENDPOINT
http://skypilot:[email protected]
提示
如果您使用的 Kubernetes 集群不支持 LoadBalancer,您可能会在上面的输出中看到一个空的 IP 地址。在这种情况下,请改用 NodePort 选项。
提示
有关 LoadBalancer 服务的细粒度控制,请参阅 ingress-nginx 的 helm 值。请注意,所有值都应放在 ingress-nginx.
前缀下,因为 ingress-nginx chart 是作为子 chart 安装的。
在您的节点上选择两个未使用的端口,并允许网络入站流量通过这些端口。本示例将使用 30050 和 30051。
升级 API 服务器以使用 NodePort,并将节点端口设置为选定的端口
$ helm upgrade --namespace $NAMESPACE $RELEASE_NAME skypilot/skypilot-nightly --devel \
--set ingress-nginx.controller.service.type=NodePort \
--set ingress-nginx.controller.service.nodePorts.http=30050 \
--set ingress-nginx.controller.service.nodePorts.https=30051
使用以下命令获取 ingress 控制器 URL
$ NODE_PORT=$(kubectl get svc ${RELEASE_NAME}-ingress-controller-np --namespace $NAMESPACE -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}')
$ NODE_IP=$(kubectl get nodes -o jsonpath='{ $.items[0].status.addresses[?(@.type=="ExternalIP")].address }')
$ ENDPOINT=http://${WEB_USERNAME}:${WEB_PASSWORD}@${NODE_IP}:${NODE_PORT}
$ echo $ENDPOINT
http://skypilot:[email protected]:30050
提示
您也可以省略 ingress-nginx.controller.service.nodePorts.http
和 ingress-nginx.controller.service.nodePorts.https
,以使用 NodePort 范围内的随机端口(默认 30000-32767)。如果您这样做,请确保这些端口在您的节点上是开放的。
提示
为了避免云提供商频繁更改节点上的 IP 地址,您可以为您的节点附加一个静态 IP 地址(GKE 说明),并在上面的命令中将其用作 NODE_IP
。
步骤 3:测试 API 服务器#
通过 curl 请求健康检查端点来测试 API 服务器
$ curl ${ENDPOINT}/api/health
{"status":"healthy","api_version":"1","commit":"ba7542c6dcd08484d83145d3e63ec9966d5909f3-dirty","version":"1.0.0-dev0"}
如果一切顺利,您现在就可以开始使用 API 服务器了。请参阅 连接到 API 服务器 以将您的本地 SkyPilot 客户端连接到 API 服务器。
可选:配置云账户#
以下标签页描述了如何在 API 服务器上配置不同云的凭据。所有云凭据都存储在 Kubernetes secrets 中。
注意
如果您还没有部署 SkyPilot API 服务器,请参阅 步骤 1:部署 API 服务器 Helm chart,了解您在下面的 helm 部署过程中可能需要设置的其他值。
在 API 服务器部署后配置凭据时,将自动触发 API 服务器重启以应用新凭据。请参阅 升级 SkyPilot API 服务器 了解有关潜在停机时间和缓解措施的更多详细信息。
默认情况下,SkyPilot API 服务器被授予权限使用其托管 Kubernetes 集群,并将在与 API 服务器相同的命名空间中启动任务
要禁用使用托管 Kubernetes 集群,请在 Helm chart 值中设置
kubernetesCredentials.useApiServerCluster=false
。要为任务使用不同的命名空间,请在 Helm chart 值中设置
kubernetesCredentials.inclusterNamespace=<namespace>
。
提示
授予 API 服务器的默认权限可以直接使用。为了进一步加固,您可以参阅 在 helm 部署中设置最小权限 了解权限以及如何自定义它们。
要向其他集群进行身份验证,首先使用具有 所需权限 的 kubeconfig 文件创建 Kubernetes secret
kubectl create secret generic kube-credentials \
--namespace $NAMESPACE \
--from-file=config=~/.kube/config
创建 secret 后,在 Helm chart 值中设置 kubernetesCredentials.useKubeconfig=true
和 kubernetesCredentials.kubeconfigSecretName
以使用 kubeconfig 进行身份验证
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
# keep the Helm chart values set in the previous step
--reuse-values \
--set kubernetesCredentials.useKubeconfig=true \
--set kubernetesCredentials.kubeconfigSecretName=kube-credentials
提示
如果您使用的 kubeconfig 文件包含 基于 exec 的身份验证(例如 GKE 默认的基于 gke-gcloud-auth-plugin
的身份验证),您需要从 exec 配置的 command
字段中剥离路径信息。您可以使用 exec_kubeconfig_converter.py
脚本来完成此操作。
python -m sky.utils.kubernetes.exec_kubeconfig_converter --input ~/.kube/config --output ~/.kube/config.converted
然后使用转换后的 kubeconfig 文件 ~/.kube/config.converted
创建 Kubernetes secret。
要使用多个 Kubernetes 集群,您需要在 SkyPilot 配置中将上下文名称添加到 allowed_contexts
。下面显示了一个允许使用托管 Kubernetes 集群和另外两个 Kubernetes 集群的示例配置文件
kubernetes:
allowed_contexts:
# The hosting Kubernetes cluster, you cannot set this if the hosting cluster is disabled by kubernetesCredentials.useApiServerCluster=false
- in-cluster
# The additional Kubernetes context names in the kubeconfig you configured
- context1
- context2
请参阅 设置 SkyPilot 配置 了解如何在 Helm chart 值中设置 SkyPilot 配置。
请确保您拥有访问密钥 ID 和秘密访问密钥。
使用您的 AWS 凭据创建一个 Kubernetes secret
kubectl create secret generic aws-credentials \
--namespace $NAMESPACE \
--from-literal=aws_access_key_id=YOUR_ACCESS_KEY_ID \
--from-literal=aws_secret_access_key=YOUR_SECRET_ACCESS_KEY
将 YOUR_ACCESS_KEY_ID
和 YOUR_SECRET_ACCESS_KEY
替换为您的实际 AWS 凭据。
在 Helm values 文件中设置 awsCredentials.enabled=true
和 awsCredentials.awsSecretName=aws-credentials
以启用 AWS 凭据。
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
# keep the Helm chart values set in the previous step
--reuse-values \
--set awsCredentials.enabled=true
使用现有的 AWS 凭据
您还可以设置以下值来使用已包含您的 AWS 凭据的 secret
我们使用服务账户与 GCP 进行身份验证。请参阅 GCP 服务账户 指南了解如何设置服务账户。
一旦您拥有服务账户的 JSON 密钥,创建一个 Kubernetes secret 来存储它
kubectl create secret generic gcp-credentials \
--namespace $NAMESPACE \
--from-file=gcp-cred.json=YOUR_SERVICE_ACCOUNT_JSON_KEY.json
安装或升级 Helm chart 时,通过设置 gcpCredentials.enabled=true
和 gcpCredentials.projectId
为您的项目 ID 来启用 GCP 凭据
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
# keep the Helm chart values set in the previous step
--reuse-values \
--set gcpCredentials.enabled=true \
--set gcpCredentials.projectId=YOUR_PROJECT_ID
使用现有的 GCP 凭据
您还可以设置以下值来使用已包含您的 GCP 凭据的 secret
# TODO: replace with your secret name
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
--reuse-values \
--set gcpCredentials.enabled=true \
--set gcpCredentials.gcpSecretName=your_secret_name
SkyPilot API 服务器使用 API 密钥 与 RunPod 进行身份验证。要配置 RunPod 访问,请访问 RunPod 控制台上的 设置 页面并生成 API 密钥。
密钥生成后,创建一个 Kubernetes secret 来存储它
kubectl create secret generic runpod-credentials \
--namespace $NAMESPACE \
--from-literal api_key=YOUR_API_KEY
安装或升级 Helm chart 时,通过设置 runpodCredentials.enabled=true
来启用 RunPod 凭据
使用现有的 RunPod 凭据
您还可以设置以下值来使用已包含您的 RunPod API 密钥的 secret
# TODO: replace with your secret name
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
--reuse-values \
--set runpodCredentials.enabled=true \
--set runpodCredentials.runpodSecretName=your_secret_name
SkyPilot API 服务器使用 API 密钥 与 Lambda 进行身份验证。要配置 Lambda 访问,请访问您的 Lambda Cloud 控制台上的 API 密钥 页面并生成 API 密钥。
密钥生成后,创建一个 Kubernetes secret 来存储它
kubectl create secret generic lambda-credentials \
--namespace $NAMESPACE \
--from-literal api_key=YOUR_API_KEY
安装或升级 Helm chart 时,通过设置 lambdaCredentials.enabled=true
来启用 Lambda 凭据
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
# keep the Helm chart values set in the previous step
--reuse-values \
--set lambdaCredentials.enabled=true
使用现有的 Lambda 凭据
您还可以设置以下值来使用已包含您的 Lambda 凭据的 secret
# TODO: replace with your secret name
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
--reuse-values \
--set lambdaCredentials.enabled=true \
--set lambdaCredentials.lambdaSecretName=your_secret_name
我们使用服务账户与 Nebius 进行身份验证。请参阅 Nebius 服务账户 指南了解如何设置服务账户。
一旦您拥有服务账户的 JSON 凭据,创建一个 Kubernetes secret 来存储它
kubectl create secret generic nebius-credentials \
--namespace $NAMESPACE \
--from-file=credentials.json=$HOME/.nebius/credentials.json
安装或升级 Helm chart 时,通过设置 nebiusCredentials.enabled=true
和 nebiusCredentials.tenantId
为您的租户 ID 来启用 Nebius 凭据
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
# keep the Helm chart values set in the previous step
--reuse-values \
--set nebiusCredentials.enabled=true \
--set nebiusCredentials.tenantId=YOUR_TENANT_ID
使用现有的 Nebius 凭据
您还可以设置以下值来使用已包含您的 Nebius 凭据的 secret
# TODO: replace with your secret name
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
--reuse-values \
--set nebiusCredentials.enabled=true \
--set nebiusCredentials.nebiusSecretName=your_secret_name
您可以在 API 服务器 Pod 部署并运行后,通过 kubectl exec 进入该 Pod,并运行相关的 安装命令 手动配置其他云的凭据。
请注意,手动配置的凭据在 API 服务器重启后不会持久化。
通过 secrets 配置其他云的支持即将推出!
升级 API 服务器#
请参阅 升级 SkyPilot API 服务器 了解如何升级 API 服务器。
卸载#
要卸载 API 服务器,请运行
helm uninstall $RELEASE_NAME --namespace $NAMESPACE
这将删除 API 服务器和所有相关资源。
其他说明#
容错和状态持久化#
SkyPilot API 服务器设计为具有容错能力。如果 API 服务器 Pod 被终止,Kubernetes 将自动创建一个新的 Pod 来替换它。
为了在 Pod 终止期间保留状态,我们使用持久卷声明。持久卷声明由 Helm chart 创建的 PersistentVolume 提供支持。
您可以通过创建 values.yaml
文件并使用以下值来自定义存储设置
storage:
# Enable/disable persistent storage
enabled: true
# Storage class name - leave empty to use cluster default
storageClassName: ""
# Access modes - ReadWriteOnce or ReadWriteMany depending on storage class support
accessMode: ReadWriteOnce
# Storage size
size: 10Gi
# Optional selector for matching specific PVs
selector: {}
# matchLabels:
# environment: prod
# Optional volume name for binding to specific PV
volumeName: ""
# Optional annotations
annotations: {}
例如,要使用特定的存储类并增加存储大小
# values.yaml
storage:
enabled: true
storageClassName: "standard"
size: 20Gi
使用以下命令应用配置
helm upgrade --install skypilot skypilot/skypilot-nightly --devel -f values.yaml
EKS 的额外设置#
为了支持 API 服务器状态的持久存储,我们需要一个支持持久卷的存储类。如果您已经有一个支持持久卷的存储类,您可以跳过以下步骤。
我们将使用 Amazon EBS CSI 驱动程序 创建一个支持由 Amazon EBS 支持的持久卷的存储类。您也可以使用其他支持持久卷的存储类,例如 EFS。
以下步骤基于 官方文档。请遵循官方文档根据您的集群调整步骤。
请确保您的集群已启用 OIDC。按照此处的步骤操作。
您需要创建并绑定一个具有创建 EBS 卷权限的 IAM 角色。请参阅此处的说明。
安装 Amazon EBS CSI 驱动程序。推荐的方法是创建 EKS 插件。
安装 EBS CSI 驱动程序后,默认的 gp2
存储类将由 EBS 卷提供支持。
设置 SkyPilot 配置#
Helm chart 支持在 API 服务器上设置全局 SkyPilot 配置 YAML 文件。配置文件作为 ~/.sky/config.yaml
挂载到 API 服务器容器中。
要设置配置文件,请将 --set-file apiService.config=path/to/your/config.yaml
传递给 helm
命令
# Create the config.yaml file
cat <<EOF > config.yaml
admin_policy: admin_policy_examples.AddLabelsPolicy
jobs:
controller:
resources:
cpus: 2+
allowed_clouds:
- aws
- kubernetes
kubernetes:
allowed_contexts:
- my-context
- my-other-context
EOF
# Install the API server with the config file
helm upgrade --install skypilot skypilot/skypilot-nightly --devel \
--namespace $NAMESPACE \
# Reuse the values set in the previous steps, if any
--reuse-values \
--set-file apiService.config=config.yaml
您也可以直接在 values.yaml
文件中设置配置值,例如
apiService:
config: |
allowed_clouds:
- aws
- kubernetes
要应用新配置,请使用更新后的 values.yaml
文件重新运行 helm upgrade
。
设置管理员策略#
Helm chart 支持在 API 服务器启动前安装管理员策略。
为此,将 apiService.preDeployHook
设置为您要运行的命令。例如,要安装管理员策略,请创建包含以下内容的 values.yaml
文件
# values.yaml
apiService:
preDeployHook: |
echo "Installing admin policy"
pip install git+https://github.com/michaelvll/admin-policy-examples
config: |
admin_policy: admin_policy_examples.AddLabelsPolicy
然后在运行 helm upgrade 命令时使用 -f 标志应用 values.yaml 文件
helm upgrade --install skypilot skypilot/skypilot-nightly --devel -f values.yaml
在 helm 部署中设置最小权限#
在 helm 部署中,API 服务器被授予一组默认权限来访问托管 Kubernetes 集群。您可以在以下条件下自定义权限
通过使用
kubernetes.remote_identity
减少 RBAC 权限:默认情况下,API 服务器创建服务账户和 RBAC 角色以授予 SkyPilot 任务 Pod 权限。这反过来要求 API 服务器具有操作 RBAC 角色和服务账户的权限。您可以通过以下步骤禁用此功能请参阅 设置 SkyPilot 配置 将
kubernetes.remote_identity
设置为 API 服务器的服务账户,该账户已具有必要的权限
# TODO: replace ${RELEASE_NAME} with the actual release name in deployment step kubernetes: remote_identity: ${RELEASE_NAME}-api-sa
注意
如果您还通过
kubernetesCredentials.useKubeconfig
授予 API 服务器外部 Kubernetes 集群权限,则必须在这些 Kubernetes 集群中手动准备具有足够权限的相同服务账户。在 helm 值中设置
rbac.manageRbacPolicies=false
以禁用 RBAC 策略
helm upgrade --install skypilot skypilot/skypilot-nightly --devel --reuse-values \ --set rbac.manageRbacPolicies=false
如果您的用例不需要对象存储挂载,您可以通过设置
rbac.manageSystemComponents=false
禁用管理 SkyPilot 系统组件的权限helm upgrade --install skypilot skypilot/skypilot-nightly --devel --reuse-values \ --set rbac.manageSystemComponents=false
如果您想使用一个满足 SkyPilot 所需最小权限 的现有服务账户和权限,而不是由 Helm 管理的服务账户,您可以禁用 RBAC 策略的创建并指定要使用的服务账户名称
helm upgrade --install skypilot skypilot/skypilot-nightly --devel --reuse-values \
--set rbac.create=false \
--set rbac.serviceAccountName=my-existing-service-account
从旧版 NodePort 服务迁移#
如果您正在从早期的 0.8.0 nightly 版本升级,并且之前部署了 NodePort 服务(名为 ${RELEASE_NAME}-ingress-controller-np
),将引发错误要求进行迁移。此外,将创建一个新服务来暴露 API 服务器(默认使用 LoadBalancer
服务类型)。您可以根据您的需求选择以下任何选项继续升级过程
保留旧版 NodePort 服务,并逐步迁移到新的 LoadBalancer 服务
在您的
helm upgrade
命令中添加--set ingress.nodePortEnabled=true
以保留旧版 NodePort 服务。现有客户端可以继续使用先前的 NodePort 服务。在所有客户端迁移到新服务后,您可以通过在helm upgrade
命令中添加--set ingress.nodePortEnabled=false
来禁用旧版 NodePort 服务。禁用旧版 NodePort 服务
在您的
helm upgrade
命令中添加--set ingress.nodePortEnabled=false
以禁用旧版 NodePort 服务。客户端需要使用新服务连接到 API 服务器。
注意
禁用 NodePort 服务之前,请确保没有客户端正在使用它。
注意
请参阅 步骤 2:获取 API 服务器 URL 了解如何自定义和/或连接到新服务。
备选方案:在云虚拟机上部署#
注意
虚拟机部署不提供故障转移和优雅升级支持。我们建议在生产环境中使用 Helm 部署 部署 SkyPilot API 服务器。
您也可以使用现有的 SkyPilot 安装直接在云虚拟机上部署 API 服务器。
步骤 1:使用 SkyPilot 在云虚拟机上部署 API 服务器#
编写 SkyPilot API 服务器 YAML 文件并使用 sky launch
部署 API 服务器
# Write the YAML to a file
cat <<EOF > skypilot-api-server.yaml
resources:
cpus: 8+
memory: 16+
ports: 46580
image_id: docker:berkeleyskypilot/skypilot-nightly:latest
run: |
sky api start --deploy
EOF
# Deploy the API server
sky launch -c api-server skypilot-api-server.yaml
步骤 2:获取 API 服务器 URL#
API 服务器部署后,您可以使用以下命令获取 API 服务器 URL
$ sky status --endpoint 46580 api-server
http://a.b.c.d:46580
通过 curl 请求健康检查端点来测试 API 服务器
$ curl ${ENDPOINT}/health
SkyPilot API Server: Healthy
如果一切顺利,您现在就可以开始使用 API 服务器了。请参阅 连接到 API 服务器 以将您的本地 SkyPilot 客户端连接到 API 服务器。
注意
默认情况下,使用上述 YAML 文件部署的 API 服务器没有任何身份验证。我们建议添加一个身份验证层(例如 nginx 反向代理)或在 Kubernetes 集群上使用 SkyPilot helm chart 以获得更安全的部署。
提示
如果您在同一环境中安装 SkyPilot API 客户端,我们建议使用不同的 Python 环境(venv、conda 等),以避免与用于部署 API 服务器的 SkyPilot 安装发生冲突。