如何优雅的使用 Kubectl 来提高你的生产力

公众号关注 「奇妙的 Linux 世界」

设为「星标」,每天带你玩转 Linux !

ee1d1b10c08942dab28246487c171324.png

       如果您使用Kubernetes,那么kubectl可能是您最常用的工具之一。无论何时,只要您花了大量时间使用特定的工具,就有必要好好了解它并学习如何有效地使用它。   

     本文包含了一系列的小贴士小技巧,可以让您更高效地使用kubectl。同时,它旨在加深您对Kubernetes各方面工作原理的理解。

     本文的目标不仅是使您与Kubernetes的日常工作更高效,而且也更愉快!

d03828559a769fac919839a1384597e6.png

0. kubectl 简介

       在学习如何更有效地使用kubectl之前,您应该对它是什么以及它是如何工作的有一个基本的了解。

       从用户的角度来看,kubectl 就是你 控制Kubernetes的驾驶舱。它允许您执行所有可能的Kubernetes操作

        从技术角度来看,kubectlKubernetes API客户端

Kubernetes API是一个HTTP REST API。这个API是真正的Kubernetes用户界面user interface

通过这个 API 可以完全控制 Kubernetes集群。这意味着每个Kubernetes操作都被公开为一个API端点,可以通过对该端点的HTTP请求执行!!!

(简单地说,就是你用Postman也可以完全控制Kubernetes集群!)

1dfa66a427a439a685a56910f24376f8.png

因此,kubectl主要工作是执行对Kubernetes API的HTTP请求:

2810cfc1da0c1baa709ba85357468189.png

Kubernetes是一个完全以资源为中心的系统。这意味着,Kubernetes 维护着资源的内部状态,所有Kubernetes 操作都是对这些资源CRUD操作。您可以通过操作这些资源完全控制 Kubernetes (Kubernetes根据资源的当前状态来确定要做什么)。由于这个原因,Kubernetes API 被组织为资源类型及其相关操作列表

现在我们举个例子:

假设您想要创建一个ReplicaSet资源。为此,您需要在名为replicaset.yaml文件中定义ReplicaSet,然后运行以下命令:

$ kubectl create -f replicaset.yaml

显然,这将在Kubernetes 集群中创建ReplicaSet。但幕后发生了什么呢?

Kubernetes有一个创建 ReplicaSet 操作,和所有其他Kubernetes操作一样,它是作为API端点公开的。此操作的具体API端点如下:

POST /apis/apps/v1/namespaces/{namespace}/replicasets

您可以在 https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#create-replicaset-v1-apps 中找到所有Kubernetes操作的API端点。要向端点发出实际请求,需要将API服务器的URL添加到API引用中列

因此,当您执行上面的命令时,kubectl向上面的API端点发出一个HTTP POST请求。ReplicaSet 的定义(您在replicaset.yaml中提供的)在请求体中的body中传递过去。

kubectl 就是这样与Kubernetes集群交互的。在所有这些情况下,kubectl 只是向适当的 Kubernetes API 端点发出HTTP请求

请注意,通过手动向Kubernetes API发出HTTP请求,完全可以使用curl之类的工具来控制KubernetesKubectl只是让您更容易使用Kubernetes API

这些是kubectl基本概念工作原理。但是Kubernetes API还有很多值得kubectl用户了解的地方。为此,让我们简要地深入研究Kubernetes的内部结构

Kubernetes内部

Kubernetes由一组独立的组件组成,这些组件在集群的节点上作为独立的进程运行。有些组件运行在主节点上,有些运行在工作节点上,每个组件都有一个非常具体的功能。

这些是主节点上最重要的组件:

  • 存储后端: 存储资源定义(通常使用etcd)

  • API Server: 提供Kubernetes API,管理存储后端

  • Controller Manager: 确保资源状态与规格匹配

  • Scheduler: 将Pods调度到工作节点

这是工作节点上最重要的组件:

  • Kubelet: 管理工作节点上容器的执行

为了了解这些组件如何一起工作,让我们考虑一个示例。

假设您刚刚执行了kubectl create -f replicaset.yamlkubectl在此基础上向create ReplicaSet API端点发出HTTP POST请求(传递您的ReplicaSet资源定义)。

