Kubernetes 故障排除#
如果您无法在 Kubernetes 集群上运行 SkyPilot 任务,本指南将帮助您调试常见问题。
如果本指南未能帮助您解决问题,请通过 Slack 或 GitHub 联系我们。
验证基本设置#
步骤 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 skytest
和 kubectl 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 必须是 LoadBalancer
或 NodePort
类型,并且必须具有外部 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 是否可以在您的集群上启动服务。