<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="https://morningspace.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://morningspace.github.io/" rel="alternate" type="text/html" /><updated>2023-10-06T07:53:16+08:00</updated><id>https://morningspace.github.io/feed.xml</id><title type="html">晴耕小筑</title><subtitle>My new way to the world.</subtitle><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><entry><title type="html">在团队中使用增强版OpenShift CLI</title><link href="https://morningspace.github.io/tech/enhanced-oc-4/" rel="alternate" type="text/html" title="在团队中使用增强版OpenShift CLI" /><published>2021-08-11T00:00:00+08:00</published><updated>2021-08-11T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/enhanced-oc-4</id><content type="html" xml:base="https://morningspace.github.io/tech/enhanced-oc-4/">&lt;blockquote&gt;
  &lt;p&gt;增强版OpenShift CLI可以帮助我们高效而安全的管理大量的OpenShift集群。它是一个位于&lt;a href=&quot;https://github.com/morningspace/enhanced-oc&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;作为增强版OpenShift CLI系列文章的第四篇，本文将向大家介绍如何把保存在本地secret store里的集群访问信息分享给团队中的其他成员。&lt;/p&gt;

&lt;p&gt;通过把存有集群访问信息的本地secret store分享到远程，我们可以很方便的在整个团队范围内实现统一的集群管理。任何时候，当你有新的集群访问信息通过增强版oc加入到secret store，同样的访问信息将会被自动同步到其他团队成员的本地secret store里。这样，大家在不关心集群访问信息具体内容的情况下，只通过集群的别名就可以实现对同一集群的访问了。&lt;/p&gt;

&lt;h2 id=&quot;分享你的secretstore&quot;&gt;分享你的Secret Store&lt;/h2&gt;

&lt;p&gt;如果你打算把保存在本地secret store里的集群访问信息分享给其他人，首先需要为secret store添加git remote信息，并将本地的secret store通过git push推送到远程：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gopass git remote add origin git@github.example.com:william/team-clusters.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gopass git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当连接远程的git服务器时（比如GitHub），尽管我们可以使用HTTPS协议，但还是建议大家使用SSH进行连接。利用SSH key，我们在每次访问远程git库时，可以无需提供用户名和access token。有关如何以SSH方式连接GitHub，请参考GitHub的&lt;a href=&quot;https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh&quot;&gt;相关文档&lt;/a&gt;。&lt;/p&gt;

&lt;h2 id=&quot;为团队成员做准备&quot;&gt;为团队成员做准备&lt;/h2&gt;

&lt;p&gt;为了让团队成员能够成功解密保存在远程secret store里的经过加密的集群访问信息，我们还需要做一点准备工作。首先，要求团队成员在各自的机器上安装好必要的工具和软件，包括：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpg&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gopass&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oc&lt;/code&gt;等。然后，要求大家用如下命令生成各自的密钥对：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--full-generate-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;选择&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RSA and RSA&lt;/code&gt;作为密钥类型，keysize为2048，密钥永不过期，然后输入团队成员的用户名，邮箱地址，以及密钥对应的密码（passphrase）。&lt;/p&gt;

&lt;p&gt;等密钥对生成完毕以后，要求大家把其中的公钥导出并发送给你。在团队成员所在的机器上执行如下命令，可以找到公钥的ID：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--list-keys&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--keyid-format&lt;/span&gt; LONG
/root/.gnupg/pubring.gpg
&lt;span class=&quot;nt&quot;&gt;------------------------&lt;/span&gt;
pub   2048R/93E7B0300BB9C91B 2021-03-17
uid                          Nicole &amp;lt;nicole@example.com&amp;gt;
sub   2048R/3AE8C980579D103C 2021-03-17
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;从输出结果中选取与当前团队成员的用户名及邮箱地址相匹配的公钥，复制相应的密钥ID，即&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub&lt;/code&gt;所在的那一行，本例中为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;93E7B0300BB9C91B&lt;/code&gt;。然后用如下命令，把公钥导出到一个文件里：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--export&lt;/span&gt; 93E7B0300BB9C91B &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; nicole_pub.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当我们接收到团队成员的公钥以后，通过如下命令将公钥导入到本地：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; nicole_pub.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;并将该团队成员作为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipient&lt;/code&gt;，加入到本地的secret store里：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gopass recipients add 93E7B0300BB9C91B
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后用我们自己的私钥对团队成员的公钥进行签名，并选择对其永久信任：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--edit-key&lt;/span&gt; 93E7B0300BB9C91B
lsign
trust
save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后，重新加一次&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipient&lt;/code&gt;，以触发gopass对保存在本地secret store里的数据重新进行加密：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gopass recipients &lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;93E7B0300BB9C91B
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gopass recipients add 93E7B0300BB9C91B
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上述所有步骤都会被自动同步到远程的secret store里。&lt;/p&gt;

&lt;h2 id=&quot;克隆远程的secretstore&quot;&gt;克隆远程的Secret Store&lt;/h2&gt;

&lt;p&gt;现在，我们可以通知团队成员，让大家把远程的secret store克隆到本地了。同时，请确保这些团队成员已经以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collaborator&lt;/code&gt;的身份被添加到了远程git库里。然后在每位团队成员所在的机器上执行如下命令，将远程secret store克隆到本地：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gopass &lt;span class=&quot;nt&quot;&gt;--yes&lt;/span&gt; setup &lt;span class=&quot;nt&quot;&gt;--remote&lt;/span&gt; git@github.example.com:william/team-clusters.git &lt;span class=&quot;nt&quot;&gt;--alias&lt;/span&gt; team-clusters &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; Nicole &lt;span class=&quot;nt&quot;&gt;--email&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;nicole@example.com&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中，参数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--name&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--email&lt;/code&gt;的取值和团队成员在生成各自密钥对时所使用的取值保持一致。这样，其他人就可以和我们一样，利用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oc login&lt;/code&gt;命令及别名，对同一组集群进行访问了。&lt;/p&gt;

&lt;p&gt;下图演示了整个准备工作的端到端流程：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/enhanced-oc/enhanced-oc-4.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;本文中，我们学习了如何把保存在本地secret store里的集群访问信息分享给团队中的其他成员。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关增强版OpenShift CLI的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/oc/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/oc&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><category term="openshift" /><summary type="html">本文向大家介绍如何把集群访问信息分享给团队中的其他成员</summary></entry><entry><title type="html">增强版OpenShift CLI的更多功能</title><link href="https://morningspace.github.io/tech/enhanced-oc-3/" rel="alternate" type="text/html" title="增强版OpenShift CLI的更多功能" /><published>2021-08-02T00:00:00+08:00</published><updated>2021-08-02T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/enhanced-oc-3</id><content type="html" xml:base="https://morningspace.github.io/tech/enhanced-oc-3/">&lt;blockquote&gt;
  &lt;p&gt;增强版OpenShift CLI可以帮助我们高效而安全的管理大量的OpenShift集群。它是一个位于&lt;a href=&quot;https://github.com/morningspace/enhanced-oc&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;作为增强版OpenShift CLI系列文章的第三篇，本文将和大家分享有关这一工具所提供的更多有意思的功能。&lt;/p&gt;

&lt;h2 id=&quot;层级化管理集群&quot;&gt;层级化管理集群&lt;/h2&gt;

&lt;p&gt;在一个实际项目里，同时管理多个集群是一件很常见的事。使用增强版oc，通过指定别名可以实现在多个集群之间的快速切换，这样做即安全又高效。不过，随着集群数量的增加，管理成本还是会逐步上升。针对这种情况，一种更为有效的方法，是将这些集群以层级化的方式进行管理。&lt;/p&gt;

&lt;p&gt;增强版oc底层依赖于gopass，而gopass天生就具备层级化管理加密数据的能力。这是因为，gopass在存储加密数据时，把一组加密数据以一个独立文件的形式保存在secret store里，而彼此相关的一组文件可以根据需要存放在同一目录下面。例如，假设有三个集群，我们可以采用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;path/to/your/context&lt;/code&gt;这样的格式来为集群定义别名。&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;oc login &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; https://api.foo.example.com &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; dev-env/cluster-foo
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;oc login &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; https://api.bar.example.com &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; dev-env/cluster-bar
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;oc login &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; https://api.baz.example.com &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; dev-env/cluster-baz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样，集群的访问信息就会以层级化的方式保存在secret store里，相应的目录结构与我们定义别名时的格式保持一致。这一点可以通过执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gopass ls&lt;/code&gt;命令清楚直观的展现出来：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gopass &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;gopass
└── dev-env
    ├── cluster-foo
    ├── cluster-bar
    └── cluster-baz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当我们在这些集群之间切换时，只要给出&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;path/to/your/context&lt;/code&gt;别名即可：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;oc login &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; dev-env/cluster-foo
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;oc login &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; dev-env/cluster-bar
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;oc login &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; dev-env/cluster-baz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;在多个集群中选择&quot;&gt;在多个集群中选择&lt;/h2&gt;

&lt;p&gt;以层级化方式对集群进行管理允许我们能够非常高效的管理大量集群，我们可以把集群按照不同的用途进行分类。不过，由于别名里包含了层级结构，输入完整的别名就会变得有点冗长。&lt;/p&gt;

&lt;p&gt;增强版oc允许我们在输入集群的别名时只输入名字的一部分。例如，如果我们把所有开发用的集群环境都放到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev-env&lt;/code&gt;类别下，相应的集群别名均以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev-env&lt;/code&gt;打头。那么，当我们指定别名的时候，只要输入完整名字的几个首字母，比如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;de&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev-&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev-env&lt;/code&gt;，就会有多个满足输入条件的集群返回回来。这些集群会以有序列表的形式依次排列，要想选中其中一个集群登录，只要输入集群前面的数字即可：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;oc login &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; dev
1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; dev-env/cluster-bar
2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; dev-env/cluster-baz
3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; dev-env/cluster-foo
&lt;span class=&quot;c&quot;&gt;#? 1&lt;/span&gt;
Read context &lt;span class=&quot;s1&quot;&gt;'dev-env/cluster-bar'&lt;/span&gt; from secret store...
Context loaded successfully.
Login successful.

