Kubernetes入门指南#

先决条件#

要连接并使用Kubernetes集群,SkyPilot需要:

  • 一个现有的运行Kubernetes v1.20或更高版本的Kubernetes集群。

  • 一个包含访问凭证和要使用的命名空间的Kubeconfig文件。

支持的Kubernetes部署:

  • 托管的Kubernetes服务(EKS, GKE)

  • 本地集群(Kubeadm, Rancher, K3s)

  • 本地开发集群(KinD, minikube)

在典型的工作流程中:

  1. 集群管理员设置一个Kubernetes集群。请参考不同部署环境(Amazon EKS、Google GKE、本地和本地调试)的Kubernetes集群设置的管理指南。

  2. 想要在此集群上运行SkyPilot任务的用户将获得包含其凭据的Kubeconfig文件(kube-context)。SkyPilot读取此Kubeconfig文件以与集群通信。

启动你的第一个任务#

一旦您的集群管理员设置了一个Kubernetes集群并为您提供了一个kubeconfig文件:

  1. 确保您的本地机器上安装了kubectlsocatnc(netcat)。

    $ # MacOS
    $ brew install kubectl socat netcat
    
    $ # Linux (may have socat already installed)
    $ sudo apt-get install kubectl socat netcat
    
  2. 将您的kubeconfig文件放置在~/.kube/config

    $ mkdir -p ~/.kube
    $ cp /path/to/kubeconfig ~/.kube/config
    

    您可以通过运行kubectl get pods来验证您的凭据是否设置正确。

    注意

    如果您的集群管理员还为您提供了特定的服务账户使用,请在您的~/.sky/config.yaml文件中设置它:

    kubernetes:
      remote_identity: your-service-account-name
    
  3. 运行 sky check 并验证在 SkyPilot 中是否启用了 Kubernetes。

    $ sky check
    
    Checking credentials to enable clouds for SkyPilot.
    ...
    Kubernetes: enabled
    ...
    

    注意

    sky check 还会检查您的集群是否支持 GPU。如果不支持 GPU,它将显示原因。 要在集群上设置 GPU 支持,请参阅 Kubernetes 集群设置指南

  1. 您现在可以在您的Kubernetes集群上运行任何SkyPilot任务。

    $ sky launch --cpus 2+ task.yaml
    == Optimizer ==
    Target: minimizing cost
    Estimated cost: $0.0 / hour
    
    Considered resources (1 node):
    ---------------------------------------------------------------------------------------------------
     CLOUD        INSTANCE          vCPUs   Mem(GB)   ACCELERATORS   REGION/ZONE   COST ($)   CHOSEN
    ---------------------------------------------------------------------------------------------------
     Kubernetes   2CPU--2GB         2       2         -              kubernetes    0.00          ✔
     AWS          m6i.large         2       8         -              us-east-1     0.10
     Azure        Standard_D2s_v5   2       8         -              eastus        0.10
     GCP          n2-standard-2     2       8         -              us-central1   0.10
     IBM          bx2-8x32          8       32        -              us-east       0.38
     Lambda       gpu_1x_a10        30      200       A10:1          us-east-1     0.60
    ---------------------------------------------------------------------------------------------------.
    

注意

SkyPilot 将使用 kubeconfig 文件中 current-context 设置的集群和命名空间。要管理您的 current-context

$ # See current context
$ kubectl config current-context

$ # Switch current-context
$ kubectl config use-context mycontext

$ # Set a specific namespace to be used in the current-context
$ kubectl config set-context --current --namespace=mynamespace

查看集群状态#

要查看Kubernetes集群中所有SkyPilot资源的状态,请运行sky status --k8s

与仅列出当前用户启动的SkyPilot资源的sky status不同, sky status --k8s列出了Kubernetes集群中所有用户的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

你也可以使用sky show-gpus --cloud k8s来检查集群上的实时GPU使用情况。

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

Kubernetes per node GPU availability
NODE_NAME                  GPU_NAME  TOTAL_GPUS  FREE_GPUS
my-cluster-0               L4        4           4
my-cluster-1               L4        4           4
my-cluster-2               L4        2           2
my-cluster-3               L4        2           2
my-cluster-4               H100      8           8
my-cluster-5               H100      8           8

