Kubernetes 故障排除#

如果您无法在 Kubernetes 集群上运行 SkyPilot 任务,本指南将帮助您调试常见问题。

如果本指南未能帮助您解决问题,请通过 SlackGitHub 联系我们。

验证基本设置#

步骤 A0 - Kubectl 是否正常工作?#

您是否能够在不出现任何错误的情况下运行 kubectl get nodes

$ kubectl get nodes
# This should list all the nodes in your cluster.

确保至少有一个节点处于 Ready 状态。

如果您看到错误,请确保您的 kubeconfig 文件(位于 ~/.kube/config)已正确设置。

注意

kubectl 命令不应需要任何附加标志或环境变量即可运行。如果需要附加标志,您必须将所有配置编码到 ~/.kube/config 的 kubeconfig 文件中。例如,--context--token--certificate-authority 等都应直接在 kubeconfig 文件中配置。

步骤 A1 - 您能否创建 Pod 和 Service?#

作为健全性检查,我们现在尝试创建一个运行 HTTP 服务器的简单 Pod 和一个 Service,以验证您的集群及其网络是否正常工作。

我们将使用 SkyPilot 默认镜像 us-central1-docker.pkg.dev/skypilot-375900/skypilotk8s/skypilot:latest 来验证是否可以从注册表拉取该镜像。

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

# Verify that the pod is running by checking the status of the pod
$ kubectl get pod skytest

# Try accessing the HTTP server in the pod by port-forwarding it to your local machine
$ kubectl port-forward svc/skytest-svc 8080:8080

# Open a browser and navigate to http://localhost:8080 to see an index page

# Once you have verified that the pod is running, you can delete it
$ kubectl delete -f https://raw.githubusercontent.com/skypilot-org/skypilot/master/tests/kubernetes/cpu_test_pod.yaml

如果您的 Pod 未启动,请使用 kubectl describe skytestkubectl logs skytest 检查 Pod 的日志以查找错误。

步骤 A2 - SkyPilot 能否访问您的集群?#

运行 sky check 来验证 SkyPilot 是否可以访问您的集群。

$ sky check
# Should show `Kubernetes: Enabled`

如果您看到错误,请确保您的 kubeconfig 文件(位于 ~/.kube/config)已正确设置。

步骤 A3 - 您的节点是否有足够的磁盘空间?#

如果您的节点磁盘空间不足,在配置期间可能会在终端中出现 rpc error: code = Canceled desc = failed to pull and unpack image: context canceled 错误,导致 SkyPilot 镜像拉取失败。通过检查 kubectl describe nodes 中的 Conditions,或者运行以下命令,确保您的节点没有处于磁盘压力下:

$ kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{range .status.conditions[?(@.type=="DiskPressure")]}{.type}={.status}{"\n"}{end}{"\n"}{end}'
# Should not show DiskPressure=True for any node

步骤 A4 - 你能启动 SkyPilot 任务吗?#

步骤 A4 - 您能否启动 SkyPilot 任务?#

$ sky launch -y -c mycluster --cloud k8s -- "echo hello world"
# Task should run and print "hello world" to the console

# Once you have verified that the task runs, you can delete it
$ sky down -y mycluster

接下来,尝试运行一个简单的 hello world 任务,以验证 SkyPilot 是否可以在您的集群上启动任务。

如果您的任务未运行,请检查终端和配置日志以查找错误。配置日志的路径可在 SkyPilot 输出的开头找到,以“To view detailed progress: …”开头。

检查 GPU 支持#

如果您尝试运行 GPU 任务,请确保您已按照步骤 2 - 设置 GPU 支持中的说明设置您的集群以支持 GPU。

在本节中,我们将验证您的集群是否支持 GPU 以及 SkyPilot 是否可以访问它。

步骤 B0 - 您的集群是否已启用 GPU?#

$ kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, capacity: .status.capacity}'
# Look for the `nvidia.com/gpu` field under resources in the output. It should show the number of GPUs available for each node.

运行 kubectl describe nodes 或以下代码片段来验证您的节点是否具有 nvidia.com/gpu 资源。