You have access to 59 projects, the list has been suppressed. You can list all projects with &lt;span class=&quot;s1&quot;&gt;'oc projects'&lt;/span&gt;

Using project &lt;span class=&quot;s2&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;模糊查找&quot;&gt;模糊查找&lt;/h2&gt;

&lt;p&gt;增强版oc允许我们在输入集群的别名时只输入名字的一部分，从而进一步提高了在多个集群间切换的效率。不仅如此，如果我们安装了&lt;a href=&quot;https://github.com/junegunn/fzf&quot;&gt;fzf&lt;/a&gt;，一个通用的支持模糊查找与过滤的命令行工具，就可以在指定别名时利用typeahead实现模糊查找的功能了。增强版oc与fzf做了无缝集成，不需要额外配置，它会自动监测fzf存在与否，并开启相应的模糊查找功能。有关fzf的安装，请参考其&lt;a href=&quot;https://github.com/junegunn/fzf#installation&quot;&gt;文档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/enhanced-oc/enhanced-oc-2.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;定制shell提示&quot;&gt;定制Shell提示&lt;/h2&gt;

&lt;p&gt;我们还可以安装&lt;a href=&quot;https://github.com/jonmosco/kube-ps1&quot;&gt;kube-ps1&lt;/a&gt;。这是一个脚本程序，允许把当前集群的上下文信息，包括当前所在的namespace，在命令行的Shell提示里显示出来。当我们需要同时管理多个集群，并在这些集群之间来回切换的时候，这一功能就会非常有用。通过查看命令行的Shell提示信息，我们可以快速获知当前操作的是哪个集群，从而避免了误操作。&lt;/p&gt;

&lt;p&gt;增强版oc和kube-ps1做了无缝集成，不需要额外配置，它会自动监测kube-ps1存在与否，并对kube-ps1控制的Shell提示进行定制，将完整的集群上下文名称替换为相应的集群别名，通常而言，后者要比前者更短更易于记忆。有关kube-ps1的安装，请参考其&lt;a href=&quot;https://github.com/jonmosco/kube-ps1#installing&quot;&gt;文档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/enhanced-oc/enhanced-oc-3.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;本文中，我们学习了有关增强版oc的更多有趣的功能，比如：以层级化方式对集群进行管理；通过只输入别名的一部分，实现多个集群间的快速切换；以及通过对Shell提示的定制，显示当前操作的集群。在下一篇文章里，我将向大家介绍增强版oc的另一个重要的功能：如何将集群访问信息分享给团队中的其他成员。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关增强版OpenShift CLI的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/oc/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/oc&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><category term="openshift" /><summary type="html">本文和大家分享有关增强版oc所提供的更多有意思的功能</summary></entry><entry><title type="html">增强版OpenShift CLI快速入门</title><link href="https://morningspace.github.io/tech/enhanced-oc-2/" rel="alternate" type="text/html" title="增强版OpenShift CLI快速入门" /><published>2021-07-25T00:00:00+08:00</published><updated>2021-07-25T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/enhanced-oc-2</id><content type="html" xml:base="https://morningspace.github.io/tech/enhanced-oc-2/">&lt;blockquote&gt;
  &lt;p&gt;增强版OpenShift CLI可以帮助我们高效而安全的管理大量的OpenShift集群。它是一个位于&lt;a href=&quot;https://github.com/morningspace/enhanced-oc&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;作为增强版OpenShift CLI系列文章的第二篇，本文将向大家介绍如何安装增强版oc，并为大家演示它的一些基本用法。&lt;/p&gt;

&lt;h2 id=&quot;安装增强版openshift-cli&quot;&gt;安装增强版OpenShift CLI&lt;/h2&gt;

&lt;p&gt;为了让增强版OpenShift CLI能够正常工作，我们在安装增强版OpenShift CLI之前，首先需要确保其所依赖的软件已经安装就绪，这其中包括：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;gpg：用于数据加密和解密&lt;/li&gt;
  &lt;li&gt;git：用于存储和共享加密数据&lt;/li&gt;
  &lt;li&gt;gopass：用于加密数据的管理，运行于gpg和git之上&lt;/li&gt;
  &lt;li&gt;oc：RedHat官方提供的OpenShift CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;根据你所使用的操作系统，从下列命令中选择正确的命令，安装git与gpg：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# MacOS&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gnupg2 git
&lt;span class=&quot;c&quot;&gt;# RHEL &amp;amp; CentOS&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gnupg2 git
&lt;span class=&quot;c&quot;&gt;# Ubuntu &amp;amp; Debian&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gnupg2 git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;关于gopass的安装，推荐到gopass在GitHub上的&lt;a href=&quot;https://github.com/gopasspw/gopass/releases&quot;&gt;releases页面&lt;/a&gt;下载并安装最新的版本。根据你所使用的操作系统，选择相应的压缩包，将之下载到本地并解压，然后从中找出gopass的可执行文件，放入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PATH&lt;/code&gt;能访问的路径下。&lt;/p&gt;

&lt;p&gt;关于oc的安装，请参考&lt;a href=&quot;https://docs.openshift.com/container-platform/latest/cli_reference/openshift_cli/getting-started-cli.html#installing-openshift-cli&quot;&gt;OpenShift的官方文档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;当增强版OpenShift CLI的所有依赖软件安装完毕以后，请从GitHub上下载增强版oc的Shell脚本：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-OL&lt;/span&gt; https://raw.githubusercontent.com/morningspace/oc/master/oc.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果你用的是Bash，请在用户主目录下找到Shell初始化文件&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt;，并将下列代码加入其中。如果你用的是其他Shell，比如Zsh，则相应的Shell初始化文件会有所不同。&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /path/to/oc.sh &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; /path/to/oc.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;随后，我们打开一个新的终端窗口，并运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oc&lt;/code&gt;命令，以验证安装是否成功。如果一切正常，我们会看到，在oc命令输出的正常帮助信息前面，会有几行提示信息，代表这是一个增强版的OpenShift CLI。&lt;/p&gt;

&lt;h2 id=&quot;设置环境&quot;&gt;设置环境&lt;/h2&gt;

&lt;p&gt;gopass是依赖于gpg对数据进行加密和解密的。在我们开始使用增强版oc之前，我们必须先创建一组密钥对：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--full-generate-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;选择&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RSA and RSA&lt;/code&gt;作为密钥类型，keysize为2048，密钥永不过期，然后输入你的用户名，邮箱地址，以及密钥对应的密码（passphrase）。&lt;/p&gt;

&lt;p&gt;此外，我们还应该把下列代码加入位于用户主目录下的Shell初始化文件内：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GPG_TTY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tty&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后运行gopass命令初始化secret store：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gopass init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;根据提示，选择之前生成的密钥对中的私钥，用它对存储于secret store中的数据进行加密，随后输入你的邮箱地址用于git的配置。&lt;/p&gt;

&lt;h2 id=&quot;首次登录集群&quot;&gt;首次登录集群&lt;/h2&gt;

&lt;p&gt;第一次登录某个集群时，我们将使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oc login&lt;/code&gt;命令：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;oc login
Server &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;https://localhost:8443]: https://api.cluster-foo.example.com:6443
Username &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;kubeadmin]:
Password:
Context &lt;span class=&quot;nb&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;api-cluster-foo-example-com-6443]: cluster-foo
Login successful.

You have access to 59 projects, the list has been suppressed. You can list all projects with &lt;span class=&quot;s1&quot;&gt;'oc projects'&lt;/span&gt;

Using project &lt;span class=&quot;s2&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Save context &lt;span class=&quot;s1&quot;&gt;'cluster-foo'&lt;/span&gt; into secret store...
Context saved successfully.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;根据提示，输入集群的服务器地址，登录用户名，以及密码。这些都是原有oc命令所支持的功能。在这之后，增强版oc会提示我们为即将访问的集群指定一个便于记忆的别名。这个别名相当于一个”助记符“，不仅对应于所访问的集群，还包括所使用的登录账号等信息。稍后我们会看到，增强版oc是如何利用这个别名，实现在多个集群之间的快速切换的。&lt;/p&gt;

&lt;p&gt;当然，就像原有oc命令所支持的那样，我们也可以把上述输入的信息作为命令行参数，直接放在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oc login&lt;/code&gt;命令的后面。不过，为了避免登录信息通过命令行执行历史暴露出来，还是建议大家不要这样做。&lt;/p&gt;

&lt;h2 id=&quot;通过别名登录集群&quot;&gt;通过别名登录集群&lt;/h2&gt;

&lt;p&gt;当集群的登录会话超时以后，我们就需要用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oc login&lt;/code&gt;命令再次进行登录。不过和原有oc命令不同，这一次我们无需再重新输入全部登录信息了，只要通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-c&lt;/code&gt;参数告诉oc命令我们要访问的集群别名即可：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;oc login &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; cluster-foo
Read context &lt;span class=&quot;s1&quot;&gt;'cluster-foo'&lt;/span&gt; from secret store...
Context loaded successfully.
Login successful.

You have access to 59 projects, the list has been suppressed. You can list all projects with &lt;span class=&quot;s1&quot;&gt;'oc projects'&lt;/span&gt;

