Kubernetes 集群设置#

注意

这是为集群管理员提供的关于如何设置用于 SkyPilot 的 Kubernetes 集群的指南。

如果您是 SkyPilot 用户,并且您的集群管理员已经设置好了集群并与您共享了 kubeconfig 文件,将任务提交到 Kubernetes 解释了如何将任务提交到您的集群。

⚙️ 设置 Kubernetes 集群

配置您的 Kubernetes 集群以运行 SkyPilot。

✅️ 验证设置

确保您的集群已正确设置以便 SkyPilot 使用。

👀️ 可观测性

使用您现有的 Kubernetes 工具来监控 SkyPilot 资源。

为 SkyPilot 设置 Kubernetes 集群#

要准备一个 Kubernetes 集群来运行 SkyPilot,集群管理员必须:

  1. 部署一个 运行 Kubernetes v1.20 或更高版本的集群。

  2. 设置GPU 支持

完成这些必要步骤后,根据需要执行可选设置步骤:

完成后,管理员可以将 kubeconfig 文件共享给用户,用户随后可以使用 SkyPilot 将任务提交到集群。

步骤 1 - 部署一个 Kubernetes 集群#

提示

如果您已经有一个 Kubernetes 集群,请跳过此步骤。

下面我们提供了在不同环境中设置新 Kubernetes 集群的最小化指南链接,包括云上的托管服务。

本地开发集群

使用 sky local up 在您的笔记本电脑上运行一个本地 Kubernetes 集群。

本地集群 (RKE2, K3s 等)

用于使用 kubeadm, RKE2, K3s 或其他分发版的本地部署。

Google Cloud - GKE

Google 的托管 Kubernetes 服务。

Amazon - EKS

Amazon 的托管 Kubernetes 服务。

步骤 2 - 设置 GPU 支持#

要在 Kubernetes 上使用 GPU,您的集群必须:

  1. 在所有 GPU 节点上都有 nvidia.com/gpu 资源,并且容器引擎的默认运行时为 nvidia

  2. 在每个节点上都有一个指定 GPU 类型的标签。更多详情请参阅设置 GPU 标签

提示

要验证 Nvidia GPU Operator 在步骤 1 后已安装且 nvidia 运行时被设为默认,请运行:

$ kubectl apply -f https://raw.githubusercontent.com/skypilot-org/skypilot/master/tests/kubernetes/gpu_test_pod.yaml
$ watch kubectl get pods
# If the pod status changes to completed after a few minutes, Nvidia GPU driver is set up correctly. Move on to setting up GPU labels.

注意

有关在特定 Kubernetes 分发版(如 RKE2 和 K3s)上设置 GPU 支持的额外说明,请参阅特定 Kubernetes 分发版的注意事项

设置 GPU 标签#

提示

如果您的集群已安装 Nvidia GPU Operator 或您正在使用 GKE 或 Karpenter,您的集群已经具有必要的 GPU 标签。您可以跳过此节。

要在 SkyPilot 中使用 GPU,集群节点必须使用 GPU 类型进行标记。这将告知 SkyPilot 集群上可用的 GPU 类型。

当前支持的标签有:

  • nvidia.com/gpu.product: 由 Nvidia GPU Operator 自动创建。

  • cloud.google.com/gke-accelerator: 由 GKE 集群使用。

  • karpenter.k8s.aws/instance-gpu-name: 由 Karpenter 使用。

  • skypilot.co/accelerator: 如果以上标签均不存在,SkyPilot 使用的自定义标签。

以上任一标签都足以让 SkyPilot 检测到集群上的 GPU。

提示

要检查您的节点是否包含必要的标签,请运行:

output=$(kubectl get nodes --show-labels | awk -F'[, ]' '{for (i=1; i<=NF; i++) if ($i ~ /nvidia.com\/gpu.product=|cloud.google.com\/gke-accelerator=|karpenter.k8s.aws\/instance-gpu-name=|skypilot.co\/accelerator=/) print $i}')
if [ -z "$output" ]; then
  echo "No valid GPU labels found."
