2017-12-08 13:25:13 +08:00
为什么 Kubernetes 很酷
============================================================
在我刚开始学习 Kubernetes( 大约是一年半以前吧? ) 时, 我真的不明白为什么应该去关注它。
2018-02-03 23:42:17 +08:00
在我使用 Kubernetes 全职工作了三个多月后,我才逐渐明白了为什么我应该使用它。(我距离成为一个 Kubernetes 专家还很远!)希望这篇文章对你理解 Kubernetes 能做什么会有帮助!
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
我将尝试去解释我对 Kubernetes 感兴趣的一些原因,而不去使用 “< ruby > 原生云< rt > cloud native< / rt > < / ruby > ”、“< ruby > 编排系统< rt > orchestration< / rt > < / ruby > ”、“< ruby > 容器< rt > container< / rt > < / ruby > ”,或者任何 Kubernetes 专用的术语 :)。我去解释的这些观点主要来自一位 Kubernetes 操作者/基础设施工程师,因为,我现在的工作就是去配置 Kubernetes 和让它工作的更好。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
我不会去尝试解决一些如 “你应该在你的生产系统中使用 Kubernetes 吗?”这样的问题。那是非常复杂的问题。(不仅是因为“生产系统”根据你的用途而总是有不同的要求)
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
### Kubernetes 可以让你无需设置一台新的服务器即可在生产系统中运行代码
2017-12-08 13:25:13 +08:00
我首次被说教使用 Kubernetes 是与我的伙伴 Kamal 的下面的谈话:
大致是这样的:
2018-02-03 23:42:17 +08:00
* Kamal: 使用 Kubernetes 你可以通过一条命令就能设置一台新的服务器。
* Julia: 我觉得不太可能吧。
* Kamal: 像这样,你写一个配置文件,然后应用它,这时候,你就在生产系统中运行了一个 HTTP 服务。
* Julia: 但是,现在我需要去创建一个新的 AWS 实例,明确地写一个 Puppet 清单,设置服务发现,配置负载均衡,配置我们的部署软件,并且确保 DNS 正常工作,如果没有什么问题的话,至少在 4 小时后才能投入使用。
2017-12-08 13:25:13 +08:00
* Kamal: 是的,使用 Kubernetes 你不需要做那么多事情,你可以在 5 分钟内设置一台新的 HTTP 服务,并且它将自动运行。只要你的集群中有空闲的资源它就能正常工作!
2018-02-03 23:42:17 +08:00
* Julia: 这儿一定是一个“坑”。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
这里有一种陷阱,设置一个生产用 Kubernetes 集群(在我的经险中)确实并不容易。(查看 [Kubernetes 艰难之旅][3] 中去开始使用时有哪些复杂的东西)但是,我们现在并不深入讨论它。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
因此, Kubernetes 第一个很酷的事情是,它可能使那些想在生产系统中部署新开发的软件的方式变得更容易。那是很酷的事,而且它真的是这样,因此,一旦你使用一个运作中的 Kubernetes 集群,你真的可以仅使用一个配置文件就在生产系统中设置一台 HTTP 服务(在 5 分钟内运行这个应用程序,设置一个负载均衡,给它一个 DNS 名字,等等)。看起来真的很有趣。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
### 对于运行在生产系统中的代码, Kubernetes 可以提供更好的可见性和可管理性
2017-12-08 13:25:13 +08:00
在我看来,在理解 etcd 之前,你可能不会理解 Kubernetes 的。因此,让我们先讨论 etcd!
2018-02-03 23:42:17 +08:00
想像一下,如果现在我这样问你,“告诉我你运行在生产系统中的每个应用程序,它运行在哪台主机上?它是否状态很好?是否为它分配了一个 DNS 名字?”我并不知道这些,但是,我可能需要到很多不同的地方去查询来回答这些问题,并且,我需要花很长的时间才能搞定。我现在可以很确定地说不需要查询,仅一个 API 就可以搞定它们。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
在 Kubernetes 中,你的集群的所有状态 – 运行中的应用程序 (“pod”)、节点、DNS 名字、 cron 任务、 等等 —— 都保存在一个单一的数据库中( etcd) 。每个 Kubernetes 组件是无状态的,并且基本是通过下列方式工作的:
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
* 从 etcd 中读取状态(比如,“分配给节点 1 的 pod 列表”)
* 产生变化(比如,“在节点 1 上运行 pod A”)
2017-12-08 13:25:13 +08:00
* 更新 etcd 中的状态(比如,“设置 pod A 的状态为 ‘ running’ ”)
2018-02-03 23:42:17 +08:00
这意味着,如果你想去回答诸如 “在那个可用区中有多少台运行着 nginx 的 pod? ” 这样的问题时,你可以通过查询一个统一的 API( Kubernetes API) 去回答它。并且, 你可以在每个其它 Kubernetes 组件上运行那个 API 去进行同样的访问。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
这也意味着,你可以很容易地去管理每个运行在 Kubernetes 中的任何东西。比如说,如果你想要:
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
* 部署实现一个复杂的定制的部署策略(部署一个东西,等待 2 分钟,部署 5 个以上,等待 3.7 分钟,等等)
2017-12-08 13:25:13 +08:00
* 每当推送到 github 上一个分支,自动化 [启动一个新的 web 服务器][1]
* 监视所有你的运行的应用程序,确保它们有一个合理的内存使用限制。
2018-02-03 23:42:17 +08:00
这些你只需要写一个程序与 Kubernetes API( “controller”) 通讯就可以了。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
另一个关于 Kubernetes API 的令人激动的事情是,你不会局限于 Kubernetes 所提供的现有功能!如果对于你要部署/创建/监视的软件有你自己的方案,那么,你可以使用 Kubernetes API 去写一些代码去达到你的目的!它可以让你做到你想做的任何事情。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
### 即便每个 Kubernetes 组件都“挂了”,你的代码将仍然保持运行
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
关于 Kubernetes 我(在各种博客文章中 :))承诺的一件事情是,“如果 Kubernetes API 服务和其它组件‘挂了’也没事,你的代码将一直保持运行状态”。我认为理论上这听起来很酷,但是我不确定它是否真是这样的。
2017-12-08 13:25:13 +08:00
到目前为止,这似乎是真的!
2018-02-03 23:42:17 +08:00
我已经断开了一些正在运行的 etcd, 发生了这些情况:
2017-12-08 13:25:13 +08:00
1. 所有的代码继续保持运行状态
2. 不能做 _新的_ 事情( 你不能部署新的代码或者生成变更, cron 作业将停止工作)
3. 当它恢复时,集群将赶上这期间它错过的内容
2018-02-03 23:42:17 +08:00
这样做意味着如果 etcd 宕掉,并且你的应用程序的其中之一崩溃或者发生其它事情,在 etcd 恢复之前,它不能够恢复。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
### Kubernetes 的设计对 bug 很有弹性
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
与任何软件一样, Kubernetes 也会有 bug。例如, 到目前为止, 我们的集群控制管理器有内存泄漏, 并且, 调度器经常崩溃。bug 当然不好,但是,我发现 Kubernetes 的设计可以帮助减轻它的许多核心组件中的错误的影响。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
如果你重启动任何组件,将会发生:
2017-12-08 13:25:13 +08:00
* 从 etcd 中读取所有的与它相关的状态
2018-02-03 23:42:17 +08:00
* 基于那些状态(调度 pod、回收完成的 pod、调度 cron 作业、按需部署等等),它会去做那些它认为必须要做的事情
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
因为,所有的组件并不会在内存中保持状态,你在任何时候都可以重启它们,这可以帮助你减轻各种 bug 的影响。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
例如,如果在你的控制管理器中有内存泄露。因为,控制管理器是无状态的,你可以每小时定期去重启它,或者,在感觉到可能导致任何不一致的问题发生时重启它。又或者,在调度器中遇到了一个 bug, 它有时忘记了某个 pod, 从来不去调度它们。你可以每隔 10 分钟来重启调度器来缓减这种情况。(我们并不会这么做,而是去修复这个 bug, 但是, 你_可以这样做_ :) )
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
因此,我觉得即使在它的核心组件中有 bug, 我仍然可以信任 Kubernetes 的设计可以让我确保集群状态的一致性。并且,总在来说,随着时间的推移软件质量会提高。唯一你必须去操作的有状态的东西就是 etcd。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
不用过多地讨论“状态”这个东西 —— 而我认为在 Kubernetes 中很酷的一件事情是,唯一需要去做备份/恢复计划的东西是 etcd (除非为你的 pod 使用了持久化存储的卷)。我认为这样可以使 Kubernetes 运维比你想的更容易一些。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
### 在 Kubernetes 之上实现新的分布式系统是非常容易的
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
假设你想去实现一个分布式 cron 作业调度系统!从零开始做工作量非常大。但是,在 Kubernetes 里面实现一个分布式 cron 作业调度系统是非常容易的!(仍然没那么简单,毕竟它是一个分布式系统)
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
我第一次读到 Kubernetes 的 cron 作业控制器的代码时,我对它是如此的简单感到由衷高兴。去读读看,其主要的逻辑大约是 400 行的 Go 代码。去读它吧! => [cronjob_controller.go][4] < =
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
cron 作业控制器基本上做的是:
2017-12-08 13:25:13 +08:00
* 每 10 秒钟:
2018-02-03 23:42:17 +08:00
* 列出所有已存在的 cron 作业
2017-12-08 13:25:13 +08:00
* 检查是否有需要现在去运行的任务
2018-02-03 23:42:17 +08:00
* 如果有,创建一个新的作业对象去调度,并通过其它的 Kubernetes 控制器实际运行它
2017-12-08 13:25:13 +08:00
* 清理已完成的作业
* 重复以上工作
2018-02-03 23:42:17 +08:00
Kubernetes 模型是很受限制的(它有定义在 etcd 中的资源模式,控制器读取这个资源并更新 etcd) , 我认为这种相关的固有的/受限制的模型,可以使它更容易地在 Kubernetes 框架中开发你自己的分布式系统。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
Kamal 给我说的是 “Kubernetes 是一个写你自己的分布式系统的很好的平台” ,而不是“ Kubernetes 是一个你可以使用的分布式系统”,并且,我觉得它真的很有意思。他做了一个 [为你推送到 GitHub 的每个分支运行一个 HTTP 服务的系统][5] 的原型。这花了他一个周末的时间,大约 800 行 Go 代码,我认为它真不可思议!
2017-12-08 13:25:13 +08:00
### Kubernetes 可以使你做一些非常神奇的事情(但并不容易)
2018-02-03 23:42:17 +08:00
我一开始就说 “kubernetes 可以让你做一些很神奇的事情,你可以用一个配置文件来做这么多的基础设施,它太神奇了”。这是真的!
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
为什么说 “Kubernetes 并不容易”呢?是因为 Kubernetes 有很多部分,学习怎么去成功地运营一个高可用的 Kubernetes 集群要做很多的工作。就像我发现它给我了许多抽象的东西,我需要去理解这些抽象的东西才能调试问题和正确地配置它们。我喜欢学习新东西,因此,它并不会使我发狂或者生气,但是我认为了解这一点很重要 :)
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
对于 “我不能仅依靠抽象概念” 的一个具体的例子是,我努力学习了许多 [Linux 上网络是如何工作的][6],才让我对设置 Kubernetes 网络稍有信心,这比我以前学过的关于网络的知识要多很多。这种方式很有意思但是非常费时间。在以后的某个时间,我或许写更多的关于设置 Kubernetes 网络的困难/有趣的事情。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
或者,为了成功设置我的 Kubernetes CA, 我写了一篇 [2000 字的博客文章][7],述及了我不得不学习 Kubernetes 不同方式的 CA 的各种细节。
2017-12-08 13:25:13 +08:00
2018-02-03 23:42:17 +08:00
我觉得,像 GKE ( Google 的 Kubernetes 产品) 这样的一些监管的 Kubernetes 的系统可能更简单,因为,他们为你做了许多的决定,但是,我没有尝试过它们。
2017-12-08 13:25:13 +08:00
--------------------------------------------------------------------------------
via: https://jvns.ca/blog/2017/10/05/reasons-kubernetes-is-cool/
作者:[Julia Evans][a]
译者:[qhwdw](https://github.com/qhwdw)
2018-02-03 23:42:17 +08:00
校对:[wxy](https://github.com/wxy)
2017-12-08 13:25:13 +08:00
本文由 [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/