Kubernetes API - 获取特定节点上的Pods

240

阅读Kubernetes文档,似乎可以基于标签选择一定范围的Pod。我想选择一个节点上的所有Pod,但不想给相应节点上的每个Pod打标签。

我是否从文档中漏掉了什么,或者仅仅无法通过节点选择呢?

如果我执行:

kubectl get pods \
--output=wide
--namespace=$NS \
--server=$SERVER | head

#=>

NAME   READY     STATUS             RESTARTS   AGE       NODE

这些标题中是否有任何一个可以用作选择器?如果是,如何使用kubectl进行操作?如何使用API进行操作?


2
请考虑更改已接受的答案,因为当前接受的答案已不推荐使用。 - deiga
6个回答

456

如在已接受的答案中提到的那样,PR现在已合并,您可以按以下方式获取节点的Pods:

kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=<node>

22
这是最优雅的解决方案。 - Sergiu Marsavela
2
我有一个澄清:这个 --all-namespaces 是先从整个集群中拉取所有的 pod,然后再过滤节点吗?还是仅从该节点拉取所有 pod,而不会大量拉取整个集群中所有命名空间的 pod? - AhmFM
谢谢,这是最美的方式。 - Jean-Marc Amon
根据K8s API文档:
NodeName是一个请求,用于将此Pod调度到特定节点。如果它不为空,则调度程序会简单地将此Pod调度到该节点上,假设它符合资源要求。
因此,首先,nodeName是可选的 - 其次,在这里没有提到调度程序在将Pod分配给节点时填充此字段。这是否依赖于未记录的行为? (参考:https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#scheduling)
- Bartek Muszynski
2
你如何查询多个节点? - Shinebayar G

142

按nodeName对Pod进行排序的示例:

kubectl get pods -o wide --sort-by="{.spec.nodeName}"

使用标签过滤器获取节点上Pod的示例:

for n in $(kubectl get nodes -l your_label_key=your_label_value --no-headers | cut -d " " -f1); do 
    kubectl get pods --all-namespaces  --no-headers --field-selector spec.nodeName=${n} 
done

或者通过重新启动的次数

kubectl get pods --sort-by="{.status.containerStatuses[:1].restartCount}"

使用--template标志通过nodeName进行过滤的示例:

$ kubectl get nodes

NAME                         STATUS                     AGE
ip-10-0-90-30.ec2.internal   Ready                      2d
ip-10-0-90-35.ec2.internal   Ready                      2d
ip-10-0-90-50.ec2.internal   Ready,SchedulingDisabled   2d
ip-10-0-91-60.ec2.internal   Ready                      2d
ip-10-0-91-65.ec2.internal   Ready                      2d


$kubectl get pods --template '{{range .items}}{{if eq .spec.nodeName "ip-10-0-90-30.ec2.internal"}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}'

filebeat-pezch
app-5xole
node-exporter-6kfs8
prometheus-0
sso-359976856-wu8zt

很有趣的是可以按这些数据进行排序,但是唯一可以通过选择器过滤的是“.spec.selector”上的内容。 - Fran
1
过滤器在服务器端执行,排序在客户端执行。 - Tim Hockin
这是一个非常好的和极其有用的答案,谢谢。 - Tommy
你打错了,需要删除一个多余的括号:kubectl get pods --template '{{range .items}}{{if eq .spec.nodeName "ip-10-0-90-30.ec2.internal"}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' - Priyesh Patel

28

您可以使用以下命令查询节点上的所有Pod:

kubectl get pods -o wide --all-namespaces | grep <YOUR-NODE>

1
请在kubectl命令中使用-a选项,以便获取所有命名空间下的pod,并使用-o wide选项进行输出。然后使用grep命令过滤出您所需的节点信息。 - Pawan Kumar
6
实际上这是在查询所有Pod(然后在客户端进行过滤),在大型集群中可能会更慢。最好的解决方法是@Kristofer的答案。 - Guilherme Garnier
1
我认为“-a”不再可用。我们需要改用“-A”,例如:“kubectl get pods -A -owide | grep <node_name>”。 - NightOwl19

23
kubectl describe node $NODE

将显示运行在$NODE上的所有未终止Pod。


谢谢,这是我想养成更好利用的习惯。里面有很多出乎意料的好信息。 - Josiah

10

您想要的在Kubernetes API服务器端是这样支持的:

curl --cacert ca.crt --cert apiserver.crt --key apiserver.key  https://<server>:<port>/api/v1/namespaces/<namespace>/pods?fieldSelector=spec.nodeName%3Dsomenodename

然而,该字段选择器选项尚未内置到 kubectl 中:https://github.com/kubernetes/kubernetes/pull/50140


4
FYI这个现在已经合并了。 - deedubs

5

我已经使用Go客户端完成了同样的过程,它揭示了CLI所采用的一些快捷方式。

func doNodesHavePods(clientset *kubernetes.Clientset) error {
    nodeLabelSelector := "nodelabel=interesting_nodes"
    nodes, err := clientset.CoreV1().Nodes().List(metav1.ListOptions{LabelSelector: nodeLabelSelector})

    if err != nil {
        return err
    }

    nodeNames := []string{}
    for _, node := range nodes.Items {
        nodeNames = append(nodeNames, node.Name)
    }
    // --all-namespaces -> listing and looping on namespaces
    namespaces, err := clientset.CoreV1().Namespaces().List(metav1.ListOptions{})

    if err != nil {
        return err
    }
    for _, namespace := range namespaces.Items {
        for _, name := range nodeNames {
            // pods need a namespace to be listed.
            pods, err := clientset.CoreV1().Pods(namespace.Name).List(metav1.ListOptions{FieldSelector: "spec.nodeName=" + name})
            if err != nil {
                println("%v", err)
            }
            for _, pod := range pods.Items {
                fmt.Println(pod.Namespace, pod.Name)
            }
        }
    }
    return nil
}

我开始发现很多需要问的问题对CLI而言变得太复杂了。虽然CLI是一个好工具,但学习使用Go客户端可以帮助你找到第一个答案,并深入探究那些答案可能引发的更多问题。


3
可以使用空命名空间获取所有命名空间中的Pod。 - dimm
这是帮助了我解决问题的方案,不确定为什么会被踩。 - Ingytron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接