else
  echo "GPU Labels found:"
  echo "$output"
fi

自动标记节点#

如果您的集群上不存在以上任何标签,我们提供了一个便捷脚本,可以自动检测 GPU 类型,并使用 skypilot.co/accelerator 标签标记每个节点。您可以通过以下命令运行它:

$ python -m sky.utils.kubernetes.gpu_labeler

Created GPU labeler job for node ip-192-168-54-76.us-west-2.compute.internal
Created GPU labeler job for node ip-192-168-93-215.us-west-2.compute.internal
GPU labeling started - this may take 10 min or more to complete.
To check the status of GPU labeling jobs, run `kubectl get jobs --namespace=kube-system -l job=sky-gpu-labeler`
You can check if nodes have been labeled by running `kubectl describe nodes` and looking for labels of the format `skypilot.co/accelerator: <gpu_name>`.

注意

如果 GPU 标记过程失败,您可以运行 python -m sky.utils.kubernetes.gpu_labeler --cleanup 来清理失败的任务。

手动标记节点#

如果需要,您也可以手动标记节点。标签必须采用 skypilot.co/accelerator: <gpu_name> 格式,其中 <gpu_name> 是 GPU 名称的小写形式。

例如,一个具有 H100 GPU 的节点必须具有标签 skypilot.co/accelerator: h100

使用以下命令标记节点:

kubectl label nodes <node-name> skypilot.co/accelerator=<gpu_name>

注意

GPU 标签是区分大小写的。如果您使用 skypilot.co/accelerator 标签,请确保 GPU 名称使用小写形式。

验证设置#

集群部署完成后,并将您的 kubeconfig 文件放置在 ~/.kube/config,通过运行 sky check 来验证您的设置:

sky check kubernetes

这应该显示 Kubernetes: Enabled 且没有任何警告。

您还可以通过运行以下命令来检查节点上可用的 GPU:

$ sky show-gpus --cloud k8s
Kubernetes GPUs
GPU   REQUESTABLE_QTY_PER_NODE  UTILIZATION
L4    1, 2, 4                   12 of 12 free
H100  1, 2, 4, 8                16 of 16 free

Kubernetes per node GPU availability
NODE                       GPU       UTILIZATION
my-cluster-0               L4        4 of 4 free
my-cluster-1               L4        4 of 4 free
my-cluster-2               L4        2 of 2 free
my-cluster-3               L4        2 of 2 free
my-cluster-4               H100      8 of 8 free
my-cluster-5               H100      8 of 8 free

可选设置#

以下设置步骤是可选的,可根据您的具体需求进行:

设置 NFS 和其他卷#

可以使用 pod_config 字段将 Kubernetes 卷挂载到 SkyPilot Pods。这对于访问共享存储(如 NFS)或本地高性能存储(如 NVMe 驱动器)非常有用。

卷挂载可以直接在任务 YAML 中按任务进行,或者在 ~/.sky/config.yaml 中全局应用于所有任务。

示例

挂载一个已挂载在 Kubernetes 节点上的 NFS 共享。

按任务配置

# task.yaml
run: |
  echo "Hello, world!" > /mnt/nfs/hello.txt
  ls -la /mnt/nfs

config:
  kubernetes:
    pod_config:
      spec:
        containers:
          - volumeMounts:
              - mountPath: /mnt/nfs
                name: my-host-nfs
        volumes:
          - name: my-host-nfs
            hostPath:
              path: /path/on/host/nfs
              type: Directory

全局配置

# ~/.sky/config.yaml
kubernetes:
  pod_config:
    spec:
      containers:
        - volumeMounts:
            - mountPath: /mnt/nfs
              name: my-host-nfs
      volumes:
        - name: my-host-nfs
          hostPath:
            path: /path/on/host/nfs
            type: Directory

使用 Kubernetes 的原生 NFS 卷支持来挂载 NFS 共享。

按任务配置

# task.yaml
run: |
  echo "Hello, world!" > /mnt/nfs/hello.txt
  ls -la /mnt/nfs