Using project &lt;span class=&quot;s2&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这是因为，之前我们所提供的有关该集群的全部访问信息，连同对应的别名，都已经被保存在gopass的secret store里了。因此，只要我们提供别名信息，增强版oc就会根据别名找到对应的集群访问信息，并自动登录集群。&lt;/p&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;本文中，我们学习了增强版OpenShift CLI的安装，及其基本使用方法。在下一篇文章里，我将和大家分享有关这一工具所提供的更多有意思的功能。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关增强版OpenShift CLI的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/oc/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/oc&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><category term="openshift" /><summary type="html">本文向大家介绍增强版oc的安装及其用法演示</summary></entry><entry><title type="html">如何高效安全的管理OpenShift集群</title><link href="https://morningspace.github.io/tech/enhanced-oc-1/" rel="alternate" type="text/html" title="如何高效安全的管理OpenShift集群" /><published>2021-07-18T00:00:00+08:00</published><updated>2021-07-18T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/enhanced-oc-1</id><content type="html" xml:base="https://morningspace.github.io/tech/enhanced-oc-1/">&lt;blockquote&gt;
  &lt;p&gt;增强版OpenShift CLI可以帮助我们高效而安全的管理大量的OpenShift集群。它是一个位于&lt;a href=&quot;https://github.com/morningspace/enhanced-oc&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/enhanced-oc/enhanced-oc-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;问题的提出&quot;&gt;问题的提出&lt;/h2&gt;

&lt;p&gt;大家有没有遇到过这样的情况：手里有多个OpenShift集群同时在工作，并且访问每个集群都需要使用各自的登录账号和密码。基于安全的考虑，每次登录一个集群以后，登录会话会在一段时间之后失效。于是，为了继续操作这些集群，我们需要重新进行登录。&lt;/p&gt;

&lt;p&gt;不仅如此，如果这些集群属于池化资源，那么典型情况下，它们的创建和释放都是按需来的，相应的集群访问信息，包括访问地址和登录密码，都可能是随机生成的，因而非常难于记忆。为此，我们不得不把集群的访问信息记录在某个地方，比如一个文本文件里，而这种记录信息的方法是不安全的。&lt;/p&gt;

&lt;p&gt;并且，由于类似这样的集群资源，其生命周期往往都不会很长，所以相应的访问信息也很容易过时，手工维护这些信息费力又不讨好。&lt;/p&gt;

&lt;h2 id=&quot;增强版openshift-cli&quot;&gt;增强版OpenShift CLI&lt;/h2&gt;

&lt;p&gt;针对上面提到的问题，我在这里向大家推荐的一个解决方法，是使用增强版的OpenShift CLI。&lt;/p&gt;

&lt;p&gt;如果你接触过OpenShift集群，那么对OpenShift CLI（即oc命令）一定不会陌生。它是一个命令行工具，可以用来管理OpenShift集群，非常类似于管理标准Kubernetes集群的命令行工具kubectl。&lt;/p&gt;

&lt;p&gt;增强版OpenShift CLI（或增强版oc）并非是对原有oc命令的替换。它实际上是一个运行在原有oc命令之上的shell脚本。通过使用增强版oc，我们可以高效而安全的管理大量的OpenShift集群。&lt;/p&gt;

&lt;p&gt;增强版oc除了支持原有oc的全部命令以外，还提供了以下几个有趣的功能：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;只有在第一次登录集群时需要提供完整的登录信息，后续只要提供代表该集群的别名即可完成再次登录。&lt;/li&gt;
  &lt;li&gt;可以把数量巨大的集群以层级化方式进行管理，并在这些集群之间实现快速切换，输入集群别名时允许只输入部分名字，支持模糊查询，并和shell prompt做了很好的集成。&lt;/li&gt;
  &lt;li&gt;支持把集群的上下文信息分享给其他人，实现多人团队协作过程中的共享集群管理。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;增强版OpenShift CLI之所以能提供上述这些神奇的功能，都是因为它底层使用了&lt;a href=&quot;https://www.gopass.pw/&quot;&gt;gopass&lt;/a&gt;，一款用go开发的密码管理软件。它把集群的访问信息存入了由gopass维护的secret store，并将这些信息和一个易于记忆的别名关联起来。此外，增强版oc对原有oc进行了封装，修改了oc命令的输入参数，使得用户可以在使用oc命令登录集群时指定集群的别名作为输入参数。&lt;/p&gt;

&lt;p&gt;不仅如此，由于gopass天生具备的一些特征，增强版oc还能做很多别的事，比如：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;gopass是以层级化的文件夹及文件结构对secret进行管理的：这使我们能够同样以层级化的方式对集群访问信息进行管理，从而能够支持数量非常多的集群。&lt;/li&gt;
  &lt;li&gt;gopass在查询secret时支持非精确匹配：这使我们能够在通过别名对集群访问信息进行查询时同样也支持非精确查询及模糊查询。&lt;/li&gt;
  &lt;li&gt;gopass是以git库的形式来维护secret store的：这使得我们能够把本地的secret store分享到远程，从而让团队中的其他人也能访问到这些信息。这对于一个需要团队协作的大规模项目而言是非常有价值的。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;本文中，我们讨论了一种高效而安全的管理OpenShift集群的方案。这一方案是基于密码管理工具gopass，以及一个封装了oc命令的shell脚本来实现的。并且，由于gopass天生具备的一些特征，它为我们带来了很多有趣的功能，比如：对集群访问信息进行层级化管理，支持集群别名的非精确查询及模糊查询，允许把本地的集群访问信息分享给远程。&lt;/p&gt;

&lt;p&gt;在下一篇文章里，我将和大家分享如何安装增强版oc，并为大家演示它的一些用法。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关增强版OpenShift CLI的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/oc/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/oc&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><category term="openshift" /><summary type="html">本文向你推荐一个高效而安全的管理OpenShift集群的方案</summary></entry><entry><title type="html">集成KubeAssert与KUTTL</title><link href="https://morningspace.github.io/tech/kubeassert-4/" rel="alternate" type="text/html" title="集成KubeAssert与KUTTL" /><published>2021-07-10T00:00:00+08:00</published><updated>2021-07-10T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/kubeassert-4</id><content type="html" xml:base="https://morningspace.github.io/tech/kubeassert-4/">&lt;blockquote&gt;
  &lt;p&gt;KubeAssert是一个kubectl插件，用于在命令行声明针对Kubernetes资源的断言（assertion）。KubeAssert是一个位于&lt;a href=&quot;https://github.com/morningspace/kubeassert&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/kubeassert/kubeassert-4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;作为KubeAssert系列文章的第四篇，本文将向大家介绍，如何把KubeAssert和&lt;a href=&quot;https://kuttl.dev/&quot;&gt;KUTTL&lt;/a&gt;集成在一起，让针对Kubernetes集群的自动化测试如虎添翼。&lt;/p&gt;

&lt;h2 id=&quot;关于kuttl&quot;&gt;关于KUTTL&lt;/h2&gt;

&lt;p&gt;KUbernetes Test TooL (KUTTL)是一个Kubernetes的自动化测试工具，它利用YAML语法，提供了以声明式手段对Kubernetes进行测试的方法。KUTTL能在测试准备阶段动态注入即将要被测试的operator，并允许以YAML文件的形式对测试用例进行描述。测试过程中出现的断言，通常也是一系列YAML文件，用来验证Kubernetes资源的状态字段是否满足预期条件。此外，KUTTL也可以被用来实现Kubernetes集群的自动化部署。获取有关KUTTL的更多信息，可以访问它的&lt;a href=&quot;https://kuttl.dev/&quot;&gt;网站&lt;/a&gt;。&lt;/p&gt;

&lt;h2 id=&quot;结合kubeassert与kuttl&quot;&gt;结合KubeAssert与KUTTL&lt;/h2&gt;

&lt;p&gt;在KUTTL里，测试的断言是用YAML语言来定义的。我们可以用YAML语法来描述某个Kubernetes对象是否匹配指定的对象名称，或者相应的状态字段。如果我们为对象指定了预期的名称，KUTTL就会在集群中查找匹配该条件的Kubernetes对象。例如，假设我们定义的断言如下所示：&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Pod&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;my-pod&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;phase&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Successful&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;那么KUTTL就会在运行测试用例的namespace里寻找名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my-pod&lt;/code&gt;的pod资源，并等待其字段&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;status.phase&lt;/code&gt;的值变成&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Successful&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;然而，KUTTL的断言表达能力非常有限。例如，默认情况下，KUTTL是无法用这种YAML格式的断言来验证pod的重启次数小于某个期望数值的，它也无法验证没有pod处于terminating状态这样的情况。这就是KubeAssert的用武之地了！&lt;/p&gt;

&lt;p&gt;幸运的是，从v0.9.0开始，KUTTLE允许用户在声明断言时指定命令行命令或脚本文件。这就给了我们把KubeAssert和KUTTL集成在一起的机会，从而允许我们能写出更加灵活而强大的断言来。&lt;/p&gt;

&lt;h2 id=&quot;用kubeassert编写kuttl断言&quot;&gt;用KubeAssert编写KUTTL断言&lt;/h2&gt;

&lt;p&gt;接下来，让我们以KUTTL官网上的“&lt;a href=&quot;https://kuttl.dev/docs/kuttl-test-harness.html#writing-your-first-test&quot;&gt;Writing Your First Test&lt;/a&gt;”为例，看一下我们是如何把它改造成用KubeAssert来编写断言的。&lt;/p&gt;

&lt;h3 id=&quot;创建测试用例&quot;&gt;创建测试用例&lt;/h3&gt;

&lt;p&gt;首先，我们来创建一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tests/e2e&lt;/code&gt;目录，作为存放所有测试用例的根目录，并在该目录下创建&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example-test&lt;/code&gt;子目录，代表对应的测试用例：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tests/e2e/example-test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接下来，在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tests/e2e/example-test/&lt;/code&gt;目录下创建测试步骤&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;00-install.yaml&lt;/code&gt;，用于创建一个名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example-deployment&lt;/code&gt;的deployment：&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apps/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Deployment&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example-deployment&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;replicas&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;matchLabels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx:latest&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;containerPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后，创建测试断言&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tests/e2e/example-test/00-assert.yaml&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kuttl.dev/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TestAssert&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kubectl assert exist-enhanced deployment example-deployment -n $NAMESPACE --field-selector status.readyReplicas=3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;此处，我们使用了TestAssert，并通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;command&lt;/code&gt;定义调用了KubeAssert。判断如果&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example-deployment&lt;/code&gt;的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;status.readyReplicas&lt;/code&gt;字段取值为3，则认为测试步骤执行完毕。请注意，我们在这里使用了环境变量&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$NAMESPACE&lt;/code&gt;。这是KUTTL提供的，用来指明当前测试所在的namespace。&lt;/p&gt;

