Kubernetes 故障排除#

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

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

验证基本设置#

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

你能够无错误地运行 kubectl get nodes 吗?

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

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

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

注意

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

步骤 A1 - 你能创建 pods 和 services 吗?#

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

我们将使用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`

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

步骤 A3 - 你的节点有足够的磁盘空间吗?#

如果您的节点磁盘空间不足,在配置期间,拉取SkyPilot镜像可能会失败,终端中会出现rpc error: code = Canceled desc = failed to pull and unpack image: context canceled错误。 通过检查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 任务吗?#

接下来,尝试运行一个简单的“hello world”任务,以验证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

如果你的任务没有运行,请检查终端和配置日志以查找错误。配置日志的路径可以在SkyPilot输出的开头找到,以“要查看详细进度:…”开头。

检查GPU支持#

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

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

步骤 B0 - 你的集群是否启用了GPU?#

运行 kubectl describe nodes 或以下代码片段,以验证您的节点是否具有 nvidia.com/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.

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

提示

如果您正在使用GKE,请参考在Google Cloud GKE上部署以安装适当的驱动程序。

步骤 B1 - 你能运行一个 GPU pod 吗?#

验证是否安装了GPU操作符,并通过运行以下命令将nvidia运行时设置为默认值:

$ 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

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

如果日志显示nvidia-smi: command not found,可能是nvidia运行时未设置为默认值。请安装Nvidia GPU操作符,并确保nvidia运行时设置为默认值。 例如,对于RKE2,请参考Nvidia GPU Operator installation with Helm on RKE2上的说明,将nvidia运行时设置为默认值。

步骤 B2 - 你的节点标签是否正确?#

SkyPilot 要求节点被标记为正确的 GPU 类型以运行 GPU 任务。运行 kubectl get nodes -o json 来验证您的节点是否正确标记。

提示

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

$ 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.

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

步骤 B3 - SkyPilot 能看到你的 GPU 吗?#

运行 sky check 以验证 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

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

接下来,尝试运行一个简单的GPU任务,以验证SkyPilot可以在您的集群上启动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

如果你的任务没有运行,请检查终端和配置日志以查找错误。配置日志的路径可以在SkyPilot输出的开头找到,以“要查看详细进度:…”开头。

验证端口支持#

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

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

步骤 C0 - 验证负载均衡器服务设置#

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

提示

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

您的集群是否支持LoadBalancer服务?#

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

$ 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

如果你的服务没有获得外部IP,请使用kubectl describe svc skytest-loadbalancer检查服务的状态。你的集群可能不支持LoadBalancer服务。

步骤 C0 - 验证 Nginx Ingress 设置#

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

提示

如果您正在使用LoadBalancer服务来支持端口,可以跳过本节。

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

为了验证您的集群是否支持Nginx Ingress,我们将创建一个示例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

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

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

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

$ cat ~/.sky/config.yaml

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

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

步骤 C1 - 验证 SkyPilot 可以启动服务#

接下来,尝试使用服务运行一个简单的任务,以验证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>

如果您无法从SkyPilot获取端点, 考虑运行kubectl describe serviceskubectl describe ingress来调试它。