使用自定义图像#

默认情况下,我们维护并使用两个SkyPilot容器镜像,用于Kubernetes集群:

  1. us-central1-docker.pkg.dev/skypilot-375900/skypilotk8s/skypilot: 用于仅CPU的集群 (Dockerfile).

  2. us-central1-docker.pkg.dev/skypilot-375900/skypilotk8s/skypilot-gpu: 用于GPU集群 (Dockerfile).

这些镜像预先安装了SkyPilot依赖项,以便快速启动。

要使用您自己的镜像,请将image_id: docker: image tag>添加到任务YAML的resources部分。

resources:
  image_id: docker:myrepo/myimage:latest
...

您的图像必须满足以下要求:

  • 镜像必须是基于debian的,并且必须安装apt包管理器。

  • 镜像中的默认用户必须具有root权限或无密码sudo访问权限。

注意

如果你的集群运行在非x86_64架构上(例如,Apple Silicon),你的镜像必须为该架构原生构建。否则,你的任务可能会卡在Start streaming logs ...。更多信息请参见GitHub issue

使用私有仓库中的镜像#

要从私有仓库(例如,私有 DockerHub、Amazon ECR、Google 容器注册表)使用镜像,请在您的 Kubernetes 集群中创建一个 secret,并编辑您的 ~/.sky/config.yaml 文件以指定 secret,如下所示:

kubernetes:
  pod_config:
    spec:
      imagePullSecrets:
        - name: your-secret-here

提示

如果您使用Amazon ECR,您的秘密凭证可能每12小时过期一次。考虑使用k8s-ecr-login-renew来自动刷新您的秘密。

打开端口#

在Kubernetes上运行的SkyPilot集群上开放端口支持两种模式:

  1. LoadBalancer services (默认)

  2. Nginx IngressController

您的集群必须支持并配置其中一种模式。请参阅在Kubernetes上设置端口的指南了解如何操作。

提示

在Google GKE、Amazon EKS或其他云托管的Kubernetes服务上,默认的LoadBalancer服务模式是开箱即用的,不需要额外的配置。

一旦您的集群配置完成,通过在任务YAML的resources部分添加ports来启动一个在端口上暴露服务的任务。

# task.yaml
resources:
  ports: 8888

run: |
  python -m http.server 8888

使用sky launch -c myclus task.yaml启动集群后,您可以使用sky status --endpoints myclus获取访问端口的URL。

# List all ports exposed by the cluster
$ sky status --endpoints myclus
8888: 34.173.13.241:8888

# curl a specific port's endpoint
$ curl $(sky status --endpoint 8888 myclus)
...

提示

要了解更多关于在SkyPilot任务中打开端口的信息,请参阅打开端口

自定义SkyPilot pods#

你可以通过在~/.sky/config.yaml中设置pod_config键来覆盖SkyPilot使用的pod配置。 pod_config的值应该是一个遵循Kubernetes Pod API的字典。这将适用于由SkyPilot创建的所有pod。

例如,要设置自定义环境变量并使用GPUDirect RDMA,您可以将以下内容添加到您的~/.sky/config.yaml文件中:

# ~/.sky/config.yaml
kubernetes:
  pod_config:
    spec:
      containers:
        - env:                # Custom environment variables to set in pod
          - name: MY_ENV_VAR
            value: MY_ENV_VALUE
          resources:          # Custom resources for GPUDirect RDMA
            requests:
              rdma/rdma_shared_device_a: 1
            limits:
              rdma/rdma_shared_device_a: 1

同样地,你可以直接将Kubernetes卷(例如,一个NFS卷)附加到你的SkyPilot pods上:

# ~/.sky/config.yaml
kubernetes:
  pod_config:
    spec:
      containers:
        - volumeMounts:       # Custom volume mounts for the pod
            - mountPath: /data
              name: nfs-volume
      volumes:
        - name: nfs-volume
          nfs:                # Alternatively, use hostPath if your NFS is directly attached to the nodes
            server: nfs.example.com
            path: /nfs

提示

作为全局设置pod_config的替代方案,你也可以在任务YAML中直接使用config_overrides 字段在每个任务的基础上进行设置。

