为什么 Kubernetes 很酷
============================================================

在我刚开始学习 Kubernetes（大约是一年半以前吧？）时，我真的不明白为什么应该去关注它。

在我使用 Kubernetes 全职工作了三个多月后，我才逐渐明白了为什么我应该使用它。（我距离成为一个 Kubernetes 专家还很远！）希望这篇文章对你理解 Kubernetes 能做什么会有帮助！

我将尝试去解释我对 Kubernetes 感兴趣的一些原因，而不去使用 “<ruby>原生云<rt>cloud native</rt></ruby>”、“<ruby>编排系统<rt>orchestration</rt></ruby>”、“<ruby>容器<rt>container</rt></ruby>”，或者任何 Kubernetes 专用的术语 :)。我去解释的这些观点主要来自一位 Kubernetes 操作者/基础设施工程师，因为，我现在的工作就是去配置 Kubernetes 和让它工作的更好。

我不会去尝试解决一些如 “你应该在你的生产系统中使用 Kubernetes 吗？”这样的问题。那是非常复杂的问题。（不仅是因为“生产系统”根据你的用途而总是有不同的要求）

### Kubernetes 可以让你无需设置一台新的服务器即可在生产系统中运行代码

我首次被说教使用 Kubernetes 是与我的伙伴 Kamal 的下面的谈话：

大致是这样的：

*   Kamal： 使用 Kubernetes 你可以通过一条命令就能设置一台新的服务器。
*   Julia： 我觉得不太可能吧。
*   Kamal： 像这样，你写一个配置文件，然后应用它，这时候，你就在生产系统中运行了一个 HTTP 服务。
*   Julia： 但是，现在我需要去创建一个新的 AWS 实例，明确地写一个 Puppet 清单，设置服务发现，配置负载均衡，配置我们的部署软件，并且确保 DNS 正常工作，如果没有什么问题的话，至少在 4 小时后才能投入使用。
*   Kamal: 是的，使用 Kubernetes 你不需要做那么多事情，你可以在 5 分钟内设置一台新的 HTTP 服务，并且它将自动运行。只要你的集群中有空闲的资源它就能正常工作！
*   Julia: 这儿一定是一个“坑”。

这里有一种陷阱，设置一个生产用 Kubernetes 集群（在我的经险中）确实并不容易。（查看 [Kubernetes 艰难之旅][3] 中去开始使用时有哪些复杂的东西）但是，我们现在并不深入讨论它。

因此，Kubernetes 第一个很酷的事情是，它可能使那些想在生产系统中部署新开发的软件的方式变得更容易。那是很酷的事，而且它真的是这样，因此，一旦你使用一个运作中的 Kubernetes 集群，你真的可以仅使用一个配置文件就在生产系统中设置一台 HTTP 服务（在 5 分钟内运行这个应用程序，设置一个负载均衡，给它一个 DNS 名字，等等）。看起来真的很有趣。

### 对于运行在生产系统中的代码，Kubernetes 可以提供更好的可见性和可管理性

在我看来，在理解 etcd 之前，你可能不会理解 Kubernetes 的。因此，让我们先讨论 etcd！

想像一下，如果现在我这样问你，“告诉我你运行在生产系统中的每个应用程序，它运行在哪台主机上？它是否状态很好？是否为它分配了一个 DNS 名字？”我并不知道这些，但是，我可能需要到很多不同的地方去查询来回答这些问题，并且，我需要花很长的时间才能搞定。我现在可以很确定地说不需要查询，仅一个 API 就可以搞定它们。

在 Kubernetes 中，你的集群的所有状态 – 运行中的应用程序 (“pod”)、节点、DNS 名字、 cron 任务、 等等 —— 都保存在一个单一的数据库中（etcd）。每个 Kubernetes 组件是无状态的，并且基本是通过下列方式工作的：

