本文可以学到
.kube/config
文件中有哪些内容- 如何实现 bash 的命令补全功能
起因
在使用 kubectl 命令的过程中,经常需要查看不同 namespace 下的资源,因此命令经常需要带上 -n name
。
如果不想每次都多打这些字符,也可以设置一个默认的 namespace,
kubectl config set-context --current --namespace=xxxx
这样是方便了不少,但是一旦切换了 namespace 之后,又要重复上面的命令,而且经常还不记得。
有没有更好的办法呢? 有人开发了一个小工具,kubectx 专门用于方便的切换 ctx 和 namespace。 ctx 是什么呢? 其实就是哪个 k8s 集群。 说白了就是让你方便的在多个集群和 namespace 之间切换。
kubectx 有两种实现,一开始用的是最简单的 bash shell 脚本,新的版本开始用 k8s client API 开发。 下文的分析仅仅关注 namespace 的切换。
shell 版本的实现
这个实现非常简单,本质上就是调用几个 kubectl 命令实现 ns 切换。
首先需要知道的是,在 ~/.kube/config
路径下的 config 记录了你配置 kubectl 的信息,比如你用 kubectl 操作过几个 k8s 都会纪录在里面。
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.180.117.162
name: gke_hyrule-dev_us-central1_hyrule-us-central1
contexts:
- context:
cluster: gke_hyrule_us-central1
namespace: mi-hyrule
user: gke_hyrule-dev_us-central1_hyrule-us-central1
name: gke_hyrule-dev_us-central1_hyrule-us-central1
- context:
cluster:
user:
name:
current-context: gke_hyrule_us-central1
kind: Config
preferences: {}
users:
- name: gke_hyrule-dev_us-central1_hyrule-us-central1
user:
auth-provider:
config:
access-token: ya29.c.Ko8BCghf9Cp47iz7usZH24k_ask9OD6E4KEh-Z
cmd-args: config config-helper --format=json
cmd-path: /usr/lib/google-cloud-sdk/bin/gcloud
name: gcp
如果是多个 k8s 的话将会有多个 contexts
和 users
字段。
kubectx 命令主要就是根据这个 config 获得基本信息,再调用 kubectl 切换 ns。
先用这个内置的命令获得是哪个 k8s
$ kubectl config current-context
gke_hyrule_us-central1
然后,用 kubectl config view
显示 config 文件内容,它的输出和 .kube/config 是一样的,
$ kubectl config view -o=jsonpath="{.contexts[?(@.name==\"${cur_ctx}\")].context.namespace}")"
kubectx 用了一个表达式过滤输出的信息,这个命令获得当前 k8s 默认是哪个ns。
$ kubectl get namespaces -o=jsonpath='{range .items[*].metadata.name}{@}{"\n"}{end}'
这个命令获得所有的 namespace。
所以,切换 ns 就是用上面 3 个 命令实现自动化。
Golang 版本实现
粗略看了一下,感觉没有必要用 go 写,代码晦涩难懂,略过。
命令补全
在阅读 kubectx 和其他几个 krew 安装的 kubectl 插件源代码的过程中,发现他们都提供了 bash/zsh 的命令补全功能,于是学习了一下。
简单来说,就是要问你的 binary 文件提供了一个 bash 脚本,比如 kubectx 的如下
_kube_namespaces()
{
local curr_arg;
curr_arg=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "- $(kubectl get namespaces -o=jsonpath='{range .items[*].metadata.name}{@}{"\n"}{end}')" -- $curr_arg ) );
}
complete -F _kube_namespaces kubens kns
其中几个 bash 内置变量解释如下:
Id | Name | Description |
---|---|---|
1 | COMP_WORDS | 类型为数组;存放当前命令行中输入的所有单词 |
2 | COMP_CWORD | 类型为整数;当前光标下输入的单词位于 COMP_WORDS 数组中的索引 |
3 | COMP_LINE | 类型为字符串;表示当前的命令行输入 |
4 | COMP_WORDBREAKS | 类型为字符串;表示单词之间的分隔符 |
5 | COMPREPLY | 类型为数组;候选的补全结果 |
这样就可以实现在输入 kubectx 命令,按两下 Tab 键后会出现所有的 namespace 候选,并且还能根据你的输入即时过滤候选词。