&lt;h3 id=&quot;编写第二个测试步骤&quot;&gt;编写第二个测试步骤&lt;/h3&gt;

&lt;p&gt;在第二个测试步骤里，我们把deployment的replica数从3增加到了4。这是在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tests/e2e/example-test/01-scale.yaml&lt;/code&gt;中定义的：&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apps/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Deployment&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example-deployment&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;replicas&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;为此，我们在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tests/e2e/example-test/01-assert.yaml&lt;/code&gt;中利用KubeAssert定义了相应的断言：&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kuttl.dev/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TestAssert&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kubectl assert exist-enhanced deployment example-deployment -n $NAMESPACE --field-selector status.readyReplicas=4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;此处，我们所声明的断言几乎和前一个测试步骤里定义的一摸一样。唯一的区别是，我们把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;status.readyReplicas&lt;/code&gt;的期望值改成了4。&lt;/p&gt;

&lt;p&gt;执行该测试用例并验证测试是否通过：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl kuttl &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; - start-kind&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt; ./tests/e2e/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;有关这一示例的更多信息，请访问位于KUTTL网站上的&lt;a href=&quot;https://kuttl.dev/docs/kuttl-test-harness.html#writing-your-first-test&quot;&gt;原文&lt;/a&gt;。&lt;/p&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;如你所见，把KubeAssert与KUTTL集成在一起非常的容易。本文中，我们只演示了KubeAssert的几个非常基本的断言功能。根据实际需要，我们还可以在编写KUTTL的测试用例时定义更加复杂的KubeAssert断言。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关KubeAssert的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/kubeassert/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/kubeassert&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><summary type="html">本文向大家介绍如何集成KubeAssert与[KUTTL](https://kuttl.dev/)，让Kubernetes自动化测试如虎添翼</summary></entry><entry><title type="html">为KubeAssert定制断言</title><link href="https://morningspace.github.io/tech/kubeassert-3/" rel="alternate" type="text/html" title="为KubeAssert定制断言" /><published>2021-07-03T00:00:00+08:00</published><updated>2021-07-03T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/kubeassert-3</id><content type="html" xml:base="https://morningspace.github.io/tech/kubeassert-3/">&lt;blockquote&gt;
  &lt;p&gt;KubeAssert是一个kubectl插件，用于在命令行声明针对Kubernetes资源的断言（assertion）。KubeAssert是一个位于&lt;a href=&quot;https://github.com/morningspace/kubeassert&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/kubeassert/kubeassert-3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;作为KubeAssert系列文章的第三篇，本文将向大家介绍，当现有断言无法满足需求的时候，如何通过编写自己的断言来扩展KubeAssert的能力。&lt;/p&gt;

&lt;h2 id=&quot;自己动手写断言&quot;&gt;自己动手写断言&lt;/h2&gt;

&lt;p&gt;虽然KubeAssert默认提供的断言可以支持Kubernetes集群日常操作的很多场景，但是，也有可能这些断言并不能满足你的特定需求。KubeAssert支持定制断言，它允许你自己动手编写断言，然后让KubeAssert加载并运行。&lt;/p&gt;

&lt;p&gt;作为一个例子，本文我们将编写一个自定义断言，用来验证kubeconfig里是否包含指定的集群。其中，集群的名称是在该断言被执行的时候通过命令行参数传入的。&lt;/p&gt;

&lt;h2 id=&quot;创建shell脚本文件&quot;&gt;创建Shell脚本文件&lt;/h2&gt;

&lt;p&gt;首先，让我们创建一个shell脚本文件，取名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;custom-assertions.sh&lt;/code&gt;，并将它放到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.kubeassert&lt;/code&gt;目录下。这里是KubeAssert加载所有断言的地方。每当KubeAssert启动时，它会寻找该目录下的所有&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sh&lt;/code&gt;文件，并作为断言加载到内存。&lt;/p&gt;

&lt;p&gt;一个脚本文件可以包含多个断言，每个断言都是通过shell函数来实现的。本例中，我们只有一个断言，对应函数名是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cluster&lt;/code&gt;，目前函数体还是空的：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;cluster &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
 :
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;为了测试断言，我们可以调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl assert&lt;/code&gt;命令，并指定函数名&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cluster&lt;/code&gt;，作为该断言的名字：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert cluster
ASSERT PASS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;正常情况下，我们会看到命令能够正确返回，只是返回结果是空的。接下来，让我们为函数加入具体的实现逻辑。&lt;/p&gt;

&lt;h2 id=&quot;实现断言的逻辑&quot;&gt;实现断言的逻辑&lt;/h2&gt;

&lt;p&gt;为了实现一个断言，通常我们需要做下面这几件事情：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;验证输入参数：在本例中，就是由用户通过命令行输入的集群名。如果验证失败，比如用户没有指定集群名，可以调用函数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logger::error&lt;/code&gt;输出错误信息，然后以非零值立即返回并退出断言。&lt;/li&gt;
  &lt;li&gt;打印断言信息：通过调用函数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logger::assert&lt;/code&gt;，我们可以在命令行打印出一条断言信息，以便告诉用户这个断言即将要做的事情。&lt;/li&gt;
  &lt;li&gt;执行断言逻辑：作为断言的主体部分，此处通常会调用一系列kubectl命令或Kubernetes API，例如：调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl config&lt;/code&gt;命令，从kubeconfig中查询集群信息。&lt;/li&gt;
  &lt;li&gt;验证断言结果：通过对kubectl或Kubernetes API的返回结果进行解析，判断断言成功与否。如果断言失败，则调用函数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logger::fail&lt;/code&gt;输出一条断言失败的信息。如果成功，则不需要做任何事情，或者也可以根据需要调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logger::info&lt;/code&gt;函数打印一些日志信息。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;将下列逻辑加入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cluster&lt;/code&gt;函数：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;cluster &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Validate input arguments&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; logger::error &lt;span class=&quot;s2&quot;&gt;&quot;You must specify a cluster name.&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
  &lt;span class=&quot;c&quot;&gt;# Print assertion message&lt;/span&gt;
  logger::assert &lt;span class=&quot;s2&quot;&gt;&quot;Cluster with name &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; should be included in kubeconfig.&quot;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Run some kubectl commands&lt;/span&gt;
  kubectl config get-clusters
  &lt;span class=&quot;c&quot;&gt;# Validate results&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.kubeassert/result.txt | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; ^&lt;span class=&quot;nv&quot;&gt;$1$;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Print normal logs&lt;/span&gt;
    logger::info &lt;span class=&quot;s2&quot;&gt;&quot;Found &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in kubeconfig.&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Print failure message&lt;/span&gt;
    logger::fail &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; not found.&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可能你已经注意到了，函数中对于断言结果的验证，是通过解析一个位置处于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.kubeassert/&lt;/code&gt;目录下的名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;result.txt&lt;/code&gt;的文件实现的。KubeAssert把调用kubectl的返回结果都存入了该文件。&lt;/p&gt;

&lt;p&gt;现在，让我们试一下执行该断言时不指定集群名的情况：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert cluster
ERROR You must specify a cluster name.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;结果报错，并提示调用断言时必须指定集群名。再试一下指定一个kubeconfig中不存在的集群名：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert cluster kind
ASSERT Cluster with name kind should be included &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;kubeconfig.
ASSERT FAIL kind not found.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;结果显示断言失败，并给出了原因。指定一个kubeconfig中存在的集群名：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert cluster kind-foo
ASSERT Cluster with name kind-foo should be included &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;kubeconfig.
INFO Found kind-foo &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;kubeconfig.
ASSERT PASS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这次结果显示断言成功了。&lt;/p&gt;

&lt;p&gt;如果断言执行过程中遇到了问题，需要进行排查，我们也可以在执行断言时加上&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-v&lt;/code&gt;参数，以打开详细日志输出的开关。这样，我们就可以看到断言中涉及了哪些kubectl调用，以及它们各自的返回结果是什么。&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert cluster kind-foo &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
ASSERT Cluster with name kind-foo should be included &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;kubeconfig.
INFO kubectl config get-clusters
NAME
kind-foo
kind-bar
INFO Found kind-foo &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;kubeconfig.
ASSERT PASS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;为断言添加注释&quot;&gt;为断言添加注释&lt;/h2&gt;

&lt;p&gt;到目前为止，我们已经实现了断言的全部逻辑。不过，还有一件事情我们需要做。当执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl assert&lt;/code&gt;并带着&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-h/--help&lt;/code&gt;参数或者不带任何参数时，为了能够让我们的断言出现在已安装断言的列表里，我们还需要为断言添加一个特别的注释。&lt;/p&gt;

&lt;p&gt;此外，当我们执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl assert &amp;lt;assertion&amp;gt;&lt;/code&gt;命令并带着&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-h/--help&lt;/code&gt;参数时，为了能够打印输出针对该断言的帮助信息，我们还需要提前准备好相应的帮助信息。这些信息也是通过断言注释添加的。&lt;/p&gt;