*   从 etcd 中读取状态（比如，“分配给节点 1 的 pod 列表”）
*   产生变化（比如，“在节点 1 上运行 pod A”）
*   更新 etcd 中的状态（比如，“设置 pod A 的状态为 ‘running’”）

这意味着，如果你想去回答诸如 “在那个可用区中有多少台运行着 nginx 的 pod？” 这样的问题时，你可以通过查询一个统一的 API（Kubernetes API）去回答它。并且，你可以在每个其它 Kubernetes 组件上运行那个 API 去进行同样的访问。

这也意味着，你可以很容易地去管理每个运行在 Kubernetes 中的任何东西。比如说，如果你想要：

*   部署实现一个复杂的定制的部署策略（部署一个东西，等待 2 分钟，部署 5 个以上，等待 3.7 分钟，等等）
*   每当推送到 github 上一个分支，自动化 [启动一个新的 web 服务器][1]
*   监视所有你的运行的应用程序，确保它们有一个合理的内存使用限制。

这些你只需要写一个程序与 Kubernetes API（“controller”）通讯就可以了。

另一个关于 Kubernetes API 的令人激动的事情是，你不会局限于 Kubernetes 所提供的现有功能！如果对于你要部署/创建/监视的软件有你自己的方案，那么，你可以使用 Kubernetes API 去写一些代码去达到你的目的！它可以让你做到你想做的任何事情。

### 即便每个 Kubernetes 组件都“挂了”，你的代码将仍然保持运行

关于 Kubernetes 我（在各种博客文章中 :)）承诺的一件事情是，“如果 Kubernetes API 服务和其它组件‘挂了’也没事，你的代码将一直保持运行状态”。我认为理论上这听起来很酷，但是我不确定它是否真是这样的。

到目前为止，这似乎是真的！

我已经断开了一些正在运行的 etcd，发生了这些情况：

1.  所有的代码继续保持运行状态
2.  不能做 _新的_ 事情（你不能部署新的代码或者生成变更，cron 作业将停止工作）
3.  当它恢复时，集群将赶上这期间它错过的内容

这样做意味着如果 etcd 宕掉，并且你的应用程序的其中之一崩溃或者发生其它事情，在 etcd 恢复之前，它不能够恢复。

### Kubernetes 的设计对 bug 很有弹性

与任何软件一样，Kubernetes 也会有 bug。例如，到目前为止，我们的集群控制管理器有内存泄漏，并且，调度器经常崩溃。bug 当然不好，但是，我发现 Kubernetes 的设计可以帮助减轻它的许多核心组件中的错误的影响。

如果你重启动任何组件，将会发生：

*   从 etcd 中读取所有的与它相关的状态
*   基于那些状态（调度 pod、回收完成的 pod、调度 cron 作业、按需部署等等），它会去做那些它认为必须要做的事情

因为，所有的组件并不会在内存中保持状态，你在任何时候都可以重启它们，这可以帮助你减轻各种 bug 的影响。

例如，如果在你的控制管理器中有内存泄露。因为，控制管理器是无状态的，你可以每小时定期去重启它，或者，在感觉到可能导致任何不一致的问题发生时重启它。又或者，在调度器中遇到了一个 bug，它有时忘记了某个 pod，从来不去调度它们。你可以每隔 10 分钟来重启调度器来缓减这种情况。（我们并不会这么做，而是去修复这个 bug，但是，你_可以这样做_ :））

因此，我觉得即使在它的核心组件中有 bug，我仍然可以信任 Kubernetes 的设计可以让我确保集群状态的一致性。并且，总在来说，随着时间的推移软件质量会提高。唯一你必须去操作的有状态的东西就是 etcd。

不用过多地讨论“状态”这个东西 —— 而我认为在 Kubernetes 中很酷的一件事情是，唯一需要去做备份/恢复计划的东西是 etcd （除非为你的 pod 使用了持久化存储的卷）。我认为这样可以使 Kubernetes 运维比你想的更容易一些。

