如果你正在使用Kubernetes,那么kubectl一定是你最常使用的工具。无论你需要学习任何工具,都应该先提前了解kubectl并有效地使用它。本文包含了一系列技巧,可以让你更高效而且有效地使用kubectl。同时,可以加深你对Kubernetes各个方面工作方式的理解。
本文的目标不仅是使你使用Kubernetes的日常工作更高效,而且更愉快!
什么是kubectl
在学习如何更高效地使用kubectl之前,你应该对它是什么以及如何工作有个基本的了解。从用户的角度来说,kubectl是你控制Kubernetes的“驾驶舱”。它可以让你执行所有可能的Kubernetes操作。
从技术角度上看,kubectl是Kubernetes API的客户端。Kubernetes API是一个 HTTP REST API。这个API是真正的Kubernetes用户界面。Kubernetes完全受这个API控制,这意味着每个Kubernetes操作都作为API端点公开,并且可以由对此端点的HTTP请求执行。因此,kubectl的主要工作是执行对Kubernetes API的HTTP请求:
Kubernetes是一个完全以资源为中心的系统。这意味着,Kubernetes维护资源的内部状态并且所有的Kubernetes操作都是针对这些资源的CRUD(增加、读取、更新、删除)操作。你完全可以通过操控这些资源(Kubernetes会根据资源的当前状态找出解决方案)来控制Kubernetes。因此,Kubernetes API reference主要是资源类型及其相关操作的列表。
来,我们来看一个例子。
假设你想要创建一个ReplicaSet资源。为了达成此目标,你在一个名为replicaset.yaml的文件中定义ReplicaSet,然后运行以下命令:
kubectl create -f replicaset.yaml
显然,在Kubernetes已经创建了你的ReplicaSet。但之后会发生什么呢?
Kubernetes有一个创建ReplicaSet的操作,并且它和其他所有Kubernetes操作一样,都会作为API端点暴露。对于这个操作而言,该特定API端点如下:
POST /apis/apps/v1/namespaces/{namespace}/replicasets
你可以在API reference中找到所有Kubernetes操作对应的API端点,包括以上端点(https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.13 )。要向端点发出实际请求,你需要一开始就在API reference中列出的端点路径中添加API server的URL。
因此,当你执行上述命令时,kubectl将向上述API端点发出HTTP POST请求。ReplicaSet定义(你在replicaset.yaml文件中所提供的)在请求的正文中传递。
这就是kubectl对于与Kubernetes集群交互的所有命令的工作方式。在这些情况下,kubectl只需向适当的Kubernetes API端点发出HTTP请求即可。
请注意,通过手动向Kubernetes API发出HTTP请求,完全有可能使用curl之类的工具来控制Kubernetes。Kubectl只是让你更轻松地使用Kubernetes API。
以上就是什么是kubectl及其工作原理的简单介绍。但是,每个kubectl用户都应该了解更多有关Kubernetes API的信息。为此,我们先简要地介绍一下Kubernetes的内部结构。
Kubernetes 内部
Kubernetes由一系列独立组件构成,这些组件会在集群的节点上作为单独的进程运行。一些组件运行在master节点,一些组件运行在worker节点,每个组件都有其特定功能。
在master节点上,有以下重要组件:
存储后端:存储资源定义(通常使用etcd)
API Server:提供Kubernetes API并管理存储后端
Controller manager:确保资源状态与规范相匹配
Scheduler:将Pod调度到worker节点
在worker节点上最重要的组件为:
- Kubelet:在worker节点上管理容器的执行
为了充分了解这些组件是如何一起工作的,让我们来看一个例子。
假设你刚刚执行了kubectl create -f replicaset.yaml
,此后,kubectl向_create ReplicaSet API端点
_发出了HTTP POST请求(传递你的ReplicaSet资源定义)。哪些因素会导致集群中出现这种情况?如下:
执行kubectl create -f replicaset.yaml
之后,API server将会在存储后端保存你的ReplicaSet资源定义。
这将触发controller manager中的ReplicaSet controller,后者监视ReplicaSet资源的创建,更新和删除。
ReplicaSet controller为每个ReplicaSet副本创建了一个Pod定义(根据在ReplicaSet定义中的Pod模板创建)并将它们保存到存储后端。
这触发了scheduler,它监视尚未被分配给worker节点的Pod。
Scheduler为每个Pod选择一个合适的worker节点,并在存储后端中添加该信息到Pod定义中。
请注意,到目前为止,集群中任何地方都没有运行工作负载的代码。至今,我们所完成的事就是在master节点上的存储后端中创建和更新资源。
这触发了在Pod所调度到的worker节点上的kubelet,它监视调度到其worker节点上的pod。
Kubelet从存储后端读取Pod定义并指示容器运行时(比如,Docker)来运行在worker节点上的容器。
此时,你的ReplicaSet应用程序已经在运行啦!
Kubernetes API的角色
从上述例子可知,Kubernetes组件(除了API server和存储后端)通过在存储后端监视资源更改和操控资源工作。然而,这些组件无法直接访问存储后端,仅能通过Kubernetes API进行访问。
看一下以下示例:
ReplicaSet controller使用带有watch参数_的list ReplicaSets API 端点_API操作来监视ReplicaSet资源的更改。
ReplicaSet controller使用_create Pod API 端点_来创建Pod
Scheduler使用_patch Pod API端点_以及有关选定的worker节点信息来更新Pod。
正如你所见,这与kubectl所使用的API相同。
Kubernetes API对于内部组件和外部用户的重复操作是Kubernetes的基本设计概念。现在,我们来总结一下Kubernetes如何工作的:
存储后端存储(如,资源)Kubernetes的状态
API server以Kubernetes API的形式提供到存储后端的接口
- 所有其他Kubernetes的组件和用户通过Kubernetes API读取、监视以及操控Kubernetes的状态(如资源)。
熟悉这些概念将在很大程度上帮助你更好地理解kubectl并利用它。
接下来,我们来看一下具体的技巧,来帮助你提升kubectl的生产力。
1、 使用命令补全功能保存输入
命令补全是提高kubectl生产率的最有用但经常被忽略的技巧之一。
命令补全功能使你可以使用Tab键自动完成kubectl命令的各个部分。这适用于子命令、选项和参数,包括诸如资源名称之类难以键入的内容。
在这里,你可以看到kubectl命令的完成情况:
命令补全可用于Bash和Zsh Shell。
官方文档中包含有关设置命令完成的详细说明(https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion),但是以下部分会简要向您介绍如何设置。
命令补全功能工作方式
总体而言,命令补全是通过补全脚本而起作用的Shell功能。补全脚本是一个shell脚本,它为特定命令定义了补全行为。通过输入补全脚本可以补全相应的命令。Kubectl可以使用以下命令为Bash和Zsh自动生成并print out补全脚本:
kubectl completion bash
# or
kubectl completion zsh
理论上,在合适的shell(Bash或Zsh)中提供此命令的输出将会启用kubectl的命令补全功能。然而,实际上,在Bash和Zsh之间存在一些细微的差别(包括在Linux和macOS之间也存在差别)。以下部分将对此进行详细解释。
Bash on Linux
Bash的补全脚本主要依赖bash-completion项目(https://github.com/scop/bash-completion ),所以你需要先安装它。
你可以使用不同的软件包管理器安装bash-completion。如:
sudo apt-get install bash-completion
# or
yum install bash-completion
你可以使用以下命令测试bash-completion是否正确安装:
type \_init\_completion
如果输出的是shell功能的代码,那么bash-completion就已经正确安装了。如果命令输出的是not found
错误,你必须添加以下命令行到你的~/.bashrc
文件:
source /usr/share/bash-completion/bash_completion
你是否需要添加这一行到你的~/.bashrc
文件中,取决于你用于安装bash-completion的软件包管理器。对于APT来说,这是必要的,对于yum则不是。
bash-completion安装完成之后,你需要进行一些设置,以便在所有的shell会话中获得kubectl补全脚本。一种方法是将以下命令行添加到~/.bashrc
文件中:
source <(kubectl completion bash)
另一种可能性是将kubectl补充脚本添加到/etc/bash_completion.d
目录中(如果不存在,则需要先创建它):
kubectl completion bash >/etc/bash_completion.d/kubectl
/etc/bash_completion.d
目录中的所有补全脚本均由bash-completion自动提供。
以上两种方法都是一样的效果。重新加载shell后,kubectl命令补全就能正常工作啦!
Bash on macOS
使用macOS时,会有些复杂。原因是截至成文时macOS上Bash的默认版本是3.2,这已经过时了。不幸的是,kubectl补全脚本至少需要Bash 4.1,因此不适用于Bash 3.2。
苹果依旧在macOS上默认使用过时的Bash版本是因为更新版本的Bash使用的是GPLv3 license,而苹果不支持这一license。
这意味着,要在macOS上使用kubectl命令补全功能,你必须安装较新版本的Bash。你甚至可以将其设置为新的默认shell,这将在将来为你省去很多此类麻烦。这实际上并不难,你可以在我之前写的文章中找到说明:
https://itnext.io/upgrading-bash-on-macos-7138bd1066ba
在继续剩下的步骤之前,确保你现在已经在使用Bash 4.1或更高的版本(使用bash --version查看版本)。
同上一部分一样,Bash的补全脚本主要依赖bash-completion项目(https://github.com/scop/bash-completion ),所以你需要先安装它。
你可以使用Homebrew安装bash-completion:
brew install bash-completion@2
@2
代表bash-completion v2。Kubectl补全脚本要求bash-completion v2,而bash-completion v2要求至少是Bash 4.1。这就是你不能在低于4.1的Bash版本上使用kubectl补全脚本的原因。
brew intall
命令的输出包括一个“Caveats”部分,其中的说明将以下行添加~/.bash_profile
文件:
export BASH\_COMPLETION\_COMPAT_DIR=/usr/local/etc/bash_completion.d
[[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh"
你必须执行此操作才能完成bash-completion的安装。但是,我建议将这些行添加到~/.bashrc
而不是~/.bash_profile
文件中。这可以确保bash-completion在子shell中也可用。
重新加载shell之后,你可以使用以下命令测试bash-completion是否正确安装:
type \_init\_completion
如果输出为shell功能的代码,意味着一切都设置完成。现在,你需要进行一些设置,以便在所有的shell会话中获得kubectl补全脚本。一种方法是将以下命令行添加到~/.bashrc
文件中:
source <(kubectl completion bash)
另一种方法是将kubectl补全脚本添加到/usr/local/etc/bash_completion.d
目录中:
kubectl completion bash >/usr/local/etc/bash_completion.d/kubectl
仅当你使用Homebrew安装了bash-completion时,此方法才有效。在这种情况下,bash-completion会在此目录中提供所有补全脚本。
如果你还用Homebrew安装了kubectl,则甚至不必执行上述步骤,因为补全脚本应该已经由kubectl Homebrew公式放置在/usr/local/etc/bash_completion.d
目录中。在这种情况下,kubectl补全应该在安装bash-completion后自动开始工作。所有方法都是效果都是一致的。
重新加载shell后,kubectl完成就能正常工作!
Zsh
Zsh的补全脚本没有任何依赖项。所以,你所需要做的是去进行一些设置,以便它能在所有的shell会话中被获取到。
你可以通过添加以下命令行到你的~/.zshrc
文件中来实现这一效果:
source <(kubectl completion zsh)
如果在重新加载你的shell之后,你获得了command not found: compdef
错误,你需要启动内置的compdef
,你可以在将以下行添加到开始的~/.zshrc
文件中:
autoload -Uz compinit
compinit
2、迅速查看资源规范
当你创建YAML资源定义时,你需要知道字段以及这些资源的意义。API reference中提供了一个查找此类信息的位置,其中包含所有资源的完整规范:
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.13/
然而,每次你需要查找某些内容时都要切换到Web浏览器,这十分繁琐。因此,kubectl提供了kubectl explain命令,它能在你的terminal中正确地输入所有资源规范。
kubectl explain
的用法如下:
kubectl explain resource\[.field\]...
该命令输出所请求资源或字段的规范。kubectl explain
所显示的信息与API reference中的信息相同。默认情况下,kubectl explain
仅显示单个级别的字段。你可以使用--recursive
标志来显示所有级别的字段:
kubectl explain deployment.spec --recursive
如果你不确定哪个资源名称可以用于kubectl explain
,你可以使用以下命令查看:
kubectl api-resources
该命令以复数形式显示资源名称(如deployments
)。它同时显示资源名称的缩写(如deploy
)。无需担心这些差别,所有名称变体对于kubectl都是等效的。也就是说,你可以使用它们中的任何一个。
例如,以下命令效果都是一样的:
kubectl explain deployments.spec
# or
kubectl explain deployment.spec
# or
kubectl explain deploy.spec
3、 使用自定义列输出格式
kubectl ge
t命令默认的输出方式如下(该命令用于读取资源):
kubectl get pods
NAME READY STATUS RESTARTS AGE
engine-544b6b6467-22qr6 1/1 Running 0 78d
engine-544b6b6467-lw5t8 1/1 Running 0 78d
engine-544b6b6467-tvgmg 1/1 Running 0 78d
web-ui-6db964458-8pdw4 1/1 Running 0 78d
这是一种很好的可读格式,但是它仅包含有限的信息量。如你所见,每个资源仅显示了一些字段,而不是完整的资源定义。此时,自定义列输出格式应运而生,它使你可以自由定义列和想在其中显示的数据。你可以选择资源的任何字段,使其在输出中显示为单独的列。
自定义列输出选项的用法如下:
-o custom-columns=<header>:<jsonpath>\[,<header>:<jsonpath>\]...
你必须将每个输出列定义为<header>:<jsonpath>
对:
让我们看一个简单的例子:
kubectl get pods -o custom-columns='NAME:metadata.name'
NAME
engine-544b6b6467-22qr6
engine-544b6b6467-lw5t8
engine-544b6b6467-tvgmg
web-ui-6db964458-8pdw4
在这里,输出包括显示所有Pod名称的一列。
选择Pod名称的表达式是meta.name
。原因是Pod的名称是在Pod资源的元数据字段的name字段中定义的(你可以在API reference中或使用kubectl explain pod.metadata.name
进行查找)。
现在,假设你想在输出中添加一个附加列,例如,显示每个Pod在其上运行的节点。为此,你只需在自定义列选项中添加适当的列规范即可:
kubectl get pods \
-o custom-columns='NAME:metadata.name,NODE:spec.nodeName'
NAME NODE
engine-544b6b6467-22qr6 ip-10-0-80-67.ec2.internal
engine-544b6b6467-lw5t8 ip-10-0-36-80.ec2.internal
engine-544b6b6467-tvgmg ip-10-0-118-34.ec2.internal
web-ui-6db964458-8pdw4 ip-10-0-118-34.ec2.internal
选择节点名称的表达式是spec.nodeName
。这是因为已将Pod调度的节点保存在Pod的spec.nodeName
字段中(请参阅kubectl explain pod.spec.nodeName
)。
请注意,Kubernetes资源字段区分大小写。
你可以通过这种方式将资源的任何字段设置为输出列。只需浏览资源规范并尝试使用任何你喜欢的字段即可!
但是首先,让我们仔细看看这些字段选择表达式。
JSONPath 表达式
用于选择资源字段的表达式基于JSONPath:
https://goessner.net/articles/JsonPath/index.html
JSONPath是一种用于从JSON文档提取数据的语言(类似于XPath for XML)。选择单个字段只是JSONPath的最基本用法。它具有很多功能,例如list selector、filter等。
但是,kubectl explain
,仅支持JSONPath功能的子集。以下通过示例用法总结了这些得到支持的功能:
# Select all elements of a list
kubectl get pods -o custom-columns='DATA:spec.containers[*].image'
# Select a specific element of a list
kubectl get pods -o custom-columns='DATA:spec.containers[0].image'
# Select those elements of a list that match a filter expression
kubectl get pods -o custom-columns='DATA:spec.containers[?(@.image!="nginx")].image'
# Select all fields under a specific location, regardless of their name
kubectl get pods -o custom-columns='DATA:metadata.*'
# Select all fields with a specific name, regardless of their location
kubectl get pods -o custom-columns='DATA:..image'
特别重要的是[ ]
运算符。Kubernetes资源的许多字段都是列表,使用此运算符可以选择这些列表中的项目。它通常与通配符一起用作[*]
,以选择列表中的所有项目。
在下面,你将找到一些使用此符号的示例。
示例应用程序
使用自定义列输出格式有无限可能,因为你可以在输出中显示资源的任何字段或字段组合。以下是一些示例应用程序,但你可以自己探索并找到对你有用的应用程序。
Tip:如果你经常使用这些命令,则可以为其创建一个shell别名。
显示Pod的容器镜像
kubectl get pods \
-o custom-columns='NAME:metadata.name,IMAGES:spec.containers[*].image'
NAME IMAGES
engine-544b6b6467-22qr6 rabbitmq:3.7.8-management,nginx
engine-544b6b6467-lw5t8 rabbitmq:3.7.8-management,nginx
engine-544b6b6467-tvgmg rabbitmq:3.7.8-management,nginx
web-ui-6db964458-8pdw4 wordpress
此命令显示每个Pod的所有容器镜像的名称。
请记住,一个Pod可能包含多个容器。在这种情况下,单个Pod的容器镜像在同一列中显示为由逗号分隔的列表。
显示节点的可用区
kubectl get nodes \
-o custom-columns='NAME:metadata.name,ZONE:metadata.labels.failure-domain\.beta\.kubernetes\.io/zone'
NAME ZONE
ip-10-0-118-34.ec2.internal us-east-1b
ip-10-0-36-80.ec2.internal us-east-1a
ip-10-0-80-67.ec2.internal us-east-1b
如果您的Kubernetes集群部署在公有云基础架构(例如AWS,Azure或GCP)上,则此命令很有用。它显示每个节点所在的可用区。
可用区是一个公有云的概念,表示一个地理区域内的复制点。
每个节点的可用区均通过特殊的failure-domain.beta.kubernetes.io/zone
标签获得。如果集群在公有云基础架构上运行,则将自动创建此标签,并将其值设置为节点的可用性区域的名称。
标签不是Kubernetes资源规范的一部分,因此您无法在API reference中找到以上标签。但是,如果将节点输出为YAML或JSON,则可以看到它(以及所有其他标签):
kubectl get nodes -o yaml
# or
kubectl get nodes -o json
除了探索资源规范外,这通常是发现更多有关资源的信息的好方法。
4、轻松在集群和命名空间之间切换
当kubectl必须向Kubernetes API发出请求时,它将读取系统上的所谓kubeconfig文件,以获取它需要访问的所有连接参数并向API服务器发出请求。
默认的kubeconfig文件是〜/ .kube / config
。该文件通常是通过某些命令自动创建或更新的(例如,如果使用托管的Kubernetes服务,则为aws eks update-kubeconfig
或gcloud container clusters get-credentials
)。
使用多个集群时,在kubeconfig文件中配置了多个集群的连接参数。这意味着,你需要一种方法来告诉kubectl要将其连接到哪些集群中。
在集群中,您可以设置多个命名空间(命名空间是物理集群中的一种“虚拟”集群)。Kubectl还可确定kubeconfig文件中用于请求的命名空间。因此,你需要一种方法来告诉kubectl你要使用哪个命名空间。
请注意,您还可以通过在KUBECONFIG环境变量中列出它们,以拥有多个kubeconfig文件。在这种情况下,所有这些文件将在执行时合并为一个有效的配置。你还可以为每个kubectl命令使用--kubeconfig
选项覆盖默认的kubeconfig文件。具体请参阅官方文档:
https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/
Kubeconfig文件
让我们看看kubeconfig文件实际包含什么:
如你所见,kubeconfig文件由一组上下文组成。上下文包含以下三个元素:
集群:集群的API server的URL
用户:集群中特定用户的身份验证凭据
命名空间:连接到集群时要使用的命名空间
实际上,人们通常在其kubeconfig文件中为每个集群使用单个上下文。但是,每个集群也可以有多个上下文,它们的用户或命名空间不同。但这似乎不太常见,因此集群和上下文之间通常存在一对一的映射。
在任何给定时间中,这些上下文其中之一都可以被设置为当前上下文(通过kubeconfig文件中的专用字段):
当kubectl读取kubeconfig文件时,它总是使用当前上下文中的信息。因此,在上面的示例中,kubectl将连接到Hare集群。
因此,要切换到另一个集群时,你只需在kubeconfig文件中更改当前上下文即可:
在上面的示例中,kubectl现在将连接到Fox集群。
并切换到同一集群中的另一个命名空间,可以更改当前上下文的命名空间元素的值:
在上面的示例中,kubectl现在将在Fox集群中使用Prod命名空间(而不是之前设置的Test命名空间)。
请注意,kubectl还提供了—cluster
、-user
、-namespace
和--context
选项,无论kubeconfig文件中设置了什么,它们都可以覆盖单个元素和当前上下文本身。请参阅kubectl options
从理论上讲,你可以通过手动编辑kubeconfig文件来进行这些更改。但是,这十分繁琐。以下各节介绍了各种工具,可让你自动进行这些更改。
Kubectx
Kubectx可以有效帮助集群和命名空间之间进行切换。该工具提供了kubectx和kubens命令,使你可以分别更改当前上下文和命名空间。
如前所述,如果每个集群只有一个上下文,则更改当前上下文意味着更改集群。
在这里,你可以看到这两个命令的作用:
如上一节所述,这些命令仅需在后台编辑kubeconfig文件即可。
要安装kubectx,只需按照GitHub页面上的说明进行操作即可:
https://github.com/ahmetb/kubectx/#installation
kubectx和kubens都通过补全脚本提供命令补全功能。这使你可以自动完成上下文名称和命名空间的输入。你也可以在GitHub页面上找到设置完成的说明:
https://github.com/ahmetb/kubectx/#installation
kubectx的另一个十分有用的功能是交互模式。这与fzf工具(它必须单独安装)一起工作(实际上,安装fzf会自动启用kubectx交互模式)。交互式模式允许你通过交互式模糊搜索界面(由fzf提供)选择目标上下文或命名空间。
fzf Github主页:https://github.com/junegunn/fzf
使用shell别名
实际上,你并不需要单独的工具来更改当前上下文和命名空间,因为kubectl也提供了执行此操作的命令。特别是,kubectl config命令提供了用于编辑kubeconfig文件的子命令。这里是其中的一些:
kubectl config get-contexts
:列出所有上下文
kubectl config current-context
:获取当前上下文
kubectl config use-context
:更改当前上下文
kubectl config set-context
:更改上下文的元素
但是,直接使用这些命令不是很方便,因为它们的键入时间很长。但是你可以做的是将它们包装到可以更容易执行的shell别名中。
我根据这些命令创建了一组别名,这些别名提供了与kubectx类似的功能。在这里,你可以看到它们的作用:
请注意,别名使用fzf提供的交互式模糊搜索界面(例如kubectx的交互式模式)。这意味着,你需要安装fzf才能使用这些别名。
以下是别名的定义:
# Get current context
alias krc='kubectl config current-context'
# List all contexts
alias klc='kubectl config get-contexts -o name | sed "s/^/ /;\\|^ $(krc)$|s/ /*/"'
# Change current context
alias kcc='kubectl config use-context "$(klc | fzf -e | sed "s/^..//")"'
# Get current namespace
alias krn='kubectl config get-contexts --no-headers "$(krc)" | awk "{print \$5}" | sed "s/^$/default/"'
# List all namespaces
alias kln='kubectl get -o name ns | sed "s|^.*/| |;\\|^ $(krn)$|s/ /*/"'
# Change current namespace
alias kcn='kubectl config set-context --current --namespace "$(kln | fzf -e | sed "s/^..//")"'
要安装这些别名,只需将以上定义添加到〜/ .bashrc
或〜/ .zshrc
文件中,然后重新加载你的shell。
使用插件
Kubectl允许安装可以像原生命令一样调用的插件。例如,你可以安装名为kubectl-foo的插件,然后将其作为kubectl foo
调用。kubectl插件将在本文后面的部分中详细介绍。
能够像这样更改当前上下文和命名空间不是很好吗?例如,运行kubectl ctx
更改上下文,运行kubectl ns
更改命名空间?
我创建了两个可以实现这一功能的插件:
在内部,插件建立在上一部分的别名基础上。
在这里,你可以看到正在使用的插件:
请注意,插件使用fzf提供的交互式模糊搜索界面。这意味着,您需要安装fzf才能使用这些插件。
要安装插件,只需将名为kubectl-ctx
和kubectl-ns
的shell脚本下载到PATH中的任何目录,并使它们可执行(例如,使用chmod + x)。之后,你应该立即可以使用kubectl ctx
和kubectl ns
。
5、 使用自动生成的别名保存输入
Shell别名通常是保存输入内容的好方法。kubectl-aliases项目则是这一想法的具体体现,并为常见的kubectl命令提供了约800个别名:
https://github.com/ahmetb/kubectl-aliases
你可能想知道如何记住800个别名?实际上,你不需要记住它们,因为它们都是根据简单的方案生成的,如下所示:
如你所见,别名由组件组成,每个组件代表kubectl命令的特定元素。每个别名可以具有一个用于基本命令、操作和资源的组件,以及一个用于选项的多个组件,你只需按照上述方案从左到右“填充”这些组件即可。
请注意,当前详细的方案位于GitHub页面上:
https://github.com/ahmetb/kubectl-aliases/blob/master/.kubectl_aliases
在这里您还可以找到别名的完整列表:
https://github.com/ahmetb/kubectl-aliases#syntax-explanation
例如,别名kgpooyamlall
代表命令kubectl get pods -o yaml --all-namespaces
:
k→ kubectl
g→ get
po→ pods
oyaml→ -o yaml
- all→ --all-namespaces
请注意,大多数选项组件的相对顺序无关紧要。因此,kgpooyamlall
等同于kgpoalloyaml
。
你不需要使用所有组件作为别名。例如,k
、kg
、klo
、ksys
或kgpo
也是有效的别名。此外,你可以在命令行上将别名与其他单词组合在一起。
例如,你可以使用k proxy
来运行kubectl proxy
。或使用kg roles
来运行kubectl get roles
(当前不存在Roles资源的别名组件)。要获得特定的Pod,你可以使用kgpo my-pod
来运行kubectl get pod my-pod
。
请注意,某些别名甚至需要在命令行上进一步输入参数。例如,kgpol别名代表kubectl get pods -l
。-l
选项需要一个参数(标签规范)。因此,你必须使用此别名,例如:
因此,你只能在别名末尾使用a
,f
和l
组件。
总而言之,一旦掌握了该方案,就可以从要执行的命令中直观地推断出别名,并节省大量输入!
安装
要安装kubectl-aliases,只需从GitHub下载.kubectl-aliases
文件,然后将其从〜/ .bashrc
或〜/ .zshrc
文件中获取即可:
source ~/.kubectl_aliases
重新加载shell后,你应该可以使用所有800个kubectl别名!
补全功能
如你所见,你经常在命令行上将其他单词附加到别名上。例如:
kgpooyaml test-pod-d4b77b989
如果使用kubectl命令补全功能,则可能习惯于自动完成资源名称之类的事情。但是当你使用别名时仍然可以这样做吗?
这是一个重要的问题,因为如果补全功能无法正常工作,这些别名的某些好处将会被削弱。
那么,这一问题的答案取决于你所使用的shell。
对于Zsh,补全可以立即和别名一起使用。
对于Bash,默认情况下补全功能将不会正常工作。但是它可以通过一些额外的步骤来使其正常运行。
在Bash中同时启用别名和补全功能
Bash的问题在于,它会在别名名称上(而不是在别名命令上)尝试补全(无论何时按Tab键)。由于你没有所有800个别名的补全脚本,因此无法使用。
complete-alias项目提供了解决此问题的通用方法(https://github.com/cykerway/complete-alias )。它利用别名的补全机制,在内部将别名扩展为别名命令,并返回扩展命令的补全建议。这意味着,别名的补全行为与别名命令的行为完全相同。
在下面的内容中,我将首先说明如何安装complete-alias,然后如何配置它以启用所有kubectl别名的补全。
安装complete-alias
首先,complete-alias依赖于bash-completion。因此,在安装complete-alias之前,你需要确保已安装bash-completion。前面已经针对Linux和macOS给出了相关说明。
对于macOS用户的重要说明:与kubectl补全脚本一样,complete-alias不适用于Bash 3.2,后者是macOS上Bash的默认版本。特别是,complete-alias依赖于bash-completion v2(brew install bash-completion@2
),至少需要Bash 4.1。这意味着,要在macOS上使用complete-alias,您需要安装较新版本的Bash。
要安装complete-alias,你只需要从GitHub存储库(https://github.com/cykerway/complete-alias )下载bash_completion.sh
脚本,并将其source到你的〜/ .bashrc
文件中:
source ~/bash_completion.sh
重新加载你的shell之后,complete-alias将完成安装。
为kubectl别名启用补全功能
从技术上讲,complete-alias提供了_complete_alias
shell函数。此函数检查别名,并返回别名命令的补全建议。
要将其与特定别名联系起来,你必须使用完整的Bash内置函数将_complete_alias
设置为别名的补全功能。
例如,让我们使用k
别名代表kubectl命令。要将_complete_alias
设置为该别名的补全功能,你必须执行以下命令:
complete -F _complete_alias k
这样的效果是,每当你对k别名自动补全时,就会调用_complete_alias
函数,该函数将检查别名并返回kubectl命令的补全建议。
再举一个例子,让我们使用代表kubectl get
的kg
别名:
complete -F _complete_alias kg
同样,这样做的效果是,当你对kg自动补全时,你将获得与kubectl get相同的补全建议。
请注意,可以通过这种方式对系统上的任何别名使用complete-alias。
因此,要为所有kubectl别名启用补全功能,只需为每个别名运行以上命令。如下所示(假设你将kubectl-aliases安装到〜/ .kubectl-aliases
):
for _a in $(sed '/^alias /!d;s/^alias //;s/=.*$//' ~/.kubectl_aliases); do complete -F _complete_alias "$_a"
done
只需将此片段添加到你的〜/ .bashrc
文件中,重新加载你的shell,现在你就可以对800个kubectl别名使用补全功能了!
6、使用插件扩展kubectl
从1.12版开始,kubectl包含插件机制,可让你使用自定义命令扩展kubectl。
这是一个可以作为kubectl hello
调用的kubectl插件的示例:
如果你对此十分熟悉,其实kubectl插件机制与Git插件机制的设计十分相近。
本节将向您展示如何安装插件,你可以在其中找到现有插件以及如何创建自己的插件。
安装插件
Kubectl插件作为简单的可执行文件分发,名称形式为kubectl-x。前缀kubectl-是必填项,其后是允许调用插件的新的kubectl子命令。
例如,上面显示的hello插件将作为名为kubectl-hello的文件分发。
要安装插件,你只需要将kubectl-x文件复制到PATH中的任何目录并使其可执行(例如,使用chmod + x)。之后,你可以立即使用kubectl x调用插件。
你可以使用以下命令列出系统上当前安装的所有插件:
kubectl plugin list
如果你有多个具有相同名称的插件,或者存在无法执行的插件文件,此命令还会显示警告。
使用krew查找和安装插件
Kubectl插件使自己像软件包一样可以共享和重用。但是在哪里可以找到其他人共享的插件?
krew项目旨在为共享、查找、安装和管理kubectl插件提供统一的解决方案(https://github.com/GoogleContainerTools/krew )。该项目将自己称为“ kubectl插件的软件包管理器”(krew
与brew
十分相似)。
Krew根据kubectl插件进行索引,你可以从中选择和安装。在这里,你可以看到实际操作:
如你所见,krew本身就是一个kubectl插件。这意味着,安装krew本质上就像安装其他任何kubectl插件一样。你可以在GitHub页面上找到krew的详细安装说明:
https://github.com/GoogleContainerTools/krew/#installation
最重要的krew命令如下:
# Search the krew index (with an optional search query)
kubectl krew search [<query>]
# Display information about a plugin
kubectl krew info <plugin>
# Install a plugin
kubectl krew install <plugin>
# Upgrade all plugins to the newest versions
kubectl krew upgrade
# List all plugins that have been installed with krew
kubectl krew list
# Uninstall a plugin
kubectl krew remove <plugin>
请注意,使用krew安装插件不会阻止你继续使用传统方式安装插件。即使你使用krew,你仍然可以通过其他方式安装在其他地方找到的插件(或创建自己的插件)。
此外,kubectl krew list命令仅列出已与krew一起安装的插件,而kubectl plugin list命令列出了所有插件,即,与krew一起安装的插件和以其他方式安装的插件。
在其他地方寻找插件
Krew仍然是一个年轻的项目,目前krew索引中只有大约30个插件。如果找不到所需的内容,则可以在其他地方(例如,在GitHub上)查找插件。
我建议你查看kubectl-plugins GitHub主题。你会在这里找到几十个可用的插件:
https://github.com/topics/kubectl-plugins
创建自己的插件
当然,你也可以创建自己的kubectl插件,这并不困难。
你只需要创建一个执行所需操作的可执行文件,将其命名为kubectl-x,然后按照如上所述的方式安装即可。
可执行文件可以是任何类型,可以是Bash脚本、已编译的Go程序、Python脚本,这些类型实际上并不重要。唯一的要求是它可以由操作系统直接执行。
让我们现在创建一个示例插件。在上一节中,你使用了kubectl命令列出每个Pod的容器镜像。你可以轻松地将此命令转换为可以使用kubectl img
调用的插件。
为此,只需创建一个名为kubectl-img
的文件,其内容如下:
#!/bin/bash kubectl get pods -o custom-columns='NAME:metadata.name,IMAGES:spec.containers\[*\].image'
现在,使用chmod + x kubectl-img使该文件可执行,并将其移动到PATH中的任何目录。之后,你可以立即将插件与kubectl img一起使用!
如前所述,kubectl插件可以用任何编程或脚本语言编写。如果使用Shell脚本,则具有可以轻松从插件调用kubectl的优势。但是,你可以使用真实的编程语言编写更复杂的插件,例如,使用Kubernetes客户端库。如果使用Go,还可以使用cli-runtime库,该库专门用于编写kubectl插件。
共享你的插件
如果你认为其中一个插件可能对其他人有用,欢迎在GitHub上共享。只需将其添加到kubectl-plugins主题,其他人就可以方便地找到它。
你还可以将插件添加到krew索引。你可以在krew GitHub存储库中找到有关如何执行此操作的说明。
命令补全功能
遗憾的是,目前插件机制尚不支持命令补全。这意味着你需要完整键入插件名称以及插件的所有参数。但是,kubectl GitHub存储库中对此有一个开放功能请求。因此,将来有可能实现此功能。