喜欢尝鲜的同学可能会注意到最新的kubernetes在执行kubectl get cs时输出内容有一些变化,以前是这样的:
> kubectl get componentstatuses
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health":"true"}
现在变成了:
> kubectl get componentstatuses
NAME Age
controller-manager <unknown>
scheduler <unknown>
etcd-0 <unknown>
起初可能会以为集群部署有问题,通过kubectl get cs -o yaml发现status、message等信息都有,只是没有打印出来。原来是kubectl get cs的输出格式有变化,那么为什么会有此变化,我们来一探究竟。
<!--more-->
定位问题原因
尝试之前的版本,发现1.15还是正常的,调试代码发现对componentstatuses的打印代码在k8s.io/kubernetes/pkg/printers/internalversion/printers.go中,其中的AddHandlers方法负责把各种资源的打印函数注册进来。
// AddHandlers adds print handlers for default Kubernetes types dealing with internal versions.
// TODO: handle errors from Handler
func AddHandlers(h printers.PrintHandler) {
......
componentStatusColumnDefinitions := []metav1beta1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
{Name: "Status", Type: "string", Description: "Status of the component conditions"},
{Name: "Message", Type: "string", Description: "Message of the component conditions"},
{Name: "Error", Type: "string", Description: "Error of the component conditions"},
}
h.TableHandler(componentStatusColumnDefinitions, printComponentStatus)
h.TableHandler(componentStatusColumnDefinitions, printComponentStatusList)
对AddHandlers的调用位于k8s.io/kubernetes/pkg/kubectl/cmd/get/humanreadable_flags.go(正在迁移到staging中,如果找不到就去staging中找)中,如下32行位置:
// ToPrinter receives an outputFormat and returns a printer capable of
// handling human-readable output.
func (f *HumanPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) {
if len(outputFormat) > 0 && outputFormat != "wide" {
return nil, genericclioptions.NoCompatiblePrinterError{Options: f, AllowedFormats: f.AllowedFormats()}
}
showKind := false
if f.ShowKind != nil {
showKind = *f.ShowKind
}
showLabels := false
if f.ShowLabels != nil {
showLabels = *f.ShowLabels
}
columnLabels := []string{}
if f.ColumnLabels != nil {
columnLabels = *f.ColumnLabels
}
p := printers.NewTablePrinter(printers.PrintOptions{
Kind: f.Kind,
WithKind: showKind,
NoHeaders: f.NoHeaders,
Wide: outputFormat == "wide",
WithNamespace: f.WithNamespace,
ColumnLabels: columnLabels,
ShowLabels: showLabels,
})
printersinternal.AddHandlers(p)
// TODO(juanvallejo): handle sorting here
return p, nil
}
查看humanreadable_flags.go文件的修改历史,发现是在2019.6.28日特意去掉了对内部对象的打印,影响版本从1.16之后。
为什么修改
我没有查到官方的说明,在此做一些个人猜测,还原整个过程:
-
最初对api resource的表格打印都是在kubectl中实现
-
这样对于其他客户端需要做重复的事情,而且可能实现的行为不一致,因此有必要将表格打印放到服务端,也就是apiserver中
-
服务端打印的支持经过一个逐步的过程,所以客户端并没有完全去除,是同时支持的,kubectl判断服务端返回的Table就直接打印,否则使用具体对象的打印,客户端和服务端对特定对象的打印都是调用k8s.io/kubernetes/pkg/printers/internalversion/printers.go来实现
-
1.11版本将kubectl的命令行参数
--server-p