- Kubernetes进阶实战(第2版)
- 马永亮
- 5012字
- 2021-03-12 17:08:49
2.3 kubectl命令与资源管理
Kubernetes API是管理各种资源对象的唯一入口,它提供了一个RESTful风格的CRUD(Create、Read、Update和Delete)接口用于查询和修改集群状态,并将结果存储在集群状态存储系统etcd中。事实上,API Server也是用于更新etcd中资源对象状态的唯一途径,Kubernetes的其他所有组件和客户端都要通过它完成查询或修改操作,如图2-10所示。从这个角度来讲,它们都算得上是API Server的客户端。
任何RESTful风格API的核心概念都是“资源”,资源可以根据其特性分组,每个组是同一类型资源的集合,即仅包含一种类型的资源,并且各资源间不存在顺序的概念,集合本身也是资源。对应于Kubernetes中,Pod、Deployment和Service等都是所谓的资源类型,它们由相应类型的对象集合而成。
kubectl的核心功能在于通过API Server操作Kubernetes的各种资源对象,它支持3种操作方式,其中直接命令式使用最为简便,是了解Kubernetes集群管理的有效途径。
2.3.1 资源管理的操作
Kubernetes API资源管理的操作可简单归结为增、删、改、查这4种,kubectl提供了一系列子命令用于执行此类任务,例如create、delete、patch、apply、replace、edit、get等。其中,有些命令必须基于资源清单进行,例如apply和replace命令,有些命令既可基于清单文件进行,也可实时作用于活动资源之上,例如create、get、patch和delete等。
kubectl命令能够读取任何以.yaml、.yml或.json为后缀的文件(可称为配置清单或配置文件,后文将不加区别地使用这两个术语)。在实践中,用户既可以为每个资源使用专用的清单文件,也可以将多个相关的资源(例如属于同一个应用或微服务)组织在同一个清单文件中。但在YAML格式的清单文件中,多个资源彼此间要使用“---”符号作为单独的一行进行资源分割,多个资源将以清单文件中定义的次序由create、apply等子命令调用。
kubectl的多数子命令支持使用-f选项指定使用的清单文件路径或URL,甚至直接指定存储有清单文件的目录,而该选项在同一命令中也可重复使用多次。若指定的目录路径存在子目录,也可按需同时使用-R选项以递归获取子目录中的配置清单。
支持在资源对象上使用标签和注解是Kubernetes的一大特色,它为资源管理机制增色不少,类似于delete和get之类的命令都能基于标签挑选目标对象,有些资源甚至必须依赖标签才能正常工作,例如Service和Deployment等资源类型。子命令label用于管理资源标签,而管理资源注解的子命令是annotate。
就地更新(修改)现有的资源也是一种常见操作。apply命令通过比较资源在清单文件中的版本及前一次的版本执行更新操作,而不对未定义的属性产生额外作用。edit命令相当于先使用get命令获取资源配置,由用户通过交互式编辑器修改后再自动使用apply命令将其应用。patch命令基于JSON补丁、JSON合并补丁及策略合并补丁对资源进行就地更新操作。
提示
为利用apply命令的优势,建议用户使用apply命令或create --save-config命令创建资源。
2.3.2 kubectl的命令格式
如前所述,kubectl是最常用的客户端工具之一,它提供了基于命令行访问Kubernetes API的简洁方式,支持对各种类型资源的CRUD操作,能够满足针对Kubernetes系统的绝大部分的操作需求。例如,需要创建资源对象时,kubectl能够将资源清单内容以POST方式提交至API Server并接收其响应。本节将描述kubectl的基本功能和常用选项。
提示
Kubernetes项目为kubectl提供了适配各平台的程序管理器格式的程序包,例如rpm包、deb包和exe程序等,用户根据平台类型的不同获取相匹配的版本安装即可。
kubectl特性丰富且功能强大,是Kubernetes管理员最常用的集群管理工具。其最基本的语法格式为kubectl [command] [TYPE] [NAME] [flags],其中各部分的简要说明如下。
▪command:对资源执行相应操作的子命令,例如get、create、delete、run等;常用的核心子命令如表2-3所示。
▪TYPE:要操作的资源类型,例如pods、services等;类型名称大小写敏感,但支持使用单数、复数或简写格式。
▪NAME:要操作的资源对象名称,大小写敏感;省略时,则表示指定TYPE的所有资源对象;同一类型的资源名称可于TYPE后同时给出多个,也可以直接使用TYPE/NAME的格式来为每个资源对象分别指定类型。
▪flags:命令行选项,例如-s或--server等;另外,get等命令在输出时还有一个常用的标志-o <format>用于指定输出格式,如表2-3表示。
同时,kubectl get命令能够支持多种不同的输出格式(见表2-4),一些高级命令的格式甚至为用户提供了非常灵活的自定义输出机制,例如jsonpath、go-tempate和custom-columns等。
此外,kubectl还有许多通用选项,这个可以使用kubectl options命令获取。其中比较常用的选项如下所示。
▪-s或--server:指定API Server的地址和端口。
▪--kubeconfig:使用的kubeconfig配置文件路径,默认为~/.kube/config。
▪-n或--namespace:命令执行的目标名称空间。
2.3.3 kubectl命令常用操作示例
为了便于读者快速了解kubectl命令及Kubernetes API资源管理的基本操作,这里给出几个使用示例以说明其基本使用方法,更多的使用方法会在后面章节随着需要再展开说明。
1. 创建资源对象
Kubernetes系统的大部分资源都隶属于名称空间级别,默认的名称空间为default,若需要获取指定Namespace对象中的资源对象的信息,则需要使用-n或--namespace指明其名称。直接通过kubectl命令及相关的选项创建资源对象的方式即直接命令式操作。例如,在下面的命令中,第一条命令创建了名为dev的Namespace对象,后两条命令在dev名称空间中分别创建了名为demoapp的Deployment控制器资源对象和名为demoapp的Service资源对象。
~$ kubectl create namespace dev ~$ kubectl create deployment demoapp --image="ikubernetes/demoapp:v1.0" -n dev ~$ kubectl create service clusterip demoapp --tcp=80 -n dev
注意
Deployment和Service对象还分别有一个创建命令kubectl run和kubectl expose,但它们即将废弃。
若要直接运行一个自主式Pod对象,也可使用kubectl run命令实现。例如下面第一条命令创建了一个名为demoapp的Pod对象,内部容器由指定的镜像运行,而第二条命令创建的Pod对象则在前台改为运行由用户指定的命令,且退出后将被自动删除。
~$ kubectl run demoapp --image="ikubernetes/dmeoapp:v1.0" ~$ kubectl run demoapp-$RANDOM --image="ikubernetes/demoapp:v1.0" --rm -it \ --command -- /bin/sh
另外,我们也可以根据资源清单创建资源对象,即采用“命令式对象配置文件”管理方式。例如,假设存在定义了Deployment对象的deployment-demoapp.yaml文件,以及定义了Service对象的service-demoapp.yaml文件,使用kubectl create命令即可进行基于命令式对象配置文件的创建操作:
~$ kubectl create -f deployment-demoapp.yaml -f service-demoapp.yaml
甚至还可以将创建交由kubectl自行确定,用户只需要声明期望的状态,这种方式称为声明式对象配置。仍以deployment-demoapp.yaml和service-demoapp.yaml文件为例,使用kubectl apply命令即可实现声明式配置:
~$ kubectl apply -f deployment-demoapp.yaml -f service-demoapp.yaml
2.4节主要描述第一种资源管理方式,第二种和第三种方式将在后面的章节中展开讲述。
2. 查看资源对象
运行着实际负载的Kubernetes系统上通常会存在多种资源对象,用户可分类列出感兴趣的资源对象及其相关的状态信息,kubectl get正是完成此类功能的命令。例如下面的命令能够列出系统上所有的Namespace资源对象。
~$ kubectl get namespaces
我们也可以一次查看多个资源类别下的资源对象,例如,列出默认名称空间内的所有Pod和Service对象,并输出额外信息。可以使用如下形式的kubectl get命令实现。
~$ kubectl get pods,services -o wide
使用类似如下命令列出kube-namespace名称空间中拥有k8s-app标签名称的所有Pod对象。
~$ kubectl get pods -l k8s-app -n kube-system
如表2-4所示,kubectl get命令支持多种不同的输出格式,例如wide、yaml、json、custom-columns、jsonpath和go-template等,每一种格式都以不同的输出格式打印资源对象的信息。例如,下面的命令能够取出kube-system名称空间中带有k8s-app=kube-dns标签的Pod对象的资源名称。
~$ kubectl get pods -l k8s-app=kube-dns -n kube-system -o jsonpath="{.items[0].metadata.name}"
3. 打印资源对象的详细信息
每个资源对象都有用户期望的状态(Spec)和现有的实际状态(Status)两种状态信息,kubectl get -o {yaml|josn}可分别以YAML或JSON格式打印资源对象的规范,而kubectl describe命令则能够打印出指定资源对象的详细描述信息。
例如,查看kube-system名称空间中API Server相关Pod对象的资源配置清单(期望的状态)及当前的状态信息,并输出为YAML格式:
~$ kubectl get pods kube-apiserver-k8s-master01.ilinux.io -o yaml -n kube-system
而kubectl describe命令还能显示当前对象相关的其他资源对象,如Event或Controller等。例如,查看kube-system名称空间中拥有标签component=kube-apiserver的Pod对象的详细描述信息,可以使用下面的命令:
~$ kubectl describe pods -l component=kube-apiserver -n kube-system
这两个命令都支持以TYPE NAME或TYPE/NAME的格式指定具体的资源对象,例如pods kube-apiserver-master.ilinux.io或pods/kube-apiserver-master.ilinux.io,以了解特定资源对象的详细属性信息及状态信息。
4. 打印容器中的日志信息
通常一个应用容器中仅会运行一个进程(及其子进程),该进程作为1号进程接收并处理信号,同时负责将日志直接输出至容器终端中,因此容器日志信息的获取一般要通过容器控制台进行。kubectl logs命令可打印Pod对象内指定容器的日志信息,命令格式为kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER] [options]。若Pod对象内仅有一个容器,则-c选项及容器名可选。例如,下面的命令先取出kube-system名称空间中带有指定标签的一个Pod对象,而第二条命令则能够查看该Pod对象的日志。
~$ DNS_POD=$(kubectl get pods -l k8s-app=kube-dns -n kube-system \ -o jsonpath="{.items[0].metadata.name}") ~$ kubectl logs $DNS_POD -n kube-system
为上面的命令添加-f选项,还能用于持续监控指定容器中的日志输出,其行为类似于使用了-f选项的tail命令。
5. 在容器中执行命令
容器的隔离属性使得对其内部信息的获取变得不再直观,这在用户需要了解容器内进程的运行特性、文件系统上的文件及路径布局等信息时需要穿透其隔离边界进行。kubectl exec命令便是在指定的容器运行其他应用程序的命令,例如在kube-system名称空间中的Pod对象kube-apiserver-master.ilinux.io上的唯一容器中运行ps命令:
~$ kubectl exec kube-apiserver-master.ilinux.io -n kube-system -- ps
类似于logs命令,若Pod对象中存在多个容器,需要以-c选项指定容器后才能运行指定的命令,而指定的命令程序也必须在容器中存在才能成功运行。
6. 删除资源对象
kubectl delete命令能够删除指定的资源对象,例如下面的命令可删除default名称空间中名为demoapp-svc的Service资源对象:
~$ kubectl delete services demoapp-svc
而下面的命令可删除kube-system名称空间中带有k8s-app=kube-proxy标签的所有Pod对象(危险操作,切勿在生产集群中测试执行):
~$ kubectl delete pods -l k8s-app=kube-proxy -n kube-system
若要删除指定名称空间中的所有某类对象,可以使用类似kubectl delete TYPE --all -n NS格式的命令。例如,下面的命令可删除kube-public名称空间中的所有Pod对象:
~$ kubectl delete pods --all -n kube-public
另外,有些资源类型支持优雅删除的机制,它们有着默认的删除宽限期,例如Pod资源的默认宽限期为30秒,但用户可在命令中使用--grace-period选项或--now选项来覆盖默认的宽限期。下面的命令就用于强制删除指定的Pod对象,但这种删除操作可能会导致相关容器无法终止并退出。
~$ kubectl delete pods demoapp --force --grace-period=0
需要特别说明的是,对于受控于控制器的对象来说,仅删除受控对象自身,其控制器可能会重建出类似的对象,例如Deployment控制器下的Pod对象被删除时即会被重建。
2.3.4 kubectl插件
kubectl插件是指能够由kubectl调用的外部独立应用程序,这类应用程序都以kubectl-$plugin_name格式命名,表现为kubectl的名字是$plugin_name的子命令。例如,应用程序/usr/bin/kubectl-whoami就是whoami插件,我们可以使用kubectl whoami的格式来运行它。因此,可为kubectl插件添加新的可用子命令,丰富kubectl的功能。
插件程序能够从kubectl继承环境信息,但kubectl的插件机制并不会在该程序及调用的外部程序之间传递任何信息,它仅仅提供了调用外部程序的一个统一接口,于是我们可以使用任何熟悉的脚本语言或编程语言来开发kubectl插件,但最终的脚本或程序文件需要以“kubectl-”为名称前缀。而安装插件的过程,也不过是将插件程序的可执行文件移动到系统的PATH环境变量上,指向任一路径即可。事实上,kubectl plugin list命令可遍历PATH环境变量指向的每一个路径,搜索并列出每一个以“kubectl-”为前缀的可执行程序文件路径。
Kubernetes SIG CLI社区还提供了一个插件管理器——Krew,它能够帮助用户打包、分发、查找、安装和管理kubectl插件,项目地址为https://krew.sigs.k8s.io/。Krew以跨平台的方式打包和分发插件,因此单一打包格式即能适配主流的系统平台(Linux、Windows或macOS等)。为了便于插件分发,Krew还维护有一个插件索引,以方便用户发现主流的可用插件。
Krew自身也表现为kubectl的一个插件,需要以手动方式独立安装。下面的脚本(krew-install.sh)能自动完成Krew插件的安装,该脚本仅适用于类UNIX系统平台,并以bash解释器运行,其他平台上的部署方式请参考Krew项目的官方文档。
#!/bin/bash set -x; cd "$(mktemp -d)" curl -fSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/ krew.{tar.gz,yaml}" tar zxvf krew.tar.gz KREW=./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" "$KREW" install --manifest=krew.yaml --archive=krew.tar.gz "$KREW" update
Krew默认以用户主目录下的隐藏目录.krew为工作目录,由Krew安装的插件都位于$HOME/.krew/bin路径下,因此脚本执行完成后,会通过如下信息提示用户将该路径添加到PATH环境变量,并重启shell进程。
WARNING: To be able to run kubectl plugins, you need to add the following to your ~/.bash_profile or ~/.bashrc: export PATH="${PATH}:${HOME}/.krew/bin" and restart your shell.
于是,我们编辑$HOME/.bash_profile文件,将export一行命令添加其中,并重启当前shell解释器。
~$ echo 'export PATH="${PATH}:${HOME}/.krew/bin"' >> $HOME/.bash_profile ~$ exec $SHELL
设定完成后,kubectl krew子命令便能执行Krew插件管理器的相关功能,例如查找和安装所需要的插件,它拥有help、list、search、info、install、upgrade和uninstall等二级子命令。下面的命令搜索Krew索引中包含字符串who的插件。
~$ kubectl krew search who NAME DESCRIPTION INSTALLED who-can Shows who has RBAC permissions to access Kubern... no whoami Show the subject that's currently authenticated... no
插件的简要描述能够通过info子命令打印。例如,下面的命令打印了whoami插件的相关描述,该插件能够返回当前kubectl客户端将以哪个主体(subject)身份请求认证的信息。
~$ kubectl krew info whoami NAME: whoami …… DESCRIPTION: This plugin show the subject that's currently authenticated as. ……
安装插件则需要使用install命令,命令格式为install PLUGIN_NAME。仍然以whoami插件为例,使用如下命令即能完成该插件的安装。
~$ kubectl krew install whoami
whoami插件功能非常简单,它没有更多的选项可以使用,因此,kubectl whoami便能返回当前kubectl客户端会以哪种身份凭据认证到API Server。下面命令的结果显示:当前客户端基于kubeconfig配置文件(kubecfg)加载X509数字证书格式的身份凭据(certauth),并由API Server认证为管理员(admin)。
~$ kubectl whoami kubecfg:certauth:admin
Krew索引中的各插件几乎都从更便捷、更丰富或更完整等角度进一步完善了kubectl功能。例如status能够以更加简便、直观的方式返回资源的简要状态,ctx以更便捷的方式完成kubeconfig中的context切换等。本书后面的章节也会用到其中的部分插件,包括whoami、rbac-view、ns、ctx等,这里一并直接安装它们。
~$ kubectl krew install whoami rbac-view ns ctx