f3fceab96eba37fc84d62f481616eb81.png

在集群中有什么影响? 看下图:

1. 对create ReplicaSet端点API请求由API Server处理。API Server验证请求并在存储后端(etcd)中保存ReplicaSet资源定义

ce94a19a58406a626028773085dc7059.png

36e710ed9bc872ae84cb52135ff366d7.gif

2. 此事件首先会触发ReplicaSet controller,它是Controller Manager的一个子进程。(因为ReplicaSet controller一直在监视存储后端etcd中ReplicaSet资源的CRUD)。一旦存储后端etcd中ReplicaSet 的数据被修改,ReplicaSet Controller 会立即获得事件通知

aa07a6dfb03007ba6f0249a7ea65ec8e.png

9e6f13209003be8cfc4792bd0fe49793.gif

3. ReplicaSet controller任务确保存在所需数量的ReplicaSet副本Pod。在我们的示例中,目前还不存在相应的Pod,因此ReplicaSet控制器创建这些Pod的定义(根据ReplicaSet定义中的Pod模板),并将它们保存在存储后端etcd中。

cd83926dc03ed490c3c67a99877c6ca9.png

abb9a48b838d172f2702503d71660072.gif

4. 创建新的Pod触发SchedulerScheduler监视尚未调度到工作节点Worker Node的Pod定义

c52457e59dc298f55b29afa2e420bd7a.png

7d5408425ec56e6ea0541bff1fe7dc07.gif

5. Scheduler为每个Pod选择一个合适的工作节点Worker Node,并使用此信息更新存储后端etcd中的Pod定义

f3ac4539454a698dad079ff854d3df34.png

2763e3b43494eae285f317f972798b33.gif

6. 这个事件会触发kubelet,这些kubelet监视调度到其工作节点的Pod

f5375dad9e7baf49b14e3e733d8fa48a.png

ce6cad9b1e6c2929667c2c359b215314.gif

7. ReplicaSet Pods的工作节点的kubelet已被安排用于指示配置的容器运行时(可能是Docker)下载所需的容器映像运行容器

7bb48a132fc3a5bbb83745cb8b58dfc0.png

此时,您的ReplicaSet应用程序终于开始运行了!

12758509b2f74060b17b249eb0ab28fc.png

Kubernetes API的角色

从上面的示例中可以看到,Kubernetes组件(API Server和存储后端etcd除外)的工作方式是:

1. 观察存储后端中的资源变化

2. 操作存储后端中的资源

但是,这些组件(Controller Manager, Scheduller, kubectl,kubelet等)不能直接访问存储后端etcd,而只能通过Kubernetes API来和后端交互。

考虑以下例子:

  • ReplicaSet控制器使用 ReplicaSets API端点API操作和一个监视参数来监视对ReplicaSet资源的更改

  • ReplicaSet控制器使用create Pod API端点来创建Pod

  • 调度器使用 patch Pod API端点更新所选工作节点的信息。

可以看到,kubectl也使用了相同的API

Kubernetes API对内部组件和外部用户的双重使用是Kubernetes的基本设计理念

有了这些知识,你可以总结Kubernetes的工作方式如下:

3f0f0ca3b3d4b9a9f6d37cc02c63e8a2.png

Kubernetes的工作方式

1. 存储后端 etcd 存储Kubernetes的状态(即资源)。

2. API server以 Kubernetes API 的形式提供了修改存储后端etcd的接口。

3. 所有其他Kubernetes组件和用户都可以通过Kubernetes API读取、观察和操作Kubernetes的状态(即资源)。

熟悉这些概念将帮助您更好地理解kubectl,并充分利用它!

3ddf7e3c5244b7c0daea5f716cc3177c.png

现在让我们看看一系列具体的提示和技巧,以帮助您提高kubectl的生产力。

01

命令自动补全

提高kubectl生产效率率的一个最有用但经常被忽视的技巧是命令自动补全。

命令补全允许您使用Tab键自动补全kubectl命令的各个部分。这适用于子命令、选项参数,包括难以输入的东西,如资源名。

这里你可以看到 kubectl 命令补全的效果:

3d897388d87e99f83a501cb6c7a852db.gif