config:
  kubernetes:
    pod_config:
      spec:
         containers:
           - volumeMounts:
               - mountPath: /mnt/nfs
                 name: nfs-volume
         volumes:
           - name: nfs-volume
             nfs:
               server: nfs.example.com
               path: /shared
               readOnly: false

全局配置

# ~/.sky/config.yaml
kubernetes:
  pod_config:
    spec:
      containers:
        - volumeMounts:
            - mountPath: /mnt/nfs
              name: nfs-volume
      volumes:
        - name: nfs-volume
          nfs:
            server: nfs.example.com
            path: /shared
            readOnly: false

挂载已挂载在 Kubernetes 节点上的本地 NVMe 存储。

按任务配置

# task.yaml
run: |
  echo "Hello, world!" > /mnt/nvme/hello.txt
  ls -la /mnt/nvme

config:
  kubernetes:
    pod_config:
      spec:
         containers:
           - volumeMounts:
               - mountPath: /mnt/nvme
                 name: nvme
         volumes:
           - name: nvme
             hostPath:
               path: /path/on/host/nvme
               type: Directory

全局配置

# ~/.sky/config.yaml
kubernetes:
  pod_config:
    spec:
      containers:
        - volumeMounts:
            - mountPath: /mnt/nvme
              name: nvme
      volumes:
        - name: nvme
          hostPath:
            path: /path/on/host/nvme
            type: Directory

注意

使用 hostPath 卷时,指定的路径必须已存在于 Pod 调度的 Kubernetes 节点上。

对于使用 hostPath 的 NFS 挂载,请确保 NFS 挂载已在所有 Kubernetes 节点上配置。

设置优先级和抢占#

默认情况下,所有 SkyPilot Pods 都使用您的集群中配置的默认 Kubernetes 优先级类。如果资源不足,Pod 将排队。

要为 SkyPilot Pods 分配优先级并启用抢占以优先处理关键任务,请参阅优先级与抢占

设置命名空间和服务账户#

提示

默认情况下,SkyPilot 在当前 kube-context 配置的命名空间中运行,并创建一个名为 skypilot-service-account 的服务账户来运行任务。如果您使用这些默认值,则无需执行此步骤。

如果您的集群需要将 SkyPilot 任务隔离到特定的命名空间并限制授予用户的权限,您可以为 SkyPilot 创建一个新的命名空间和服务账户。

所需服务账户的最小权限可以在最小 Kubernetes 权限页面上找到。

为了简化设置,我们提供了一个脚本,可以为给定的服务账户名称和命名空间创建具有必要权限的命名空间和服务账户。

# Download the script
wget https://raw.githubusercontent.com/skypilot-org/skypilot/master/sky/utils/kubernetes/generate_kubeconfig.sh
chmod +x generate_kubeconfig.sh

# Execute the script to generate a kubeconfig file with the service account and namespace
# Replace my-sa and my-namespace with your desired service account name and namespace
# The script will create the namespace if it does not exist and create a service account with the necessary permissions.
SKYPILOT_SA_NAME=my-sa SKYPILOT_NAMESPACE=my-namespace ./generate_kubeconfig.sh

您可以将生成的 kubeconfig 文件分发给用户,他们随后可以使用它将任务提交到集群。

设置为暴露服务#

提示

如果您使用 GKE 或 EKS,或者不打算在 Kubernetes 上公开暴露端口(例如 sky launch --ports, SkyServe),则无需额外设置。在 GKE 和 EKS 上,SkyPilot 将自动创建一个 LoadBalancer 服务。

运行 SkyServe 或需要暴露端口的任务需要额外设置才能暴露运行服务的端口。SkyPilot 支持以下两种模式来暴露端口:

更多详情请参阅在 Kubernetes 上暴露服务

设置 FUSE 代理#

默认情况下,SkyPilot 会自动设置一个 FUSE 代理,允许由 SkyPilot 创建的 Pods 在没有 root 权限的情况下执行 FUSE 挂载/卸载操作。该代理需要 root 权限和 SYS_ADMIN 能力,这可能需要额外的安全审计。