### 在 Kubernetes 之上实现新的分布式系统是非常容易的

假设你想去实现一个分布式 cron 作业调度系统！从零开始做工作量非常大。但是，在 Kubernetes 里面实现一个分布式 cron 作业调度系统是非常容易的！（仍然没那么简单，毕竟它是一个分布式系统）

我第一次读到 Kubernetes 的 cron 作业控制器的代码时，我对它是如此的简单感到由衷高兴。去读读看，其主要的逻辑大约是 400 行的 Go 代码。去读它吧！ => [cronjob_controller.go][4] <=

cron 作业控制器基本上做的是：

*   每 10 秒钟：
    *   列出所有已存在的 cron 作业
    *   检查是否有需要现在去运行的任务
    *   如果有，创建一个新的作业对象去调度，并通过其它的 Kubernetes 控制器实际运行它
    *   清理已完成的作业
    *   重复以上工作

Kubernetes 模型是很受限制的（它有定义在 etcd 中的资源模式，控制器读取这个资源并更新 etcd），我认为这种相关的固有的/受限制的模型，可以使它更容易地在 Kubernetes 框架中开发你自己的分布式系统。

Kamal 给我说的是 “Kubernetes 是一个写你自己的分布式系统的很好的平台” ，而不是“ Kubernetes 是一个你可以使用的分布式系统”，并且，我觉得它真的很有意思。他做了一个 [为你推送到 GitHub 的每个分支运行一个 HTTP 服务的系统][5] 的原型。这花了他一个周末的时间，大约 800 行 Go 代码，我认为它真不可思议！

### Kubernetes 可以使你做一些非常神奇的事情（但并不容易）

我一开始就说 “kubernetes 可以让你做一些很神奇的事情，你可以用一个配置文件来做这么多的基础设施，它太神奇了”。这是真的！

为什么说 “Kubernetes 并不容易”呢？是因为 Kubernetes 有很多部分，学习怎么去成功地运营一个高可用的 Kubernetes 集群要做很多的工作。就像我发现它给我了许多抽象的东西，我需要去理解这些抽象的东西才能调试问题和正确地配置它们。我喜欢学习新东西，因此，它并不会使我发狂或者生气，但是我认为了解这一点很重要 :）

对于 “我不能仅依靠抽象概念” 的一个具体的例子是，我努力学习了许多 [Linux 上网络是如何工作的][6]，才让我对设置 Kubernetes 网络稍有信心，这比我以前学过的关于网络的知识要多很多。这种方式很有意思但是非常费时间。在以后的某个时间，我或许写更多的关于设置 Kubernetes 网络的困难/有趣的事情。

或者，为了成功设置我的 Kubernetes CA，我写了一篇 [2000 字的博客文章][7]，述及了我不得不学习 Kubernetes 不同方式的 CA 的各种细节。

我觉得，像 GKE （Google 的 Kubernetes 产品) 这样的一些监管的 Kubernetes 的系统可能更简单，因为，他们为你做了许多的决定，但是，我没有尝试过它们。

--------------------------------------------------------------------------------

via: https://jvns.ca/blog/2017/10/05/reasons-kubernetes-is-cool/

作者：[Julia Evans][a]
译者：[qhwdw](https://github.com/qhwdw)
校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

[a]:https://jvns.ca/about
[1]:https://github.com/kamalmarhubi/kubereview
[2]:https://jvns.ca/categories/kubernetes
[3]:https://github.com/kelseyhightower/kubernetes-the-hard-way
[4]:https://github.com/kubernetes/kubernetes/blob/e4551d50e57c089aab6f67333412d3ca64bc09ae/pkg/controller/cronjob/cronjob_controller.go
[5]:https://github.com/kamalmarhubi/kubereview
[6]:https://jvns.ca/blog/2016/12/22/container-networking/
[7]:https://jvns.ca/blog/2017/08/05/how-kubernetes-certificates-work/