Bash和Zsh shell 都支持命令自动补全。

官方文档包含了关于设置命令自动补全的详细说明,但以下部分将为您提供一个概述。

971652f66891a9240580002a8234ba42.png

点击上方图片,打开小程序,『饿了么外卖』红包天天免费领!

命令补全是如何工作的

999ced24b0f63ea119c5bd9b934ed6a7.png

一般来说,命令补全是一种shell特性,它通过补全脚本来工作。完成脚本是一种shell脚本,它定义了特定命令的完成行为。查找完成脚本可以完成相应的命令。

Kubectl可以使用以下命令自动生成并打印Bash和Zsh的完成脚本:

$ kubectl completion bash
# or
$ kubectl completion zsh

理论上,在适当的shell中查找该命令的输出都可以通过kubectl命令完成。

但是,在实践中,Bash(包括Linux和macOS之间的差异)和Zsh的细节是不同的。下面几节将解释所有这些情况:

* 为Linux上的Bash设置命令完成

* 在macOS上为Bash设置命令完成

* 为Zsh设置命令完成

8fa71bc04c3039f59350be8e7c5ec16f.png

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-comletion完成是否正确安装

$ type _init_completion

如果输出shell函数的代码,则正确安装了bash-completion。如果命令输出一个not found错误,您必须将以下行添加到~/.bashrc文件中 :(

6ea4b01dad4901e24d9caba882eaaaa7.png

是否必须将这一行添加到~/.bashrc文件,取决于你用来安装bash-completion的包管理器。对于apt来说这是必要的,而对于yum则不是。

一旦安装了bash-completion,就必须进行设置,以便在所有shell会话中都能找到kubectl 的自动补全脚本。

一种方法是在~/.bashrc 里添加一行:

a5eed3ddf60e58fab873def22a89c997.png

另一种方法是将kubectl完成脚本添加到/etc/bash_completion中。(如果不存在这个目录,那么我们自己创建一下 ):

kubectl completion bash >/etc/bash_completion.d/kubectl

/etc/bash_completion 目录中的所有自动补全脚本会被 bash-completion source

这两种方法是等价的。

重新加载shell后,kubectl命令补全应该可以工作了!

Bash on macOS

对于macOS,有一点复杂。原因是Bash在macOS上的默认版本是3.2,这已经相当过时了。不幸的是,kubectl完成脚本至少需要Bash 4.1,因此不能与Bash 3.2一起工作。

苹果之所以在macOS中包含一个过时的Bash版本,是因为新版本使用了苹果不支持的GPLv3许可证。

这意味着,要在macOS上使用kubectl命令补全,必须安装更新版本的Bash。您甚至可以将其设置为新的默认shell,这将为您在将来省去许多类似的麻烦。这实际上并不困难,您可以在我以前写的一篇关于在macOS上升级Bash的文章中找到相关说明。

在继续之前,请确保您现在确实在使用Bash 4.1或更新版本($bash --version)。

Bash的完成脚本依赖于bash-completion项目,因此必须首先安装它。

你可以在Homebrew中安装bash-completion:

brew install bash-completion@2

@2代表bash-completion v2。kubectl完成脚本需要bash-completion v2,而bash-completion至少需要Bash 4.1。这就是为什么您不能在低于4.1的Bash版本上使用kubectl完成脚本的原因。

brew install命令的输出包括一个“警告”部分,说明如何将以下行添加到~/.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文件 :(

1ec5eb300b6ae271d8eba50353b2955c.png

另一种可能是将kubectl自动完成脚本添加到目录 /usr/local/etc/bash_completion

$ kubectl completion bash >/usr/local/etc/bash_completion.d/kubectl

假如你是通过brew 安装的bash_completion的话,上面的命令才会生效!

如果您还使用Homebrew安装了kubectl,则甚至不需要执行上述步骤,因为自动完成脚本应该已经放在/usr/local/etc/bash_completion.d目录中。在这种情况下,安装bash-completion之后kubectl 应该就可以实现命令自动补全。

最后,所有这些方法都是等效的。

在重新加载shell后,kubectl命令自动完成应该可以工作了!

Zsh

Zsh的完成脚本没有任何依赖项。所以,你所要做的就是设置一下。

您可以通过将以下行添加到~/.zshrc中 来实现这一点:

46346371f8ecdf143cf6396797735e03.png

如果在重新加载shell后遇到command not found: compdef错误,则必须启用内置的compdef,可以在~/.zshrc中的开头添加以下内容:

".zshrc
autoload -Uz compinit
compinit

02

快速查看resource spec

在创建YAML资源定义时,需要知道这些资源的字段及其含义。可以查找此信息的一个位置是API reference, 其中包含f

然而,每次需要查找东西时都切换到浏览器是很乏味的。因此,kubectl提供了kubectl explain命令,该命令可以打印出终端中所有资源的资源规范。

kubectl explain的用法如下:

$ kubectl explain resource[.field]...

该命令输出请求的资源或字段的规范。kubectl explain 所显示的信息与API引用中的信息相同。

这里你可以看到 kubectl explain:

2ea6264609a808b6f346d7d860550462.gif

默认情况下,kubectl explain 只显示单一级别的字段。你可以使用--recursive 标志来显示整个字段树:

$ kubectl explain deployment.spec --recursive

如果你不确定kubectl explain可以使用哪些resource name,你可以用以下命令显示所有资源名:

$ kubectl api-resources

这个命令以复数形式显示资源名(例如,部署而不是部署)。它还会显示具有短名称的资源的短名称(例如deploy)。不要担心这些差异。所有这些名称变体对于kubectl都是等效的。也就是说,您可以使用任何kubectl解释。

例如,下面所有的命令都是等价的:

$ kubectl explain deployments.spec
# or
$ kubectl explain deployment.spec
# or
$ kubectl explain deploy.spec

03

自定义列输出

kubectl get 命令(用于读取资源)的默认输出格式如下:

$ 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

这是一种很好的人类可读格式,但它只包含有限数量的信息。可以看到,每个资源只显示了一些字段(与完整的资源定义相比)。

这就是使用custom columns output format地方。它允许您自由地定义列和要在其中显示的数据。您可以选择将资源的任何字段显示为输出中的单独列

-o custom-columns=<header>:<jsonpath>[,<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名称的表达式是 metadata.name。这样做的原因是Pod的名称是在Pod资源的元数据字段的名称字段中定义的(您可以在API引用中或使用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解释Pod .spec.nodeName)。

注意,Kubernetes资源字段是区分大小写的。

您可以通过这种方式将资源的任何字段设置为输出列。只需浏览资源规范,并使用您喜欢的任何字段进行尝试!

但首先,让我们仔细看看这些字段选择表达式。

JSONPath表达式

选择资源字段的表达式基于

JSONPath(https://goessner.net/articles/JsonPath/index.html

JSONPath是一种从JSON文档中提取数据的语言(它类似于XML的XPath)。选择单个字段只是JSONPath最基本的用法。它有很多特性,比如列表选择器、过滤器等等。

但是,使用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资源的许多字段都是列表,这个操作符允许您选择这些列表中的项目。它通常与通配符[*]一起使用,以选择列表中的所有项。

下面你会发现一些使用这种符号的例子。

示例应用程序

使用自定义列输出格式的可能性是无限的,因为您可以在输出中显示资源的任何字段或字段组合。这里有一些示例应用程序,但您可以自行探索并找到对您有用的应用程序!

提示:如果您经常使用这些命令中的一个,您可以为它创建一个shell alias。

显示Pods的容器图像

$ 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的容器 image 以逗号分隔的列表显示在同一列中。

aeb874e6bd128f18f3e0923555578fe5.png

显示节点的可用分区

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

除了探索资源规范之外,这通常是发现更多关于 resource specifications.的好方法。

4. 

在集群和命名空间之间随意切换

kubectl必须向Kubernetes API发出请求时,它会读取系统上所谓的kubecconfig 文件,以获得访问所需的所有连接参数,并向API服务器发出请求。

默认的kubeconfig文件是~/.kube/config。这个文件通常由一些命令自动创建或更新(例如,aws eks update-kubeconfig或gcloud容器集群get-credentials,如果你使用managed Kubernetes服务)。

当您使用多个集群时,您可以在kubeconfig文件中配置多个集群的连接参数。这意味着,您需要一种方法来告诉kubectl您希望它连接到这些集群中的哪一个。

在集群中,您可以设置多个命名空间(命名空间是物理集群中的“虚拟”集群)。Kubectl还确定kubecconfig文件中的请求使用哪个命名空间。因此,您需要一种方法来告诉kubectl您希望它使用这些命名空间中的一个。

本节将解释这是如何工作的,以及如何轻松地完成它。

注意,您还可以通过在kubeconfig环境变量中列出多个kubeconfig文件。在这种情况下,所有这些文件将在执行时合并到一个有效的配置中。您还可以为每个kubectl命令使用——kubecconfig选项覆盖默认的kubecconfig文件。请参阅官方文档。

Kubeconfig 文件

让我们看看kubecconfig文件实际上包含了什么:

fe1253e448fc53d0a0806c0ad83f89f1.png

kubeconfig文件包含一组上下文

可以看到,kubeconfig文件由一组上下文组成。上下文包含以下三个元素:

kubeconfig

Welfare treatment

e6b7e9444d1300ba7fbadf1d4175d8d8.png

Cluster集群API服务器的URL

User

集群中特定用户的身份验证凭证

命名空间
连接集群时使用的命名空间

在实践中,人们经常在kubeconfig文件中为每个集群使用一个上下文。但是,每个集群也可以有多个上下文,它们的用户或名称空间不同。但这似乎不太常见,因此集群和上下文之间经常存在一对一的映射。

在任何给定的时间,这些上下文中的一个被设置为当前上下文current context (通过 kubecconfig 文件中的专用字段):

099e69a6d5fe39ed5683fe898e95de98.png

kubectl读取kubecconfig文件时,它总是使用来自当前上下文(CURRENT CONTEXT)中的信息。因此,在上面的示例中,kubectl 将连接到 Hare 集群。

因此,要切换到另一个集群,你只需要改变kubeconfig文件中的当前上下文(CURRENT CONTEXT):

939e6b3552ed29af0bcbc58c10af0136.png

更改kubeconfig文件的当前上下文(CURRENT CONTEXT)

3799c0a3470e1798a1196fd171261ac3.png

在上面的例子中,kubectl现在将连接到 Fox 集群。

要切换到同一集群中的另一个名称空间,可以更改当前上下文的命名空间元素:

在kubeconfig文件中更改当前上下文的名称空间

在上面的例子中,kubectl现在将在Fox集群中使用Prod名称空间(而不是之前设置的Test名称空间)。

请注意,kubectl还提供了——cluster、——user、——namespace和——context选项,这些选项允许您覆盖单个元素和当前上下文本身,而不管kubeconfig文件中设置了什么。看到kubectl选项。

理论上,您可以通过手动编辑 kubeconfig 文件来完成这些更改。当然,这很乏味。下面的部分介绍了各种工具,它们允许您自动执行这些更改。

7e252fbd91827a673c86c96992b4dc12.png

使用kubectx

6fd9314fd5c12f0ab10cbc7e393a5908.png

kubectx 是一个非常流行的用于在集群和名称空间之间切换的工具

该工具提供了kubectx 和 kubens命令,分别允许您更改当前上下文和名称空间

如前所述,如果每个集群只有一个上下文,那么更改当前上下文意味着更改集群。

这里你可以看到这两个命令在运行:

4b1090b762afffae52ed4ac9a72487e2.gif

本质上说,这些命令只是编辑kubeconfig文件,正如上一节所解释的那样。

要安装kubectx,只需遵循GitHub页面上的说明(https://github.com/ahmetb/kubectx/#installation)。

kubectxkubens都通过自动完成脚本提供命令完成。这允许您自动完成上下文名称和命名空间,从而不必完全键入它们。你也可以在GitHub页面上找到设置完成的说明。

kubectx的另一个有用特性是交互模式。您必须单独安装的fzf工具一起工作(事实上,安装 fzf 会自动启用 kubectx 交互模式)。交互模式允许您通过交互式模糊搜索接口(由fzf提供)选择目标上下文或名称空间

bfe078451152e35f5d8e56b79bf2163b.png

使用aliases

0e9c3b1799d1293017e876eab5e9ad7a.png

实际上,您并不真的需要单独的工具来更改当前上下文和名称空间,因为kubectl 也提供了这样做的命令。特别是,kubectl config 命令提供了用于编辑 kubecconfig 文件的子命令。以下是其中一些:

a089aacd4d933670b4a3a38b6b63a9d6.png

kubectl config

c44f560b3d7ae84a7030e6405f52cd9f.png

kubectl config get-contexts:  列出所有上下文

kubectl config current-context: 获取当前上下文

kubectl config use-context: 更改当前上下文

kubectl config set-context: 更改上下文的一个元素

但是,直接使用这些命令不是很方便,因为输入它们很长。但是,您可以将它们封装到shell aliases 中,这样更容易执行。

我基于这些命令创建了一组别名,它们提供了与kubectx类似的功能。这里你可以看到实际使用的情况:

98328504a7f2d1a54043d7c44f84c900.gif

请注意,别名使用fzf提供交互式模糊搜索界面(类似于kubectx的交互模式)。这意味着,您需要安装fzf才能使用这些别名。

下面是.bashrc 文件中别名 aliases 的定义:

# 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!

670f22c31730975b58c9a4cab5eec450.png

使用插件

e93ae7265ab5b51e8f19607147a39df5.png

Kubectl允许安装可以像调用本机命令一样调用的插件。例如,你可以安装一个名为kubectl-foo的插件,然后以kubectl foo的形式调用它。

Kubectl插件将在本文的后面部分详细描述。

如果能够更改当前的上下文和名称,那不是很好吗

我创建了两个插件:

  • kubectl-ctx

  • kubectl-ns

在内部,插件构建于上一节中的别名之上。

这里你可以看到插件的运行:

d884c27219c3ba564b293251b8b32e02.gif

注意,这些插件使用fzf提供一个交互式模糊搜索界面。这意味着,您需要安装fzf才能使用这些插件。

要安装插件,您只需将名为kubectl-ctx和kubectl-ns的shell脚本下载到PATH中的任意目录,并使它们可执行(例如,使用chmod +x)。就是这样!在此之后,您应该能够使用kubectl ctx和kubectl ns!

5. 使用

使用自动生成的别名

Shell别名通常是一种节省输入的好方法。kubectl-aliases项目将这个想法铭记于心,并为常见的kubectl命令提供了大约800个别名

你可能会想,你怎么可能记住800个别名?实际上,你不需要记住它们,因为它们都是根据一个简单的方案生成的,下面显示了一些示例别名:

尝试将鼠标悬停在示例别名上以获得视觉效果。

e42d15ec296f481cf224a3cf65bcf07e.png

kgpooyaml

fb029d44c0a98db92823f621640152af.png

2983f39020bf41f6ee7382a0beaddb6e.png

ksysrmcm

3c2435ba9631183bc8a85779eac9f07a.png

fdd91ea1d5715a02a15416bb13ecde71.png

ksysgsvcw

1670d1f3481c9063e2679a4ce7bd48f1.png

83be4647c3af19eec568b924ae8318fc.png

kgdepallsl

eabe94bd8efe4512f9e3e9e814a80ea0.png

如您所见,别名由组件组成,每个组件代表kubectl命令的一个特定元素。每个别名可以有一个用于基本命令、操作和资源的组件,以及多个用于选项的组件,您只需根据上述方案从左到右“填写”这些组件。

例如,您可以使用k proxy 来运行 kubectl proxy:

12ad99fdb00cc79f929a7f88db1e1681.gif

或者你可以使用kg roles来运行kubectl get roles(目前还没有role资源的别名组件):

e19e91e8304c10784b56c8b71a263bb5.gif

要获得一个特定的Pod,你可以使用kgpo my-pod来运行kubectl get pod my-pod:

e4223e25fdb7644a34a415485206b661.gif

请注意,GitHub页面上有当前的详细方案。在那里你还可以找到别名的完整列表。

例如,别名kgpooyamlall代表命令kubectl get pods -o yaml --all-name espaces:2b74243026545cc442547dc919bb66a2.gif

注意,有些别名甚至需要命令行上的进一步参数。例如,kgpol别名代表kubectl get pods -l。-l选项需要一个参数(一个标签规范)。所以,你必须像这样使用这个别名,例如,:

95580ff4840fd703c66427f12f46a828.gif

所以,在需要使用 a, f, l 组件的时候,只能把他们放在别名的最后。

通常,一旦您掌握了这种模式,您就可以从您想要执行的命令中直观地推断出别名,并节省大量输入!

0f488f7e7a92db990b8ef5aefd50d57a.png

安装

要安装kubectl-aliases,你只需要从GitHub下载到 ~/.kubectl-aliases 文件夹李,并在~/.bashrc 或 ~/.zshrc中添加:

source ~/.kubectl_aliases

就是这样! 在重新加载shell之后,您应该能够使用所有800个kubectl别名!

4458589412847ccc368e9307a093b924.png

自动完成

如您所见,您可以经常在命令行上向别名追加更多的单词。例如:

kgpooyaml test-pod-d4b77b989

如果您使用kubectl命令补全,那么您可能已经习惯于自动补全资源名之类的东西。但当你使用别名时,你还能做到吗?

这是一个重要的问题,因为如果它不起作用,就会抵消这些别名的一些好处!

答案取决于您使用的shell

对于Zsh,没有问题!

不幸的是,对于Bash,默认情况下别名的自动完成不工作。好消息是,它可以通过一些额外的步骤来工作。下一节将解释如何做到这一点。

822634e510c9ece60dae5e8ccc53178e.png

在Bash中启用别名自动完成

Bash的问题是,它会尝试对别名进行补全(每当您按Tab时),而不是对带有别名的命令(如Zsh)进行补全。由于您没有针对所有800个别名的完成脚本,所以这是不起作用的。

 complete-alias 项目为这个问题提供了一个通用的解决方案。它利用别名的完成机制,在内部将别名扩展为别名命令,并返回扩展命令的完成建议。这意味着,它使别名的完成行为与别名命令的完成行为完全相同

在下面的文章中,我将首先解释如何安装complete-alias,然后说明如何配置它以启用它。

安装complete-alias

首先,complete-alias依赖于bash-completion。因此,在安装complete-alias之前,您需要确保已安装bash-completion。对于Linux和macOS,前面已经给出了这方面的说明。

macOS用户需要注意的是:像kubectl完成脚本一样,complete-alias在Bash 3.2中不起作用,而Bash 3.2是macOS上的默认版本。特别地,complete-alias依赖于Bash -completion v2 (brew install bash-completion@2),这至少需要Bash 4.1。这意味着,要在macOS上使用完整别名,您需要安装一个更新版本的Bash。

要安装complete-alias,您只需要从GitHub存储库下载bash_complete .sh脚本并在~/.bashrc文件里添加下面一行 :(

source ~/bash_completion.sh


在重新加载shell之后,应该正确地安装了complete-alias

ce43d3227061652733028acab9aa9b95.png

启用kubectl别名命令自动完成

从技术上讲,complete-alias提供了_complete_alias shell函数。此函数检查别名并返回别名命令的补全建议。

要将其与特定的别名连接起来,必须使用complete Bash内置函数设置_complete_alias作为别名的补全函数

例如,让我们以代表kubectl命令的k别名为例。要设置_complete_alias作为这个别名的补全函数,必须执行以下命令:

$ complete -F _complete_alias k

这样做的效果是,每当您对k别名进行自动补全时,都会调用_complete_alias函数,该函数会检查别名并返回kubectl命令的补全建议。

另一个例子,让我们以表示kubectl get的kg别名为例:

$ complete -F _complete_alias kg

类似地,当您在kg上自动完成时,您将得到与kubectl get相同的完成建议。

注意,可以以这种方式为系统上的任何别名使用完整别名。

因此,要为所有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

ec016bbcc5fe2546f486d75143299669.png

1.12版本开始,kubectl包含了一个插件机制,允许您使用自定义命令扩展kubectl。

下面是kubectl插件的一个例子,它可以按kubectl hello 方式调用:

90e2096aeceea2926d1364dc3cba5a58.gif

kubectl插件机制与Git插件机制的设计密切相关,如果您对它比较熟悉的话。

本节将向您展示如何安装插件,您可以在哪里找到现有的插件,以及如何创建自己的插件。

安装插件

Kubectl插件以Kubectl -x的形式作为简单的可执行文件分发。前缀kubectl-是必须的,接下来是新的kubectl子命令,允许调用插件

例如,上面所示的hello插件将作为一个名为kubectl-hello的文件分发。

要安装插件,只需将kubectl-x文件复制到PATH中的任意目录并使其可执行(例如,使用chmod +x)。在此之后,您可以使用kubectl x调用插件。

你可以使用下面的命令列出系统中当前安装的所有插件:

kubectl plugin list

如果您有多个同名的插件,或者有一个不可执行的插件文件,该命令也会显示警告。

使用krew查找并安装插件

b3316e26fa0b8c9c4511019020cea1a1.png

Kubectl插件可以像软件包一样被共享和重用。但是在哪里可以找到别人共享的插件呢?

krew项目旨在为共享、查找、安装和管理kubectl插件提供一个统一的解决方案。这个项目称自己为“kubectl插件的包管理器”(krew这个名字暗示了brew)。

Krew以kubectl插件的索引为中心,您可以从中选择和安装。这里你可以看到krew的使用:

a93beea2b845439dcfb9da60a2ba0717.gif

正如你所看到的,krew本身就是一个kubectl插件。这意味着,安装krew本质上就像安装其他kubectl插件一样。你可以在GitHub页面找到krew的详细安装说明。

最重要的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安装的插件和那些用其他方式安装的插件。

0c83e644a9f24ae16442505dd1a4862b.gif

创建自己的插件

847ee7213483f8fc07754653a5878eba.png

当然,您可以创建您自己的kubectl插件,这是非常容易做到的。

您只需要创建一个执行您想要的操作的可执行文件,给它一个kubectl-x 形式的名称,然后按照上面的描述安装它。

可执行文件可以是任何类型的,一个Bash脚本,一个编译过的Go程序,一个Python脚本,都没关系。唯一的要求是它可以直接由操作系统执行。

现在让我们创建一个示例插件。在前一节中,您使用kubectl命令列出每个pod的容器映像。您可以很容易地将此命令转换为一个插件,您可以使用kubectl img调用该插件。

为此,只需创建一个名为kubectl-img的文件,包含以下内容:

现在使用chmod +x kubectl-img使该文件成为可执行文件,并将其移动到PATH中的任意目录。之后,你就可以开始使用kubectl img插件了!

正如前面提到的,kubectl插件可以用任何编程语言或脚本语言编写。如果您使用shell脚本,那么您的优势在于可以轻松地从插件中调用kubectl。但是,您可以使用真正的编程语言编写更复杂的插件,例如,使用Kubernetes客户端库。如果使用Go,还可以使用cli运行时库,它是专门用于编写kubectl插件的。

9affe175349877ab61c26af8f4e6cb08.png

分享你的插件

如果您认为您的某个插件可能对其他人有用,请随时在GitHub上分享它。请确保将其添加到kubectl-plugins主题中,以便其他人能够找到它。

你也可以要求将插件添加到krew索引中。您可以在krew GitHub存储库中找到如何做到这一点的说明。

命令自动完成?

4d77e685b1545cce5b015af93505ef47.png935c9893b46347fb1a50c2d091f9525c.png

不幸的是,目前插件机制还不支持命令补全。这意味着您需要完全键入插件名,以及插件的任何参数。

然而,在kubectl GitHub存储库中有一个开放特性的请求。因此,有可能在将来某个时候实现该特性。

原文链接:https://learnk8s.io/blog/kubectl-productivity

本文转载自:「云原生架构之美」,原文:https://tinyurl.com/yw86kczb,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-linux.com。

642e2180e1a54d97b4f39631aa8f6ff3.gif

0e6b7c789ba695699c5a7da848ab66fc.png

你可能还喜欢

点击下方图片即可阅读

af524d8ae957d06e1a877d6e32c2a661.png

一文搞懂 4 种常用的 Kubernetes 容器

07baadaa8fc5b15f73926fd52b9cedc4.png
『美团|饿了么』外卖红包天天免费领,吃饭省钱杠杠滴!

73685e6bd51e38eb83cdee1441524c8f.png

更多有趣的互联网新鲜事,关注「奇妙的互联网」视频号全了解!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值