在大多数集群中,SkyPilot 将 FUSE 代理设置为一个特权的 DaemonSet,用户不需要手动配置

但是,如果您在权限受限的集群中操作,您可以在外部部署 DaemonSet,以避免需要授予 SkyPilot 创建特权 DaemonSets 的权限。SkyPilot 将自动发现该 DaemonSet 并将其用作 FUSE 代理:

# If you do not want to grant SkyPilot the ability to create privileged daemonsets, manually deploy the FUSE proxy:
$ kubectl create namespace skypilot-system || true
$ kubectl -n skypilot-system apply -f https://raw.githubusercontent.com/skypilot-org/skypilot/master/sky/provision/kubernetes/manifests/fusermount-server-daemonset.yaml

管理员的可观测性#

所有 SkyPilot 任务都在 Kubernetes 集群内的 Pods 中运行。作为集群管理员,您可以检查正在运行的 Pods(例如,使用 kubectl get pods -n namespace)以查看正在运行哪些任务以及它们正在集群上消耗多少资源。

下面,我们提供了关于如何监控 Kubernetes 集群上 SkyPilot 资源的提示。

列出所有用户的 SkyPilot 资源#

我们提供了一个方便的命令 sky status --k8s,用于查看集群中所有 SkyPilot 资源的状态。

与仅列出当前用户启动的 SkyPilot 资源的 sky status 不同,sky status --k8s 列出集群中所有用户的 SkyPilot 资源。

$ sky status --k8s
Kubernetes cluster state (context: mycluster)
SkyPilot clusters
USER     NAME                           LAUNCHED    RESOURCES                                  STATUS
alice    infer-svc-1                    23 hrs ago  1x Kubernetes(cpus=1, mem=1, {'L4': 1})    UP
alice    sky-jobs-controller-80b50983   2 days ago  1x Kubernetes(cpus=4, mem=4)               UP
alice    sky-serve-controller-80b50983  23 hrs ago  1x Kubernetes(cpus=4, mem=4)               UP
bob      dev                            1 day ago   1x Kubernetes(cpus=2, mem=8, {'H100': 1})  UP
bob      multinode-dev                  1 day ago   2x Kubernetes(cpus=2, mem=2)               UP
bob      sky-jobs-controller-2ea485ea   2 days ago  1x Kubernetes(cpus=4, mem=4)               UP

Managed jobs
In progress tasks: 1 STARTING
USER     ID  TASK  NAME      RESOURCES   SUBMITTED   TOT. DURATION  JOB DURATION  #RECOVERIES  STATUS
alice    1   -     eval      1x[CPU:1+]  2 days ago  49s            8s            0            SUCCEEDED
bob      4   -     pretrain  1x[H100:4]  1 day ago   1h 1m 11s      1h 14s        0            SUCCEEDED
bob      3   -     bigjob    1x[CPU:16]  1 day ago   1d 21h 11m 4s  -             0            STARTING
bob      2   -     failjob   1x[CPU:1+]  1 day ago   54s            9s            0            FAILED
bob      1   -     shortjob  1x[CPU:1+]  2 days ago  1h 1m 19s      1h 16s        0            SUCCEEDED

Kubernetes 面板#

您可以部署诸如 Kubernetes 面板的工具,以便轻松查看和管理集群上的 SkyPilot 资源。

Kubernetes dashboard

作为演示,我们提供了一个示例 Kubernetes 面板部署清单,您可以使用以下命令部署:

$ kubectl apply -f https://raw.githubusercontent.com/skypilot-org/skypilot/master/tests/kubernetes/scripts/dashboard.yaml

要访问面板,请运行:

$ kubectl proxy

在浏览器中打开 http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/,并在出现凭据提示时点击“跳过”。

请注意,此面板只能从执行 kubectl proxy 命令的机器访问。

注意

演示面板不安全,不应在生产环境中使用。请参考 Kubernetes 文档,了解有关如何设置面板访问控制的更多信息。

Kubernetes 设置故障排除#

如果您在设置 Kubernetes 集群时遇到问题,请参考故障排除指南来诊断和修复问题。