&lt;p&gt;为断言添加的注释必须以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;##&lt;/code&gt;开头，并以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;##&lt;/code&gt;结尾，两者之间包含了若干个字段，每个字段的名字都是以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt;打头的。下面是一个注释模版，包含了每个字段的详细解释：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Name: &amp;lt;Input your single-line assertion name here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Description: &amp;lt;Input your single-line assertion description here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Usage: &amp;lt;Input your single-line assertion usage information here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Options:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &amp;lt;Input help information for all your options started from here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &amp;lt;It supports multiple lines&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Examples:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &amp;lt;Input detailed information for all examples started from here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &amp;lt;It supports multiple lines&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;对于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options&lt;/code&gt;字段，KubeAssert提供了几个预定义变量可供我们使用。如果我们的断言支持某些KubeAssert预定义的通用Option，那么在定义&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options&lt;/code&gt;字段时，我们就可以引用这些预定义变量作为占位符。在输出实际的帮助信息时，KubeAssert会把这些占位符替换成真正的内容。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;${GLOBAL_OPTIONS}：该变量代表了适用于所有断言的全局Option，比如：用于输出帮助信息的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-h/--help&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;${SELECT_OPTIONS}：该变量代表了用于对资源进行过滤的Option，比如：用于标签过滤的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l/--selector&lt;/code&gt;，以及用于指定namespace的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n/--namespace&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;${OP_VAL_OPTIONS}：该变量代表了比较运算符，例如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-eq&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-lt&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-gt&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ge&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-le&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;通过使用这些变量，我们可以确保所有断言的帮助信息里涉及这些Option的描述都是一致的。&lt;/p&gt;

&lt;p&gt;下面是针对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cluster&lt;/code&gt;断言的注释内容：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Name: cluster&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Description: Assert specified cluster included in kubeconfig&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Usage: kubectl assert cluster (NAME) [options]&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Options:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ${GLOBAL_OPTIONS}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Examples:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# # To assert a cluster is included in kubeconfig&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kubectl assert cluster kind-foo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;cluster &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
 ...
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;为了验证，我们可以执行如下命令，看一下我们的断言是否已经出现在已安装断言的列表中了：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果一切正常，我们会在返回结果中找到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cluster&lt;/code&gt;。执行如下命令，打印输出断言的帮助信息：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert cluster &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们会看到如下输出结果，这正是我们在注释里定义的内容：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Assert cluster with specified name included &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;kubeconfig file
Usage: kubectl assert cluster &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;NAME&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;options]
Options:
  &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;, &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;: Print the &lt;span class=&quot;nb&quot;&gt;help &lt;/span&gt;information.
  &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;, &lt;span class=&quot;nt&quot;&gt;--verbose&lt;/span&gt;: Enable the verbose log.
  &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt;, &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;: Print the version information.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;断言cluster的最终版本如下：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Name: cluster&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Description: Assert specified cluster included in kubeconfig&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Usage: kubectl assert cluster (NAME) [options]&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Options:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   ${GLOBAL_OPTIONS}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Examples:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   # To assert a cluster is included in kubeconfig&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   kubectl assert cluster kind-foo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;cluster &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Validate input arguments&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; logger::error &lt;span class=&quot;s2&quot;&gt;&quot;You must specify a cluster name.&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
  &lt;span class=&quot;c&quot;&gt;# Print assertion message&lt;/span&gt;
  logger::assert &lt;span class=&quot;s2&quot;&gt;&quot;Cluster with name &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; should be included in kubeconfig.&quot;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Run some kubectl commands&lt;/span&gt;
  kubectl config get-clusters
  &lt;span class=&quot;c&quot;&gt;# Validate results&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.kubeassert/result.txt | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; ^&lt;span class=&quot;nv&quot;&gt;$1$;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Print normal logs&lt;/span&gt;
    logger::info &lt;span class=&quot;s2&quot;&gt;&quot;Found &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in kubeconfig.&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Print failure message&lt;/span&gt;
    logger::fail &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; not found.&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如你所见，为KubeAssert定制断言是非常容易的。在下一篇文章里，我将和大家分享，如何把KubeAssert和&lt;a href=&quot;https://kuttl.dev/&quot;&gt;KUTTL&lt;/a&gt;集成在一起，让针对Kubernetes集群的自动化测试如虎添翼。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关KubeAssert的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/kubeassert/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/kubeassert&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><summary type="html">本文向大家介绍如何编写自己的断言来扩展KubeAssert的能力</summary></entry><entry><title type="html">高效使用KubeAssert</title><link href="https://morningspace.github.io/tech/kubeassert-2/" rel="alternate" type="text/html" title="高效使用KubeAssert" /><published>2021-06-26T00:00:00+08:00</published><updated>2021-06-26T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/kubeassert-2</id><content type="html" xml:base="https://morningspace.github.io/tech/kubeassert-2/">&lt;blockquote&gt;
  &lt;p&gt;KubeAssert是一个kubectl插件，用于在命令行声明针对Kubernetes资源的断言（assertion）。KubeAssert是一个位于&lt;a href=&quot;https://github.com/morningspace/kubeassert&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/kubeassert/kubeassert-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;作为KubeAssert系列文章的第二篇，本文将和大家分享一些有关KubeAssert使用的技巧。&lt;/p&gt;

&lt;h2 id=&quot;使用多个label及field-selector&quot;&gt;使用多个Label及Field Selector&lt;/h2&gt;

&lt;p&gt;当使用像&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exist&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not-exist&lt;/code&gt;这样的断言，对Kubernetes资源进行验证时，我们可以利用label selector或field selector对返回的查询结果进行过滤。例如，为了验证foo namespace下存在标签&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app&lt;/code&gt;值为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo&lt;/code&gt;的pod，且处于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Running&lt;/code&gt;状态，我们可以采用下面的断言，并同时指定label selector和field selector：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist pods &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; status.phase&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Running &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们还可以在同一个断言里根据需要同时指定多个label及field selector。例如，为了验证位于指定namespace下的处于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Running&lt;/code&gt;状态的pod同时满足多个标签及其取值，我们可以这样声明断言：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist pods &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;proxy &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; metadata.namespace&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;foo &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; status.phase&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Running &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--all-namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;或者，我们也可以用一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--field-selector&lt;/code&gt;参数后跟一个逗号分隔的列表，达到同样的效果。例如，下面的断言和之前的断言效果一样，但看起来更加紧凑：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist pods &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt;,component&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;proxy &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; metadata.namespace&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;foo,status.phase&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Running &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--all-namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;使用增强的field-selector&quot;&gt;使用增强的Field Selector&lt;/h2&gt;

&lt;p&gt;当使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exist&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not-exist&lt;/code&gt;断言对Kubernetes资源进行验证时，尽管我们可以通过指定field selector对查询结果进行过滤，但是这种field selector的功能是非常受限的。这是因为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exist&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not-exist&lt;/code&gt;在底层都是利用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl get&lt;/code&gt;来实现针对资源的查询的，并且它们都是直接用的由kubectl提供的原生&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--field-selector&lt;/code&gt;参数。但是根据Kubernetes官方文档，这种通过字段进行过滤的操作是在服务器端完成的，而且Kubernetes在服务器端根据资源类型的不同，只支持非常有限的字段查询能力。举个例子，当对pod声明断言时，我们可以使用field selector针对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;status&lt;/code&gt;下的某些字段进行过滤查询。但是同样的过滤条件对于deployment却不适用：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist deployments &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; status.replicas&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
ASSERT deployments matching label criteria &lt;span class=&quot;s1&quot;&gt;'app=echo'&lt;/span&gt; and field criteria &lt;span class=&quot;s1&quot;&gt;'status.replicas=1'&lt;/span&gt; should exist.
Error from server &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;BadRequest&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: Unable to find &lt;span class=&quot;s2&quot;&gt;&quot;extensions/v1beta1, Resource=deployments&quot;&lt;/span&gt; that match label selector &lt;span class=&quot;s2&quot;&gt;&quot;app=echo&quot;&lt;/span&gt;, field selector &lt;span class=&quot;s2&quot;&gt;&quot;status.replicas=1&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;status.replicas&quot;&lt;/span&gt; is not a known field selector: only &lt;span class=&quot;s2&quot;&gt;&quot;metadata.name&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;metadata.namespace&quot;&lt;/span&gt;
ASSERT FAIL Error getting resource&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;由于这个原因，KubeAssert提供了两个额外的断言，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exist-enhanced&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not-exist-enhanced&lt;/code&gt;，它们提供了和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exist&lt;/code&gt;以及&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not-exist&lt;/code&gt;同样的功能，但是对field selector做了增强。因此，我们可以将上述针对deployment的断言改写如下：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist-enhanced deployments &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; status.replicas&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
ASSERT deployments matching label criteria &lt;span class=&quot;s1&quot;&gt;'app=echo'&lt;/span&gt; and field criteria &lt;span class=&quot;s1&quot;&gt;'status.replicas=1'&lt;/span&gt; should exist.
INFO   Found 1 resource&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
NAME   NAMESPACE   COL0
&lt;span class=&quot;nb&quot;&gt;echo   &lt;/span&gt;default     1
ASSERT PASS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;原生的field selector支持&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt;，以及&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!=&lt;/code&gt;操作符，其中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt;含义相同。而经过增强的field selector除了支持这些操作符以外，甚至还支持正则表达式匹配符&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=~&lt;/code&gt;。这使得我们在定义field selector时变得更加灵活和强大。下面是几个例子：&lt;/p&gt;

&lt;p&gt;验证foo namespace下的service account是否包含指定的secret：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist-enhanced serviceaccounts &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'secrets[*].name=~my-secret'&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;验证某个custom resource的status下面，至少有一个condition，其type的取值为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Deployed&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist-enhanced MyResources &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'status.conditions[*].type=~Deployed'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;验证某个custom resource的所有实例名都是以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar&lt;/code&gt;，或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;baz&lt;/code&gt;打头的：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist-enhanced MyResource &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; metadata.name&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~&lt;span class=&quot;s1&quot;&gt;'foo.*|bar.*|baz.*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;验证pod的状态&quot;&gt;验证Pod的状态&lt;/h2&gt;

&lt;p&gt;尽管原则上我们可以利用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exist&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not-exist&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exist-enhanced&lt;/code&gt;，以及&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not-exist-enhanced&lt;/code&gt;对pod的状态进行验证，但是要在一条命令里用这些断言完成针对pod的某些验证是非常复杂的。&lt;/p&gt;

