系列目录
前面两节我们由浅入深介绍了不少 kubernetes 管理比较常用的命令. 本节我们通过案例讲解一些需要更为复杂的操作才能完成的命令.
选择一个 deployment 下的所有 pod
前面讲到过, kubernetes 的 deployment 和 pod 的命令上有关联关系, 我们可以通过查看 deployment 的名称, 然后记下来, 然后再查找所有的 pod 通过 grep 输入 deploy 的名称为关键字进行过滤.
比如集群中有以下 deployment
- [CentOS@k8s-master ~]$ kubectl get deploy
- NAME READY UP-TO-DATE AVAILABLE AGE
- easymock-dep 1/1 1 1 21h
- helloworld 1/1 1 1 88m
- Redis-cache 0/3 3 0 6h5m
- sagent 3/3 3 3 2d1h
- stodagent 3/3 3 3 6d23h
- trackingapi-gateway-dep 1/1 1 1 28d
如果我们想要找 helloworld 所控制的 pod, 我们就可以通过以下命令来达到效果
- [CentOS@k8s-master ~]$ kubectl get pod|grep helloworld
- helloworld-66fc98fd57-lc7tm 1/1 Running 0 89m
但是这种匹配可能是不准确的, 如果仅仅是查看可能没问题, 但是在编程环境中这样做显然不是好的办法. 前面我们提到过先通过 kubectl get deploy helloworld -ojson 然后通过 jq 工具拿到 selector, 然后使用 kubectl get pod -l = 查找到的标签. 这里标签需要我们手动输入, 因为选择器里过滤到的结果是 "key":"value" 格式, 而 - l 接受的格式为 key=value 形式, 当然我们也可以通过简单的命令转换以上两种格式. 但是选择器里也可能包含多个标签(如下面示例), 这样我们通过简单命令很难处理了.
- [CentOS@k8s-master ~]$ kubectl get deploy helloworld -ojson|jq .spec.selector.matchLabels
- {
- "app": "helloworld",
- "version": "1.0"
- }
下面我们一步步讲解如何通过可编程的方式根据以上信息选择名为 helloworld 的 deployment 所控制的所有 pod
首先, 以上的键 App 和 version 都是由用户定义的, 并且不知道共有多少个, 我们没法直接通过. 属性名的方式获取到它, 我们可以通过 jq 的 to_entries 把它转为键值数组, 数组是可以遍历的. 操作如下:
- [CentOS@k8s-master ~]$ kubectl get deploy helloworld -ojson|jq '.spec.selector.matchLabels|to_entries'
- [
- {
- "key": "app",
- "value": "helloworld"
- },
- {
- "key": "version",
- "value": "1.0"
- }
- ]
这样数组里的所有对象都包含两个键值, 且键是固定的(分别为 key 和 value), 这样 key 我们就都全知道了. 下面我们把它们组装成 App=helloworld 这样形式, 以便 kubectl get po 的 - l 参数可用
[CentOS@k8s-master ~]$ kubectl get deploy helloworld -ojson|jq '.spec.selector.matchLabels|to_entries|.[]|"\(.key)=\(.value)"'"app=helloworld""version=1.0"以上的操作有一点很关键那就是使用 to_entries 函数把对象转为数组. 后面管道跟.[]获取数组对象. 后面我们把结果放在"" 把结果拼接为字符串这里 \ 为 jq 的语法, 在字符串里使用 "" 可以把后面跟的括号内的内容识别为命令, 而不是普通字符串.
这样基本满足要求了, 但是有多个 label 时,-l 接收的参数形式为 lable1=value1,label2=value2 这样形式的. 因此我们要删除这两个字符串的换行符, 把它们合并到一行, 并且中间加一个逗号.
以上字符串外面都包了一层引号 (""), 虽然 - l 变量也可以接收带引号的, 但是也可以不要引号, jq 里通过参数 - r(aw) 来获取原始字符串, 要把结果合并为一行则使用 - j(oin), 改造后的命令如下
- [CentOS@k8s-master ~]$ kubectl get deploy helloworld -ojson|jq -r -j '.spec.selector.matchLabels|to_entries|.[]|"\(.key)=\(.value),"'
- App=helloworld,version=1.0,
以上结果基本上达到预期效果, 只是最后面多了一个逗号, 我们可以接一个 sed 管道把它去掉
- kubectl get deploy helloworld -ojson|jq -r -j '.spec.selector.matchLabels|to_entries|.[]|"\(.key)=\(.value),"'|sed"s/.$//"
- App=helloworld,version=1.0
我们把它赋值给一个变量, 然后在选择 pod 的时候使用它
- [CentOS@k8s-master ~]$ label=$( kubectl get deploy helloworld -ojson|jq -r -j '.spec.selector.matchLabels|to_entries|.[]|"\(.key)=\(.value),"'|sed"s/.$//")
- [CentOS@k8s-master ~]$ kubectl get pod -l=$label
- NAME READY STATUS RESTARTS AGE
- helloworld-66fc98fd57-lc7tm 1/1 Running 0 3h22m
显示集群中所有 pod 的标签
把集群中所有的 pod 全部列出来非常容易. 使用 kubectl get pod --all-namespace 即可. 重要的是我们要循环遍历所有的 pod, 把它们的名称和标签信息过滤出来展示.
前面我们说过, 在使用 kubectl get pod 时如果使用 - o=name 便可以只列出 pod 的名称. 它并不是简单地把 kubectl get po 命令展示的名称过滤出来, 而是通过资源类型 / 资源名称的方式展示. 比如有个 pod 名称叫作 consul-0, 使用 kubectl get pod -o=name 展示出来它的名称为 pod/consul-0, 这样我们就可以直接使用 kubectl get 来获取到它
- [CentOS@k8s-master ~]$ kubectl get pod/consul-0
- NAME READY STATUS RESTARTS AGE
- consul-0 1/1 Running 0 3d2h
k8s 除了支持 kubectl get + 资源类型 + 资源名称外, 还支持 kubectl get 资源类型 / 资源名称这种形式. 虽然平时我们不经常这样写, 但是有特定场景下非常有用.
这样, 我们就可以遍历 kubectl get pod -o=name 的结果, 在循环中取出每个 pod 的编排信息, 然后从中过滤出我们想要的信息(即 pod 的标签信息), 操作和上面获取 matchLabels 有很多类似的地方.
关键代码如下:
- [CentOS@k8s-master ~]$ for item in $( kubectl get pod --output=name); do kubectl get "$item" --output=JSON | jq -r '.metadata.labels | to_entries | .[] |" \(.key)=\(.value)"'; done
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-0
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-1
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-2
- App=easymock
- pod-template-hash=84767b6f75
- App=helloworld
- pod-template-hash=d5d5c5866
- version=1.0
- App=helloworld
- pod-template-hash=d5d5c5866
- version=1.0
- App=helloworld
- ...
以上循环获取到的每一个 pod 的名称, 然后遍历他们, 取出它们的. metadata.labels 字段, 后面是对键值的重新组装, 和上面获取 deploy 下的 pod 一节的操作类似.
从输出结果中可以看出, 我们只输出的所有 pod 的标签, 这样可读性是非常差的, 我们也无法确定某一个标签归属于哪一个 pod. 我们需要把它们的名字也输出:
- [CentOS@k8s-master ~]$ for item in $( kubectl get pod --output=name); do printf "Labels for %s\n" "$item"; kubectl get "$item" --output=JSON | jq -r '.metadata.labels | to_entries | .[] |" \(.key)=\(.value)"'; done
- Labels for pod/consul-0
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-0
- Labels for pod/consul-1
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-1
- Labels for pod/consul-2
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-2
- Labels for pod/easymock-dep-84767b6f75-l84r4
- App=easymock
- pod-template-hash=84767b6f75
- Labels for pod/helloworld-d5d5c5866-24nzr
- App=helloworld
- pod-template-hash=d5d5c5866
- version=1.0
- ...
这查比前面清析一些了, 但是仍然不是十分容易识别, 我们在遍历的时候每个 item 结束后输出一个空行, 这样把不同的结果用空行隔离开来, 可读性更高.
- [CentOS@k8s-master ~]$ for item in $( kubectl get pod --output=name); do printf "Labels for %s\n" "$item"; kubectl get "$item" --output=JSON | jq -r '.metadata.labels | to_entries | .[] |" \(.key)=\(.value)"';printf"\n"; done
- Labels for pod/consul-0
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-0
- Labels for pod/consul-1
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-1
- Labels for pod/consul-2
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-2
- Labels for pod/easymock-dep-84767b6f75-l84r4
- App=easymock
- pod-template-hash=84767b6f75
这样基本 ok 了, 我们使用 grep 把名称着色显示, 这样在屏幕上的输出可读性就更高了.
- [CentOS@k8s-master ~]$ for item in $( kubectl get pod --output=name); do printf "Labels for %s\n" "$item"|grep --color -E '[^/]+$'; kubectl get "$item" --output=JSON | jq -r '.metadata.labels | to_entries | .[] |" \(.key)=\(.value)"';printf"\n"; done
- Labels for pod/consul-0
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-0
- Labels for pod/consul-1
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-1
- Labels for pod/consul-2
- App=consul
- controller-revision-hash=consul-744777c4bd
- statefulset.kubernetes.io/pod-name=consul-2
大家从上面文本中可能并看不出差别, 但是如果是在 Linux 终端就可以看到 pod 的名称都被着色显示了.
来源: https://www.cnblogs.com/tylerzhou/p/11061163.html