# task.yaml
run: |
  python myscript.py

# Set pod_config for this task
experimental:
  config_overrides:
    pod_config:
      ...

常见问题解答#

  • 我可以将多个Kubernetes集群与SkyPilot一起使用吗?

    SkyPilot 可以与您的 kubeconfig 文件中设置的多个 Kubernetes 上下文一起工作。默认情况下,SkyPilot 将使用当前活动的上下文。要使用不同的上下文,请使用 kubectl config use-context 更改您的当前上下文。

    如果您希望在故障转移期间无缝使用多个上下文,请查看高级配置中的allowed_contexts功能。

  • 是否支持自动扩展Kubernetes集群?

    要在自动扩展集群上运行,请在~/.sky/config.yaml中将provision_timeout键设置为一个较大的值,以便为集群自动扩展器提供足够的时间来配置新节点。 这将指示SkyPilot在集群扩展之前等待,然后再切换到下一个候选资源(例如,下一个云)。

    如果您在零扩展设置中使用GPU,您还应将autoscaler键设置为集群的自动扩展类型。更多详细信息请参见高级配置

    # ~/.sky/config.yaml
    kubernetes:
      provision_timeout: 900  # Wait 15 minutes for nodes to get provisioned before failover. Set to -1 to wait indefinitely.
      autoscaler: gke  # [gke, karpenter, generic]; required if using GPUs in scale-to-zero setting
    
  • SkyPilot 能为我配置一个 Kubernetes 集群吗?SkyPilot 会为我的 Kubernetes 集群添加更多节点吗?

    Kubernetes支持的目标是在现有的Kubernetes集群上运行SkyPilot任务。它不会配置任何新的Kubernetes集群,也不会向现有的Kubernetes集群添加新节点。

  • 我的组织中有多个用户共享同一个Kubernetes集群。我如何为他们的SkyPilot工作负载提供隔离?

    为了实现隔离,您可以创建单独的Kubernetes命名空间,并将它们设置在分发给用户的kubeconfig中。SkyPilot将使用kubeconfig中设置的命名空间来运行所有任务。

  • 如何查看我在Kubernetes集群上由SkyPilot创建的pods?

    您可以使用现有的可观测性工具来过滤带有标签 parent=skypilot 的资源 (kubectl get pods -l 'parent=skypilot')。例如,按照 这里 的说明在您的集群上部署 Kubernetes Dashboard。

  • 我正在使用自定义镜像。如何加快pod的启动时间?

    您可以在自定义镜像中预安装SkyPilot依赖项,以加快pod启动时间。只需在Dockerfile末尾添加以下行:

    FROM <your base image>
    
    # Install system dependencies
    RUN apt update -y && \
        apt install git gcc rsync sudo patch openssh-server pciutils fuse unzip socat netcat-openbsd curl -y && \
        rm -rf /var/lib/apt/lists/*
    
    # Install conda and other python dependencies
    RUN curl https://repo.anaconda.com/miniconda/Miniconda3-py310_23.11.0-2-Linux-x86_64.sh -o Miniconda3-Linux-x86_64.sh && \
        bash Miniconda3-Linux-x86_64.sh -b && \
        eval "$(~/miniconda3/bin/conda shell.bash hook)" && conda init && conda config --set auto_activate_base true && conda activate base && \
        grep "# >>> conda initialize >>>" ~/.bashrc || { conda init && source ~/.bashrc; } && \
        rm Miniconda3-Linux-x86_64.sh && \
        export PIP_DISABLE_PIP_VERSION_CHECK=1 && \
        python3 -m venv ~/skypilot-runtime && \
        PYTHON_EXEC=$(echo ~/skypilot-runtime)/bin/python && \
        $PYTHON_EXEC -m pip install 'skypilot-nightly[remote,kubernetes]' 'ray[default]==2.9.3' 'pycryptodome==3.12.0' && \
        $PYTHON_EXEC -m pip uninstall skypilot-nightly -y && \
        curl -LO "https://dl.k8s.io/release/v1.28.11/bin/linux/amd64/kubectl" && \
        sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl && \
        echo 'export PATH="$PATH:$HOME/.local/bin"' >> ~/.bashrc