&lt;p&gt;为了方便起见，KubeAssert为我们提供了几个专门针对pod的断言，它们都是以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pod-&lt;/code&gt;打头的。用它们对pod的状态进行验证，可以变得更加高效：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pod-ready&lt;/code&gt;用于验证pod的就绪状态；&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pod-restarts&lt;/code&gt;用于验证pod的重启次数；&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pod-not-terminating&lt;/code&gt;用于验证pod是否处于terminating状态；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这里有几个例子。&lt;/p&gt;

&lt;p&gt;验证某个namespace下或所有namespace下的所有pod都处于就绪状态：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert pod-ready pods &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; foo
kubectl assert pod-ready pods &lt;span class=&quot;nt&quot;&gt;--all-namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;验证某个namespace下或所有namespace下都不存在任何处于terminating状态的pod：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert pod-not-terminating &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; foo
kubectl assert pod-not-terminating &lt;span class=&quot;nt&quot;&gt;--all-namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;验证某个namespace下或所有namespace下的pod，其重启次数都小于指定数值：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert pod-restarts &lt;span class=&quot;nt&quot;&gt;-lt&lt;/span&gt; 10 &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; foo
kubectl assert pod-restarts &lt;span class=&quot;nt&quot;&gt;-lt&lt;/span&gt; 10 &lt;span class=&quot;nt&quot;&gt;--all-namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;检查处于terminating状态的对象&quot;&gt;检查处于Terminating状态的对象&lt;/h2&gt;

&lt;p&gt;虽然&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pod-not-terminating&lt;/code&gt;可以被用来检查pod是否处于terminating状态，但并非只有pod才有可能遇到这种情况。如果想检查除pod以外的其他Kubernetes资源是否也存在这种情况，可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exist-enhanced&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not-exist-enhanced&lt;/code&gt;，或者编写自己的断言。&lt;/p&gt;

&lt;p&gt;例如，假如要判断某个custom resource在任何namespace下都不存在处于terminating状态的对象，我们可以检查它是否有元数据&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deletionTimestamp&lt;/code&gt;，且&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;status.phase&lt;/code&gt;字段为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Running&lt;/code&gt;。当一个资源被删除时，Kubernetes会自动为其加上&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deletionTimestamp&lt;/code&gt;元数据。如果一个资源被删除，但同时还保持运行状态，那它就很可能是一个陷入terminating状态的对象：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert not-exist-enhanced MyResources &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; metadata.deletionTimestamp!&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&amp;lt;none&amp;gt;'&lt;/span&gt;,status.phase&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;Running &lt;span class=&quot;nt&quot;&gt;--all-namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;再来看一个例子，为了判断集群里没有处于terminating状态的namespace，我们可以检查namespace是否同时具备&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deletionTimestamp&lt;/code&gt;元数据和finalizer。如果满足这一条件，就说明该namespace很有可能陷入了terminating状态，因为只要namespace有finalizer存在，Kubernetes就不会主动把它删除。&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert not-exist-enhanced namespace &lt;span class=&quot;nt&quot;&gt;--field-selector&lt;/span&gt; metadata.deletionTimestamp!&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&amp;lt;none&amp;gt;'&lt;/span&gt;,spec.finalizers[&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]!=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&amp;lt;none&amp;gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;如你所见，利用各种不同的断言以及相应的参数组合，我们可以非常灵活的对Kubernetes资源进行检验。在下一篇文章里，我将和大家分享，当现有断言无法满足需求的时候，如何通过编写自己的断言来扩展KubeAssert的能力。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关KubeAssert的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/kubeassert/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/kubeassert&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><summary type="html">本文将和大家分享一些有关KubeAssert使用的技巧</summary></entry><entry><title type="html">KubeAssert快速入门</title><link href="https://morningspace.github.io/tech/kubeassert-1/" rel="alternate" type="text/html" title="KubeAssert快速入门" /><published>2021-06-19T00:00:00+08:00</published><updated>2021-06-19T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/kubeassert-1</id><content type="html" xml:base="https://morningspace.github.io/tech/kubeassert-1/">&lt;blockquote&gt;
  &lt;p&gt;KubeAssert是一个kubectl插件，用于在命令行声明针对Kubernetes资源的断言（assertion）。KubeAssert是一个位于&lt;a href=&quot;https://github.com/morningspace/kubeassert&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/kubeassert/kubeassert-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;作为KubeAssert系列文章的第一篇，本文将告诉你什么是KubeAssert，如何安装并运行KubeAssert。&lt;/p&gt;

&lt;h2 id=&quot;什么是kubeassert&quot;&gt;什么是KubeAssert&lt;/h2&gt;

&lt;p&gt;KubeAssert是一个kubectl插件，它提供了一组断言（assertion），可以用于在命令行对Kubernetes资源进行判断。利用KubeAssert，可以帮助我们检查和分析Kubernetes集群的状态，集群中资源的部署情况。例如，我们可以通过KubeAssert来判断：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;某个资源是否存在于当前集群中；&lt;/li&gt;
  &lt;li&gt;某个资源的状态是否满足指定条件；&lt;/li&gt;
  &lt;li&gt;某个资源的实例数是否小于或等于指定数值；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;使用KubeAssert声明针对Kubernetes资源的断言和我们在代码里用xUnit编写单元测试中的断言非常类似。将这样的一组断言放到一个脚本文件里，可以作为针对Kubernetes集群的自动化测试的一部分，和CI/CD pipeline进行集成。&lt;/p&gt;

&lt;h2 id=&quot;安装kubeassert&quot;&gt;安装KubeAssert&lt;/h2&gt;

&lt;p&gt;由于KubeAssert本质上是由脚本实现的，所以它可以作为一个独立的命令在命令行执行。但同时，它也可以被安装成一个kubectl插件，这样我们就可以像执行普通的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl &amp;lt;command&amp;gt;&lt;/code&gt;命令那样执行KubeAssert了。&lt;/p&gt;

&lt;p&gt;KubeAssert目前已被提交至&lt;a href=&quot;https://krew.sigs.k8s.io/&quot;&gt;krew&lt;/a&gt;。作为Kubernetes社区官方的kubectl插件管理工具，krew提供了&lt;a href=&quot;https://sigs.k8s.io/krew-index&quot;&gt;krew-index&lt;/a&gt;，用于在社区范围内集中发布与分享kubectl插件。因此，安装KubeAssert最简单的方式就是使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;krew&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;krew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;assert
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果没有安装krew，也没关系。我们可以从GitHub库将其下载到本地，并将文件设置为可执行：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; https://raw.githubusercontent.com/morningspace/kubeassert/master/kubectl-assert.sh &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; kubectl-assert
&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x kubectl-assert
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;把脚本文件放到任何&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;环境变量能够找到的地方，比如：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mv&lt;/span&gt; ./kubectl-assert /usr/local/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后，我们就可以像执行普通的kubectl命令那样调用KubeAssert了：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;执行上述命令，将会返回KubeAssert的帮助信息，以及一个KubeAssert当前支持的断言清单。如果在执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl assert&lt;/code&gt;命令时指定了断言的名字以及&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--help&lt;/code&gt;参数，就会得到更多有关雨如何使用相应断言的详细信息。例如：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;使用kubeassert&quot;&gt;使用KubeAssert&lt;/h2&gt;

&lt;p&gt;以下给出的是目前为止KubeAssert默认提供的所有断言：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Assertion&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;exist&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Assert resource should exist.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;not-exist&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Assert resource should not exist.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;exist-enhanced&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Assert resource should exist using enhanced field selector.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;not-exist-enhanced&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Assert resource should not exist using enhanced field selector.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;num&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Assert the number of resource should match specified criteria.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;pod-ready&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Assert pod should be ready.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;pod-not-terminating&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Assert pod should not keep terminating.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;pod-restarts&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Assert pod restarts should match specified criteria.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;apiservice-available&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Assert API service should be available.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;这里给出了一些例子，演示了如何利用这些断言来帮助我们对Kubernetes集群中的资源进行检查。&lt;/p&gt;

&lt;p&gt;检查foo namespace下是否存在任何满足标签&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app&lt;/code&gt;取值为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo&lt;/code&gt;的pod：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert exist pods -l app=echo -n foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;检查是否所有namespace下的pod都处于就绪（ready）状态：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert pod-ready --all-namespaces
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;检查pod的重启次数小于指定数值：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl assert restarts pods -n foo -lt 10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;如你所见，KubeAssert的使用非常简单。在下一篇文章里，我将和大家分享更多有关KubeAssert使用的技巧。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关KubeAssert的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/kubeassert/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/kubeassert&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><summary type="html">本文将告诉你什么是KubeAssert，如何安装并运行KubeAssert</summary></entry><entry><title type="html">编写自己的Kube Macro</title><link href="https://morningspace.github.io/tech/kubemacro-3/" rel="alternate" type="text/html" title="编写自己的Kube Macro" /><published>2021-06-12T00:00:00+08:00</published><updated>2021-06-12T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/kubemacro-3</id><content type="html" xml:base="https://morningspace.github.io/tech/kubemacro-3/">&lt;blockquote&gt;
  &lt;p&gt;KubeMacro是一个kubectl插件，它用于把一组针对于kubectl命令或Kubernetes API的调用封装成一个命令，以便于在命令行多次执行。KubeMacro是一个位于&lt;a href=&quot;https://github.com/morningspace/kubemacro&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/kubemacro/kubemacro-3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;作为KubeMacro系列的第三篇文章，本文将向大家介绍如何编写一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kube macro&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&quot;自己动手写macro&quot;&gt;自己动手写Macro&lt;/h2&gt;

&lt;p&gt;KubeMacro本质上是一个kube macro的执行器。默认情况下，它并不绑定任何预定义的macro。我们可以通过访问 &lt;a href=&quot;https://morningspace.github.io/kubemacro-hub/&quot;&gt;KubeMacro Hub&lt;/a&gt; 网站浏览并安装由他人开发的kube macro。&lt;/p&gt;

