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