如果您没有看到 nvidia.com/gpu 字段,您的集群很可能没有安装 Nvidia GPU Operator。请按照步骤 2 - 设置 GPU 支持中的说明安装 Nvidia GPU Operator。请注意,GPU Operator 的安装可能需要几分钟,并且在安装完成之前,nvidia.com/gpu 资源的容量可能显示为 0。

提示

如果您使用 GKE,请参考在 Google Cloud GKE 上部署中的说明安装相应的驱动程序。

步骤 B1 - 您能否运行 GPU Pod?#

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

# Verify that the pod is running by checking the status of the pod
$ kubectl get pod skygputest

$ kubectl logs skygputest
# Should print the nvidia-smi output to the console

# Once you have verified that the pod is running, you can delete it
$ kubectl delete -f https://raw.githubusercontent.com/skypilot-org/skypilot/master/tests/kubernetes/gpu_test_pod.yaml

通过运行以下命令验证 GPU Operator 是否已安装以及 nvidia 运行时是否设置为默认值:

如果 Pod 状态为 pending,请在上一步中确保您的节点上提供了 nvidia.com/gpu 资源。您可以通过运行 kubectl describe pod skygputest 进行进一步调试。

如果日志显示 nvidia-smi: command not found,则很可能未将 nvidia 运行时设置为默认值。请安装 Nvidia GPU Operator,并确保 nvidia 运行时设置为默认值。例如,对于 RKE2,请参考 使用 Helm 在 RKE2 上安装 Nvidia GPU Operator 的说明来将 nvidia 运行时设置为默认值。

步骤 B2 - 您的节点是否已正确标记?#

如果您没有看到 nvidia.com/gpu 字段,您的集群很可能没有安装 Nvidia GPU Operator。请按照步骤 2 - 设置 GPU 支持中的说明安装 Nvidia GPU Operator。请注意,GPU Operator 的安装可能需要几分钟,并且在安装完成之前,nvidia.com/gpu 资源的容量可能显示为 0。

SkyPilot 要求节点使用正确的 GPU 类型进行标记才能运行 GPU 任务。运行 kubectl get nodes -o json 来验证您的节点是否已正确标记。

$ kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, labels: .metadata.labels}'
# Look for the `skypilot.co/accelerator` label in the output. It should show the GPU type for each node.

如果您使用 GKE,您的节点应自动标记为 cloud.google.com/gke-accelerator。您可以跳过此步骤。

如果您没有看到 skypilot.co/accelerator 标记,您的节点未正确标记。请按照步骤 2 - 设置 GPU 支持中的说明标记您的节点。

步骤 B3 - SkyPilot 能否看到您的 GPU?#

$ sky check
# Should show `Kubernetes: Enabled` and should not print any warnings about GPU support.

# List the available GPUs in your cluster
$ sky show-gpus --cloud k8s

运行 sky check 来验证 SkyPilot 是否可以看到您的 GPU。

步骤 B4 - 尝试启动一个虚拟 GPU 任务#

# Replace the GPU type from the sky show-gpus output in the task launch command
$ sky launch -y -c mygpucluster --cloud k8s --gpu <gpu-type>:1 -- "nvidia-smi"

# Task should run and print the nvidia-smi output to the console

# Once you have verified that the task runs, you can delete it
$ sky down -y mygpucluster

接下来,尝试运行一个简单的 hello world 任务,以验证 SkyPilot 是否可以在您的集群上启动任务。

接下来,尝试运行一个简单的 GPU 任务,以验证 SkyPilot 是否可以在您的集群上启动 GPU 任务。

验证端口支持#

如果您尝试运行需要开放端口的任务,请确保您已按照 :ref:_kubernetes-ports 中的说明配置 SkyPilot 和您的集群,以使用所需的端口支持方法(LoadBalancer Service 或 Nginx Ingress)。

在本节中,我们将首先验证您的集群是否支持端口,以及 SkyPilot 启动的服务是否可以访问。

步骤 C0 - 验证 LoadBalancer Service 设置#