&lt;p&gt;如果现有的macro无法满足需求，你也可以编写属于你自己的macro。本文里，我将带着大家一步一步编写出一个macro，用于打印一组pod及其所包含的容器。此外，也非常欢迎大家把自己开发的macro提交到KubeMacro Hub，这样其他人也可以从中获益。&lt;/p&gt;

&lt;h2 id=&quot;创建shell脚本文件&quot;&gt;创建Shell脚本文件&lt;/h2&gt;

&lt;p&gt;首先，让我们创建一个shell脚本文件，取名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get-pod-containers.sh&lt;/code&gt;，并将它放到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.kubemacro&lt;/code&gt;目录下。这里是KubeMacro加载所有macro的地方。每当KubeMacro启动时，它会寻找该目录下的所有&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sh&lt;/code&gt;文件，并作为macro加载到内存。&lt;/p&gt;

&lt;p&gt;在这个脚本文件里，我们是通过一个shell函数来实现macro的逻辑的。在我们的例子里，这个函数的名字是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get-pod-containers&lt;/code&gt;，目前函数体还是空的：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;get-pod-containers &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
 :
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;为了测试这个macro，我们可以调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl macro&lt;/code&gt;命令，并指定函数名&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get-pod-containers&lt;/code&gt;作为该macro的名字：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl macro get-pod-containers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;正常情况下，我们会看到命令能够正确返回，只是返回结果是空的。接下来，让我们为函数加入具体的实现逻辑。&lt;/p&gt;

&lt;h2 id=&quot;实现macro的逻辑&quot;&gt;实现Macro的逻辑&lt;/h2&gt;

&lt;p&gt;将下列逻辑加入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get-pod-containers&lt;/code&gt;函数：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;get-pod-containers &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=()&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Parse the arguments input from command line&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$# &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-gt&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    case&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;ns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;
      args+&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;shift
      shift&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--all-namespaces&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;ns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;all namespaces&quot;&lt;/span&gt;
      args+&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;shift&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      args+&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;shift&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Run kubectl get and define custom columns to include pod container names&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;custom_columns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;NAME:.metadata.name,CONTAINERS:.spec.containers[*].name&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;all namespaces&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;custom_columns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;NAMESPACE:.metadata.namespace,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$custom_columns&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi
  &lt;/span&gt;kubectl get pods &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; custom-columns&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$custom_columns&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;大体而言，上述函数做了两件事情：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;解析从命令行传入的输入参数。&lt;/li&gt;
  &lt;li&gt;执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl get&lt;/code&gt;命令，并定制了输出列，通过指定JSONPath，把从pod定义中解析得到的容器名显示输出。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;现在，让我们再次执行该macro。这一次我们会看到，命令会把所有位于当前namespace下的pod及其容器都返回回来：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl macro get-pod-containers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;为macro添加注释&quot;&gt;为Macro添加注释&lt;/h2&gt;

&lt;p&gt;到目前为止，我们已经实现了macro的全部逻辑。是不是很简单啊？不过，还有一件事情我们需要做。当执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl macro&lt;/code&gt;并带着&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-h/--help&lt;/code&gt;参数或者不带任何参数时，为了能够让我们的macro出现在已安装macro的列表里，我们还需要为macro添加一个特别的注释。&lt;/p&gt;

&lt;p&gt;此外，当我们执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl macro &amp;lt;macro&amp;gt;&lt;/code&gt;命令并带着&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-h/--help&lt;/code&gt;参数时，为了能够打印输出针对该macro的帮助信息，我们还需要提前准备好相应的帮助信息。这些信息也是通过macro注释添加的。&lt;/p&gt;

&lt;p&gt;不仅如此，如果你希望通过KubeMacro Hub把自己的macro分享给其他人，为macro定义更为详细的描述说明与使用方法同样也必须通过这个macro注释来实现。&lt;/p&gt;

&lt;p&gt;为macro添加的注释必须以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;##&lt;/code&gt;开头，并以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;##&lt;/code&gt;结尾，两者之间包含了若干个字段，每个字段的名字都是以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt;打头的。下面是一个注释模版，包含了每个字段的详细解释：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Name: &amp;lt;Input your single-line macro name here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Description: &amp;lt;Input your single-line macro description here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &amp;lt;Input detailed description for your macro started from here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &amp;lt;It supports multiple lines and markdown syntax&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Author: &amp;lt;Input single-line author name here, support markdown syntax&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Usage: &amp;lt;Input your single-line macro usage information here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Options:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   &amp;lt;Input help information for all your options started from here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   &amp;lt;It supports multiple lines&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Examples:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   &amp;lt;Input detailed information for all examples started from here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   &amp;lt;It supports multiple lines&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Dependencies: &amp;lt;Input single-line comma-separated dependencies of your macro here&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;下面是针对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get-pod-containers&lt;/code&gt;的注释内容：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Name: get-pod-containers&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Description: List the pods with their containers.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# This is a sample macro to demonstrate how to write a macro by your own.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# It can be used to list pods and their containers. For example, to list&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# all pods and their containers in `kube-system` namespace:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ```shell&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kubectl macro get-pod-containers -n kube-system&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# NAME                                         CONTAINERS&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# coredns-6955765f44-gtx2q                     coredns&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# coredns-6955765f44-tz96m                     coredns&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# etcd-kind-control-plane                      etcd&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kindnet-4pzm7                                kindnet-cni&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kube-apiserver-kind-control-plane            kube-apiserver&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kube-controller-manager-kind-control-plane   kube-controller-manager&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kube-proxy-b6wn8                             kube-proxy&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kube-scheduler-kind-control-plane            kube-scheduler&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ```&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Author: [morningspace](https://github.com/morningspace/)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Usage: kubectl macro get-pod-containers [options]&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Options:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   -A, --all-namespaces=false: If present, list the requested object(s) across all namespaces. Namespace in current&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   context is ignored even if specified with --namespace.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   -h, --help: Print the help information.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   -n, --namespace='': If present, the namespace scope for this CLI request.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   -l, --selector='': Selector (label query) to filter on, not including uninitialized ones.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#       --version: Print the version information.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   -w, --watch=false: After listing/getting the requested object, watch for changes. Uninitialized objects are excluded&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   if no object name is provided.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#       --watch-only=false: Watch for changes to the requested object(s), without listing/getting first.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Examples:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   # To list all pods with their containers in a namespace.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   kubectl macro get-pod-containers -n foo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   # To list all pods with their containers in all namespaces.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   kubectl macro get-pod-containers -A&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# @Dependencies: kubectl&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;cluster &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  ...
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;为了验证，我们可以执行如下命令，看一下我们的macro是否已经出现在已安装macro的列表中了：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl macro &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果一切正常，我们会在返回结果中找到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get-pod-containers&lt;/code&gt;。执行如下命令，打印输出macro的帮助信息：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl macro get-pod-containers &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们会看到如下输出结果，这正是我们在注释里定义的内容：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;get-pod-containers: List the pods with their containers.
Usage: kubectl macro get-pod-containers [options]
Options:
  -A, --all-namespaces=false: If present, list the requested object(s) across all namespaces. Namespace in current
  context is ignored even if specified with --namespace.
  -h, --help: Print the help information.
  -n, --namespace='': If present, the namespace scope for this CLI request.
  -l, --selector='': Selector (label query) to filter on, not including uninitialized ones.
      --version: Print the version information.
  -w, --watch=false: After listing/getting the requested object, watch for changes. Uninitialized objects are excluded
  if no object name is provided.
      --watch-only=false: Watch for changes to the requested object(s), without listing/getting first.
Examples:
  # To list all pods with their containers in a namespace.
  kubectl macro get-pod-containers -n foo
  # To list all pods with their containers in all namespaces.
  kubectl macro get-pod-containers -A
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;关于macro的依赖&quot;&gt;关于Macro的依赖&lt;/h2&gt;

&lt;p&gt;也许你已经注意到了，在前面的macro注释里有一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Dependencies&lt;/code&gt;字段。一个macro可能会包含多个依赖。比如，有的macro需要用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jq&lt;/code&gt;命令来解析JSON数据，有的macro则依赖于其他macro来共同完成一项任务。为了成功执行一个macro，需要确保其所依赖的部分已经事先安装好了。&lt;/p&gt;

&lt;p&gt;当编写一个macro的时候，我们可以根据需要为macro定义它的依赖。每当KubeMacro执行一个macro时，它首先会检查该macro是否存在任何依赖。如果有的话，KubeMacro会检查这些依赖是否已存在。如果不存在，则会报错。&lt;/p&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;get-pod-containers的最终版本可以从&lt;a href=&quot;https://github.com/morningspace/kubemacro/blob/main/docs/assets/get-pod-containers.sh&quot;&gt;这里&lt;/a&gt;找到。至此，我们可以看到，编写一个kube macro是非常容易的。如果你发现现有macro都不能满足你的需求时，那就自己动手写一个吧。你还可以以pull request的形式把macro提交到KubeMacro Hub的&lt;a href=&quot;http://github.com/morningspace/kubemacro-hub&quot;&gt;GitHub库&lt;/a&gt;。一旦被成功合并，其他人也能从中获益。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关KubeMacro的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/kubemacro/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/kubemacro&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><summary type="html">本文将向大家介绍如何编写一个`kube macro`</summary></entry><entry><title type="html">KubeMacro Hub：寻找你的Kube Macro</title><link href="https://morningspace.github.io/tech/kubemacro-2/" rel="alternate" type="text/html" title="KubeMacro Hub：寻找你的Kube Macro" /><published>2021-06-05T00:00:00+08:00</published><updated>2021-06-05T00:00:00+08:00</updated><id>https://morningspace.github.io/tech/kubemacro-2</id><content type="html" xml:base="https://morningspace.github.io/tech/kubemacro-2/">&lt;blockquote&gt;
  &lt;p&gt;KubeMacro是一个kubectl插件，它用于把一组针对于kubectl命令或Kubernetes API的调用封装成一个命令，以便于在命令行多次执行。KubeMacro是一个位于&lt;a href=&quot;https://github.com/morningspace/kubemacro&quot;&gt;GitHub&lt;/a&gt;上的开源项目。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/studio/kubemacro/kubemacro-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;作为KubeMacro系列的第二篇文章，本文首先将会向大家介绍KubeMacro Hub，一个用于发布和分享kube macro的网站，然后介绍几个通过该网站发布的，非常有意思的macro，以及它们的使用方法。&lt;/p&gt;