如果您没有看到 nvidia.com/gpu 字段,您的集群很可能没有安装 Nvidia GPU Operator。请按照步骤 2 - 设置 GPU 支持中的说明安装 Nvidia GPU Operator。请注意,GPU Operator 的安装可能需要几分钟,并且在安装完成之前,nvidia.com/gpu 资源的容量可能显示为 0。

如果您使用 LoadBalancer Service 来支持端口,请按照以下步骤验证您的集群是否配置正确。

如果您使用 Nginx Ingress 来支持端口,请跳至步骤 C0 - 验证 Nginx Ingress 设置

您的集群是否支持 LoadBalancer Service?#

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

# Verify that the service gets an external IP
# Note: It may take some time on cloud providers to change from pending to an external IP
$ watch kubectl get svc skytest-loadbalancer

# Once you get an IP, try accessing the HTTP server by curling the external IP
$ IP=$(kubectl get svc skytest-loadbalancer -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ curl $IP:8080

# Once you have verified that the service is accessible, you can delete it
$ kubectl delete -f https://raw.githubusercontent.com/skypilot-org/skypilot/master/tests/kubernetes/cpu_test_pod.yaml
$ kubectl delete -f https://raw.githubusercontent.com/skypilot-org/skypilot/master/tests/kubernetes/loadbalancer_test_svc.yaml

为了验证您的集群是否支持 LoadBalancer Service,我们将创建一个示例 Service 并验证它是否获得了外部 IP。

如果您的 Service 未获得外部 IP,请使用 kubectl describe svc skytest-loadbalancer 检查 Service 的状态。您的集群可能不支持 LoadBalancer Service。

步骤 C0 - 验证 Nginx Ingress 设置#

如果您没有看到 nvidia.com/gpu 字段,您的集群很可能没有安装 Nvidia GPU Operator。请按照步骤 2 - 设置 GPU 支持中的说明安装 Nvidia GPU Operator。请注意,GPU Operator 的安装可能需要几分钟,并且在安装完成之前,nvidia.com/gpu 资源的容量可能显示为 0。

如果您使用 Nginx Ingress 来支持端口,请参考Nginx Ingress获取关于如何安装和配置 Nginx Ingress 的说明。

如果您使用 LoadBalancer Service 来支持端口,可以跳过本节。

您的集群是否支持 Nginx Ingress?#

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

# Get the external IP of the ingress using the externalIPs field or the loadBalancer field
$ IP=$(kubectl get service ingress-nginx-controller -n ingress-nginx -o jsonpath='{.spec.externalIPs[*]}') && [ -z "$IP" ] && IP=$(kubectl get service ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[*].ip}')
$ echo "Got IP: $IP"
$ curl http://$IP/skytest

# Once you have verified that the service is accessible, you can delete it
$ kubectl delete -f https://raw.githubusercontent.com/skypilot-org/skypilot/master/tests/kubernetes/cpu_test_pod.yaml
$ kubectl delete -f https://raw.githubusercontent.com/skypilot-org/skypilot/master/tests/kubernetes/ingress_test_svc.yaml

为了验证您的集群是否支持 Nginx Ingress,我们将创建一个示例 Ingress。

如果未获取到 IP,请使用 kubectl describe svc ingress-nginx-controller -n ingress-nginx 检查 Service 的状态。您的 Ingress 的 Service 必须是 LoadBalancerNodePort 类型,并且必须具有外部 IP。

SkyPilot 是否配置为使用 Nginx Ingress?#

$ cat ~/.sky/config.yaml

# Output should contain:
#
# kubernetes:
#   ports: ingress

查看您的 ~/.sky/config.yaml 文件,验证 ports: ingress 部分是否配置正确。

如果未配置,请将 ports: ingress 部分添加到您的 ~/.sky/config.yaml 文件中。

步骤 C1 - 验证 SkyPilot 能否启动服务#

$ sky launch -y -c myserver --cloud k8s --ports 8080 -- "python -m http.server 8080"

# Obtain the endpoint of the service
$ sky status --endpoint 8080 myserver

# Try curling the endpoint to verify that the service is accessible
$ curl <endpoint>

接下来,尝试运行一个包含 Service 的简单任务,以验证 SkyPilot 是否可以在您的集群上启动服务。