&lt;h2 id=&quot;什么是kubemacro-hub&quot;&gt;什么是KubeMacro Hub&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://morningspace.github.io/kubemacro-hub/&quot;&gt;KubeMacro Hub&lt;/a&gt;就像是一个kube macro的“集散地”，它为人们在社区范围内发布和分享kube macro提供了一个集中的场所。你可以在这里浏览由别人开发的macro，也可以把你自己开发的macro通过KubeMacro Hub分享给别人，以便让大家都能够从中获益。&lt;/p&gt;

&lt;p&gt;如果你想把自己的macro贡献给社区，只需要向KubeMacro Hub的&lt;a href=&quot;https://github.com/morningspace/kubemacro-hub&quot;&gt;GitHub库&lt;/a&gt;提交一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pull request&lt;/code&gt;。一旦代码被合并，大约几秒钟之后，你的macro就可以出现在KubeMacro Hub的网站上了。在这一系列的后续文章里，我将向大家详细介绍如何编写一个kube macro。&lt;/p&gt;

&lt;h2 id=&quot;浏览kubemacro-hub&quot;&gt;浏览KubeMacro Hub&lt;/h2&gt;

&lt;p&gt;既然你已经了解了KubeMacro Hub的作用，接下来让我们一起看一下如何浏览KubeMacro Hub网站及其所提供的那些kube macro。&lt;/p&gt;

&lt;p&gt;首先让我们打开 &lt;a href=&quot;https://morningspace.github.io/kubemacro-hub/&quot;&gt;KubeMacro Hub&lt;/a&gt; 网站，我们可以看到在网站页面的左侧有一个macro的列表，点击其中任意一个macro，会在网页右侧打开该macro的对应详情页面。此外，网页左上方还有一个搜索框，我们可以在里面输入关键词，然后在下方的搜索结果里寻找想要的macro。点击对应的搜索结果，同样会打开macro的详情页面。在macro详情页面的顶部，我们会看到该macro的名称和一个简短的描述。&lt;/p&gt;

&lt;p&gt;除此以外，下方还有几个标签页：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;标签页&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Description&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;提供了有关该macro的详细说明，比如：用途，用法等。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Usage &amp;amp; Options&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;提供了该macro的调用格式，以及所支持的命令行参数。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Examples&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;列举了该macro的一些使用范例，可以供我们在实际使用时参考。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dependencies&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;列举了该macro在执行过程中需要的所有依赖。为了保证macro的正常执行，这些依赖必须事先安装好。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Code&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;给出了该macro的源代码，我们可以通过阅读代码来了解该macro的工作原理。同时，这个标签页上还有如何安装该macro的说明文字。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;如你所见，浏览KubeMacro Hub上的kube macro非常简单，只需在列表里选择你想要的macro，然后阅读详情页面的使用说明，比如了解它的用途，用法，支持的参数，以及参考示例等。最后，下载该macro，或者直接复制粘贴源代码到本地，就大功告成了。&lt;/p&gt;

&lt;p&gt;接下来，我将向大家介绍几个KubeMacro Hub上发布的，非常意思的macro，并演示它们的使用方法。&lt;/p&gt;

&lt;h2 id=&quot;macro-delete-pod-by-svc&quot;&gt;Macro: delete-pod-by-svc&lt;/h2&gt;

&lt;p&gt;该macro可以用来删除所有和某个Kubernetes service相关联的pod。当我们遇到某些service由于其背后的pod出现故障而无法正常工作的时候，就可以使用这个macro。通过删除这些pod，它能强制触发pod的重启。&lt;/p&gt;

&lt;p&gt;众所周知，Kubernetes service的实际功能是由pod来实现的。要找到与service相关联的pod，我们需要查看service的定义，找到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spec.selector&lt;/code&gt;字段。让我们以下面这个service为例：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl get svc prometheus-adapter &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; openshift-monitoring &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;从service定义的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spec.selector&lt;/code&gt;字段中获知，与该service相关联的pod应该具备&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prometheus-adapter&lt;/code&gt;标签：&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;prometheus-adapter&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;openshift-monitoring&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;clusterIP&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;172.30.179.161&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;443&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TCP&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;6443&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;prometheus-adapter&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;sessionAffinity&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;None&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ClusterIP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们可以列出所有满足这一条件的pod，然后决定是否要删除这些pod：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl get pod &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;prometheus-adapter  &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; openshift-monitoring
NAME                                  READY   STATUS    RESTARTS   AGE
prometheus-adapter-6856976f54-42jzh   0/1     Pending   0          3d
prometheus-adapter-6856976f54-d428c   0/1     Pending   0          3d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;每当我们遇到需要重启pod的时候，手工完成上述步骤会非常的繁琐。这个macro的作用就是为了把这一过程完全自动化，我们只需要告诉它service的名字就行了。此外，删除pod的时候，我们还可以指定额外的参数对删除行为进行控制，比如：指定&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--force&lt;/code&gt;参数实现强制删除，指定&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dry-run&lt;/code&gt;参数实现“dry run”模式下的删除，以便在我们真正决定删除之前做一些检查。&lt;/p&gt;

&lt;p&gt;下面是几个实际使用该macro的例子，供大家参考：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# To delete pods associated with a service.&lt;/span&gt;
kubectl macro delete-pod-by-svc &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; foo
&lt;span class=&quot;c&quot;&gt;# To force delete pods associated with a service.&lt;/span&gt;
kubectl macro delete-pod-by-svc &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--force&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# To delete pods associated with a service in dry run mode.&lt;/span&gt;
kubectl macro delete-pod-by-svc &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--dry-run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;macro-get-by-owner-ref&quot;&gt;Macro: get-by-owner-ref&lt;/h2&gt;

&lt;p&gt;该macro通过遍历Kubernetes资源的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadata.ownerReferences&lt;/code&gt;字段，可以用来列举某个namespace下的一个或多个资源及其祖先。&lt;/p&gt;

&lt;p&gt;我们知道，在Kubernetes里一些资源和另一些资源存在着从属关系。比如，一组pod可能从属于某个ReplicaSet。ReplicaSet就是pod的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;owner&lt;/code&gt;，而pod则被称为ReplicaSet的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dependent&lt;/code&gt;。每个dependent对象，都有一个字段，名字叫做&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadata.ownerReferences&lt;/code&gt;，它指向了对应的owner对象。&lt;/p&gt;

&lt;p&gt;利用该macro，当我们手里有一个或多个资源时，可以通过它来揭示这些资源及其祖先资源的从属关系。其输出结果是以树状形式呈现的。例如，要列举名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo-5ffc7f444f-pj5xj&lt;/code&gt;的pod及其祖先，可以执行如下命令：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl macro get-by-owner-ref pod echo-5ffc7f444f-pj5xj &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; foo
pod/echo-5ffc7f444f-pj5xj
└──ReplicaSet/echo-5ffc7f444f
   └──Deployment/echoCopy to clipboardErrorCopied
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;由于该macro背后是通过对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl get&lt;/code&gt;的调用来实现的，所以我们还可以指定某些&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl get&lt;/code&gt;所支持的参数，从而实现对返回结果的定制。例如，为了展示所有具备指定标签的pod及其从属关系，可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l&lt;/code&gt;参数：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl macro get-by-owner-ref pod &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'app=echo'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上述命令可以打印出所有标签&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app&lt;/code&gt;为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo&lt;/code&gt;的pod及其祖先。&lt;/p&gt;

&lt;p&gt;我们甚至还可以列举某个namespace下的所有pod资源及其祖先，例如：&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl macro get-by-owner-ref pods &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上述命令可以打印出foo namespace下的所有pod及其祖先。&lt;/p&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;通过本文，我们了解了如何访问KubeMacro Hub网站，浏览并安装相应的kube macro。同时，我们还学习了几个KubeMacro Hub上发布的，非常有意思的macro。欢迎大家访问 &lt;a href=&quot;https://morningspace.github.io/kubemacro-hub/&quot;&gt;KubeMacro Hub&lt;/a&gt; 网站，看看上面是否有你所感兴趣的macro。如果没有任何一个macro能满足你的需求，也没关系，你可以选择开发自己的macro，然后提交给KubeMacro Hub在GitHub上的&lt;a href=&quot;http://github.com/morningspace/kubemacro-hub/&quot;&gt;代码库&lt;/a&gt;。在下一篇文章里，我将向大家介绍如何编写自己的kube macro。&lt;/p&gt;

&lt;p&gt;如果你想了解更多有关KubeMacro的信息，请阅读它的&lt;a href=&quot;https://morningspace.github.io/kubemacro/docs/&quot;&gt;在线文档&lt;/a&gt;。如果你喜欢这个项目，欢迎给它&lt;a href=&quot;https://github.com/morningspace/kubemacro&quot;&gt;加星&lt;/a&gt;。同时，也非常欢迎针对该项目的任何形式的贡献，比如bug报告以及代码提交。&lt;/p&gt;</content><author><name>MornigSpace</name><email>morningspace@yahoo.com</email><uri>https://morningspace.github.io</uri></author><category term="tech" /><category term="kubernetes" /><summary type="html">本文将向大家介绍KubeMacro Hub网站，以及通过该网站发布的几个有趣的macro</summary></entry></feed>